FFmpeg
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"
23 #include "libavutil/intreadwrite.h"
24 #include "libavutil/mem_internal.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 
38 static const int dst_fmts[] = {
39 // AV_PIX_FMT_BGR48BE,
40 // AV_PIX_FMT_BGR48LE,
41 // AV_PIX_FMT_RGB48BE,
42 // AV_PIX_FMT_RGB48LE,
53 // AV_PIX_FMT_RGB444,
54 // AV_PIX_FMT_BGR444,
55 // AV_PIX_FMT_RGB8,
56 // AV_PIX_FMT_BGR8,
57 // AV_PIX_FMT_RGB4,
58 // AV_PIX_FMT_BGR4,
59 // AV_PIX_FMT_RGB4_BYTE,
60 // AV_PIX_FMT_BGR4_BYTE,
61 // AV_PIX_FMT_MONOBLACK,
63 };
64 
65 static int cmp_off_by_n(const uint8_t *ref, const uint8_t *test, size_t n, int accuracy)
66 {
67  for (size_t i = 0; i < n; i++) {
68  if (abs(ref[i] - test[i]) > accuracy)
69  return 1;
70  }
71  return 0;
72 }
73 
74 static int cmp_555_by_n(const uint8_t *ref, const uint8_t *test, size_t n, int accuracy)
75 {
76  const uint16_t *ref16 = (const uint16_t *) ref;
77  const uint16_t *test16 = (const uint16_t *) test;
78  for (size_t i = 0; i < n; i++) {
79  if (abs(( ref16[i] & 0x1f) - ( test16[i] & 0x1f)) > accuracy)
80  return 1;
81  if (abs(((ref16[i] >> 5) & 0x1f) - ((test16[i] >> 5) & 0x1f)) > accuracy)
82  return 1;
83  if (abs(((ref16[i] >> 10) & 0x1f) - ((test16[i] >> 10) & 0x1f)) > accuracy)
84  return 1;
85  }
86  return 0;
87 }
88 
89 static int cmp_565_by_n(const uint8_t *ref, const uint8_t *test, size_t n, int accuracy)
90 {
91  const uint16_t *ref16 = (const uint16_t *) ref;
92  const uint16_t *test16 = (const uint16_t *) test;
93  for (size_t i = 0; i < n; i++) {
94  if (abs(( ref16[i] & 0x1f) - ( test16[i] & 0x1f)) > accuracy)
95  return 1;
96  if (abs(((ref16[i] >> 5) & 0x3f) - ((test16[i] >> 5) & 0x3f)) > accuracy)
97  return 1;
98  if (abs(((ref16[i] >> 11) & 0x1f) - ((test16[i] >> 11) & 0x1f)) > accuracy)
99  return 1;
100  }
101  return 0;
102 }
103 
104 static void check_yuv2rgb(int src_pix_fmt)
105 {
106  const AVPixFmtDescriptor *src_desc = av_pix_fmt_desc_get(src_pix_fmt);
107 #define MAX_LINE_SIZE 1920
108 #define SRC_STRIDE_PAD 32
109 #define NUM_LINES 4
110  static const int input_sizes[] = {8, 128, 1080, MAX_LINE_SIZE};
111 
112  declare_func(int, SwsInternal *c, const uint8_t *const src[],
113  const int srcStride[], int srcSliceY, int srcSliceH,
114  uint8_t *const dst[], const int dstStride[]);
115 
116  LOCAL_ALIGNED_8(uint8_t, src_y, [(MAX_LINE_SIZE + SRC_STRIDE_PAD) * NUM_LINES]);
117  LOCAL_ALIGNED_8(uint8_t, src_u, [(MAX_LINE_SIZE + SRC_STRIDE_PAD) * NUM_LINES]);
118  LOCAL_ALIGNED_8(uint8_t, src_v, [(MAX_LINE_SIZE + SRC_STRIDE_PAD) * NUM_LINES]);
119  LOCAL_ALIGNED_8(uint8_t, src_a, [(MAX_LINE_SIZE + SRC_STRIDE_PAD) * NUM_LINES]);
120  const uint8_t *src[4] = { src_y, src_u, src_v, src_a };
121 
122  LOCAL_ALIGNED_8(uint8_t, dst0_0, [NUM_LINES * MAX_LINE_SIZE * 6]);
123  LOCAL_ALIGNED_8(uint8_t, dst0_1, [NUM_LINES * MAX_LINE_SIZE]);
124  LOCAL_ALIGNED_8(uint8_t, dst0_2, [NUM_LINES * MAX_LINE_SIZE]);
125  uint8_t *dst0[4] = { dst0_0, dst0_1, dst0_2 };
126 
127  LOCAL_ALIGNED_8(uint8_t, dst1_0, [NUM_LINES * MAX_LINE_SIZE * 6]);
128  LOCAL_ALIGNED_8(uint8_t, dst1_1, [NUM_LINES * MAX_LINE_SIZE]);
129  LOCAL_ALIGNED_8(uint8_t, dst1_2, [NUM_LINES * MAX_LINE_SIZE]);
130  uint8_t *dst1[4] = { dst1_0, dst1_1, dst1_2 };
131 
136 
137  for (int dfi = 0; dfi < FF_ARRAY_ELEMS(dst_fmts); dfi++) {
138  int dst_pix_fmt = dst_fmts[dfi];
139  const AVPixFmtDescriptor *dst_desc = av_pix_fmt_desc_get(dst_pix_fmt);
140  int sample_size = av_get_padded_bits_per_pixel(dst_desc) >> 3;
141  for (int isi = 0; isi < FF_ARRAY_ELEMS(input_sizes); isi++) {
142  SwsContext *sws;
143  SwsInternal *c;
144  int log_level;
145  int width = input_sizes[isi];
146  int srcSliceY = 0;
147  int srcSliceH = NUM_LINES;
148  /* Use av_image_get_linesize so that semi-planar formats (NV12,
149  * NV21) get the correct interleaved-UV stride (= width bytes),
150  * not (width >> log2_chroma_w) which would only count UV pairs. */
151  int chroma_linesize = av_image_get_linesize(src_pix_fmt, width, 1);
152  int srcStride[4] = {
154  chroma_linesize + SRC_STRIDE_PAD,
155  chroma_linesize + SRC_STRIDE_PAD,
157  };
158  int dstStride[4] = {
159  MAX_LINE_SIZE * 6,
162  };
163 
164  // override log level to prevent spamming of the message
165  // "No accelerated colorspace conversion found from %s to %s"
166  log_level = av_log_get_level();
168  sws = sws_getContext(width, srcSliceH, src_pix_fmt,
169  width, srcSliceH, dst_pix_fmt,
170  0, NULL, NULL, NULL);
171  av_log_set_level(log_level);
172  if (!sws)
173  fail();
174 
175  c = sws_internal(sws);
176  if (check_func(c->convert_unscaled, "%s_%s_%d", src_desc->name, dst_desc->name, width)) {
177  memset(dst0_0, 0xFF, NUM_LINES * MAX_LINE_SIZE * 6);
178  memset(dst1_0, 0xFF, NUM_LINES * MAX_LINE_SIZE * 6);
179  if (dst_pix_fmt == AV_PIX_FMT_GBRP) {
180  memset(dst0_1, 0xFF, NUM_LINES * MAX_LINE_SIZE);
181  memset(dst0_2, 0xFF, NUM_LINES * MAX_LINE_SIZE);
182  memset(dst1_1, 0xFF, NUM_LINES * MAX_LINE_SIZE);
183  memset(dst1_2, 0xFF, NUM_LINES * MAX_LINE_SIZE);
184  }
185 
186  call_ref(c, src, srcStride, srcSliceY,
187  srcSliceH, dst0, dstStride);
188  call_new(c, src, srcStride, srcSliceY,
189  srcSliceH, dst1, dstStride);
190 
191  if (dst_pix_fmt == AV_PIX_FMT_ARGB ||
192  dst_pix_fmt == AV_PIX_FMT_ABGR ||
193  dst_pix_fmt == AV_PIX_FMT_RGBA ||
194  dst_pix_fmt == AV_PIX_FMT_BGRA ||
195  dst_pix_fmt == AV_PIX_FMT_RGB24 ||
196  dst_pix_fmt == AV_PIX_FMT_BGR24) {
197  for (int row = 0; row < srcSliceH; row++)
198  if (cmp_off_by_n(dst0_0 + row * dstStride[0],
199  dst1_0 + row * dstStride[0],
200  width * sample_size, 3))
201  fail();
202  } else if (dst_pix_fmt == AV_PIX_FMT_RGB565 ||
203  dst_pix_fmt == AV_PIX_FMT_BGR565) {
204  for (int row = 0; row < srcSliceH; row++)
205  if (cmp_565_by_n(dst0_0 + row * dstStride[0],
206  dst1_0 + row * dstStride[0],
207  width, 2))
208  fail();
209  } else if (dst_pix_fmt == AV_PIX_FMT_RGB555 ||
210  dst_pix_fmt == AV_PIX_FMT_BGR555) {
211  for (int row = 0; row < srcSliceH; row++)
212  if (cmp_555_by_n(dst0_0 + row * dstStride[0],
213  dst1_0 + row * dstStride[0],
214  width, 2))
215  fail();
216  } else if (dst_pix_fmt == AV_PIX_FMT_GBRP) {
217  for (int p = 0; p < 3; p++)
218  for (int row = 0; row < srcSliceH; row++)
219  if (cmp_off_by_n(dst0[p] + row * dstStride[p],
220  dst1[p] + row * dstStride[p],
221  width, 3))
222  fail();
223  } else {
224  fail();
225  }
226 
227  bench_new(c, src, srcStride, srcSliceY,
228  srcSliceH, dst0, dstStride);
229  }
230  sws_freeContext(sws);
231  }
232  }
233 }
234 
235 #undef NUM_LINES
236 #undef SRC_STRIDE_PAD
237 #undef MAX_LINE_SIZE
238 
240 {
242  report("yuv420p");
244  report("yuv422p");
246  report("yuva420p");
248  report("nv12");
250  report("nv21");
251 }
mem_internal.h
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:3456
sws_freeContext
void sws_freeContext(SwsContext *swsContext)
Free the swscaler context swsContext.
Definition: utils.c:2297
pixdesc.h
AVPixFmtDescriptor::name
const char * name
Definition: pixdesc.h:70
test
Definition: idctdsp.c:35
check_func
#define check_func
Definition: test.h:480
AV_PIX_FMT_BGR24
@ AV_PIX_FMT_BGR24
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition: pixfmt.h:76
AV_PIX_FMT_BGRA
@ AV_PIX_FMT_BGRA
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition: pixfmt.h:102
bench_new
#define bench_new
Definition: test.h:486
call_ref
#define call_ref
Definition: test.h:484
randomize_buffers
#define randomize_buffers(buf, size)
Definition: sw_yuv2rgb.c:32
cmp_565_by_n
static int cmp_565_by_n(const uint8_t *ref, const uint8_t *test, size_t n, int accuracy)
Definition: sw_yuv2rgb.c:89
checkasm.h
MAX_LINE_SIZE
#define MAX_LINE_SIZE
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:210
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
cmp_555_by_n
static int cmp_555_by_n(const uint8_t *ref, const uint8_t *test, size_t n, int accuracy)
Definition: sw_yuv2rgb.c:74
intreadwrite.h
AV_PIX_FMT_YUVA420P
@ AV_PIX_FMT_YUVA420P
planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
Definition: pixfmt.h:108
input_sizes
static const int input_sizes[]
Definition: sw_rgb.c:347
declare_func
#define declare_func
Definition: test.h:488
check_yuv2rgb
static void check_yuv2rgb(int src_pix_fmt)
Definition: sw_yuv2rgb.c:104
AV_PIX_FMT_YUV420P
@ 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_RGBA
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition: pixfmt.h:100
LOCAL_ALIGNED_8
#define LOCAL_ALIGNED_8(t, v,...)
Definition: mem_internal.h:128
SRC_STRIDE_PAD
#define SRC_STRIDE_PAD
av_log_get_level
int av_log_get_level(void)
Get the current log level.
Definition: log.c:472
fail
#define fail
Definition: test.h:478
NULL
#define NULL
Definition: coverity.c:32
abs
#define abs(x)
Definition: cuda_runtime.h:35
cmp_off_by_n
static int cmp_off_by_n(const uint8_t *ref, const uint8_t *test, size_t n, int accuracy)
Definition: sw_yuv2rgb.c:65
AV_PIX_FMT_ABGR
@ AV_PIX_FMT_ABGR
packed ABGR 8:8:8:8, 32bpp, ABGRABGR...
Definition: pixfmt.h:101
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
AV_PIX_FMT_RGB24
@ AV_PIX_FMT_RGB24
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition: pixfmt.h:75
av_get_padded_bits_per_pixel
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:3421
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:87
i
#define i(width, name, range_min, range_max)
Definition: cbs_h264.c:63
checkasm_check_sw_yuv2rgb
void checkasm_check_sw_yuv2rgb(void)
Definition: sw_yuv2rgb.c:239
AV_PIX_FMT_BGR555
#define AV_PIX_FMT_BGR555
Definition: pixfmt.h:532
AV_PIX_FMT_ARGB
@ AV_PIX_FMT_ARGB
packed ARGB 8:8:8:8, 32bpp, ARGBARGB...
Definition: pixfmt.h:99
av_image_get_linesize
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
av_log_set_level
void av_log_set_level(int level)
Set the log level.
Definition: log.c:477
common.h
AV_PIX_FMT_RGB555
#define AV_PIX_FMT_RGB555
Definition: pixfmt.h:527
swscale_internal.h
NUM_LINES
#define NUM_LINES
AV_PIX_FMT_NV21
@ AV_PIX_FMT_NV21
as above, but U and V bytes are swapped
Definition: pixfmt.h:97
AV_PIX_FMT_BGR565
#define AV_PIX_FMT_BGR565
Definition: pixfmt.h:531
call_new
#define call_new
Definition: test.h:485
AV_PIX_FMT_RGB565
#define AV_PIX_FMT_RGB565
Definition: pixfmt.h:526
SwsInternal
Definition: swscale_internal.h:337
AV_PIX_FMT_NV12
@ 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
sws_getContext
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:1966
ref
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:117
Windows::Graphics::DirectX::Direct3D11::p
IDirect3DDxgiInterfaceAccess _COM_Outptr_ void ** p
Definition: vsrc_gfxcapture_winrt.hpp:53
AV_PIX_FMT_GBRP
@ AV_PIX_FMT_GBRP
planar GBR 4:4:4 24bpp
Definition: pixfmt.h:165
report
#define report
Definition: test.h:479
AV_PIX_FMT_YUV422P
@ AV_PIX_FMT_YUV422P
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition: pixfmt.h:77
AVPixFmtDescriptor
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:69
dst_fmts
static const int dst_fmts[]
Definition: sw_yuv2rgb.c:38
imgutils.h
sws_internal
static SwsInternal * sws_internal(const SwsContext *sws)
Definition: swscale_internal.h:79
width
#define width
Definition: dsp.h:89
SwsContext
Main external API structure.
Definition: swscale.h:229
src
#define src
Definition: vp8dsp.c:248
swscale.h