FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libswscale/x86/yuv2rgb.c
Date: 2024-11-20 23:03:26
Exec Total Coverage
Lines: 77 78 98.7%
Functions: 10 10 100.0%
Branches: 41 50 82.0%

Line Branch Exec Source
1 /*
2 * software YUV to RGB converter
3 *
4 * Copyright (C) 2001-2007 Michael Niedermayer
5 * Copyright (C) 2009-2010 Konstantin Shishkov
6 *
7 * MMX/MMXEXT template stuff (needed for fast movntq support),
8 * 1,4,8bpp support and context / deglobalize stuff
9 * by Michael Niedermayer (michaelni@gmx.at)
10 *
11 * This file is part of FFmpeg.
12 *
13 * FFmpeg is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU Lesser General Public
15 * License as published by the Free Software Foundation; either
16 * version 2.1 of the License, or (at your option) any later version.
17 *
18 * FFmpeg is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * Lesser General Public License for more details.
22 *
23 * You should have received a copy of the GNU Lesser General Public
24 * License along with FFmpeg; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 */
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <inttypes.h>
31
32 #include "config.h"
33 #include "libswscale/rgb2rgb.h"
34 #include "libswscale/swscale.h"
35 #include "libswscale/swscale_internal.h"
36 #include "libavutil/attributes.h"
37 #include "libavutil/x86/asm.h"
38 #include "libavutil/x86/cpu.h"
39 #include "libavutil/cpu.h"
40
41 #if HAVE_X86ASM
42
43 #define YUV2RGB_LOOP(depth) \
44 h_size = (c->dstW + 7) & ~7; \
45 if (h_size * depth > FFABS(dstStride[0])) \
46 h_size -= 8; \
47 \
48 vshift = c->srcFormat != AV_PIX_FMT_YUV422P; \
49 \
50 for (y = 0; y < srcSliceH; y++) { \
51 uint8_t *image = dst[0] + (y + srcSliceY) * dstStride[0]; \
52 const uint8_t *py = src[0] + y * srcStride[0]; \
53 const uint8_t *pu = src[1] + (y >> vshift) * srcStride[1]; \
54 const uint8_t *pv = src[2] + (y >> vshift) * srcStride[2]; \
55 x86_reg index = -h_size / 2; \
56
57 extern void ff_yuv_420_rgb24_ssse3(x86_reg index, uint8_t *image, const uint8_t *pu_index,
58 const uint8_t *pv_index, const uint64_t *pointer_c_dither,
59 const uint8_t *py_2index);
60 extern void ff_yuv_420_bgr24_ssse3(x86_reg index, uint8_t *image, const uint8_t *pu_index,
61 const uint8_t *pv_index, const uint64_t *pointer_c_dither,
62 const uint8_t *py_2index);
63
64 extern void ff_yuv_420_rgb15_ssse3(x86_reg index, uint8_t *image, const uint8_t *pu_index,
65 const uint8_t *pv_index, const uint64_t *pointer_c_dither,
66 const uint8_t *py_2index);
67 extern void ff_yuv_420_rgb16_ssse3(x86_reg index, uint8_t *image, const uint8_t *pu_index,
68 const uint8_t *pv_index, const uint64_t *pointer_c_dither,
69 const uint8_t *py_2index);
70 extern void ff_yuv_420_rgb32_ssse3(x86_reg index, uint8_t *image, const uint8_t *pu_index,
71 const uint8_t *pv_index, const uint64_t *pointer_c_dither,
72 const uint8_t *py_2index);
73 extern void ff_yuv_420_bgr32_ssse3(x86_reg index, uint8_t *image, const uint8_t *pu_index,
74 const uint8_t *pv_index, const uint64_t *pointer_c_dither,
75 const uint8_t *py_2index);
76 extern void ff_yuva_420_rgb32_ssse3(x86_reg index, uint8_t *image, const uint8_t *pu_index,
77 const uint8_t *pv_index, const uint64_t *pointer_c_dither,
78 const uint8_t *py_2index, const uint8_t *pa_2index);
79 extern void ff_yuva_420_bgr32_ssse3(x86_reg index, uint8_t *image, const uint8_t *pu_index,
80 const uint8_t *pv_index, const uint64_t *pointer_c_dither,
81 const uint8_t *py_2index, const uint8_t *pa_2index);
82 #if ARCH_X86_64
83 extern void ff_yuv_420_gbrp24_ssse3(x86_reg index, uint8_t *image, uint8_t *dst_b, uint8_t *dst_r,
84 const uint8_t *pu_index, const uint8_t *pv_index,
85 const uint64_t *pointer_c_dither,
86 const uint8_t *py_2index);
87 #endif
88
89 12 static inline int yuv420_rgb15_ssse3(SwsInternal *c, const uint8_t *const src[],
90 const int srcStride[],
91 int srcSliceY, int srcSliceH,
92 uint8_t *const dst[], const int dstStride[])
93 {
94 int y, h_size, vshift;
95
96
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 12 times.
36 YUV2RGB_LOOP(2)
97
98 24 c->blueDither = ff_dither8[y & 1];
99 24 c->greenDither = ff_dither8[y & 1];
100 24 c->redDither = ff_dither8[(y + 1) & 1];
101
102 24 ff_yuv_420_rgb15_ssse3(index, image, pu - index, pv - index, &(c->redDither), py - 2 * index);
103 }
104 12 return srcSliceH;
105 }
106
107 12 static inline int yuv420_rgb16_ssse3(SwsInternal *c, const uint8_t *const src[],
108 const int srcStride[],
109 int srcSliceY, int srcSliceH,
110 uint8_t *const dst[], const int dstStride[])
111 {
112 int y, h_size, vshift;
113
114
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 12 times.
36 YUV2RGB_LOOP(2)
115
116 24 c->blueDither = ff_dither8[y & 1];
117 24 c->greenDither = ff_dither4[y & 1];
118 24 c->redDither = ff_dither8[(y + 1) & 1];
119
120 24 ff_yuv_420_rgb16_ssse3(index, image, pu - index, pv - index, &(c->redDither), py - 2 * index);
121 }
122 12 return srcSliceH;
123 }
124
125 8 static inline int yuv420_rgb32_ssse3(SwsInternal *c, const uint8_t *const src[],
126 const int srcStride[],
127 int srcSliceY, int srcSliceH,
128 uint8_t *const dst[], const int dstStride[])
129 {
130 int y, h_size, vshift;
131
132
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 8 times.
24 YUV2RGB_LOOP(4)
133
134 16 ff_yuv_420_rgb32_ssse3(index, image, pu - index, pv - index, &(c->redDither), py - 2 * index);
135 }
136 8 return srcSliceH;
137 }
138
139 8 static inline int yuv420_bgr32_ssse3(SwsInternal *c, const uint8_t *const src[],
140 const int srcStride[],
141 int srcSliceY, int srcSliceH,
142 uint8_t *const dst[], const int dstStride[])
143 {
144 int y, h_size, vshift;
145
146
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 8 times.
24 YUV2RGB_LOOP(4)
147
148 16 ff_yuv_420_bgr32_ssse3(index, image, pu - index, pv - index, &(c->redDither), py - 2 * index);
149 }
150 8 return srcSliceH;
151 }
152
153 4 static inline int yuva420_rgb32_ssse3(SwsInternal *c, const uint8_t *const src[],
154 const int srcStride[],
155 int srcSliceY, int srcSliceH,
156 uint8_t *const dst[], const int dstStride[])
157 {
158 int y, h_size, vshift;
159
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 4 times.
12 YUV2RGB_LOOP(4)
160
161 8 const uint8_t *pa = src[3] + y * srcStride[3];
162 8 ff_yuva_420_rgb32_ssse3(index, image, pu - index, pv - index, &(c->redDither), py - 2 * index, pa - 2 * index);
163 }
164 4 return srcSliceH;
165 }
166
167 4 static inline int yuva420_bgr32_ssse3(SwsInternal *c, const uint8_t *const src[],
168 const int srcStride[],
169 int srcSliceY, int srcSliceH,
170 uint8_t *const dst[], const int dstStride[])
171 {
172 int y, h_size, vshift;
173
174
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 4 times.
12 YUV2RGB_LOOP(4)
175
176 8 const uint8_t *pa = src[3] + y * srcStride[3];
177 8 ff_yuva_420_bgr32_ssse3(index, image, pu - index, pv - index, &(c->redDither), py - 2 * index, pa - 2 * index);
178 }
179 4 return srcSliceH;
180 }
181
182 12 static inline int yuv420_rgb24_ssse3(SwsInternal *c, const uint8_t *const src[],
183 const int srcStride[],
184 int srcSliceY, int srcSliceH,
185 uint8_t *const dst[], const int dstStride[])
186 {
187 int y, h_size, vshift;
188
189
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 12 times.
36 YUV2RGB_LOOP(3)
190
191 24 ff_yuv_420_rgb24_ssse3(index, image, pu - index, pv - index, &(c->redDither), py - 2 * index);
192 }
193 12 return srcSliceH;
194 }
195
196 12 static inline int yuv420_bgr24_ssse3(SwsInternal *c, const uint8_t *const src[],
197 const int srcStride[],
198 int srcSliceY, int srcSliceH,
199 uint8_t *const dst[], const int dstStride[])
200 {
201 int y, h_size, vshift;
202
203
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 12 times.
36 YUV2RGB_LOOP(3)
204
205 24 ff_yuv_420_bgr24_ssse3(index, image, pu - index, pv - index, &(c->redDither), py - 2 * index);
206 }
207 12 return srcSliceH;
208 }
209
210 #if ARCH_X86_64
211 12 static inline int yuv420_gbrp_ssse3(SwsInternal *c, const uint8_t *const src[],
212 const int srcStride[],
213 int srcSliceY, int srcSliceH,
214 uint8_t *const dst[], const int dstStride[])
215 {
216 int y, h_size, vshift;
217
218 12 h_size = (c->dstW + 7) & ~7;
219
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (h_size * 3 > FFABS(dstStride[0]))
220 h_size -= 8;
221
222 12 vshift = c->srcFormat != AV_PIX_FMT_YUV422P;
223
224
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 12 times.
36 for (y = 0; y < srcSliceH; y++) {
225 24 uint8_t *dst_g = dst[0] + (y + srcSliceY) * dstStride[0];
226 24 uint8_t *dst_b = dst[1] + (y + srcSliceY) * dstStride[1];
227 24 uint8_t *dst_r = dst[2] + (y + srcSliceY) * dstStride[2];
228 24 const uint8_t *py = src[0] + y * srcStride[0];
229 24 const uint8_t *pu = src[1] + (y >> vshift) * srcStride[1];
230 24 const uint8_t *pv = src[2] + (y >> vshift) * srcStride[2];
231 24 x86_reg index = -h_size / 2;
232
233 24 ff_yuv_420_gbrp24_ssse3(index, dst_g, dst_b, dst_r, pu - index, pv - index, &(c->redDither), py - 2 * index);
234 }
235 12 return srcSliceH;
236 }
237 #endif
238
239 #endif /* HAVE_X86ASM */
240
241 1716 av_cold SwsFunc ff_yuv2rgb_init_x86(SwsInternal *c)
242 {
243 #if HAVE_X86ASM
244 1716 int cpu_flags = av_get_cpu_flags();
245
246
2/2
✓ Branch 0 taken 924 times.
✓ Branch 1 taken 792 times.
1716 if (EXTERNAL_SSSE3(cpu_flags)) {
247
8/8
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 84 times.
✓ Branch 2 taken 84 times.
✓ Branch 3 taken 84 times.
✓ Branch 4 taken 84 times.
✓ Branch 5 taken 84 times.
✓ Branch 6 taken 84 times.
✓ Branch 7 taken 336 times.
924 switch (c->dstFormat) {
248 84 case AV_PIX_FMT_RGB32:
249
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 56 times.
84 if (c->srcFormat == AV_PIX_FMT_YUVA420P) {
250 #if CONFIG_SWSCALE_ALPHA
251 28 return yuva420_rgb32_ssse3;
252 #endif
253 break;
254 } else
255 56 return yuv420_rgb32_ssse3;
256 84 case AV_PIX_FMT_BGR32:
257
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 56 times.
84 if (c->srcFormat == AV_PIX_FMT_YUVA420P) {
258 #if CONFIG_SWSCALE_ALPHA
259 28 return yuva420_bgr32_ssse3;
260 #endif
261 break;
262 } else
263 56 return yuv420_bgr32_ssse3;
264 84 case AV_PIX_FMT_RGB24:
265 84 return yuv420_rgb24_ssse3;
266 84 case AV_PIX_FMT_BGR24:
267 84 return yuv420_bgr24_ssse3;
268 84 case AV_PIX_FMT_RGB565:
269 84 return yuv420_rgb16_ssse3;
270 84 case AV_PIX_FMT_RGB555:
271 84 return yuv420_rgb15_ssse3;
272 #if ARCH_X86_64
273 84 case AV_PIX_FMT_GBRP:
274 84 return yuv420_gbrp_ssse3;
275 #endif
276 }
277 }
278
279 #endif /* HAVE_X86ASM */
280 1128 return NULL;
281 }
282