FFmpeg
mpegvideoencdsp.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 "libavutil/common.h"
20 #include "libavutil/intreadwrite.h"
21 #include "libavutil/mem_internal.h"
22 
23 #include "libavcodec/mathops.h"
25 
26 #include "checkasm.h"
27 
28 #define randomize_buffers(buf, size) \
29  do { \
30  for (int j = 0; j < size; j += 4) \
31  AV_WN32((char*)buf + j, rnd()); \
32  } while (0)
33 
34 #define randomize_buffer_clipped(buf, min, max) \
35  do { \
36  for (size_t j = 0; j < FF_ARRAY_ELEMS(buf); ++j) \
37  buf[j] = rnd() % (max - min + 1) + min; \
38  } while (0)
39 
41 {
42  declare_func(void, int16_t block[64], int dct_error_sum[64],
43  const uint16_t dct_offset[64]);
44 
45  if (check_func(c->denoise_dct, "denoise_dct")) {
46  DECLARE_ALIGNED(16, int16_t, block_ref)[64];
47  DECLARE_ALIGNED(16, int16_t, block_new)[64];
48  DECLARE_ALIGNED(16, int, dct_error_sum_ref)[64];
49  DECLARE_ALIGNED(16, int, dct_error_sum_new)[64];
50  DECLARE_ALIGNED(16, uint16_t, dct_offset)[64];
51 
52  for (size_t i = 0; i < FF_ARRAY_ELEMS(block_ref); ++i) {
53  unsigned random = rnd();
54  block_ref[i] = random & (1 << 16) ? random : 0;
55  }
56  randomize_buffers(dct_offset, sizeof(dct_offset));
57  randomize_buffer_clipped(dct_error_sum_ref, 0, (1 << 24) - 1);
58  memcpy(block_new, block_ref, sizeof(block_new));
59  memcpy(dct_error_sum_new, dct_error_sum_ref, sizeof(dct_error_sum_ref));
60 
61  call_ref(block_ref, dct_error_sum_ref, dct_offset);
62  call_new(block_new, dct_error_sum_new, dct_offset);
63  if (memcmp(block_ref, block_new, sizeof(block_ref)) ||
64  memcmp(dct_error_sum_new, dct_error_sum_ref, sizeof(dct_error_sum_new)))
65  fail();
66 
67  bench_new(block_new, dct_error_sum_new, dct_offset);
68  }
69 }
70 
72 {
73  declare_func(void, int16_t rem[64], const int16_t basis[64], int scale);
74  if (check_func(c->add_8x8basis, "add_8x8basis")) {
75  // FIXME: What are the actual ranges for these values?
76  int scale = sign_extend(rnd(), 12);
77  DECLARE_ALIGNED(16, int16_t, rem1)[64];
78  DECLARE_ALIGNED(16, int16_t, rem2)[64];
79  DECLARE_ALIGNED(16, int16_t, basis)[64];
80 
81  randomize_buffer_clipped(basis, -15760, 15760);
82  randomize_buffers(rem1, sizeof(rem1));
83  memcpy(rem2, rem1, sizeof(rem2));
84  call_ref(rem1, basis, scale);
85  call_new(rem2, basis, scale);
86  if (memcmp(rem1, rem2, sizeof(rem1)))
87  fail();
88  bench_new(rem1, basis, scale);
89  }
90 }
91 
93 {
94  LOCAL_ALIGNED_16(uint8_t, src, [16 * 16]);
95 
96  declare_func(int, const uint8_t *pix, ptrdiff_t line_size);
97 
98  randomize_buffers(src, 16 * 16);
99 
100  for (int n = 0; n < 2; n++) {
101  const char *negstride_str = n ? "_negstride" : "";
102  if (check_func(c->pix_sum, "pix_sum%s", negstride_str)) {
103  int sum0, sum1;
104  const uint8_t *pix = src + (n ? (15 * 16) : 0);
105  ptrdiff_t line_size = 16 * (n ? -1 : 1);
106  sum0 = call_ref(pix, line_size);
107  sum1 = call_new(pix, line_size);
108  if (sum0 != sum1)
109  fail();
110  bench_new(pix, line_size);
111  }
112  }
113 }
114 
116 {
117  LOCAL_ALIGNED_16(uint8_t, src, [16 * 16]);
118 
119  declare_func(int, const uint8_t *pix, ptrdiff_t line_size);
120 
121  randomize_buffers(src, 16 * 16);
122 
123  for (int n = 0; n < 2; n++) {
124  const char *negstride_str = n ? "_negstride" : "";
125  if (check_func(c->pix_norm1, "pix_norm1%s", negstride_str)) {
126  int sum0, sum1;
127  const uint8_t *pix = src + (n ? (15 * 16) : 0);
128  ptrdiff_t line_size = 16 * (n ? -1 : 1);
129  sum0 = call_ref(pix, line_size);
130  sum1 = call_new(pix, line_size);
131  if (sum0 != sum1)
132  fail();
133  bench_new(pix, line_size);
134  }
135  }
136 }
137 
138 #define NUM_LINES 4
139 #define MAX_LINE_SIZE 1920
140 #define EDGE_WIDTH 16
141 #define LINESIZE (EDGE_WIDTH + MAX_LINE_SIZE + EDGE_WIDTH)
142 #define BUFSIZE ((EDGE_WIDTH + NUM_LINES + EDGE_WIDTH) * LINESIZE)
143 
145 {
146  static const int input_sizes[] = {8, 128, 1080, MAX_LINE_SIZE, -MAX_LINE_SIZE};
147  LOCAL_ALIGNED_16(uint8_t, buf0, [BUFSIZE]);
148  LOCAL_ALIGNED_16(uint8_t, buf1, [BUFSIZE]);
149 
150  declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *buf, ptrdiff_t wrap, int width, int height,
151  int w, int h, int sides);
152 
153  for (int isi = 0; isi < FF_ARRAY_ELEMS(input_sizes); isi++) {
154  int input_size = input_sizes[isi];
155  int negstride = input_size < 0;
156  const char *negstride_str = negstride ? "_negstride" : "";
157  int width = FFABS(input_size);
158  ptrdiff_t linesize = EDGE_WIDTH + width + EDGE_WIDTH;
159  /* calculate height based on specified width to use the entire buffer. */
160  int height = (BUFSIZE / linesize) - (2 * EDGE_WIDTH);
161  uint8_t *dst0 = buf0 + EDGE_WIDTH * linesize + EDGE_WIDTH;
162  uint8_t *dst1 = buf1 + EDGE_WIDTH * linesize + EDGE_WIDTH;
163 
164  if (negstride) {
165  dst0 += (height - 1) * linesize;
166  dst1 += (height - 1) * linesize;
167  linesize *= -1;
168  }
169 
170  for (int shift = 0; shift < 3; shift++) {
171  int edge = EDGE_WIDTH >> shift;
172  if (check_func(c->draw_edges, "draw_edges_%d_%d_%d%s", width, height, edge, negstride_str)) {
173  randomize_buffers(buf0, BUFSIZE);
174  memcpy(buf1, buf0, BUFSIZE);
175  call_ref(dst0, linesize, width, height, edge, edge, EDGE_BOTTOM | EDGE_TOP);
176  call_new(dst1, linesize, width, height, edge, edge, EDGE_BOTTOM | EDGE_TOP);
177  if (memcmp(buf0, buf1, BUFSIZE))
178  fail();
179  bench_new(dst1, linesize, width, height, edge, edge, EDGE_BOTTOM | EDGE_TOP);
180  }
181  }
182  }
183 }
184 
185 #undef NUM_LINES
186 #undef MAX_LINE_SIZE
187 #undef EDGE_WIDTH
188 #undef LINESIZE
189 #undef BUFSIZE
190 
192 {
193  AVCodecContext avctx = {
194  .bits_per_raw_sample = 8,
195  };
196  MpegvideoEncDSPContext c = { 0 };
197 
198  ff_mpegvideoencdsp_init(&c, &avctx);
199 
201  report("denoise_dct");
202  check_pix_sum(&c);
203  report("pix_sum");
204  check_pix_norm1(&c);
205  report("pix_norm1");
207  report("draw_edges");
209  report("add_8x8basis");
210 }
declare_func_emms
#define declare_func_emms(cpu_flags, ret,...)
Definition: checkasm.h:204
mem_internal.h
EDGE_BOTTOM
#define EDGE_BOTTOM
Definition: mpegvideoencdsp.h:30
basis
static int16_t basis[64][64]
Definition: mpegvideo_enc.c:4275
w
uint8_t w
Definition: llviddspenc.c:38
check_func
#define check_func(func,...)
Definition: checkasm.h:198
call_ref
#define call_ref(...)
Definition: checkasm.h:213
pix
enum AVPixelFormat pix
Definition: ohcodec.c:55
checkasm_check_mpegvideoencdsp
void checkasm_check_mpegvideoencdsp(void)
Definition: mpegvideoencdsp.c:191
check_pix_norm1
static void check_pix_norm1(MpegvideoEncDSPContext *c)
Definition: mpegvideoencdsp.c:115
fail
#define fail()
Definition: checkasm.h:207
wrap
#define wrap(func)
Definition: neontest.h:65
checkasm.h
check_pix_sum
static void check_pix_sum(MpegvideoEncDSPContext *c)
Definition: mpegvideoencdsp.c:92
rnd
#define rnd()
Definition: checkasm.h:191
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
intreadwrite.h
MAX_LINE_SIZE
#define MAX_LINE_SIZE
Definition: mpegvideoencdsp.c:139
input_sizes
static const int input_sizes[]
Definition: sw_rgb.c:347
LOCAL_ALIGNED_16
#define LOCAL_ALIGNED_16(t, v,...)
Definition: mem_internal.h:130
AVCodecContext::bits_per_raw_sample
int bits_per_raw_sample
Bits per sample/pixel of internal libavcodec pixel/sample format.
Definition: avcodec.h:1553
FFABS
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
Definition: common.h:74
call_new
#define call_new(...)
Definition: checkasm.h:316
mathops.h
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
height
#define height
Definition: dsp.h:89
DECLARE_ALIGNED
#define DECLARE_ALIGNED(n, t, v)
Definition: mem_internal.h:104
shift
static int shift(int a, int b)
Definition: bonk.c:261
MpegvideoEncDSPContext
Definition: mpegvideoencdsp.h:32
report
#define report
Definition: checkasm.h:210
bench_new
#define bench_new(...)
Definition: checkasm.h:401
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
common.h
BUFSIZE
#define BUFSIZE
Definition: mpegvideoencdsp.c:142
randomize_buffer_clipped
#define randomize_buffer_clipped(buf, min, max)
Definition: mpegvideoencdsp.c:34
EDGE_WIDTH
#define EDGE_WIDTH
Definition: mpegvideoencdsp.c:140
randomize_buffers
#define randomize_buffers(buf, size)
Definition: mpegvideoencdsp.c:28
AV_CPU_FLAG_MMX
#define AV_CPU_FLAG_MMX
standard MMX
Definition: cpu.h:32
AVCodecContext
main external API structure.
Definition: avcodec.h:431
EDGE_TOP
#define EDGE_TOP
Definition: mpegvideoencdsp.h:29
mpegvideoencdsp.h
sign_extend
static av_const int sign_extend(int val, unsigned bits)
Definition: mathops.h:132
declare_func
#define declare_func(ret,...)
Definition: checkasm.h:202
scale
static void scale(int *out, const int *in, const int w, const int h, const int shift)
Definition: intra.c:273
ff_mpegvideoencdsp_init
av_cold void ff_mpegvideoencdsp_init(MpegvideoEncDSPContext *c, AVCodecContext *avctx)
Definition: mpegvideoencdsp.c:276
check_draw_edges
static void check_draw_edges(MpegvideoEncDSPContext *c)
Definition: mpegvideoencdsp.c:144
block
The exact code depends on how similar the blocks are and how related they are to the block
Definition: filter_design.txt:207
h
h
Definition: vp9dsp_template.c:2070
width
#define width
Definition: dsp.h:89
src
#define src
Definition: vp8dsp.c:248
check_add_8x8basis
static void check_add_8x8basis(MpegvideoEncDSPContext *c)
Definition: mpegvideoencdsp.c:71
check_denoise_dct
static void check_denoise_dct(MpegvideoEncDSPContext *c)
Definition: mpegvideoencdsp.c:40