FFmpeg
Loading...
Searching...
No Matches
sw_range_convert.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
21#include "libavutil/common.h"
23#include "libavutil/mem.h"
25
26#include "libswscale/swscale.h"
28
29#include "checkasm.h"
30
39
40static void randomize_buffers(int16_t *buf0, int16_t *buf1, int bit_depth, int width)
41{
42 int32_t *buf0_32 = (int32_t *) buf0;
43 int32_t *buf1_32 = (int32_t *) buf1;
44 int mask = (1 << bit_depth) - 1;
45 int src_shift = bit_depth <= 14 ? 15 - bit_depth : 19 - bit_depth;
46 for (int i = 0; i < width; i++) {
47 int32_t r = rnd() & mask;
48 if (bit_depth == 16) {
49 buf0_32[i] = r << src_shift;
50 buf1_32[i] = r << src_shift;
51 } else {
52 buf0[i] = r << src_shift;
53 buf1[i] = r << src_shift;
54 }
55 }
56}
57
59{
60 const char *func_str = from ? "lumRangeFromJpeg" : "lumRangeToJpeg";
61#define LARGEST_INPUT_SIZE 1920
62 static const int input_sizes[] = {8, LARGEST_INPUT_SIZE};
63 SwsContext *sws;
65
66 LOCAL_ALIGNED_32(int16_t, dst0, [LARGEST_INPUT_SIZE * 2]);
67 LOCAL_ALIGNED_32(int16_t, dst1, [LARGEST_INPUT_SIZE * 2]);
68 int32_t *dst0_32 = (int32_t *) dst0;
69 int32_t *dst1_32 = (int32_t *) dst1;
70
71 declare_func(void, int16_t *dst, int width,
72 uint32_t coeff, int64_t offset);
73
74 sws = sws_alloc_context();
75 if (sws_init_context(sws, NULL, NULL) < 0)
76 fail();
77
78 c = sws_internal(sws);
79 sws->src_range = from;
80 sws->dst_range = !from;
81
82 for (int pfi = 0; pfi < FF_ARRAY_ELEMS(pixel_formats); pfi++) {
85 int bit_depth = desc->comp[0].depth;
86 int sample_size = bit_depth == 16 ? sizeof(int32_t) : sizeof(int16_t);
87 int src_shift = bit_depth <= 14 ? 15 - bit_depth : 19 - bit_depth;
88 int mpeg_min = 16 << (bit_depth - 8);
89 int mpeg_max = 235 << (bit_depth - 8);
90 int jpeg_max = (1 << bit_depth) - 1;
91 sws->src_format = pix_fmt;
92 sws->dst_format = pix_fmt;
93 c->dstBpc = bit_depth;
95 for (int dstWi = 0; dstWi < FF_ARRAY_ELEMS(input_sizes); dstWi++) {
96 int width = input_sizes[dstWi];
97 if (check_func(c->lumConvertRange, "%s%d_%d", func_str, bit_depth, width)) {
98 randomize_buffers(dst0, dst1, bit_depth, width);
99 if (bit_depth == 16) {
100 if (!from) {
101 dst1_32[0] = dst0_32[0] = mpeg_min << src_shift;
102 dst1_32[1] = dst0_32[1] = mpeg_max << src_shift;
103 }
104 dst1_32[2] = dst0_32[2] = -1;
105 } else {
106 if (!from) {
107 dst1[0] = dst0[0] = mpeg_min << src_shift;
108 dst1[1] = dst0[1] = mpeg_max << src_shift;
109 }
110 dst1[2] = dst0[2] = -1;
111 }
112 call_ref(dst0, width,
113 c->lumConvertRange_coeff, c->lumConvertRange_offset);
114 call_new(dst1, width,
115 c->lumConvertRange_coeff, c->lumConvertRange_offset);
116 if (memcmp(dst0, dst1, width * sample_size))
117 fail();
118 if (!from) {
119 /* check that the mpeg range is respected */
120 if (bit_depth == 16) {
121 if ((dst1_32[0] >> src_shift) > 0 || (dst1_32[1] >> src_shift) != jpeg_max)
122 fail();
123 } else {
124 if ((dst1[0] >> src_shift) > 0 || (dst1[1] >> src_shift) != jpeg_max)
125 fail();
126 }
127 }
128 if (width == LARGEST_INPUT_SIZE && (bit_depth == 8 || bit_depth == 16))
129 bench_new(dst1, width,
130 c->lumConvertRange_coeff, c->lumConvertRange_offset);
131 }
132 }
133 }
134
135 sws_freeContext(sws);
136}
137#undef LARGEST_INPUT_SIZE
138
140{
141 const char *func_str = from ? "chrRangeFromJpeg" : "chrRangeToJpeg";
142#define LARGEST_INPUT_SIZE 1920
143 static const int input_sizes[] = {8, LARGEST_INPUT_SIZE};
144 SwsContext *sws;
145 SwsInternal *c;
146
147 LOCAL_ALIGNED_32(int16_t, dstU0, [LARGEST_INPUT_SIZE * 2]);
148 LOCAL_ALIGNED_32(int16_t, dstV0, [LARGEST_INPUT_SIZE * 2]);
149 LOCAL_ALIGNED_32(int16_t, dstU1, [LARGEST_INPUT_SIZE * 2]);
150 LOCAL_ALIGNED_32(int16_t, dstV1, [LARGEST_INPUT_SIZE * 2]);
151 int32_t *dstU0_32 = (int32_t *) dstU0;
152 int32_t *dstU1_32 = (int32_t *) dstU1;
153
154 declare_func(void, int16_t *dstU, int16_t *dstV, int width,
155 uint32_t coeff, int64_t offset);
156
157 sws = sws_alloc_context();
158 if (sws_init_context(sws, NULL, NULL) < 0)
159 fail();
160
161 c = sws_internal(sws);
162 sws->src_range = from;
163 sws->dst_range = !from;
164
165 for (int pfi = 0; pfi < FF_ARRAY_ELEMS(pixel_formats); pfi++) {
168 int bit_depth = desc->comp[0].depth;
169 int sample_size = bit_depth == 16 ? sizeof(int32_t) : sizeof(int16_t);
170 int src_shift = bit_depth <= 14 ? 15 - bit_depth : 19 - bit_depth;
171 int mpeg_min = 16 << (bit_depth - 8);
172 int mpeg_max = 240 << (bit_depth - 8);
173 int jpeg_max = (1 << bit_depth) - 1;
174 sws->src_format = pix_fmt;
175 sws->dst_format = pix_fmt;
176 c->dstBpc = bit_depth;
178 for (int dstWi = 0; dstWi < FF_ARRAY_ELEMS(input_sizes); dstWi++) {
179 int width = input_sizes[dstWi];
180 if (check_func(c->chrConvertRange, "%s%d_%d", func_str, bit_depth, width)) {
181 randomize_buffers(dstU0, dstU1, bit_depth, width);
182 randomize_buffers(dstV0, dstV1, bit_depth, width);
183 if (bit_depth == 16) {
184 if (!from) {
185 dstU1_32[0] = dstU0_32[0] = mpeg_min << src_shift;
186 dstU1_32[1] = dstU0_32[1] = mpeg_max << src_shift;
187 }
188 dstU1_32[2] = dstU0_32[2] = -1;
189 } else {
190 if (!from) {
191 dstU1[0] = dstU0[0] = mpeg_min << src_shift;
192 dstU1[1] = dstU0[1] = mpeg_max << src_shift;
193 }
194 dstU1[2] = dstU0[2] = -1;
195 }
196 call_ref(dstU0, dstV0, width,
197 c->chrConvertRange_coeff, c->chrConvertRange_offset);
198 call_new(dstU1, dstV1, width,
199 c->chrConvertRange_coeff, c->chrConvertRange_offset);
200 if (memcmp(dstU0, dstU1, width * sample_size) ||
201 memcmp(dstV0, dstV1, width * sample_size))
202 fail();
203 if (!from) {
204 /* check that the mpeg range is respected */
205 if (bit_depth == 16) {
206 if ((dstU1_32[0] >> src_shift) > 0 || (dstU1_32[1] >> src_shift) != jpeg_max)
207 fail();
208 } else {
209 if ((dstU1[0] >> src_shift) > 0 || (dstU1[1] >> src_shift) != jpeg_max)
210 fail();
211 }
212 }
213 if (width == LARGEST_INPUT_SIZE && (bit_depth == 8 || bit_depth == 16))
214 bench_new(dstU1, dstV1, width,
215 c->chrConvertRange_coeff, c->chrConvertRange_offset);
216 }
217 }
218 }
219
220 sws_freeContext(sws);
221}
222#undef LARGEST_INPUT_SIZE
223
225{
227 report("lumRangeFromJpeg");
229 report("chrRangeFromJpeg");
231 report("lumRangeToJpeg");
233 report("chrRangeToJpeg");
234}
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition dsp.h:87
static void bit_depth(AudioStatsContext *s, const uint64_t *const mask, uint8_t *depth)
Definition af_astats.c:246
int32_t
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define rnd
Definition checkasm.h:136
common internal and external API header
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
static enum AVPixelFormat pix_fmt
#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
av_warn_unused_result int sws_init_context(SwsContext *sws_context, SwsFilter *srcFilter, SwsFilter *dstFilter)
Initialize the swscaler context sws_context.
Definition utils.c:1884
SwsContext * sws_alloc_context(void)
Allocate an empty SwsContext and set its fields to default values.
Definition utils.c:1032
void sws_freeContext(SwsContext *swsContext)
Free the swscaler context swsContext.
Definition utils.c:2250
#define r
Definition input.c:42
unsigned offset
Definition libaomenc.c:763
const char * from
Definition jacosubdec.c:64
const char * desc
Definition libsvtav1.c:83
static const uint16_t mask[17]
Definition lzw.c:38
Memory handling functions.
#define LOCAL_ALIGNED_32(t, v,...)
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3460
#define AV_PIX_FMT_YUV444P12
Definition pixfmt.h:552
#define AV_PIX_FMT_YUV444P9
Definition pixfmt.h:544
AVPixelFormat
Pixel format.
Definition pixfmt.h:71
@ AV_PIX_FMT_YUV444P
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition pixfmt.h:78
#define AV_PIX_FMT_YUV444P14
Definition pixfmt.h:555
#define AV_PIX_FMT_YUV444P16
Definition pixfmt.h:558
#define AV_PIX_FMT_YUV444P10
Definition pixfmt.h:548
#define FF_ARRAY_ELEMS(a)
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition pixdesc.h:69
Main external API structure.
Definition swscale.h:227
int dst_format
Destination pixel format.
Definition swscale.h:275
int src_format
Source pixel format.
Definition swscale.h:274
int dst_range
Destination is full range.
Definition swscale.h:277
int src_range
Source is full range.
Definition swscale.h:276
#define LARGEST_INPUT_SIZE
static void check_chrConvertRange(int from)
void checkasm_check_sw_range_convert(void)
static void check_lumConvertRange(int from)
static const int input_sizes[]
Definition sw_rgb.c:351
void ff_sws_init_scale(SwsInternal *c)
Definition swscale.c:697
external API header
static SwsInternal * sws_internal(const SwsContext *sws)
#define randomize_buffers()
Definition alacdsp.c:32
#define width
Definition dsp.h:89
static const double coeff[2][5]
static enum AVPixelFormat pixel_formats[]
Definition vf_sr.c:64
static double c[64]