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 <assert.h>
20 #include <stdint.h>
21 #include <string.h>
22 
23 #include "config.h"
24 #include "libavutil/avassert.h"
25 #include "libavutil/attributes.h"
26 #include "libavutil/imgutils.h"
27 #include "avcodec.h"
28 #include "mathops.h"
29 #include "mpegvideoencdsp.h"
30 
31 static void denoise_dct_c(int16_t block[64], int dct_error_sum[64],
32  const uint16_t dct_offset[64])
33 {
34  for (int i = 0; i < 64; ++i) {
35  int level = block[i];
36 
37  if (level) {
38  if (level > 0) {
39  dct_error_sum[i] += level;
40  level -= dct_offset[i];
41  if (level < 0)
42  level = 0;
43  } else {
44  dct_error_sum[i] -= level;
45  level += dct_offset[i];
46  if (level > 0)
47  level = 0;
48  }
49  block[i] = level;
50  }
51  }
52 }
53 
54 static int try_8x8basis_c(const int16_t rem[64], const int16_t weight[64],
55  const int16_t basis[64], int scale)
56 {
57  int i;
58  unsigned int sum = 0;
59 
60  for (i = 0; i < 8 * 8; i++) {
61  int b = rem[i] + ((basis[i] * scale +
62  (1 << (BASIS_SHIFT - RECON_SHIFT - 1))) >>
64  int w = weight[i];
65  b >>= RECON_SHIFT;
66  av_assert2(-512 < b && b < 512);
67 
68  sum += (w * b) * (w * b) >> 4;
69  }
70  return sum >> 2;
71 }
72 
73 static void add_8x8basis_c(int16_t rem[64], const int16_t basis[64], int scale)
74 {
75  int i;
76 
77  for (i = 0; i < 8 * 8; i++)
78  rem[i] += (basis[i] * scale +
79  (1 << (BASIS_SHIFT - RECON_SHIFT - 1))) >>
81 }
82 
83 static int pix_sum_c(const uint8_t *pix, ptrdiff_t line_size)
84 {
85  int s = 0, i, j;
86 
87  for (i = 0; i < 16; i++) {
88  for (j = 0; j < 16; j += 8) {
89  s += pix[0];
90  s += pix[1];
91  s += pix[2];
92  s += pix[3];
93  s += pix[4];
94  s += pix[5];
95  s += pix[6];
96  s += pix[7];
97  pix += 8;
98  }
99  pix += line_size - 16;
100  }
101  return s;
102 }
103 
104 static int pix_norm1_c(const uint8_t *pix, ptrdiff_t line_size)
105 {
106  int s = 0, i, j;
107  const uint32_t *sq = ff_square_tab + 256;
108 
109  for (i = 0; i < 16; i++) {
110  for (j = 0; j < 16; j += 8) {
111 #if HAVE_FAST_64BIT
112  register uint64_t x = *(uint64_t *) pix;
113  s += sq[x & 0xff];
114  s += sq[(x >> 8) & 0xff];
115  s += sq[(x >> 16) & 0xff];
116  s += sq[(x >> 24) & 0xff];
117  s += sq[(x >> 32) & 0xff];
118  s += sq[(x >> 40) & 0xff];
119  s += sq[(x >> 48) & 0xff];
120  s += sq[(x >> 56) & 0xff];
121 #else
122  register uint32_t x = *(uint32_t *) pix;
123  s += sq[x & 0xff];
124  s += sq[(x >> 8) & 0xff];
125  s += sq[(x >> 16) & 0xff];
126  s += sq[(x >> 24) & 0xff];
127  x = *(uint32_t *) (pix + 4);
128  s += sq[x & 0xff];
129  s += sq[(x >> 8) & 0xff];
130  s += sq[(x >> 16) & 0xff];
131  s += sq[(x >> 24) & 0xff];
132 #endif
133  pix += 8;
134  }
135  pix += line_size - 16;
136  }
137  return s;
138 }
139 
140 static av_always_inline void draw_edges_lr(uint8_t *ptr, ptrdiff_t wrap, int width, int height, int w)
141 {
142  for (int i = 0; i < height; i++) {
143  memset(ptr - w, ptr[0], w);
144  memset(ptr + width, ptr[width - 1], w);
145  ptr += wrap;
146  }
147 }
148 
149 /* draw the edges of width 'w' of an image of size width, height */
150 // FIXME: Check that this is OK for MPEG-4 interlaced.
151 static void draw_edges_8_c(uint8_t *buf, ptrdiff_t wrap, int width, int height,
152  int w, int h, int sides)
153 {
154  uint8_t *last_line;
155  int i;
156 
157  /* left and right */
158  if (w == 16) {
159  draw_edges_lr(buf, wrap, width, height, 16);
160  } else if (w == 8) {
161  draw_edges_lr(buf, wrap, width, height, 8);
162  } else {
163  av_assert1(w == 4);
164  draw_edges_lr(buf, wrap, width, height, 4);
165  }
166 
167  /* top and bottom + corners */
168  buf -= w;
169  last_line = buf + (height - 1) * wrap;
170  if (sides & EDGE_TOP)
171  for (i = 0; i < h; i++)
172  // top
173  memcpy(buf - (i + 1) * wrap, buf, width + w + w);
174  if (sides & EDGE_BOTTOM)
175  for (i = 0; i < h; i++)
176  // bottom
177  memcpy(last_line + (i + 1) * wrap, last_line, width + w + w);
178 }
179 
180 /* This wrapper function only serves to convert the stride parameters
181  * from ptrdiff_t to int for av_image_copy_plane(). */
182 static void copy_plane_wrapper(uint8_t *dst, ptrdiff_t dst_wrap,
183  const uint8_t *src, ptrdiff_t src_wrap,
184  int width, int height)
185 {
186  av_image_copy_plane(dst, dst_wrap, src, src_wrap, width, height);
187 }
188 
189 /* 2x2 -> 1x1 */
190 static void shrink22(uint8_t *dst, ptrdiff_t dst_wrap,
191  const uint8_t *src, ptrdiff_t src_wrap,
192  int width, int height)
193 {
194  int w;
195  const uint8_t *s1, *s2;
196  uint8_t *d;
197 
198  for (; height > 0; height--) {
199  s1 = src;
200  s2 = s1 + src_wrap;
201  d = dst;
202  for (w = width; w >= 4; w -= 4) {
203  d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
204  d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 2;
205  d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 2;
206  d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 2;
207  s1 += 8;
208  s2 += 8;
209  d += 4;
210  }
211  for (; w > 0; w--) {
212  d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
213  s1 += 2;
214  s2 += 2;
215  d++;
216  }
217  src += 2 * src_wrap;
218  dst += dst_wrap;
219  }
220 }
221 
222 /* 4x4 -> 1x1 */
223 static void shrink44(uint8_t *dst, ptrdiff_t dst_wrap,
224  const uint8_t *src, ptrdiff_t src_wrap,
225  int width, int height)
226 {
227  int w;
228  const uint8_t *s1, *s2, *s3, *s4;
229  uint8_t *d;
230 
231  for (; height > 0; height--) {
232  s1 = src;
233  s2 = s1 + src_wrap;
234  s3 = s2 + src_wrap;
235  s4 = s3 + src_wrap;
236  d = dst;
237  for (w = width; w > 0; w--) {
238  d[0] = (s1[0] + s1[1] + s1[2] + s1[3] +
239  s2[0] + s2[1] + s2[2] + s2[3] +
240  s3[0] + s3[1] + s3[2] + s3[3] +
241  s4[0] + s4[1] + s4[2] + s4[3] + 8) >> 4;
242  s1 += 4;
243  s2 += 4;
244  s3 += 4;
245  s4 += 4;
246  d++;
247  }
248  src += 4 * src_wrap;
249  dst += dst_wrap;
250  }
251 }
252 
253 /* 8x8 -> 1x1 */
254 static void shrink88(uint8_t *dst, ptrdiff_t dst_wrap,
255  const uint8_t *src, ptrdiff_t src_wrap,
256  int width, int height)
257 {
258  int w, i;
259 
260  for (; height > 0; height--) {
261  for(w = width;w > 0; w--) {
262  int tmp = 0;
263  for (i = 0; i < 8; i++) {
264  tmp += src[0] + src[1] + src[2] + src[3] +
265  src[4] + src[5] + src[6] + src[7];
266  src += src_wrap;
267  }
268  *(dst++) = (tmp + 32) >> 6;
269  src += 8 - 8 * src_wrap;
270  }
271  src += 8 * src_wrap - 8 * width;
272  dst += dst_wrap - width;
273  }
274 }
275 
277  AVCodecContext *avctx)
278 {
279  c->denoise_dct = denoise_dct_c;
280 
281  c->try_8x8basis = try_8x8basis_c;
282  c->add_8x8basis = add_8x8basis_c;
283 
284  c->shrink[0] = copy_plane_wrapper;
285  c->shrink[1] = shrink22;
286  c->shrink[2] = shrink44;
287  c->shrink[3] = shrink88;
288 
289  c->pix_sum = pix_sum_c;
290  c->pix_norm1 = pix_norm1_c;
291 
292  c->draw_edges = draw_edges_8_c;
293 
294 #if ARCH_AARCH64
296 #elif ARCH_ARM
298 #elif ARCH_PPC
300 #elif ARCH_RISCV
302 #elif ARCH_X86
304 #elif ARCH_MIPS
306 #endif
307 }
level
uint8_t level
Definition: svq3.c:208
add_8x8basis_c
static void add_8x8basis_c(int16_t rem[64], const int16_t basis[64], int scale)
Definition: mpegvideoencdsp.c:73
EDGE_BOTTOM
#define EDGE_BOTTOM
Definition: mpegvideoencdsp.h:30
copy_plane_wrapper
static void copy_plane_wrapper(uint8_t *dst, ptrdiff_t dst_wrap, const uint8_t *src, ptrdiff_t src_wrap, int width, int height)
Definition: mpegvideoencdsp.c:182
basis
static int16_t basis[64][64]
Definition: mpegvideo_enc.c:4275
w
uint8_t w
Definition: llviddspenc.c:38
b
#define b
Definition: input.c:42
ff_mpegvideoencdsp_init_x86
void ff_mpegvideoencdsp_init_x86(MpegvideoEncDSPContext *c, AVCodecContext *avctx)
Definition: mpegvideoencdsp_init.c:174
pix
enum AVPixelFormat pix
Definition: ohcodec.c:55
av_image_copy_plane
void av_image_copy_plane(uint8_t *dst, int dst_linesize, const uint8_t *src, int src_linesize, int bytewidth, int height)
Copy image plane from src to dst.
Definition: imgutils.c:374
ff_mpegvideoencdsp_init_mips
av_cold void ff_mpegvideoencdsp_init_mips(MpegvideoEncDSPContext *c, AVCodecContext *avctx)
Definition: mpegvideoencdsp_init_mips.c:28
wrap
#define wrap(func)
Definition: neontest.h:65
draw_edges_lr
static av_always_inline void draw_edges_lr(uint8_t *ptr, ptrdiff_t wrap, int width, int height, int w)
Definition: mpegvideoencdsp.c:140
weight
const h264_weight_func weight
Definition: h264dsp_init.c:33
shrink22
static void shrink22(uint8_t *dst, ptrdiff_t dst_wrap, const uint8_t *src, ptrdiff_t src_wrap, int width, int height)
Definition: mpegvideoencdsp.c:190
avassert.h
av_cold
#define av_cold
Definition: attributes.h:106
s
#define s(width, name)
Definition: cbs_vp9.c:198
BASIS_SHIFT
#define BASIS_SHIFT
Definition: mpegvideoencdsp.h:26
try_8x8basis_c
static int try_8x8basis_c(const int16_t rem[64], const int16_t weight[64], const int16_t basis[64], int scale)
Definition: mpegvideoencdsp.c:54
pix_sum_c
static int pix_sum_c(const uint8_t *pix, ptrdiff_t line_size)
Definition: mpegvideoencdsp.c:83
tmp
static uint8_t tmp[40]
Definition: aes_ctr.c:52
shrink44
static void shrink44(uint8_t *dst, ptrdiff_t dst_wrap, const uint8_t *src, ptrdiff_t src_wrap, int width, int height)
Definition: mpegvideoencdsp.c:223
ff_mpegvideoencdsp_init_ppc
av_cold void ff_mpegvideoencdsp_init_ppc(MpegvideoEncDSPContext *c, AVCodecContext *avctx)
Definition: mpegvideoencdsp.c:151
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
ff_mpegvideoencdsp_init_riscv
void ff_mpegvideoencdsp_init_riscv(MpegvideoEncDSPContext *c, AVCodecContext *avctx)
Definition: mpegvideoencdsp_init.c:32
height
#define height
Definition: dsp.h:89
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:87
pix_norm1_c
static int pix_norm1_c(const uint8_t *pix, ptrdiff_t line_size)
Definition: mpegvideoencdsp.c:104
RECON_SHIFT
#define RECON_SHIFT
Definition: mpegvideoencdsp.h:27
denoise_dct_c
static void denoise_dct_c(int16_t block[64], int dct_error_sum[64], const uint16_t dct_offset[64])
Definition: mpegvideoencdsp.c:31
attributes.h
ff_mpegvideoencdsp_init_aarch64
av_cold void ff_mpegvideoencdsp_init_aarch64(MpegvideoEncDSPContext *c, AVCodecContext *avctx)
Definition: mpegvideoencdsp_init.c:34
MpegvideoEncDSPContext
Definition: mpegvideoencdsp.h:32
av_assert2
#define av_assert2(cond)
assert() equivalent, that does lie in speed critical code.
Definition: avassert.h:68
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
av_assert1
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
Definition: avassert.h:57
av_always_inline
#define av_always_inline
Definition: attributes.h:63
ff_square_tab
const EXTERN uint32_t ff_square_tab[512]
Definition: mathops.h:35
avcodec.h
shrink88
static void shrink88(uint8_t *dst, ptrdiff_t dst_wrap, const uint8_t *src, ptrdiff_t src_wrap, int width, int height)
Definition: mpegvideoencdsp.c:254
AVCodecContext
main external API structure.
Definition: avcodec.h:431
EDGE_TOP
#define EDGE_TOP
Definition: mpegvideoencdsp.h:29
draw_edges_8_c
static void draw_edges_8_c(uint8_t *buf, ptrdiff_t wrap, int width, int height, int w, int h, int sides)
Definition: mpegvideoencdsp.c:151
ff_mpegvideoencdsp_init_arm
av_cold void ff_mpegvideoencdsp_init_arm(MpegvideoEncDSPContext *c, AVCodecContext *avctx)
Definition: mpegvideoencdsp_init_arm.c:30
mpegvideoencdsp.h
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
imgutils.h
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