FFmpeg
Loading...
Searching...
No Matches
vc1dsp.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2022 Ben Avison
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 <string.h>
22
23#include "checkasm.h"
24
25#include "libavcodec/vc1dsp.h"
26
27#include "libavutil/common.h"
28#include "libavutil/internal.h"
30#include "libavutil/mem.h"
32
33#define VC1DSP_TEST(func) { #func, offsetof(VC1DSPContext, func) },
34#define VC1DSP_SIZED_TEST(func, width, height) { #func, offsetof(VC1DSPContext, func), width, height },
35
36typedef struct {
37 const char *name;
38 size_t offset;
39 int width;
40 int height;
41} test;
42
43typedef struct matrix {
44 size_t width;
45 size_t height;
46 float d[];
47} matrix;
48
49static const matrix T8 = { 8, 8, {
50 12, 12, 12, 12, 12, 12, 12, 12,
51 16, 15, 9, 4, -4, -9, -15, -16,
52 16, 6, -6, -16, -16, -6, 6, 16,
53 15, -4, -16, -9, 9, 16, 4, -15,
54 12, -12, -12, 12, 12, -12, -12, 12,
55 9, -16, 4, 15, -15, -4, 16, -9,
56 6, -16, 16, -6, -6, 16, -16, 6,
57 4, -9, 15, -16, 16, -15, 9, -4
58} };
59
60static const matrix T4 = { 4, 4, {
61 17, 17, 17, 17,
62 22, 10, -10, -22,
63 17, -17, -17, 17,
64 10, -22, 22, -10
65} };
66
67static const matrix T8t = { 8, 8, {
68 12, 16, 16, 15, 12, 9, 6, 4,
69 12, 15, 6, -4, -12, -16, -16, -9,
70 12, 9, -6, -16, -12, 4, 16, 15,
71 12, 4, -16, -9, 12, 15, -6, -16,
72 12, -4, -16, 9, 12, -15, -6, 16,
73 12, -9, -6, 16, -12, -4, 16, -15,
74 12, -15, 6, 4, -12, 16, -16, 9,
75 12, -16, 16, -15, 12, -9, 6, -4
76} };
77
78static const matrix T4t = { 4, 4, {
79 17, 22, 17, 10,
80 17, 10, -17, -22,
81 17, -10, -17, 22,
82 17, -22, 17, -10
83} };
84
85static matrix *new_matrix(size_t width, size_t height)
86{
87 matrix *out = av_mallocz(sizeof (matrix) + height * width * sizeof (float));
88 if (out == NULL) {
89 fprintf(stderr, "Memory allocation failure\n");
90 exit(EXIT_FAILURE);
91 }
92 out->width = width;
93 out->height = height;
94 return out;
95}
96
97static matrix *multiply(const matrix *a, const matrix *b)
98{
99 matrix *out;
100 if (a->width != b->height) {
101 fprintf(stderr, "Incompatible multiplication\n");
102 exit(EXIT_FAILURE);
103 }
104 out = new_matrix(b->width, a->height);
105 for (int j = 0; j < out->height; ++j)
106 for (int i = 0; i < out->width; ++i) {
107 float sum = 0;
108 for (int k = 0; k < a->width; ++k)
109 sum += a->d[j * a->width + k] * b->d[k * b->width + i];
110 out->d[j * out->width + i] = sum;
111 }
112 return out;
113}
114
115static void normalise(matrix *a)
116{
117 for (int j = 0; j < a->height; ++j)
118 for (int i = 0; i < a->width; ++i) {
119 float *p = a->d + j * a->width + i;
120 *p *= 64;
121 if (a->height == 4)
122 *p /= (const unsigned[]) { 289, 292, 289, 292 } [j];
123 else
124 *p /= (const unsigned[]) { 288, 289, 292, 289, 288, 289, 292, 289 } [j];
125 if (a->width == 4)
126 *p /= (const unsigned[]) { 289, 292, 289, 292 } [i];
127 else
128 *p /= (const unsigned[]) { 288, 289, 292, 289, 288, 289, 292, 289 } [i];
129 }
130}
131
132static void divide_and_round_nearest(matrix *a, float by)
133{
134 for (int j = 0; j < a->height; ++j)
135 for (int i = 0; i < a->width; ++i) {
136 float *p = a->d + j * a->width + i;
137 *p = rintf(*p / by);
138 }
139}
140
141static void tweak(matrix *a)
142{
143 for (int j = 4; j < a->height; ++j)
144 for (int i = 0; i < a->width; ++i) {
145 float *p = a->d + j * a->width + i;
146 *p += 1;
147 }
148}
149
150/* The VC-1 spec places restrictions on the values permitted at three
151 * different stages:
152 * - D: the input coefficients in frequency domain
153 * - E: the intermediate coefficients, inverse-transformed only horizontally
154 * - R: the fully inverse-transformed coefficients
155 *
156 * To fully cater for the ranges specified requires various intermediate
157 * values to be held to 17-bit precision; yet these conditions do not appear
158 * to be utilised in real-world streams. At least some assembly
159 * implementations have chosen to restrict these values to 16-bit precision,
160 * to accelerate the decoding of real-world streams at the cost of strict
161 * adherence to the spec. To avoid our test marking these as failures,
162 * reduce our random inputs.
163 */
164#define ATTENUATION 4
165
167{
168 matrix *raw, *tmp, *D, *E, *R;
169 raw = new_matrix(width, height);
170 for (int i = 0; i < width * height; ++i)
171 raw->d[i] = (int) (rnd() % (1024/ATTENUATION)) - 512/ATTENUATION;
172 tmp = multiply(height == 8 ? &T8 : &T4, raw);
173 D = multiply(tmp, width == 8 ? &T8t : &T4t);
174 normalise(D);
176 for (int i = 0; i < width * height; ++i) {
177 if (D->d[i] < -2048/ATTENUATION || D->d[i] > 2048/ATTENUATION-1) {
178 /* Rare, so simply try again */
179 av_free(raw);
180 av_free(tmp);
181 av_free(D);
183 }
184 }
185 E = multiply(D, width == 8 ? &T8 : &T4);
187 for (int i = 0; i < width * height; ++i)
188 if (E->d[i] < -4096/ATTENUATION || E->d[i] > 4096/ATTENUATION-1) {
189 /* Rare, so simply try again */
190 av_free(raw);
191 av_free(tmp);
192 av_free(D);
193 av_free(E);
195 }
196 R = multiply(height == 8 ? &T8t : &T4t, E);
197 tweak(R);
199 for (int i = 0; i < width * height; ++i)
200 if (R->d[i] < -512/ATTENUATION || R->d[i] > 512/ATTENUATION-1) {
201 /* Rare, so simply try again */
202 av_free(raw);
203 av_free(tmp);
204 av_free(D);
205 av_free(E);
206 av_free(R);
208 }
209 av_free(raw);
210 av_free(tmp);
211 av_free(E);
212 av_free(R);
213 return D;
214}
215
216#define RANDOMIZE_BUFFER16(name, size) \
217 do { \
218 int i; \
219 for (i = 0; i < size; ++i) { \
220 uint16_t r = rnd(); \
221 AV_WN16A(name##0 + i, r); \
222 AV_WN16A(name##1 + i, r); \
223 } \
224 } while (0)
225
226#define RANDOMIZE_BUFFER8(name, size) \
227 do { \
228 int i; \
229 for (i = 0; i < size; ++i) { \
230 uint8_t r = rnd(); \
231 name##0[i] = r; \
232 name##1[i] = r; \
233 } \
234 } while (0)
235
236#define RANDOMIZE_BUFFER8_MID_WEIGHTED(name, size) \
237 do { \
238 uint8_t *p##0 = name##0, *p##1 = name##1; \
239 int i = (size); \
240 while (i-- > 0) { \
241 int x = 0x80 | (rnd() & 0x7F); \
242 x >>= rnd() % 9; \
243 if (rnd() & 1) \
244 x = -x; \
245 *p##1++ = *p##0++ = 0x80 + x; \
246 } \
247 } while (0)
248
249static void check_inv_trans_inplace(void)
250{
251 /* Inverse transform input coefficients are stored in a 16-bit buffer
252 * with row stride of 8 coefficients irrespective of transform size.
253 * vc1_inv_trans_8x8 differs from the others in two ways: coefficients
254 * are stored in column-major order, and the outputs are written back
255 * to the input buffer, so we oversize it slightly to catch overruns. */
256 LOCAL_ALIGNED_16(int16_t, inv_trans_in0, [10 * 8]);
257 LOCAL_ALIGNED_16(int16_t, inv_trans_in1, [10 * 8]);
258
260
262
263 if (check_func(h.vc1_inv_trans_8x8, "vc1dsp.vc1_inv_trans_8x8")) {
264 matrix *coeffs;
265 declare_func(void, int16_t *);
266 RANDOMIZE_BUFFER16(inv_trans_in, 10 * 8);
268 for (int j = 0; j < 8; ++j)
269 for (int i = 0; i < 8; ++i) {
270 int idx = 8 + i * 8 + j;
271 inv_trans_in1[idx] = inv_trans_in0[idx] = coeffs->d[j * 8 + i];
272 }
273 call_ref(inv_trans_in0 + 8);
274 call_new(inv_trans_in1 + 8);
275 if (memcmp(inv_trans_in0, inv_trans_in1, 10 * 8 * sizeof (int16_t)))
276 fail();
277 bench_new(inv_trans_in1 + 8);
278 av_free(coeffs);
279 }
280}
281
282static void check_inv_trans_adding(void)
283{
284 /* Inverse transform input coefficients are stored in a 16-bit buffer
285 * with row stride of 8 coefficients irrespective of transform size. */
286 LOCAL_ALIGNED_16(int16_t, inv_trans_in0, [8 * 8]);
287 LOCAL_ALIGNED_16(int16_t, inv_trans_in1, [8 * 8]);
288
289 /* For all but vc1_inv_trans_8x8, the inverse transform is narrowed and
290 * added with saturation to an array of unsigned 8-bit values. Oversize
291 * this by 8 samples left and right and one row above and below. */
292 LOCAL_ALIGNED_8(uint8_t, inv_trans_out0, [10 * 24]);
293 LOCAL_ALIGNED_8(uint8_t, inv_trans_out1, [10 * 24]);
294
296
297 const test tests[] = {
298 VC1DSP_SIZED_TEST(vc1_inv_trans_8x4, 8, 4)
299 VC1DSP_SIZED_TEST(vc1_inv_trans_4x8, 4, 8)
300 VC1DSP_SIZED_TEST(vc1_inv_trans_4x4, 4, 4)
301 VC1DSP_SIZED_TEST(vc1_inv_trans_8x8_dc, 8, 8)
302 VC1DSP_SIZED_TEST(vc1_inv_trans_8x4_dc, 8, 4)
303 VC1DSP_SIZED_TEST(vc1_inv_trans_4x8_dc, 4, 8)
304 VC1DSP_SIZED_TEST(vc1_inv_trans_4x4_dc, 4, 4)
305 };
306
308
309 for (size_t k = 0; k < FF_ARRAY_ELEMS(tests); ++k) {
310 void (*func)(uint8_t *, ptrdiff_t, int16_t *) = *(void **)((intptr_t) &h + tests[k].offset);
311 if (check_func(func, "vc1dsp.%s", tests[k].name)) {
312 matrix *coeffs;
313 declare_func(void, uint8_t *, ptrdiff_t, int16_t *);
314 RANDOMIZE_BUFFER16(inv_trans_in, 8 * 8);
315 RANDOMIZE_BUFFER8(inv_trans_out, 10 * 24);
317 for (int j = 0; j < tests[k].height; ++j)
318 for (int i = 0; i < tests[k].width; ++i) {
319 int idx = j * 8 + i;
320 inv_trans_in1[idx] = inv_trans_in0[idx] = coeffs->d[j * tests[k].width + i];
321 }
322 call_ref(inv_trans_out0 + 24 + 8, 24, inv_trans_in0);
323 call_new(inv_trans_out1 + 24 + 8, 24, inv_trans_in1);
324 if (memcmp(inv_trans_out0, inv_trans_out1, 10 * 24))
325 fail();
326 bench_new(inv_trans_out1 + 24 + 8, 24, inv_trans_in1);
327 av_free(coeffs);
328 }
329 }
330}
331
332static void check_loop_filter(void)
333{
334 /* Deblocking filter buffers are big enough to hold a 16x16 block,
335 * plus 16 columns left and 4 rows above to hold filter inputs
336 * (depending on whether v or h neighbouring block edge, oversized
337 * horizontally to maintain 16-byte alignment) plus 16 columns and
338 * 4 rows below to catch write overflows */
339 LOCAL_ALIGNED_16(uint8_t, filter_buf0, [24 * 48]);
340 LOCAL_ALIGNED_16(uint8_t, filter_buf1, [24 * 48]);
341
343
344 const test tests[] = {
345 VC1DSP_TEST(vc1_v_loop_filter4)
346 VC1DSP_TEST(vc1_h_loop_filter4)
347 VC1DSP_TEST(vc1_v_loop_filter8)
348 VC1DSP_TEST(vc1_h_loop_filter8)
349 VC1DSP_TEST(vc1_v_loop_filter16)
350 VC1DSP_TEST(vc1_h_loop_filter16)
351 };
352
354
355 for (size_t k = 0; k < FF_ARRAY_ELEMS(tests); ++k) {
356 void (*func)(uint8_t *, ptrdiff_t, int) = *(void **)((intptr_t) &h + tests[k].offset);
357 declare_func(void, uint8_t *, ptrdiff_t, int);
358 if (check_func(func, "vc1dsp.%s", tests[k].name)) {
359 for (int count = 1000; count > 0; --count) {
360 int pq = rnd() % 31 + 1;
361 RANDOMIZE_BUFFER8_MID_WEIGHTED(filter_buf, 24 * 48);
362 call_ref(filter_buf0 + 4 * 48 + 16, 48, pq);
363 call_new(filter_buf1 + 4 * 48 + 16, 48, pq);
364 if (memcmp(filter_buf0, filter_buf1, 24 * 48))
365 fail();
366 }
367 }
368 for (int j = 0; j < 24; ++j)
369 for (int i = 0; i < 48; ++i)
370 filter_buf1[j * 48 + i] = 0x60 + 0x40 * (i >= 16 && j >= 4);
371 if (check_func(func, "vc1dsp.%s_bestcase", tests[k].name))
372 bench_new(filter_buf1 + 4 * 48 + 16, 48, 1);
373 if (check_func(func, "vc1dsp.%s_worstcase", tests[k].name))
374 bench_new(filter_buf1 + 4 * 48 + 16, 48, 31);
375 }
376}
377
378#define TEST_UNESCAPE \
379 do { \
380 for (int count = 100; count > 0; --count) { \
381 escaped_offset = rnd() & 7; \
382 unescaped_offset = rnd() & 7; \
383 escaped_len = (1u << (rnd() % 8) + 3) - (rnd() & 7); \
384 RANDOMIZE_BUFFER8(unescaped, UNESCAPE_BUF_SIZE); \
385 len0 = call_ref(escaped0 + escaped_offset, escaped_len, unescaped0 + unescaped_offset); \
386 len1 = call_new(escaped1 + escaped_offset, escaped_len, unescaped1 + unescaped_offset); \
387 if (len0 != len1 || memcmp(unescaped0, unescaped1, UNESCAPE_BUF_SIZE)) \
388 fail(); \
389 } \
390 } while (0)
391
392static void check_unescape(void)
393{
394 /* This appears to be a typical length of buffer in use */
395#define LOG2_UNESCAPE_BUF_SIZE 17
396#define UNESCAPE_BUF_SIZE (1u<<LOG2_UNESCAPE_BUF_SIZE)
397 LOCAL_ALIGNED_8(uint8_t, escaped0, [UNESCAPE_BUF_SIZE]);
398 LOCAL_ALIGNED_8(uint8_t, escaped1, [UNESCAPE_BUF_SIZE]);
399 LOCAL_ALIGNED_8(uint8_t, unescaped0, [UNESCAPE_BUF_SIZE]);
400 LOCAL_ALIGNED_8(uint8_t, unescaped1, [UNESCAPE_BUF_SIZE]);
401
403
405
406 if (check_func(h.vc1_unescape_buffer, "vc1dsp.vc1_unescape_buffer")) {
407 int len0, len1, escaped_offset, unescaped_offset, escaped_len;
408 declare_func(int, const uint8_t *, int, uint8_t *);
409
410 /* Test data which consists of escapes sequences packed as tightly as possible */
411 for (int x = 0; x < UNESCAPE_BUF_SIZE; ++x)
412 escaped1[x] = escaped0[x] = 3 * (x % 3 == 0);
414
415 /* Test random data */
418
419 /* Test data with escape sequences at random intervals */
420 for (int x = 0; x <= UNESCAPE_BUF_SIZE - 4;) {
421 int gap, gap_msb;
422 escaped1[x+0] = escaped0[x+0] = 0;
423 escaped1[x+1] = escaped0[x+1] = 0;
424 escaped1[x+2] = escaped0[x+2] = 3;
425 escaped1[x+3] = escaped0[x+3] = rnd() & 3;
426 gap_msb = 2u << (rnd() % 8);
427 gap = (rnd() &~ -gap_msb) | gap_msb;
428 x += gap;
429 }
431
432 /* Test data which is known to contain no escape sequences */
433 memset(escaped0, 0xFF, UNESCAPE_BUF_SIZE);
434 memset(escaped1, 0xFF, UNESCAPE_BUF_SIZE);
436
437 /* Benchmark the no-escape-sequences case */
438 bench_new(escaped1, UNESCAPE_BUF_SIZE, unescaped1);
439 }
440}
441
442static void check_mspel_pixels(void)
443{
444 enum {
445 MAX_BLOCK_SIZE = 16,
446 MAX_STRIDE = 64,
447 /// BUF_SIZE is bigger than necessary in order to test strides > block width.
449 /**
450 * Due to qpel interpolation the input needs one extra line at the top
451 * and two at the bottom; horizontal interpolation also needs one pixel
452 * to the left and two to the right. At least the x86 implementation
453 * actually accesses three pixels to the right.
454 * The input is not subject to alignment requirements; making the input buffer
455 * bigger (by MAX_BLOCK_SIZE - 1) allows us to use a random misalignment.
456 */
457 INPUT_BUF_SIZE = (MAX_BLOCK_SIZE - 1) + 1 +
458 (MAX_BLOCK_SIZE + 1 + 2 - 1) * MAX_STRIDE + MAX_BLOCK_SIZE + 2 + 1,
459 };
460 DECLARE_ALIGNED(16, uint8_t, dstbuf0)[BUF_SIZE];
461 DECLARE_ALIGNED(16, uint8_t, dstbuf1)[BUF_SIZE];
462 uint8_t srcbuf0[INPUT_BUF_SIZE];
463 uint8_t srcbuf1[INPUT_BUF_SIZE];
464
466
467 const struct MSPelTest {
468 const char *name;
469 size_t offset;
470 } tests[] = {
471#define MSPEL_TEST(elem) { .name = #elem, offsetof(VC1DSPContext, elem) }
472 MSPEL_TEST(put_vc1_mspel_pixels_tab),
473 MSPEL_TEST(avg_vc1_mspel_pixels_tab),
474 };
475
477
478 for (size_t k = 0; k < FF_ARRAY_ELEMS(tests); ++k) {
479 const vc1op_pixels_func (*func)[16] = (vc1op_pixels_func(*)[16])((char*)&h + tests[k].offset);
480 for (unsigned j = 0; j < 2; ++j) {
481 const unsigned blocksize = 16 >> j;
482
483 for (unsigned dxy = 0; dxy < 16; ++dxy) {
484 if (!check_func(func[j][dxy], "vc1dsp.%s_mc%u%u_%u", tests[k].name, dxy & 3, dxy >> 2, blocksize))
485 continue;
486 declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *, const uint8_t*, ptrdiff_t, int);
487 size_t dst_offset = (rnd() % (MAX_BLOCK_SIZE / blocksize)) * blocksize;
488 ptrdiff_t stride = (rnd() % (MAX_STRIDE / blocksize) + 1) * blocksize;
489 size_t src_offset = 1 + stride + rnd() % MAX_BLOCK_SIZE;
490 const uint8_t *src0 = srcbuf0 + src_offset, *src1 = srcbuf1 + src_offset;
491 uint8_t *dst0 = dstbuf0 + dst_offset, *dst1 = dstbuf1 + dst_offset;
492
493 if (rnd() & 1) {
494 // Flip stride.
495 dst1 += (blocksize - 1) * stride;
496 dst0 += (blocksize - 1) * stride;
497 // We need one line above src and two lines below the block,
498 // hence blocksize * stride.
499 src0 += blocksize * stride;
500 src1 += blocksize * stride;
501 stride = -stride;
502 }
503 RANDOMIZE_BUFFER8(srcbuf, sizeof(srcbuf0));
504 for (int round = 0; round <= 1; ++round) {
505 RANDOMIZE_BUFFER8(dstbuf, sizeof(dstbuf0));
506 call_ref(dst0, src0, stride, round);
507 call_new(dst1, src1, stride, round);
508 if (memcmp(dstbuf0, dstbuf1, sizeof(dstbuf0))) {
509 fail();
510 }
511 }
512 bench_new(dst1, src1, stride, 0);
513 }
514 }
515 }
516}
517
519{
522 report("inv_trans");
523
525 report("loop_filter");
526
528 report("unescape_buffer");
529
531 report("mspel_pixels");
532}
static FILE * out
#define E
Definition avdct.c:34
#define D
Definition avdct.c:35
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define rnd
Definition checkasm.h:136
common internal and external API header
#define NULL
Definition coverity.c:32
static __device__ float rintf(float a)
const TestCase tests[]
Definition fifo_muxer.c:363
#define declare_func
Definition test.h:489
#define fail
Definition test.h:479
#define bench_new
Definition test.h:487
#define check_func
Definition test.h:481
#define call_new
Definition test.h:486
#define call_ref
Definition test.h:485
#define report
Definition test.h:480
#define declare_func_emms
Definition test.h:490
int a
#define R
Definition huffyuv.h:44
#define MAX_BLOCK_SIZE
Definition imgutils.c:580
#define b
Definition input.c:43
unsigned offset
Definition libaomenc.c:763
int(* func)(AVBPrint *dst, const char *in, const char *arg)
Definition jacosubdec.c:66
av_cold void ff_vc1dsp_init(VC1DSPContext *dsp)
Definition vc1dsp.c:968
#define AV_CPU_FLAG_MMX
standard MMX
Definition cpu.h:32
common internal API header
static av_always_inline av_const double round(double x)
Definition libm.h:446
Memory handling functions.
#define DECLARE_ALIGNED(n, t, v)
Declare a variable that is aligned in memory.
#define LOCAL_ALIGNED_16(t, v,...)
#define LOCAL_ALIGNED_8(t, v,...)
const char * name
Definition qsvenc.c:142
#define BUF_SIZE
Definition setpts.c:159
#define FF_ARRAY_ELEMS(a)
float d[]
Definition vc1dsp.c:46
size_t height
Definition vc1dsp.c:45
size_t width
Definition vc1dsp.c:44
Definition idctdsp.c:35
int width
Definition vc1dsp.c:39
int height
Definition vc1dsp.c:40
#define stride
#define av_free(p)
#define av_mallocz(s)
static uint8_t tmp[40]
Definition aes_ctr.c:52
#define src1
Definition h264pred.c:141
#define src0
Definition h264pred.c:140
#define INPUT_BUF_SIZE
Definition hpeldsp.c:38
#define MAX_STRIDE
Definition hpeldsp.c:31
#define RANDOMIZE_BUFFER16(name, size)
Definition vc1dsp.c:216
static void check_loop_filter(void)
Definition vc1dsp.c:332
static const matrix T8
Definition vc1dsp.c:49
static matrix * multiply(const matrix *a, const matrix *b)
Definition vc1dsp.c:97
static void normalise(matrix *a)
Definition vc1dsp.c:115
static void check_inv_trans_inplace(void)
Definition vc1dsp.c:249
static void check_inv_trans_adding(void)
Definition vc1dsp.c:282
#define RANDOMIZE_BUFFER8(name, size)
Definition vc1dsp.c:226
#define RANDOMIZE_BUFFER8_MID_WEIGHTED(name, size)
Definition vc1dsp.c:236
static void check_unescape(void)
Definition vc1dsp.c:392
static matrix * generate_inverse_quantized_transform_coefficients(size_t width, size_t height)
Definition vc1dsp.c:166
static matrix * new_matrix(size_t width, size_t height)
Definition vc1dsp.c:85
#define TEST_UNESCAPE
Definition vc1dsp.c:378
static void check_mspel_pixels(void)
Definition vc1dsp.c:442
static const matrix T4t
Definition vc1dsp.c:78
#define UNESCAPE_BUF_SIZE
static const matrix T4
Definition vc1dsp.c:60
#define VC1DSP_TEST(func)
Definition vc1dsp.c:33
#define MSPEL_TEST(elem)
static const matrix T8t
Definition vc1dsp.c:67
#define ATTENUATION
Definition vc1dsp.c:164
void checkasm_check_vc1dsp(void)
Definition vc1dsp.c:518
static void divide_and_round_nearest(matrix *a, float by)
Definition vc1dsp.c:132
static void tweak(matrix *a)
Definition vc1dsp.c:141
#define VC1DSP_SIZED_TEST(func, width, height)
Definition vc1dsp.c:34
#define height
Definition dsp.h:89
#define width
Definition dsp.h:89
VC-1 and WMV3 decoder.
void(* vc1op_pixels_func)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int round)
Definition vc1dsp.h:33