FFmpeg
png.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2026 Zhao Zhili <quinkblack@foxmail.com>
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 
22 #include "libavutil/mem_internal.h"
23 #include "libavcodec/pngdsp.h"
24 
25 #include "checkasm.h"
26 
27 #define BUF_SIZE 4096
28 
29 #define randomize_buf(buf, size) \
30  do { \
31  for (int i = 0; i < size; i++) \
32  buf[i] = (uint8_t)rnd(); \
33  } while (0)
34 
35 static void check_add_bytes_l2(const PNGDSPContext *c)
36 {
37  LOCAL_ALIGNED_16(uint8_t, dst0, [BUF_SIZE]);
38  LOCAL_ALIGNED_16(uint8_t, dst1, [BUF_SIZE]);
39  LOCAL_ALIGNED_16(uint8_t, src, [2], [BUF_SIZE]);
40 
41  declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t * dst, const uint8_t *src1,
42  const uint8_t *src2, int w);
43 
44  randomize_buf(dst0, BUF_SIZE);
45  memcpy(dst1, dst0, BUF_SIZE);
48 
49  const int size[] = {15, 2043, 4096};
50  for (int i = 0; i < FF_ARRAY_ELEMS(size); i++) {
51  if (check_func(c->add_bytes_l2, "add_bytes_l2_%d", size[i])) {
52  call_ref(dst0, src[0], src[1], size[i]);
53  call_new(dst1, src[0], src[1], size[i]);
54  checkasm_check(uint8_t, dst0, BUF_SIZE, dst1, BUF_SIZE, BUF_SIZE, 1, "dst");
55  if (size[i] == BUF_SIZE)
56  bench_new(dst1, src[0], src[1], BUF_SIZE);
57  }
58  }
59 }
60 
62 {
63  LOCAL_ALIGNED_16(uint8_t, dst0_buf, [BUF_SIZE]);
64  LOCAL_ALIGNED_16(uint8_t, dst1_buf, [BUF_SIZE]);
65  LOCAL_ALIGNED_16(uint8_t, src, [BUF_SIZE]);
66  LOCAL_ALIGNED_16(uint8_t, top_buf, [BUF_SIZE]);
67 
68  randomize_buf(dst0_buf, BUF_SIZE);
70  randomize_buf(top_buf, BUF_SIZE);
71 
72  declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t * dst, const uint8_t *src,
73  const uint8_t *top, int w, int bpp);
74 
75  const int bpps[] = {3, 4, 6, 8};
76  for (int i = 0; i < FF_ARRAY_ELEMS(bpps); i++) {
77  int bpp = bpps[i];
78  if (check_func(c->add_paeth_prediction, "add_paeth_prediction_%d", bpp)) {
79  // add_paeth_prediction reads start from (dst - bpp) and (top - bpp).
80  uint8_t *dst0 = &dst0_buf[bpp];
81  uint8_t *dst1 = &dst1_buf[bpp];
82  uint8_t *top = &top_buf[bpp];
83  int w = (BUF_SIZE - bpp) / bpp * bpp;
84 
85  // dst buffer is both read and written, so dst0 and dst1 must remain the same before test
86  memcpy(dst1_buf, dst0_buf, BUF_SIZE);
87 
88  call_ref(dst0, src, top, w, bpp);
89  call_new(dst1, src, top, w, bpp);
90 
91  /* This match the use case in ff_png_filter_row, that x86 asm version of
92  * add_paeth_prediction doesn't write last two bytes for bpp = 3 and 6.
93  * The C function takes care to rewrite the last 3 bytes.
94  */
95  if (bpp & 3) {
96  for (int j = w - 3; j < w; j++)
97  dst1[j] = dst0[j];
98  }
99  // check dst_buf to ensure there is no overwrite
100  checkasm_check(uint8_t, dst0_buf, 0, dst1_buf, 0, BUF_SIZE, 1, "dst");
101  bench_new(dst1, src, top, w, bpp);
102  }
103  }
104 }
105 
107 {
109 
110  ff_pngdsp_init(&c);
111 
113  report("add_bytes_l2");
115  report("add_paeth_prediction");
116 }
PNGDSPContext
Definition: pngdsp.h:29
declare_func_emms
#define declare_func_emms(cpu_flags, ret,...)
Definition: checkasm.h:215
mem_internal.h
src1
const pixel * src1
Definition: h264pred_template.c:420
check_func
#define check_func(func,...)
Definition: checkasm.h:208
call_ref
#define call_ref(...)
Definition: checkasm.h:224
checkasm.h
pngdsp.h
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
LOCAL_ALIGNED_16
#define LOCAL_ALIGNED_16(t, v,...)
Definition: mem_internal.h:130
call_new
#define call_new(...)
Definition: checkasm.h:232
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
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:87
size
int size
Definition: twinvq_data.h:10344
BUF_SIZE
#define BUF_SIZE
Definition: png.c:27
ff_pngdsp_init
av_cold void ff_pngdsp_init(PNGDSPContext *dsp)
Definition: pngdsp.c:85
report
#define report
Definition: checkasm.h:221
bench_new
#define bench_new(...)
Definition: checkasm.h:423
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
checkasm_check_png
void checkasm_check_png(void)
Definition: png.c:106
src2
const pixel * src2
Definition: h264pred_template.c:421
check_add_paeth_prediction
static void check_add_paeth_prediction(const PNGDSPContext *c)
Definition: png.c:61
AV_CPU_FLAG_MMX
#define AV_CPU_FLAG_MMX
standard MMX
Definition: cpu.h:32
randomize_buf
#define randomize_buf(buf, size)
Definition: png.c:29
w
uint8_t w
Definition: llvidencdsp.c:39
checkasm_check
#define checkasm_check(prefix,...)
Definition: checkasm.h:467
check_add_bytes_l2
static void check_add_bytes_l2(const PNGDSPContext *c)
Definition: png.c:35
src
#define src
Definition: vp8dsp.c:248