1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with FFmpeg; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <assert.h>
#include <stddef.h>
#include "checkasm.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/macros.h"
#include "libavutil/mem_internal.h"
#include "libavcodec/vp3dsp.h"
enum {
MAX_STRIDE = 64,
MIN_STRIDE = 8,
/// Horizontal tests operate on 4x8 blocks
HORIZONTAL_BUF_SIZE = ((8 /* lines */ - 1) * MAX_STRIDE + 4 /* width */ + 7 /* misalignment */),
/// Vertical tests operate on 8x4 blocks
VERTICAL_BUF_SIZE = ((4 /* lines */ - 1) * MAX_STRIDE + 8 /* width */ + 7 /* misalignment */),
};
#define randomize_buffers(buf0, buf1, size) \
do { \
static_assert(sizeof(buf0[0]) == 1 && sizeof(buf1[0]) == 1, \
"Pointer arithmetic needs to be adapted"); \
for (size_t k = 0; k < (size & ~3); k += 4) { \
uint32_t r = rnd(); \
AV_WN32A(buf0 + k, r); \
AV_WN32A(buf1 + k, r); \
} \
for (size_t k = size & ~3; k < size; ++k) \
buf0[k] = buf1[k] = rnd(); \
} while (0)
static void vp3_check_loop_filter(void)
{
DECLARE_ALIGNED(8, uint8_t, hor_buf0)[HORIZONTAL_BUF_SIZE];
DECLARE_ALIGNED(8, uint8_t, hor_buf1)[HORIZONTAL_BUF_SIZE];
DECLARE_ALIGNED(8, uint8_t, ver_buf0)[VERTICAL_BUF_SIZE];
DECLARE_ALIGNED(8, uint8_t, ver_buf1)[VERTICAL_BUF_SIZE];
DECLARE_ALIGNED(16, int, bounding_values_array)[256 + 4];
int *const bounding_values = bounding_values_array + 127;
VP3DSPContext vp3dsp;
static const struct {
const char *name;
size_t offset;
int lines_above, lines_below;
int pixels_left, pixels_right;
unsigned alignment;
int horizontal;
} tests[] = {
#define TEST(NAME) .name = #NAME, .offset = offsetof(VP3DSPContext, NAME)
{ TEST(v_loop_filter_unaligned), 2, 1, 0, 7, 1, 0 },
{ TEST(h_loop_filter_unaligned), 0, 7, 2, 1, 1, 1 },
{ TEST(v_loop_filter), 2, 1, 0, 7, VP3_LOOP_FILTER_NO_UNALIGNED_SUPPORT ? 8 : 1, 0 },
{ TEST(h_loop_filter), 0, 7, 2, 1, VP3_LOOP_FILTER_NO_UNALIGNED_SUPPORT ? 8 : 1, 1 },
};
declare_func(void, uint8_t *src, ptrdiff_t stride, int *bounding_values);
ff_vp3dsp_init(&vp3dsp);
int filter_limit = rnd() % 128;
ff_vp3dsp_set_bounding_values(bounding_values_array, filter_limit);
for (size_t i = 0; i < FF_ARRAY_ELEMS(tests); ++i) {
void (*loop_filter)(uint8_t *, ptrdiff_t, int*) = *(void(**)(uint8_t *, ptrdiff_t, int*))((char*)&vp3dsp + tests[i].offset);
if (check_func(loop_filter, "%s", tests[i].name)) {
uint8_t *buf0 = tests[i].horizontal ? hor_buf0 : ver_buf0;
uint8_t *buf1 = tests[i].horizontal ? hor_buf1 : ver_buf1;
size_t bufsize = tests[i].horizontal ? HORIZONTAL_BUF_SIZE : VERTICAL_BUF_SIZE;
ptrdiff_t stride = (rnd() % (MAX_STRIDE / MIN_STRIDE) + 1) * MIN_STRIDE;
// Don't always use pointers that are aligned to 8.
size_t offset = FFALIGN(tests[i].pixels_left, tests[i].alignment) +
(rnd() % (MIN_STRIDE / tests[i].alignment)) * tests[i].alignment
+ stride * tests[i].lines_above;
uint8_t *dst0 = buf0 + offset, *dst1 = buf1 + offset;
if (rnd() & 1) {
// Flip stride.
dst1 += (tests[i].lines_below - tests[i].lines_above) * stride;
dst0 += (tests[i].lines_below - tests[i].lines_above) * stride;
stride = -stride;
}
randomize_buffers(buf0, buf1, bufsize);
call_ref(dst0, stride, bounding_values);
call_new(dst1, stride, bounding_values);
if (memcmp(buf0, buf1, bufsize))
fail();
bench_new(dst0, stride, bounding_values);
}
}
}
void checkasm_check_vp3dsp(void)
{
vp3_check_loop_filter();
}
|