FFmpeg
Loading...
Searching...
No Matches
vf_colordetect.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 modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (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
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with FFmpeg; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
19#include <string.h>
20#include "checkasm.h"
21
24
25#define WIDTH 540
26#define HEIGHT 16
27#define STRIDE FFALIGN(WIDTH, 32)
28
29static void check_range_detect(int depth)
30{
31 const int mpeg_min = 16 << (depth - 8);
32 const int mpeg_max = 235 << (depth - 8);
33
36
37 declare_func(int, const uint8_t *, ptrdiff_t, ptrdiff_t, ptrdiff_t, int, int);
38
39 /* Initialize to 128, which should always return 0 */
40 LOCAL_ALIGNED_32(uint8_t, in, [HEIGHT * STRIDE]);
41 memset(in, 0x80, HEIGHT * STRIDE);
42
43 /* Place an out-of-range value in a random position near the center */
44 const int h2 = HEIGHT >> 1;
45 int idx0 = ((rnd() % h2) + h2) * STRIDE + (rnd() % WIDTH);
46 if (depth > 8) {
47 idx0 &= ~1;
48 in[idx0] = in[idx0 + 1] = 0;
49 } else {
50 in[idx0] = 0;
51 }
52
53 int w = WIDTH;
54 if (depth > 8)
55 w /= 2;
56
57 if (check_func(dsp.detect_range, "detect_range_%d", depth)) {
58 /* Test increasing height, to ensure we hit the placed 0 eventually */
59 for (int h = 1; h <= HEIGHT; h++) {
60 int res_ref = call_ref(in, STRIDE, w, h, mpeg_min, mpeg_max);
61 int res_new = call_new(in, STRIDE, w, h, mpeg_min, mpeg_max);
62 if (res_ref != res_new)
63 fail();
64 }
65
66 /* Test performance of base case without any out-of-range values */
67 memset(in, 0x80, HEIGHT * STRIDE);
68 bench_new(in, STRIDE, w, HEIGHT, mpeg_min, mpeg_max);
69 }
70}
71
72static void check_alpha_detect(int depth, enum AVColorRange range)
73{
74 const int mpeg_min = 16 << (depth - 8);
75 const int mpeg_max = 235 << (depth - 8);
76 const int alpha_max = (1 << depth) - 1;
77 const int mpeg_range = mpeg_max - mpeg_min;
78 const int offset = alpha_max * mpeg_min + (1 << (depth - 1));
79 int res_ref, res_new;
80
82 ff_color_detect_dsp_init(&dsp, depth, range);
83
84 declare_func(int, const uint8_t *, ptrdiff_t, const uint8_t *, ptrdiff_t,
85 ptrdiff_t, ptrdiff_t, int p, int q, int k);
86
87 LOCAL_ALIGNED_32(uint8_t, luma, [HEIGHT * STRIDE]);
88 LOCAL_ALIGNED_32(uint8_t, alpha, [HEIGHT * STRIDE]);
89 memset(luma, 0x80, HEIGHT * STRIDE);
90 memset(alpha, 0xF0, HEIGHT * STRIDE);
91
92 /* Try and force overflow */
93 if (depth > 8 && range == AVCOL_RANGE_MPEG) {
94 ((uint16_t *) luma)[0] = 235 << (depth - 8);
95 ((uint16_t *) luma)[1] = 16 << (depth - 8);
96 } else {
97 luma[0] = 235;
98 luma[1] = 16;
99 }
100
101 /* Place an out-of-range value in a random position near the center */
102 const int h2 = HEIGHT >> 1;
103 int idx0 = ((rnd() % h2) + h2) * STRIDE + (rnd() % WIDTH);
104 if (depth > 8) {
105 idx0 &= ~1;
106 alpha[idx0] = alpha[idx0 + 1] = 0;
107 } else {
108 alpha[idx0] = 0;
109 }
110
111 int w = WIDTH;
112 if (depth > 8)
113 w /= 2;
114
115 if (check_func(dsp.detect_alpha, "detect_alpha_%d_%s", depth, range == AVCOL_RANGE_JPEG ? "full" : "limited")) {
116 /* Test increasing height, to ensure we hit the placed 0 eventually */
117 for (int h = 1; h <= HEIGHT; h++) {
118 res_ref = call_ref(luma, STRIDE, alpha, STRIDE, w, h, alpha_max, mpeg_range, offset);
119 res_new = call_new(luma, STRIDE, alpha, STRIDE, w, h, alpha_max, mpeg_range, offset);
120 if (res_ref != res_new)
121 fail();
122 }
123
124 /* Test base case without any out-of-range values */
125 memset(alpha, 0xFF, HEIGHT * STRIDE);
126 res_ref = call_ref(luma, STRIDE, alpha, STRIDE, w, HEIGHT, alpha_max, mpeg_range, offset);
127 res_new = call_new(luma, STRIDE, alpha, STRIDE, w, HEIGHT, alpha_max, mpeg_range, offset);
128 if (res_ref != res_new)
129 fail();
130
131 bench_new(luma, STRIDE, alpha, STRIDE, w, HEIGHT, alpha_max, mpeg_range, offset);
132 }
133}
134
136{
137 for (int depth = 8; depth <= 16; depth += 8) {
138 check_range_detect(depth);
139 report("detect_range_%d", depth);
140
143 report("detect_alpha_%d", depth);
144 }
145}
#define STRIDE
Definition aacpsdsp.c:28
#define rnd
Definition checkasm.h:136
#define declare_func
Definition test.h:489
#define fail
Definition test.h:479
#define bench_new
Definition test.h:487
#define check_func
Definition test.h:481
#define call_new
Definition test.h:486
#define call_ref
Definition test.h:485
#define report
Definition test.h:480
static const int16_t alpha[]
Definition ilbcdata.h:55
unsigned offset
Definition libaomenc.c:763
#define WIDTH
Definition c93.c:45
#define HEIGHT
Definition c93.c:46
uint8_t w
Definition llvidencdsp.c:39
enum AVColorRange range
#define LOCAL_ALIGNED_32(t, v,...)
AVColorRange
Visual content value range.
Definition pixfmt.h:748
@ AVCOL_RANGE_MPEG
Narrow or limited range content.
Definition pixfmt.h:766
@ AVCOL_RANGE_UNSPECIFIED
Definition pixfmt.h:749
@ AVCOL_RANGE_JPEG
Full range content.
Definition pixfmt.h:783
int(* detect_range)(const uint8_t *data, ptrdiff_t stride, ptrdiff_t width, ptrdiff_t height, int mpeg_min, int mpeg_max)
int(* detect_alpha)(const uint8_t *color, ptrdiff_t color_stride, const uint8_t *alpha, ptrdiff_t alpha_stride, ptrdiff_t width, ptrdiff_t height, int alpha_max, int mpeg_range, int offset)
static void check_alpha_detect(int depth, enum AVColorRange range)
static void check_range_detect(int depth)
void checkasm_check_colordetect(void)
static av_cold void ff_color_detect_dsp_init(FFColorDetectDSPContext *dsp, int depth, enum AVColorRange color_range)