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 & ~31), HEIGHT, mpeg_min, mpeg_max);
69 }
70}
71
72static void check_alpha_detect(int depth, enum AVColorRange range, int offset)
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 int res_ref, res_new;
79
80 int threshold = checkasm_rand() % FFMIN(HEIGHT, mpeg_min);
81 if (range == AVCOL_RANGE_JPEG) {
82 offset = offset ? FFMAX(threshold, 1) : 0;
83 } else {
84 offset = alpha_max * (mpeg_min + threshold) + (1 << (depth - 1));
85 }
86
89
90 declare_func(int, const uint8_t *, ptrdiff_t, const uint8_t *, ptrdiff_t,
91 ptrdiff_t, ptrdiff_t, int p, int q, int k);
92
93 LOCAL_ALIGNED_32(uint8_t, luma, [HEIGHT * STRIDE]);
94 LOCAL_ALIGNED_32(uint8_t, alpha, [HEIGHT * STRIDE]);
95 memset(luma, 0x80, HEIGHT * STRIDE);
96 memset(alpha, 0xF0, HEIGHT * STRIDE);
97
98 /* Try and force overflow and edge cases */
99 if (depth > 8 && range == AVCOL_RANGE_MPEG) {
100 for (int i = 0; i < threshold; i++) {
101 uint16_t *line = (uint16_t *) (luma + i * STRIDE);
102 line[0] = (235 << (depth - 8)) + i;
103 line[1] = ( 16 << (depth - 8)) - i;
104 }
105 } else {
106 for (int i = 0; i < threshold; i++) {
107 uint8_t *line = luma + i * STRIDE;
108 line[0] = 235 + i;
109 line[1] = 16 - i;
110 }
111 }
112
113 /* Place an out-of-range value in a random position near the center */
114 const int h2 = HEIGHT >> 1;
115 int idx0 = ((rnd() % h2) + h2) * STRIDE + (rnd() % WIDTH);
116 if (depth > 8) {
117 idx0 &= ~1;
118 alpha[idx0] = alpha[idx0 + 1] = 0;
119 } else {
120 alpha[idx0] = 0;
121 }
122
123 int w = WIDTH;
124 if (depth > 8)
125 w /= 2;
126
127 const char *name;
128 if (range == AVCOL_RANGE_JPEG)
129 name = offset ? "full_off" : "full";
130 else
131 name = "limited";
132
133 if (check_func(dsp.detect_alpha, "detect_alpha_%d_%s", depth, name)) {
134 /* Test increasing height, to ensure we hit the placed 0 eventually */
135 for (int h = 1; h <= HEIGHT; h++) {
136 res_ref = call_ref(luma, STRIDE, alpha, STRIDE, w, h, alpha_max, mpeg_range, offset);
137 res_new = call_new(luma, STRIDE, alpha, STRIDE, w, h, alpha_max, mpeg_range, offset);
138 if (res_ref != res_new)
139 fail();
140 }
141
142 /* Test base case without any out-of-range values */
143 memset(alpha, 0xFF, HEIGHT * STRIDE);
144 res_ref = call_ref(luma, STRIDE, alpha, STRIDE, w, HEIGHT, alpha_max, mpeg_range, offset);
145 res_new = call_new(luma, STRIDE, alpha, STRIDE, w, HEIGHT, alpha_max, mpeg_range, offset);
146 if (res_ref != res_new)
147 fail();
148
149 bench_new(luma, STRIDE, alpha, STRIDE, (w & ~31), HEIGHT, alpha_max, mpeg_range, offset);
150 }
151}
152
154{
155 for (int depth = 8; depth <= 16; depth += 8) {
156 check_range_detect(depth);
157 report("detect_range_%d", depth);
158
162 report("detect_alpha_%d", depth);
163 }
164}
#define STRIDE
Definition aacpsdsp.c:28
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define rnd
Definition checkasm.h:135
#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
CHECKASM_API int checkasm_rand(void)
Generate a random non-negative integer.
Definition utils.c:248
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
#define FFMIN(a, b)
Definition macros.h:49
#define FFMAX(a, b)
Definition macros.h:47
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
const char * name
Definition qsvenc.c:142
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_range_detect(int depth)
static void check_alpha_detect(int depth, enum AVColorRange range, int offset)
void checkasm_check_colordetect(void)
static av_cold void ff_color_detect_dsp_init(FFColorDetectDSPContext *dsp, int depth, int offset, enum AVColorRange color_range)