FFmpeg
llviddsp.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 Alexandra Hájková
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with FFmpeg; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20 
21 #include <stddef.h>
22 #include <string.h>
23 
24 #include "libavutil/cpu.h"
25 #include "libavutil/macros.h"
26 #include "libavutil/mem.h"
27 
29 
30 #include "checkasm.h"
31 
32 #define randomize_buffers(buf, size) \
33  do { \
34  int j; \
35  uint8_t *tmp_buf = (uint8_t *)buf;\
36  for (j = 0; j < size; j++) \
37  tmp_buf[j] = rnd() & 0xFF; \
38  } while (0)
39 
40 #define init_buffer(a0, a1, type, width)\
41  if (!a0 || !a1)\
42  fail();\
43  randomize_buffers(a0, width * sizeof(type));\
44  memcpy(a1, a0, width*sizeof(type));\
45 
46 static void check_add_bytes(LLVidDSPContext *c, int width, size_t aligned_width)
47 {
48  uint8_t *dst0 = av_mallocz(aligned_width);
49  uint8_t *dst1 = av_mallocz(aligned_width);
50  uint8_t *src0 = av_malloc(aligned_width);
51  uint8_t *src1 = av_malloc(aligned_width);
52  declare_func(void, uint8_t *dst, uint8_t *src, ptrdiff_t w);
53 
54  init_buffer(src0, src1, uint8_t, width);
55 
56  if (!dst0 || !dst1)
57  fail();
58 
59 
60  call_ref(dst0, src0, width);
61  call_new(dst1, src1, width);
62  if (memcmp(dst0, dst1, width))
63  fail();
64  bench_new(dst1, src1, width);
65 
66  av_free(src0);
67  av_free(src1);
68  av_free(dst0);
69  av_free(dst1);
70 }
71 
72 static void check_add_median_pred(LLVidDSPContext *c, int width, size_t aligned_width)
73 {
74  int a0, a1, b0, b1;
75  uint8_t *dst0 = av_mallocz(aligned_width);
76  uint8_t *dst1 = av_mallocz(aligned_width);
77  uint8_t *src0 = av_malloc(aligned_width);
78  uint8_t *src1 = av_malloc(aligned_width);
79  uint8_t *diff0 = av_malloc(aligned_width);
80  uint8_t *diff1 = av_malloc(aligned_width);
81  declare_func(void, uint8_t *dst, const uint8_t *src1,
82  const uint8_t *diff, ptrdiff_t w,
83  int *left, int *left_top);
84 
85  init_buffer(src0, src1, uint8_t, width);
86  init_buffer(diff0, diff1, uint8_t, width);
87 
88  a0 = rnd() & 0xFF;
89  b0 = rnd() & 0xFF;
90  a1 = a0;
91  b1 = b0;
92 
93 
94  call_ref(dst0, src0, diff0, width, &a0, &b0);
95  call_new(dst1, src1, diff1, width, &a1, &b1);
96  if (memcmp(dst0, dst1, width) || (a0 != a1) || (b0 != b1))
97  fail();
98  bench_new(dst1, src1, diff1, width, &a1, &b1);
99 
100  av_free(src0);
101  av_free(src1);
102  av_free(diff0);
103  av_free(diff1);
104  av_free(dst0);
105  av_free(dst1);
106 }
107 
108 static void check_add_left_pred(LLVidDSPContext *c, int width, size_t aligned_width, int acc)
109 {
110  int res0, res1;
111  declare_func(int, uint8_t *dst, const uint8_t *src, ptrdiff_t w, int acc);
112  uint8_t *dst0 = av_mallocz(aligned_width);
113  uint8_t *dst1 = av_mallocz(aligned_width);
114  uint8_t *src0 = av_malloc(aligned_width);
115  uint8_t *src1 = av_malloc(aligned_width);
116 
117  init_buffer(src0, src1, uint8_t, width);
118 
119  if (!dst0 || !dst1)
120  fail();
121 
122  res0 = call_ref(dst0, src0, width, acc);
123  res1 = call_new(dst1, src1, width, acc);
124  if ((res0 & 0xFF) != (res1 & 0xFF) || memcmp(dst0, dst1, width))
125  fail();
126  bench_new(dst1, src1, width, acc);
127 
128  av_free(src0);
129  av_free(src1);
130  av_free(dst0);
131  av_free(dst1);
132 }
133 
134 static void check_add_left_pred_16(LLVidDSPContext *c, unsigned mask, int width,
135  size_t align, unsigned acc)
136 {
137  int res0, res1;
138  uint16_t *dst0, *dst1, *src0, *src1;
139  size_t aligned_width = FFALIGN(width * sizeof(*dst0), align);
140  declare_func(int, uint16_t *dst, const uint16_t *src, unsigned mask, ptrdiff_t w, unsigned acc);
141 
142  dst0 = av_mallocz(aligned_width);
143  dst1 = av_mallocz(aligned_width);
144  src0 = av_malloc(aligned_width);
145  src1 = av_malloc(aligned_width);
146 
147  init_buffer(src0, src1, uint16_t, width);
148 
149  if (!dst0 || !dst1)
150  fail();
151 
152  res0 = call_ref(dst0, src0, mask, width, acc);
153  res1 = call_new(dst1, src1, mask, width, acc);
154  if ((res0 & 0xFFFF) != (res1 & 0xFFFF) || memcmp(dst0, dst1, width * sizeof(*dst0)))
155  fail();
156  bench_new(dst1, src1, mask, width, acc);
157 
158  av_free(src0);
159  av_free(src1);
160  av_free(dst0);
161  av_free(dst1);
162 }
163 
164 static void check_add_gradient_pred(LLVidDSPContext *c, int w, size_t align)
165 {
166  int src_size, stride;
167  uint8_t *src0, *src1;
168  declare_func(void, uint8_t *src, const ptrdiff_t stride,
169  const ptrdiff_t width);
170 
171  stride = FFALIGN(w + 32, align);
172  src_size = (stride + 32) * 2; /* dsp need previous line, and ignore the start of the line */
173  src0 = av_mallocz(src_size);
174  src1 = av_mallocz(src_size);
175 
176  init_buffer(src0, src1, uint8_t, src_size);
177 
178  call_ref(src0 + stride + 32, stride, w);
179  call_new(src1 + stride + 32, stride, w);
180  if (memcmp(src0, src1, stride)||/* previous line doesn't change */
181  memcmp(src0+stride, src1 + stride, w + 32)) {
182  fail();
183  }
184  bench_new(src1 + stride + 32, stride, w);
185 
186  av_free(src0);
187  av_free(src1);
188 }
189 
191 {
193  int accRnd = rnd() & 0xFF;
194 
195  size_t align = av_cpu_max_align();
196  int width = 1 + rnd() % 16*128;
197  size_t aligned_width = FFALIGN(width, align);
198 
200 
201  if (check_func(c.add_bytes, "add_bytes"))
202  check_add_bytes(&c, width, aligned_width);
203  report("add_bytes");
204 
205  if (check_func(c.add_median_pred, "add_median_pred"))
206  check_add_median_pred(&c, width, aligned_width);
207  report("add_median_pred");
208 
209  if (check_func(c.add_left_pred, "add_left_pred_zero"))
210  check_add_left_pred(&c, width, aligned_width, 0);
211  report("add_left_pred_zero");
212 
213  if (check_func(c.add_left_pred, "add_left_pred_rnd_acc"))
214  check_add_left_pred(&c, width, aligned_width, accRnd);
215  report("add_left_pred_rnd_acc");
216 
217  if (check_func(c.add_left_pred_int16, "add_left_pred_int16"))
218  check_add_left_pred_16(&c, 255, width, align, accRnd);
219  report("add_left_pred_int16");
220 
221  if (check_func(c.add_gradient_pred, "add_gradient_pred"))
223  report("add_gradient_pred");
224 }
check_add_gradient_pred
static void check_add_gradient_pred(LLVidDSPContext *c, int w, size_t align)
Definition: llviddsp.c:164
src1
const pixel * src1
Definition: h264pred_template.c:420
mask
int mask
Definition: mediacodecdec_common.c:154
check_func
#define check_func
Definition: test.h:481
bench_new
#define bench_new
Definition: test.h:487
cpu.h
call_ref
#define call_ref
Definition: test.h:485
b1
static double b1(void *priv, double x, double y)
Definition: vf_xfade.c:2034
macros.h
ff_llviddsp_init
av_cold void ff_llviddsp_init(LLVidDSPContext *c)
Definition: lossless_videodsp.c:114
checkasm.h
LLVidDSPContext
Definition: lossless_videodsp.h:28
declare_func
#define declare_func
Definition: test.h:489
check_add_left_pred_16
static void check_add_left_pred_16(LLVidDSPContext *c, unsigned mask, int width, size_t align, unsigned acc)
Definition: llviddsp.c:134
av_mallocz
#define av_mallocz(s)
Definition: tableprint_vlc.h:31
fail
#define fail
Definition: test.h:479
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
checkasm_check_llviddsp
void checkasm_check_llviddsp(void)
Definition: llviddsp.c:190
init_buffer
#define init_buffer(a0, a1, type, width)
Definition: llviddsp.c:40
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:87
rnd
#define rnd
Definition: checkasm.h:136
av_malloc
#define av_malloc(s)
Definition: ops_static.c:52
align
static const uint8_t *BS_FUNC() align(BSCTX *bc)
Skip bits to a byte boundary.
Definition: bitstream_template.h:419
diff
static av_always_inline int diff(const struct color_info *a, const struct color_info *b, const int trans_thresh)
Definition: vf_paletteuse.c:166
a0
static double a0(void *priv, double x, double y)
Definition: vf_xfade.c:2028
check_add_left_pred
static void check_add_left_pred(LLVidDSPContext *c, int width, size_t aligned_width, int acc)
Definition: llviddsp.c:108
av_cpu_max_align
size_t av_cpu_max_align(void)
Get the maximum data alignment that may be required by FFmpeg.
Definition: cpu.c:287
call_new
#define call_new
Definition: test.h:486
left
Tag MUST be and< 10hcoeff half pel interpolation filter coefficients, hcoeff[0] are the 2 middle coefficients[1] are the next outer ones and so on, resulting in a filter like:...eff[2], hcoeff[1], hcoeff[0], hcoeff[0], hcoeff[1], hcoeff[2] ... the sign of the coefficients is not explicitly stored but alternates after each coeff and coeff[0] is positive, so ...,+,-,+,-,+,+,-,+,-,+,... hcoeff[0] is not explicitly stored but found by subtracting the sum of all stored coefficients with signs from 32 hcoeff[0]=32 - hcoeff[1] - hcoeff[2] - ... a good choice for hcoeff and htaps is htaps=6 hcoeff={40,-10, 2} an alternative which requires more computations at both encoder and decoder side and may or may not be better is htaps=8 hcoeff={42,-14, 6,-2}ref_frames minimum of the number of available reference frames and max_ref_frames for example the first frame after a key frame always has ref_frames=1spatial_decomposition_type wavelet type 0 is a 9/7 symmetric compact integer wavelet 1 is a 5/3 symmetric compact integer wavelet others are reserved stored as delta from last, last is reset to 0 if always_reset||keyframeqlog quality(logarithmic quantizer scale) stored as delta from last, last is reset to 0 if always_reset||keyframemv_scale stored as delta from last, last is reset to 0 if always_reset||keyframe FIXME check that everything works fine if this changes between framesqbias dequantization bias stored as delta from last, last is reset to 0 if always_reset||keyframeblock_max_depth maximum depth of the block tree stored as delta from last, last is reset to 0 if always_reset||keyframequant_table quantization tableHighlevel bitstream structure:==============================--------------------------------------------|Header|--------------------------------------------|------------------------------------|||Block0||||split?||||yes no||||......... intra?||||:Block01 :yes no||||:Block02 :....... ..........||||:Block03 ::y DC ::ref index:||||:Block04 ::cb DC ::motion x :||||......... :cr DC ::motion y :||||....... ..........|||------------------------------------||------------------------------------|||Block1|||...|--------------------------------------------|------------ ------------ ------------|||Y subbands||Cb subbands||Cr subbands||||--- ---||--- ---||--- ---|||||LL0||HL0||||LL0||HL0||||LL0||HL0|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||LH0||HH0||||LH0||HH0||||LH0||HH0|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||HL1||LH1||||HL1||LH1||||HL1||LH1|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||HH1||HL2||||HH1||HL2||||HH1||HL2|||||...||...||...|||------------ ------------ ------------|--------------------------------------------Decoding process:=================------------|||Subbands|------------||||------------|Intra DC||||LL0 subband prediction ------------|\ Dequantization ------------------- \||Reference frames|\ IDWT|------- -------|Motion \|||Frame 0||Frame 1||Compensation . OBMC v -------|------- -------|--------------. \------> Frame n output Frame Frame<----------------------------------/|...|------------------- Range Coder:============Binary Range Coder:------------------- The implemented range coder is an adapted version based upon "Range encoding: an algorithm for removing redundancy from a digitised message." by G. N. N. Martin. The symbols encoded by the Snow range coder are bits(0|1). The associated probabilities are not fix but change depending on the symbol mix seen so far. bit seen|new state ---------+----------------------------------------------- 0|256 - state_transition_table[256 - old_state];1|state_transition_table[old_state];state_transition_table={ 0, 0, 0, 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 190, 191, 192, 194, 194, 195, 196, 197, 198, 199, 200, 201, 202, 202, 204, 205, 206, 207, 208, 209, 209, 210, 211, 212, 213, 215, 215, 216, 217, 218, 219, 220, 220, 222, 223, 224, 225, 226, 227, 227, 229, 229, 230, 231, 232, 234, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 248, 0, 0, 0, 0, 0, 0, 0};FIXME Range Coding of integers:------------------------- FIXME Neighboring Blocks:===================left and top are set to the respective blocks unless they are outside of the image in which case they are set to the Null block top-left is set to the top left block unless it is outside of the image in which case it is set to the left block if this block has no larger parent block or it is at the left side of its parent block and the top right block is not outside of the image then the top right block is used for top-right else the top-left block is used Null block y, cb, cr are 128 level, ref, mx and my are 0 Motion Vector Prediction:=========================1. the motion vectors of all the neighboring blocks are scaled to compensate for the difference of reference frames scaled_mv=(mv *(256 *(current_reference+1)/(mv.reference+1))+128)> the median of the scaled left
Definition: snow.txt:386
check_add_bytes
static void check_add_bytes(LLVidDSPContext *c, int width, size_t aligned_width)
Definition: llviddsp.c:46
src0
const pixel *const src0
Definition: h264pred_template.c:419
report
#define report
Definition: test.h:480
mem.h
lossless_videodsp.h
w
uint8_t w
Definition: llvidencdsp.c:39
av_free
#define av_free(p)
Definition: tableprint_vlc.h:34
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:78
b0
static double b0(void *priv, double x, double y)
Definition: vf_xfade.c:2033
a1
static double a1(void *priv, double x, double y)
Definition: vf_xfade.c:2029
stride
#define stride
Definition: h264pred_template.c:536
width
#define width
Definition: dsp.h:89
check_add_median_pred
static void check_add_median_pred(LLVidDSPContext *c, int width, size_t aligned_width)
Definition: llviddsp.c:72
src
#define src
Definition: vp8dsp.c:248