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 rem[64], const int16_t basis[64], int scale);
43  if (check_func(c->add_8x8basis, "add_8x8basis")) {
44  // FIXME: What are the actual ranges for these values?
45  int scale = sign_extend(rnd(), 12);
46  DECLARE_ALIGNED(16, int16_t, rem1)[64];
47  DECLARE_ALIGNED(16, int16_t, rem2)[64];
48  DECLARE_ALIGNED(16, int16_t, basis)[64];
49 
50  randomize_buffer_clipped(basis, -15760, 15760);
51  randomize_buffers(rem1, sizeof(rem1));
52  memcpy(rem2, rem1, sizeof(rem2));
53  call_ref(rem1, basis, scale);
54  call_new(rem2, basis, scale);
55  if (memcmp(rem1, rem2, sizeof(rem1)))
56  fail();
57  bench_new(rem1, basis, scale);
58  }
59 }
60 
62 {
63  LOCAL_ALIGNED_16(uint8_t, src, [16 * 16]);
64 
65  declare_func(int, const uint8_t *pix, ptrdiff_t line_size);
66 
67  randomize_buffers(src, 16 * 16);
68 
69  for (int n = 0; n < 2; n++) {
70  const char *negstride_str = n ? "_negstride" : "";
71  if (check_func(c->pix_sum, "pix_sum%s", negstride_str)) {
72  int sum0, sum1;
73  const uint8_t *pix = src + (n ? (15 * 16) : 0);
74  ptrdiff_t line_size = 16 * (n ? -1 : 1);
75  sum0 = call_ref(pix, line_size);
76  sum1 = call_new(pix, line_size);
77  if (sum0 != sum1)
78  fail();
79  bench_new(pix, line_size);
80  }
81  }
82 }
83 
85 {
86  LOCAL_ALIGNED_16(uint8_t, src, [16 * 16]);
87 
88  declare_func(int, const uint8_t *pix, ptrdiff_t line_size);
89 
90  randomize_buffers(src, 16 * 16);
91 
92  for (int n = 0; n < 2; n++) {
93  const char *negstride_str = n ? "_negstride" : "";
94  if (check_func(c->pix_norm1, "pix_norm1%s", negstride_str)) {
95  int sum0, sum1;
96  const uint8_t *pix = src + (n ? (15 * 16) : 0);
97  ptrdiff_t line_size = 16 * (n ? -1 : 1);
98  sum0 = call_ref(pix, line_size);
99  sum1 = call_new(pix, line_size);
100  if (sum0 != sum1)
101  fail();
102  bench_new(pix, line_size);
103  }
104  }
105 }
106 
107 #define NUM_LINES 4
108 #define MAX_LINE_SIZE 1920
109 #define EDGE_WIDTH 16
110 #define LINESIZE (EDGE_WIDTH + MAX_LINE_SIZE + EDGE_WIDTH)
111 #define BUFSIZE ((EDGE_WIDTH + NUM_LINES + EDGE_WIDTH) * LINESIZE)
112 
114 {
115  static const int input_sizes[] = {8, 128, 1080, MAX_LINE_SIZE, -MAX_LINE_SIZE};
116  LOCAL_ALIGNED_16(uint8_t, buf0, [BUFSIZE]);
117  LOCAL_ALIGNED_16(uint8_t, buf1, [BUFSIZE]);
118 
119  declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *buf, ptrdiff_t wrap, int width, int height,
120  int w, int h, int sides);
121 
122  for (int isi = 0; isi < FF_ARRAY_ELEMS(input_sizes); isi++) {
123  int input_size = input_sizes[isi];
124  int negstride = input_size < 0;
125  const char *negstride_str = negstride ? "_negstride" : "";
126  int width = FFABS(input_size);
127  ptrdiff_t linesize = EDGE_WIDTH + width + EDGE_WIDTH;
128  /* calculate height based on specified width to use the entire buffer. */
129  int height = (BUFSIZE / linesize) - (2 * EDGE_WIDTH);
130  uint8_t *dst0 = buf0 + EDGE_WIDTH * linesize + EDGE_WIDTH;
131  uint8_t *dst1 = buf1 + EDGE_WIDTH * linesize + EDGE_WIDTH;
132 
133  if (negstride) {
134  dst0 += (height - 1) * linesize;
135  dst1 += (height - 1) * linesize;
136  linesize *= -1;
137  }
138 
139  for (int shift = 0; shift < 3; shift++) {
140  int edge = EDGE_WIDTH >> shift;
141  if (check_func(c->draw_edges, "draw_edges_%d_%d_%d%s", width, height, edge, negstride_str)) {
142  randomize_buffers(buf0, BUFSIZE);
143  memcpy(buf1, buf0, BUFSIZE);
144  call_ref(dst0, linesize, width, height, edge, edge, EDGE_BOTTOM | EDGE_TOP);
145  call_new(dst1, linesize, width, height, edge, edge, EDGE_BOTTOM | EDGE_TOP);
146  if (memcmp(buf0, buf1, BUFSIZE))
147  fail();
148  bench_new(dst1, linesize, width, height, edge, edge, EDGE_BOTTOM | EDGE_TOP);
149  }
150  }
151  }
152 }
153 
154 #undef NUM_LINES
155 #undef MAX_LINE_SIZE
156 #undef EDGE_WIDTH
157 #undef LINESIZE
158 #undef BUFSIZE
159 
161 {
162  AVCodecContext avctx = {
163  .bits_per_raw_sample = 8,
164  };
165  MpegvideoEncDSPContext c = { 0 };
166 
167  ff_mpegvideoencdsp_init(&c, &avctx);
168 
169  check_pix_sum(&c);
170  report("pix_sum");
171  check_pix_norm1(&c);
172  report("pix_norm1");
174  report("draw_edges");
176  report("add_8x8basis");
177 }
declare_func_emms
#define declare_func_emms(cpu_flags, ret,...)
Definition: checkasm.h:203
mem_internal.h
EDGE_BOTTOM
#define EDGE_BOTTOM
Definition: mpegvideoencdsp.h:30
basis
static int16_t basis[64][64]
Definition: mpegvideo_enc.c:4296
w
uint8_t w
Definition: llviddspenc.c:38
check_func
#define check_func(func,...)
Definition: checkasm.h:197
call_ref
#define call_ref(...)
Definition: checkasm.h:212
pix
enum AVPixelFormat pix
Definition: ohcodec.c:55
checkasm_check_mpegvideoencdsp
void checkasm_check_mpegvideoencdsp(void)
Definition: mpegvideoencdsp.c:160
check_pix_norm1
static void check_pix_norm1(MpegvideoEncDSPContext *c)
Definition: mpegvideoencdsp.c:84
fail
#define fail()
Definition: checkasm.h:206
wrap
#define wrap(func)
Definition: neontest.h:65
checkasm.h
check_pix_sum
static void check_pix_sum(MpegvideoEncDSPContext *c)
Definition: mpegvideoencdsp.c:61
rnd
#define rnd()
Definition: checkasm.h:190
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:108
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:315
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:209
bench_new
#define bench_new(...)
Definition: checkasm.h:400
common.h
BUFSIZE
#define BUFSIZE
Definition: mpegvideoencdsp.c:111
randomize_buffer_clipped
#define randomize_buffer_clipped(buf, min, max)
Definition: mpegvideoencdsp.c:34
EDGE_WIDTH
#define EDGE_WIDTH
Definition: mpegvideoencdsp.c:109
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:30
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:201
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:253
check_draw_edges
static void check_draw_edges(MpegvideoEncDSPContext *c)
Definition: mpegvideoencdsp.c:113
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:40