FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/tests/checkasm/png.c
Date: 2026-04-21 03:24:50
Exec Total Coverage
Lines: 51 51 100.0%
Functions: 3 3 100.0%
Branches: 28 42 66.7%

Line Branch Exec Source
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 14 static void check_add_bytes_l2(const PNGDSPContext *c)
36 {
37 14 LOCAL_ALIGNED_16(uint8_t, dst0, [BUF_SIZE]);
38 14 LOCAL_ALIGNED_16(uint8_t, dst1, [BUF_SIZE]);
39 14 LOCAL_ALIGNED_16(uint8_t, src, [2], [BUF_SIZE]);
40
41 14 declare_func(void, uint8_t * dst, const uint8_t *src1,
42 const uint8_t *src2, int w);
43
44
2/2
✓ Branch 1 taken 57344 times.
✓ Branch 2 taken 14 times.
57358 randomize_buf(dst0, BUF_SIZE);
45 14 memcpy(dst1, dst0, BUF_SIZE);
46
2/2
✓ Branch 1 taken 57344 times.
✓ Branch 2 taken 14 times.
57358 randomize_buf(src[0], BUF_SIZE);
47
2/2
✓ Branch 1 taken 57344 times.
✓ Branch 2 taken 14 times.
57358 randomize_buf(src[1], BUF_SIZE);
48
49 14 const int size[] = {15, 2043, 4096};
50
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 14 times.
56 for (int i = 0; i < FF_ARRAY_ELEMS(size); i++) {
51
2/2
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 36 times.
42 if (check_func(c->add_bytes_l2, "add_bytes_l2_%d", size[i])) {
52 6 call_ref(dst0, src[0], src[1], size[i]);
53 6 call_new(dst1, src[0], src[1], size[i]);
54 6 checkasm_check(uint8_t, dst0, BUF_SIZE, dst1, BUF_SIZE, BUF_SIZE, 1, "dst");
55
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if (size[i] == BUF_SIZE)
56
1/8
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
2 bench_new(dst1, src[0], src[1], BUF_SIZE);
57 }
58 }
59 14 }
60
61 14 static void check_add_paeth_prediction(const PNGDSPContext *c)
62 {
63 14 LOCAL_ALIGNED_16(uint8_t, dst0_buf, [BUF_SIZE]);
64 14 LOCAL_ALIGNED_16(uint8_t, dst1_buf, [BUF_SIZE]);
65 14 LOCAL_ALIGNED_16(uint8_t, src, [BUF_SIZE]);
66 14 LOCAL_ALIGNED_16(uint8_t, top_buf, [BUF_SIZE]);
67
68
2/2
✓ Branch 1 taken 57344 times.
✓ Branch 2 taken 14 times.
57358 randomize_buf(dst0_buf, BUF_SIZE);
69
2/2
✓ Branch 1 taken 57344 times.
✓ Branch 2 taken 14 times.
57358 randomize_buf(src, BUF_SIZE);
70
2/2
✓ Branch 1 taken 57344 times.
✓ Branch 2 taken 14 times.
57358 randomize_buf(top_buf, BUF_SIZE);
71
72 14 declare_func(void, uint8_t * dst, const uint8_t *src,
73 const uint8_t *top, int w, int bpp);
74
75 14 const int bpps[] = {3, 4, 6, 8};
76
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 14 times.
70 for (int i = 0; i < FF_ARRAY_ELEMS(bpps); i++) {
77 56 int bpp = bpps[i];
78
2/2
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 48 times.
56 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 8 uint8_t *dst0 = &dst0_buf[bpp];
81 8 uint8_t *dst1 = &dst1_buf[bpp];
82 8 uint8_t *top = &top_buf[bpp];
83 8 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 8 memcpy(dst1_buf, dst0_buf, BUF_SIZE);
87
88 8 call_ref(dst0, src, top, w, bpp);
89 8 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
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 if (bpp & 3) {
96
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 4 times.
16 for (int j = w - 3; j < w; j++)
97 12 dst1[j] = dst0[j];
98 }
99 // check dst_buf to ensure there is no overwrite
100 8 checkasm_check(uint8_t, dst0_buf, 0, dst1_buf, 0, BUF_SIZE, 1, "dst");
101
1/8
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
8 bench_new(dst1, src, top, w, bpp);
102 }
103 }
104 14 }
105
106 14 void checkasm_check_png(void)
107 {
108 PNGDSPContext c;
109
110 14 ff_pngdsp_init(&c);
111
112 14 check_add_bytes_l2(&c);
113 14 report("add_bytes_l2");
114 14 check_add_paeth_prediction(&c);
115 14 report("add_paeth_prediction");
116 14 }
117