FFmpeg
tests
checkasm
mpeg4videodsp.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 modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation; either version 2 of the License, or
7
* (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
12
* GNU General Public License for more details.
13
*
14
* You should have received a copy of the GNU General Public License along
15
* with FFmpeg; if not, write to the Free Software Foundation, Inc.,
16
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
*/
18
19
#include <assert.h>
20
21
#include "
checkasm.h
"
22
#include "
libavcodec/mpeg4videodsp.h
"
23
#include "
libavutil/avassert.h
"
24
#include "
libavutil/intreadwrite.h
"
25
#include "
libavutil/mem_internal.h
"
26
27
enum
{
28
MAX_WIDTH
= 1024,
29
MAX_HEIGHT
= 64,
30
MAX_STRIDE
=
MAX_WIDTH
,
31
MAX_BLOCK_HEIGHT
= 16,
32
W
= 8,
33
};
34
35
static_assert(MAX_WIDTH <= MAX_STRIDE, "stride needs to be >=
width
");
36
37
#define randomize_buffer(buf) \
38
do { \
39
static_assert(!(sizeof(buf) % 4), "
Tail handling
needed
"); \
40
for (size_t k = 0; k < sizeof(buf); k += 4) { \
41
uint32_t r = rnd(); \
42
AV_WN32A(buf + k, r); \
43
} \
44
} while (0)
45
46
static int get_signed_rnd(int nb_bits)
47
{
48
int32_t r = rnd();
49
return r >> (32 - nb_bits);
50
}
51
52
static int get_mv_delta(int shift, int is_diag)
53
{
54
// The coordinates of the motion vector differences are fixed point numbers
55
// whose fractional part has 16+shift bits. We use 5+shift+4 bit mantissa
56
// for the deviation from the normal, so that the absolute value corresponds
57
// to < 2^(-7). For height 16, the maximum absolute deviation is < 1/8.
58
// Additionally, we always use zero for the four least significant bits,
59
// as the x86 implementation always falls back to the C one if it is not so.
60
return get_signed_rnd(6 + shift) * 16 + (is_diag ? (1 << (16 + shift)) : 0);
61
}
62
63
static int modify_fpel(int coordinate, int size, int block_size, int type)
64
{
65
switch (type) {
66
default: av_unreachable("
impossible
");
67
// fallthrough
68
case 2: return coordinate; // do nothing
69
// modify coordinate so that it requires pixel replication to the left/top
70
case 1: return coordinate % block_size - block_size;
71
// modify coordinate so that it requires pixel replication to the right/down
72
case 0: return coordinate + block_size + (size - (block_size + 1) - coordinate) / block_size * block_size;
73
}
74
}
75
76
static void checkasm_check_gmc(const Mpeg4VideoDSPContext *const mdsp)
77
{
78
DECLARE_ALIGNED_8(uint8_t, buf_new)[MAX_BLOCK_HEIGHT * MAX_STRIDE];
79
DECLARE_ALIGNED_8(uint8_t, buf_ref)[MAX_BLOCK_HEIGHT * MAX_STRIDE];
80
DECLARE_ALIGNED_4(uint8_t, srcbuf)[MAX_STRIDE * MAX_HEIGHT];
81
82
declare_func(void, uint8_t *dst, const uint8_t *src,
83
int stride, int h, int ox, int oy,
84
int dxx, int dxy, int dyx, int dyy,
85
int shift, int r, int width, int height);
86
87
randomize_buffer(srcbuf);
88
randomize_buffer(buf_ref);
89
memcpy(buf_new, buf_ref, sizeof(buf_new));
90
91
int shift = 1 + rnd() % 4; // range 1..4
92
const int h = rnd() & 1 ? 16 : 8;
93
const int r = (1 << (2 * shift - 1)) - (rnd() & 1);
94
const int width = FFALIGN(W + rnd() % (MAX_WIDTH - W + 1), 16); // range 8..MAX_WIDTH
95
const int height = FFALIGN(h + rnd() % (MAX_HEIGHT - h + 1), 8); // range h..MAX_HEIGHT
96
ptrdiff_t stride = FFALIGN(width + rnd() % (MAX_STRIDE - width + 1), 8);
97
const uint8_t *src = srcbuf;
98
uint8_t *dst_new = buf_new, *dst_ref = buf_ref;
99
100
if (rnd() & 1) { // negate stride
101
dst_new += stride * (h - 1);
102
dst_ref += stride * (h - 1);
103
src += stride * (height - 1);
104
stride *= -1;
105
}
106
// Get the fullpel component of the motion vector.
107
// Restrict the range so that a (W+1)x(h+1) buffer fits in srcbuf
108
// (if possible) in order to test the non-edge-emulation codepath.
109
int fpel_x = width == W ? 0 : rnd() % (width - W);
110
int fpel_y = height == h ? 0 : rnd() % (height - h);
111
int dxx = get_mv_delta(shift, 1), dxy = get_mv_delta(shift, 0);
112
int dyx = get_mv_delta(shift, 0), dyy = get_mv_delta(shift, 1);
113
114
int ox = fpel_x << (16 + shift) | rnd() & ((1 << (16 + shift)) - 1);
115
int oy = fpel_y << (16 + shift) | rnd() & ((1 << (16 + shift)) - 1);
116
117
call_ref(dst_ref, src, stride, h, ox, oy,
118
dxx, dxy, dyx, dyy, shift, r, width, height);
119
call_new(dst_new, src, stride, h, ox, oy,
120
dxx, dxy, dyx, dyy, shift, r, width, height);
121
if (memcmp(buf_new, buf_ref, sizeof(buf_new)))
122
fail();
123
124
bench_new(dst_new, src, stride, h, ox, oy,
125
dxx, dxy, dyx, dyy, shift, r, width, height);
126
127
// Now test the case of src being partially outside of the actual picture.
128
if (!check_func(mdsp->gmc, "
gmc_edge_emulation
"))
129
return; // shouldn't happen
130
int type = rnd() % 8;
131
fpel_x = modify_fpel(fpel_x, width, 8, type % 3);
132
fpel_y = modify_fpel(fpel_y, height, h, type / 3);
133
ox = fpel_x * (1 << (16 + shift)) | rnd() & ((1 << (16 + shift)) - 1);
134
oy = fpel_y * (1 << (16 + shift)) | rnd() & ((1 << (16 + shift)) - 1);
135
call_ref(dst_ref, src, stride, h, ox, oy,
136
dxx, dxy, dyx, dyy, shift, r, width, height);
137
call_new(dst_new, src, stride, h, ox, oy,
138
dxx, dxy, dyx, dyy, shift, r, width, height);
139
if (memcmp(buf_new, buf_ref, sizeof(buf_new)))
140
fail();
141
142
bench_new(dst_new, src, stride, h, ox, oy,
143
dxx, dxy, dyx, dyy, shift, r, width, height);
144
}
145
146
void checkasm_check_mpeg4videodsp(void)
147
{
148
Mpeg4VideoDSPContext mdsp;
149
150
ff_mpeg4videodsp_init(&mdsp);
151
152
if (check_func(mdsp.gmc, "
gmc
")) {
153
checkasm_check_gmc(&mdsp);
154
report("
gmc
");
155
}
156
}
mem_internal.h
MAX_WIDTH
@ MAX_WIDTH
Definition:
mpeg4videodsp.c:28
checkasm.h
MAX_STRIDE
@ MAX_STRIDE
Definition:
mpeg4videodsp.c:30
avassert.h
intreadwrite.h
needed
The exact code depends on how similar the blocks are and how related they are to the and needs to apply these operations to the correct inlink or outlink if there are several Macros are available to factor that when no extra processing is needed
Definition:
filter_design.txt:212
mpeg4videodsp.h
MAX_HEIGHT
@ MAX_HEIGHT
Definition:
mpeg4videodsp.c:29
MAX_BLOCK_HEIGHT
@ MAX_BLOCK_HEIGHT
Definition:
mpeg4videodsp.c:31
width
#define width
Definition:
dsp.h:89
W
@ W
Definition:
mpeg4videodsp.c:32
Generated on Tue Mar 24 2026 19:22:31 for FFmpeg by
1.8.17