FFmpeg
Loading...
Searching...
No Matches
mpegvideo_unquantize.c
Go to the documentation of this file.
1/*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19#include <assert.h>
20#include <stddef.h>
21
22#include "config.h"
23
24#include "checkasm.h"
25
26#include "libavcodec/idctdsp.h"
27#include "libavcodec/mathops.h"
31
34
35#define randomize_struct(TYPE, s) do { \
36 static_assert(!(_Alignof(TYPE) % 4), \
37 "can't use aligned stores"); \
38 unsigned char *ptr = (unsigned char*)s; \
39 for (size_t i = 0; i < (sizeof(*s) & ~3); i += 4) \
40 AV_WN32A(ptr + i, rnd()); \
41 for (size_t i = sizeof(*s) & ~3; i < sizeof(*s); ++i) \
42 ptr[i] = rnd(); \
43 } while (0)
44
50
54#if ARCH_X86_32 && HAVE_X86ASM
56#endif
57#if ARCH_PPC || ARCH_X86
59#endif
60#if ARCH_ARM || ARCH_AARCH64
62#endif
63#if ARCH_X86 && HAVE_X86ASM
65#endif
66};
67// Copied here to avoid #ifs.
68static const uint8_t ff_wmv1_scantable[][64] = {
69 { 0x00, 0x08, 0x01, 0x02, 0x09, 0x10, 0x18, 0x11,
70 0x0A, 0x03, 0x04, 0x0B, 0x12, 0x19, 0x20, 0x28,
71 0x30, 0x38, 0x29, 0x21, 0x1A, 0x13, 0x0C, 0x05,
72 0x06, 0x0D, 0x14, 0x1B, 0x22, 0x31, 0x39, 0x3A,
73 0x32, 0x2A, 0x23, 0x1C, 0x15, 0x0E, 0x07, 0x0F,
74 0x16, 0x1D, 0x24, 0x2B, 0x33, 0x3B, 0x3C, 0x34,
75 0x2C, 0x25, 0x1E, 0x17, 0x1F, 0x26, 0x2D, 0x35,
76 0x3D, 0x3E, 0x36, 0x2E, 0x27, 0x2F, 0x37, 0x3F, },
77 { 0x00, 0x08, 0x01, 0x02, 0x09, 0x10, 0x18, 0x11,
78 0x0A, 0x03, 0x04, 0x0B, 0x12, 0x19, 0x20, 0x28,
79 0x21, 0x30, 0x1A, 0x13, 0x0C, 0x05, 0x06, 0x0D,
80 0x14, 0x1B, 0x22, 0x29, 0x38, 0x31, 0x39, 0x2A,
81 0x23, 0x1C, 0x15, 0x0E, 0x07, 0x0F, 0x16, 0x1D,
82 0x24, 0x2B, 0x32, 0x3A, 0x33, 0x3B, 0x2C, 0x25,
83 0x1E, 0x17, 0x1F, 0x26, 0x2D, 0x34, 0x3C, 0x35,
84 0x3D, 0x2E, 0x27, 0x2F, 0x36, 0x3E, 0x37, 0x3F, },
85 { 0x00, 0x01, 0x08, 0x02, 0x03, 0x09, 0x10, 0x18,
86 0x11, 0x0A, 0x04, 0x05, 0x0B, 0x12, 0x19, 0x20,
87 0x28, 0x30, 0x21, 0x1A, 0x13, 0x0C, 0x06, 0x07,
88 0x0D, 0x14, 0x1B, 0x22, 0x29, 0x38, 0x31, 0x39,
89 0x2A, 0x23, 0x1C, 0x15, 0x0E, 0x0F, 0x16, 0x1D,
90 0x24, 0x2B, 0x32, 0x3A, 0x33, 0x2C, 0x25, 0x1E,
91 0x17, 0x1F, 0x26, 0x2D, 0x34, 0x3B, 0x3C, 0x35,
92 0x2E, 0x27, 0x2F, 0x36, 0x3D, 0x3E, 0x37, 0x3F, },
93 { 0x00, 0x08, 0x10, 0x01, 0x18, 0x20, 0x28, 0x09,
94 0x02, 0x03, 0x0A, 0x11, 0x19, 0x30, 0x38, 0x29,
95 0x21, 0x1A, 0x12, 0x0B, 0x04, 0x05, 0x0C, 0x13,
96 0x1B, 0x22, 0x31, 0x39, 0x32, 0x2A, 0x23, 0x1C,
97 0x14, 0x0D, 0x06, 0x07, 0x0E, 0x15, 0x1D, 0x24,
98 0x2B, 0x33, 0x3A, 0x3B, 0x34, 0x2C, 0x25, 0x1E,
99 0x16, 0x0F, 0x17, 0x1F, 0x26, 0x2D, 0x3C, 0x35,
100 0x2E, 0x27, 0x2F, 0x36, 0x3D, 0x3E, 0x37, 0x3F, }
101};
102
112
113static void init_idct_scantable(MPVContext *const s, const uint8_t *scantable,
114 enum idct_permutation_type idct_permutation, int intra_scantable)
115{
116 ff_init_scantable_permutation(s->idsp.idct_permutation, idct_permutation);
117 ff_init_scantable(s->idsp.idct_permutation,
118 intra_scantable ? &s->intra_scantable : &s->inter_scantable,
119 scantable);
120}
121
122static void init_h263_test(MPVContext *const s, int16_t block[64],
123 int last_nonzero_coeff, int qscale,
124 int h263_aic, int ac_pred, int intra)
125{
126 const uint8_t *permutation = s->inter_scantable.permutated;
127 if (intra) {
128 permutation = s->intra_scantable.permutated;
129 block[0] = rnd() & 511;
130 s->h263_aic = h263_aic;
131 s->ac_pred = ac_pred;
132 if (s->ac_pred)
133 last_nonzero_coeff = 63;
134 }
135 for (int i = intra; i <= last_nonzero_coeff; ++i) {
136 int random = rnd();
137 if (random & 1)
138 continue;
139 random >>= 1;
140 // Select level so that the multiplication fits into 16 bits.
141 // FIXME: The FLV and MPEG-4 decoders can have escape values exceeding this.
142 block[permutation[i]] = sign_extend(random, 10);
143 }
144}
145
146static void init_mpeg12_test(MPVContext *const s, int16_t block[64],
147 int last_nonzero_coeff, int qscale, int intra,
148 enum TestType type)
149{
150 uint16_t *matrix = intra ? s->intra_matrix : s->inter_matrix;
151
152 if (type == MPEG2)
153 qscale = s->q_scale_type ? ff_mpeg2_non_linear_qscale[qscale] : qscale << 1;
154
155 for (int i = 0; i < 64; ++i)
156 matrix[i] = 1 + rnd() % 254;
157
158 const uint8_t *permutation = s->intra_scantable.permutated;
159 if (intra) {
160 block[0] = (int8_t)rnd();
161 for (int i = 1; i <= last_nonzero_coeff; ++i) {
162 int j = permutation[i];
163 unsigned random = rnd();
164 if (random & 1)
165 continue;
166 random >>= 1;
167 // Select level so that the multiplication does not overflow
168 // an int16_t and so that it is within the possible range
169 // (-2048..2047). FIXME: It seems that this need not be fulfilled
170 // in practice for the MPEG-4 decoder at least.
171 int limit = FFMIN(INT16_MAX / (qscale * matrix[j]), 2047);
172 block[j] = random % (2 * limit + 1) - limit;
173 }
174 } else {
175 for (int i = 0; i <= last_nonzero_coeff; ++i) {
176 int j = permutation[i];
177 unsigned random = rnd();
178 if (random & 1)
179 continue;
180 random >>= 1;
181 int limit = FFMIN((INT16_MAX / (qscale * matrix[j]) - 1) / 2, 2047);
182 block[j] = random % (2 * limit + 1) - limit;
183 }
184 }
185}
186
188{
189 static const struct {
190 const char *name;
191 size_t offset;
192 int intra, intra_scantable;
193 enum TestType type;
194 } tests[] = {
195#define TEST(NAME, INTRA, INTRA_SCANTABLE, TYPE) \
196 { .name = #NAME, .offset = offsetof(MPVUnquantDSPContext, NAME), \
197 .intra = INTRA, .intra_scantable = INTRA_SCANTABLE, .type = TYPE }
198 TEST(dct_unquantize_mpeg1_intra, 1, 1, MPEG1),
199 TEST(dct_unquantize_mpeg1_inter, 0, 1, MPEG1),
200 TEST(dct_unquantize_mpeg2_intra, 1, 1, MPEG2),
201 TEST(dct_unquantize_mpeg2_inter, 0, 1, MPEG2),
202 TEST(dct_unquantize_h263_intra, 1, 1, H263),
203 TEST(dct_unquantize_h263_inter, 0, 0, H263),
204 };
205 MPVUnquantDSPContext unquant_dsp_ctx;
206 // Initialize the following parameters before any test to ensure
207 // that they are the same for all instruction sets to make benchmarks
208 // between different instruction sets meaningful.
209 int q_scale_type = rnd() & 1;
210 int block_last_index = rnd() % 64;
211 int qscale = 1 + rnd() % 31;
212 int h263_aic = rnd() & 1;
213 int ac_pred = rnd() & 1;
214 const uint8_t *scantable = scantables[rnd() % FF_ARRAY_ELEMS(scantables)];
216
217 ff_mpv_unquantize_init(&unquant_dsp_ctx, 1 /* bitexact */, q_scale_type);
218 declare_func(void, const MPVContext *s, int16_t *block, int n, int qscale);
219
220 for (size_t i = 0; i < FF_ARRAY_ELEMS(tests); ++i) {
221 void (*func)(const MPVContext *s, int16_t *block, int n, int qscale) =
222 *(void (**)(const MPVContext *, int16_t *, int, int))((char*)&unquant_dsp_ctx + tests[i].offset);
223 if (check_func(func, "%s", tests[i].name)) {
224 MPVContext new, ref;
225 DECLARE_ALIGNED(16, int16_t, block_new)[64];
226 DECLARE_ALIGNED(16, int16_t, block_ref)[64];
227
228 randomize_struct(MPVContext, &ref);
229
230 ref.q_scale_type = q_scale_type;
231
232 init_idct_scantable(&ref, scantable, idct_permutation, tests[i].intra_scantable);
233
234 memset(block_ref, 0, sizeof(block_ref));
235
236 if (tests[i].intra) {
237 // Less restricted than real dc_scale values
238 ref.y_dc_scale = 1 + rnd() % 64;
239 ref.c_dc_scale = 1 + rnd() % 64;
240 }
241
242 if (tests[i].type == H263)
243 init_h263_test(&ref, block_ref, block_last_index, qscale,
244 h263_aic, ac_pred, tests[i].intra);
245 else
246 init_mpeg12_test(&ref, block_ref, block_last_index, qscale,
247 tests[i].intra, tests[i].type);
248
249 int n = rnd() % 6;
250 ref.block_last_index[n] = block_last_index;
251
252 memcpy(&new, &ref, sizeof(new));
253 memcpy(block_new, block_ref, sizeof(block_new));
254
255 call_ref(&ref, block_ref, n, qscale);
256 call_new(&new, block_new, n, qscale);
257
258 if (memcmp(&ref, &new, sizeof(new)) || memcmp(block_new, block_ref, sizeof(block_new)))
259 fail();
260
261 bench_new(&new, block_new, n, qscale);
262 }
263 report("%s", tests[i].name);
264 }
265}
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define s(width, name)
Definition cbs_vp9.c:198
#define rnd
Definition checkasm.h:136
static int16_t block[64]
Definition dct.c:125
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
cl_device_type type
idct_permutation_type
Definition idctdsp.h:27
@ FF_IDCT_PERM_SIMPLE
Definition idctdsp.h:30
@ FF_IDCT_PERM_LIBMPEG2
Definition idctdsp.h:29
@ FF_IDCT_PERM_NONE
Definition idctdsp.h:28
@ FF_IDCT_PERM_PARTTRANS
Definition idctdsp.h:32
@ FF_IDCT_PERM_TRANSPOSE
Definition idctdsp.h:31
@ FF_IDCT_PERM_SSE2
Definition idctdsp.h:33
unsigned offset
Definition libaomenc.c:763
av_cold void ff_init_scantable_permutation(uint8_t *idct_permutation, enum idct_permutation_type perm_type)
Definition idctdsp.c:39
int(* func)(AVBPrint *dst, const char *in, const char *arg)
Definition jacosubdec.c:66
av_cold void ff_init_scantable(const uint8_t *permutation, ScanTable *st, const uint8_t *src_scantable)
#define FFMIN(a, b)
Definition macros.h:49
const uint8_t ff_zigzag_direct[64]
Definition mathtables.c:137
static av_const int sign_extend(int val, unsigned bits)
Definition mathops.h:135
#define DECLARE_ALIGNED(n, t, v)
Declare a variable that is aligned in memory.
mpegvideo header.
#define ff_mpv_unquantize_init(s, bitexact, q_scale_type)
const uint8_t ff_mpeg2_non_linear_qscale[32]
const uint8_t ff_alternate_horizontal_scan[64]
const uint8_t ff_alternate_vertical_scan[64]
const uint8_t ff_wmv1_scantable[WMV1_SCANTABLE_COUNT][64]
const char * name
Definition qsvenc.c:142
#define FF_ARRAY_ELEMS(a)
void checkasm_check_mpegvideo_unquantize(void)
static enum idct_permutation_type permutation_types[]
static void init_idct_scantable(MPVContext *const s, const uint8_t *scantable, enum idct_permutation_type idct_permutation, int intra_scantable)
#define TEST(NAME, INTRA, INTRA_SCANTABLE, TYPE)
static void init_h263_test(MPVContext *const s, int16_t block[64], int last_nonzero_coeff, int qscale, int h263_aic, int ac_pred, int intra)
static void init_mpeg12_test(MPVContext *const s, int16_t block[64], int last_nonzero_coeff, int qscale, int intra, enum TestType type)
static const uint8_t *const scantables[]
#define randomize_struct(TYPE, s)
static int ref[MAX_W *MAX_W]
static double limit(double x)