FFmpeg
Loading...
Searching...
No Matches
sw_yuv2rgb.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"
22#include "libavutil/imgutils.h"
25#include "libavutil/pixdesc.h"
26
27#include "libswscale/swscale.h"
29
30#include "checkasm.h"
31
32#define randomize_buffers(buf, size) \
33 do { \
34 for (int j = 0; j < size; j += 4) \
35 AV_WN32(buf + j, rnd()); \
36 } while (0)
37
38static const int dst_fmts[] = {
39// AV_PIX_FMT_BGR48BE,
40// AV_PIX_FMT_BGR48LE,
41// AV_PIX_FMT_RGB48BE,
42// AV_PIX_FMT_RGB48LE,
57// AV_PIX_FMT_RGB444,
58// AV_PIX_FMT_BGR444,
59// AV_PIX_FMT_RGB8,
60// AV_PIX_FMT_BGR8,
61// AV_PIX_FMT_RGB4,
62// AV_PIX_FMT_BGR4,
63// AV_PIX_FMT_RGB4_BYTE,
64// AV_PIX_FMT_BGR4_BYTE,
65// AV_PIX_FMT_MONOBLACK,
67};
68
69static int cmp_off_by_n(const uint8_t *ref, const uint8_t *test, size_t n, int accuracy)
70{
71 for (size_t i = 0; i < n; i++) {
72 if (abs(ref[i] - test[i]) > accuracy)
73 return 1;
74 }
75 return 0;
76}
77
78static int cmp_555_by_n(const uint8_t *ref, const uint8_t *test, size_t n, int accuracy, int is_be)
79{
80 for (size_t i = 0; i < n; i++) {
81 uint16_t r = is_be ? AV_RB16(ref + i * 2) : AV_RL16(ref + i * 2);
82 uint16_t t = is_be ? AV_RB16(test + i * 2) : AV_RL16(test + i * 2);
83 if (abs(( r & 0x1f) - ( t & 0x1f)) > accuracy)
84 return 1;
85 if (abs(((r >> 5) & 0x1f) - ((t >> 5) & 0x1f)) > accuracy)
86 return 1;
87 if (abs(((r >> 10) & 0x1f) - ((t >> 10) & 0x1f)) > accuracy)
88 return 1;
89 }
90 return 0;
91}
92
93static int cmp_565_by_n(const uint8_t *ref, const uint8_t *test, size_t n, int accuracy, int is_be)
94{
95 for (size_t i = 0; i < n; i++) {
96 uint16_t r = is_be ? AV_RB16(ref + i * 2) : AV_RL16(ref + i * 2);
97 uint16_t t = is_be ? AV_RB16(test + i * 2) : AV_RL16(test + i * 2);
98 if (abs(( r & 0x1f) - ( t & 0x1f)) > accuracy)
99 return 1;
100 if (abs(((r >> 5) & 0x3f) - ((t >> 5) & 0x3f)) > accuracy)
101 return 1;
102 if (abs(((r >> 11) & 0x1f) - ((t >> 11) & 0x1f)) > accuracy)
103 return 1;
104 }
105 return 0;
106}
107
108static void check_yuv2rgb(int src_pix_fmt)
109{
110 const AVPixFmtDescriptor *src_desc = av_pix_fmt_desc_get(src_pix_fmt);
111#define MAX_LINE_SIZE 1920
112#define SRC_STRIDE_PAD 32
113#define NUM_LINES 4
114 static const int input_sizes[] = {8, 128, 1080, MAX_LINE_SIZE};
115
116 declare_func(int, SwsInternal *c, const uint8_t *const src[],
117 const int srcStride[], int srcSliceY, int srcSliceH,
118 uint8_t *const dst[], const int dstStride[]);
119
120 LOCAL_ALIGNED_8(uint8_t, src_y, [(MAX_LINE_SIZE + SRC_STRIDE_PAD) * NUM_LINES]);
121 LOCAL_ALIGNED_8(uint8_t, src_u, [(MAX_LINE_SIZE + SRC_STRIDE_PAD) * NUM_LINES]);
122 LOCAL_ALIGNED_8(uint8_t, src_v, [(MAX_LINE_SIZE + SRC_STRIDE_PAD) * NUM_LINES]);
123 LOCAL_ALIGNED_8(uint8_t, src_a, [(MAX_LINE_SIZE + SRC_STRIDE_PAD) * NUM_LINES]);
124 const uint8_t *src[4] = { src_y, src_u, src_v, src_a };
125
126 LOCAL_ALIGNED_8(uint8_t, dst0_0, [NUM_LINES * MAX_LINE_SIZE * 6]);
127 LOCAL_ALIGNED_8(uint8_t, dst0_1, [NUM_LINES * MAX_LINE_SIZE]);
128 LOCAL_ALIGNED_8(uint8_t, dst0_2, [NUM_LINES * MAX_LINE_SIZE]);
129 uint8_t *dst0[4] = { dst0_0, dst0_1, dst0_2 };
130
131 LOCAL_ALIGNED_8(uint8_t, dst1_0, [NUM_LINES * MAX_LINE_SIZE * 6]);
132 LOCAL_ALIGNED_8(uint8_t, dst1_1, [NUM_LINES * MAX_LINE_SIZE]);
133 LOCAL_ALIGNED_8(uint8_t, dst1_2, [NUM_LINES * MAX_LINE_SIZE]);
134 uint8_t *dst1[4] = { dst1_0, dst1_1, dst1_2 };
135
140
141 for (int dfi = 0; dfi < FF_ARRAY_ELEMS(dst_fmts); dfi++) {
142 int dst_pix_fmt = dst_fmts[dfi];
143 const AVPixFmtDescriptor *dst_desc = av_pix_fmt_desc_get(dst_pix_fmt);
144 int sample_size = av_get_padded_bits_per_pixel(dst_desc) >> 3;
145 for (int isi = 0; isi < FF_ARRAY_ELEMS(input_sizes); isi++) {
146 SwsContext *sws;
147 SwsInternal *c;
148 int log_level;
149 int width = input_sizes[isi];
150 int srcSliceY = 0;
151 int srcSliceH = NUM_LINES;
152 /* Use av_image_get_linesize so that semi-planar formats (NV12,
153 * NV21) get the correct interleaved-UV stride (= width bytes),
154 * not (width >> log2_chroma_w) which would only count UV pairs. */
155 int chroma_linesize = av_image_get_linesize(src_pix_fmt, width, 1);
156 int srcStride[4] = {
158 chroma_linesize + SRC_STRIDE_PAD,
159 chroma_linesize + SRC_STRIDE_PAD,
161 };
162 int dstStride[4] = {
163 MAX_LINE_SIZE * 6,
166 };
167
168 // override log level to prevent spamming of the message
169 // "No accelerated colorspace conversion found from %s to %s"
170 log_level = av_log_get_level();
172 sws = sws_getContext(width, srcSliceH, src_pix_fmt,
173 width, srcSliceH, dst_pix_fmt,
174 0, NULL, NULL, NULL);
175 av_log_set_level(log_level);
176 if (!sws)
177 fail();
178
179 c = sws_internal(sws);
180 if (check_func(c->convert_unscaled, "%s_%s_%d", src_desc->name, dst_desc->name, width)) {
181 memset(dst0_0, 0xFF, NUM_LINES * MAX_LINE_SIZE * 6);
182 memset(dst1_0, 0xFF, NUM_LINES * MAX_LINE_SIZE * 6);
183 if (dst_pix_fmt == AV_PIX_FMT_GBRP) {
184 memset(dst0_1, 0xFF, NUM_LINES * MAX_LINE_SIZE);
185 memset(dst0_2, 0xFF, NUM_LINES * MAX_LINE_SIZE);
186 memset(dst1_1, 0xFF, NUM_LINES * MAX_LINE_SIZE);
187 memset(dst1_2, 0xFF, NUM_LINES * MAX_LINE_SIZE);
188 }
189
190 call_ref(c, src, srcStride, srcSliceY,
191 srcSliceH, dst0, dstStride);
192 call_new(c, src, srcStride, srcSliceY,
193 srcSliceH, dst1, dstStride);
194
195 if (dst_pix_fmt == AV_PIX_FMT_ARGB ||
196 dst_pix_fmt == AV_PIX_FMT_ABGR ||
197 dst_pix_fmt == AV_PIX_FMT_RGBA ||
198 dst_pix_fmt == AV_PIX_FMT_BGRA ||
199 dst_pix_fmt == AV_PIX_FMT_RGB24 ||
200 dst_pix_fmt == AV_PIX_FMT_BGR24) {
201 for (int row = 0; row < srcSliceH; row++)
202 if (cmp_off_by_n(dst0_0 + row * dstStride[0],
203 dst1_0 + row * dstStride[0],
204 width * sample_size, 3))
205 fail();
206 } else if (dst_pix_fmt == AV_PIX_FMT_RGB565LE ||
207 dst_pix_fmt == AV_PIX_FMT_BGR565LE ||
208 dst_pix_fmt == AV_PIX_FMT_RGB565BE ||
209 dst_pix_fmt == AV_PIX_FMT_BGR565BE) {
210 int is_be = dst_pix_fmt == AV_PIX_FMT_RGB565BE ||
211 dst_pix_fmt == AV_PIX_FMT_BGR565BE;
212 for (int row = 0; row < srcSliceH; row++)
213 if (cmp_565_by_n(dst0_0 + row * dstStride[0],
214 dst1_0 + row * dstStride[0],
215 width, 2, is_be))
216 fail();
217 } else if (dst_pix_fmt == AV_PIX_FMT_RGB555LE ||
218 dst_pix_fmt == AV_PIX_FMT_BGR555LE ||
219 dst_pix_fmt == AV_PIX_FMT_RGB555BE ||
220 dst_pix_fmt == AV_PIX_FMT_BGR555BE) {
221 int is_be = dst_pix_fmt == AV_PIX_FMT_RGB555BE ||
222 dst_pix_fmt == AV_PIX_FMT_BGR555BE;
223 for (int row = 0; row < srcSliceH; row++)
224 if (cmp_555_by_n(dst0_0 + row * dstStride[0],
225 dst1_0 + row * dstStride[0],
226 width, 2, is_be))
227 fail();
228 } else if (dst_pix_fmt == AV_PIX_FMT_GBRP) {
229 for (int p = 0; p < 3; p++)
230 for (int row = 0; row < srcSliceH; row++)
231 if (cmp_off_by_n(dst0[p] + row * dstStride[p],
232 dst1[p] + row * dstStride[p],
233 width, 3))
234 fail();
235 } else {
236 fail();
237 }
238
239 bench_new(c, src, srcStride, srcSliceY,
240 srcSliceH, dst0, dstStride);
241 }
242 sws_freeContext(sws);
243 }
244 }
245}
246
247#undef NUM_LINES
248#undef SRC_STRIDE_PAD
249#undef MAX_LINE_SIZE
250
252{
254 report("yuv420p");
256 report("yuv422p");
258 report("yuva420p");
260 report("nv12");
262 report("nv21");
263}
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition dsp.h:87
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
common internal and external API header
#define NULL
Definition coverity.c:32
#define abs(x)
#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
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
void av_log_set_level(int level)
Set the log level.
Definition log.c:476
int av_log_get_level(void)
Get the current log level.
Definition log.c:471
int av_image_get_linesize(enum AVPixelFormat pix_fmt, int width, int plane)
Compute the size of an image line with format pix_fmt and width width for the plane plane.
Definition imgutils.c:76
SwsContext * sws_getContext(int srcW, int srcH, enum AVPixelFormat srcFormat, int dstW, int dstH, enum AVPixelFormat dstFormat, int flags, SwsFilter *srcFilter, SwsFilter *dstFilter, const double *param)
Allocate and return an SwsContext.
Definition utils.c:1919
void sws_freeContext(SwsContext *swsContext)
Free the swscaler context swsContext.
Definition utils.c:2250
misc image utilities
#define r
Definition input.c:42
#define AV_RL16(p)
#define AV_RB16(p)
#define LOCAL_ALIGNED_8(t, v,...)
int av_get_padded_bits_per_pixel(const AVPixFmtDescriptor *pixdesc)
Return the number of bits per pixel for the pixel format described by pixdesc, including any padding ...
Definition pixdesc.c:3425
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3460
@ AV_PIX_FMT_NV12
planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
Definition pixfmt.h:96
@ AV_PIX_FMT_RGB24
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition pixfmt.h:75
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition pixfmt.h:73
@ AV_PIX_FMT_NV21
as above, but U and V bytes are swapped
Definition pixfmt.h:97
@ AV_PIX_FMT_BGR565BE
packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), big-endian
Definition pixfmt.h:117
@ AV_PIX_FMT_YUV422P
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition pixfmt.h:77
@ AV_PIX_FMT_ARGB
packed ARGB 8:8:8:8, 32bpp, ARGBARGB...
Definition pixfmt.h:99
@ AV_PIX_FMT_RGB555BE
packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), big-endian , X=unused/undefined
Definition pixfmt.h:114
@ AV_PIX_FMT_BGRA
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition pixfmt.h:102
@ AV_PIX_FMT_ABGR
packed ABGR 8:8:8:8, 32bpp, ABGRABGR...
Definition pixfmt.h:101
@ AV_PIX_FMT_YUVA420P
planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
Definition pixfmt.h:108
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition pixfmt.h:100
@ AV_PIX_FMT_RGB565LE
packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), little-endian
Definition pixfmt.h:113
@ AV_PIX_FMT_RGB555LE
packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), little-endian, X=unused/undefined
Definition pixfmt.h:115
@ AV_PIX_FMT_BGR555BE
packed BGR 5:5:5, 16bpp, (msb)1X 5B 5G 5R(lsb), big-endian , X=unused/undefined
Definition pixfmt.h:119
@ AV_PIX_FMT_RGB565BE
packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), big-endian
Definition pixfmt.h:112
@ AV_PIX_FMT_BGR555LE
packed BGR 5:5:5, 16bpp, (msb)1X 5B 5G 5R(lsb), little-endian, X=unused/undefined
Definition pixfmt.h:120
@ AV_PIX_FMT_BGR24
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition pixfmt.h:76
@ AV_PIX_FMT_GBRP
planar GBR 4:4:4 24bpp
Definition pixfmt.h:165
@ AV_PIX_FMT_BGR565LE
packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), little-endian
Definition pixfmt.h:118
#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
const char * name
Definition pixdesc.h:70
Main external API structure.
Definition swscale.h:227
Definition idctdsp.c:35
static const int input_sizes[]
Definition sw_rgb.c:351
static const int dst_fmts[]
Definition sw_yuv2rgb.c:38
#define SRC_STRIDE_PAD
static int cmp_off_by_n(const uint8_t *ref, const uint8_t *test, size_t n, int accuracy)
Definition sw_yuv2rgb.c:69
static int cmp_565_by_n(const uint8_t *ref, const uint8_t *test, size_t n, int accuracy, int is_be)
Definition sw_yuv2rgb.c:93
#define randomize_buffers(buf, size)
Definition sw_yuv2rgb.c:32
static int cmp_555_by_n(const uint8_t *ref, const uint8_t *test, size_t n, int accuracy, int is_be)
Definition sw_yuv2rgb.c:78
void checkasm_check_sw_yuv2rgb(void)
Definition sw_yuv2rgb.c:251
external API header
static SwsInternal * sws_internal(const SwsContext *sws)
#define NUM_LINES
static void check_yuv2rgb(void)
#define src
Definition vp8dsp.c:248
static int ref[MAX_W *MAX_W]
#define width
Definition dsp.h:89
#define MAX_LINE_SIZE
Definition vf_lut3d.c:547
static double c[64]