2 * Copyright (C) 2001-2011 Michael Niedermayer <michaelni@gmx.at>
4 * This file is part of FFmpeg.
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27 #include "swscale_internal.h"
29 #include "libavutil/intreadwrite.h"
30 #include "libavutil/avutil.h"
31 #include "libavutil/mathematics.h"
32 #include "libavutil/mem_internal.h"
33 #include "libavutil/bswap.h"
34 #include "libavutil/pixdesc.h"
35 #include "libavutil/avassert.h"
36 #include "libavutil/avconfig.h"
38 DECLARE_ALIGNED(8, static const uint8_t, dithers
)[8][8][8]={
40 { 0, 1, 0, 1, 0, 1, 0, 1,},
41 { 1, 0, 1, 0, 1, 0, 1, 0,},
42 { 0, 1, 0, 1, 0, 1, 0, 1,},
43 { 1, 0, 1, 0, 1, 0, 1, 0,},
44 { 0, 1, 0, 1, 0, 1, 0, 1,},
45 { 1, 0, 1, 0, 1, 0, 1, 0,},
46 { 0, 1, 0, 1, 0, 1, 0, 1,},
47 { 1, 0, 1, 0, 1, 0, 1, 0,},
49 { 1, 2, 1, 2, 1, 2, 1, 2,},
50 { 3, 0, 3, 0, 3, 0, 3, 0,},
51 { 1, 2, 1, 2, 1, 2, 1, 2,},
52 { 3, 0, 3, 0, 3, 0, 3, 0,},
53 { 1, 2, 1, 2, 1, 2, 1, 2,},
54 { 3, 0, 3, 0, 3, 0, 3, 0,},
55 { 1, 2, 1, 2, 1, 2, 1, 2,},
56 { 3, 0, 3, 0, 3, 0, 3, 0,},
58 { 2, 4, 3, 5, 2, 4, 3, 5,},
59 { 6, 0, 7, 1, 6, 0, 7, 1,},
60 { 3, 5, 2, 4, 3, 5, 2, 4,},
61 { 7, 1, 6, 0, 7, 1, 6, 0,},
62 { 2, 4, 3, 5, 2, 4, 3, 5,},
63 { 6, 0, 7, 1, 6, 0, 7, 1,},
64 { 3, 5, 2, 4, 3, 5, 2, 4,},
65 { 7, 1, 6, 0, 7, 1, 6, 0,},
67 { 4, 8, 7, 11, 4, 8, 7, 11,},
68 { 12, 0, 15, 3, 12, 0, 15, 3,},
69 { 6, 10, 5, 9, 6, 10, 5, 9,},
70 { 14, 2, 13, 1, 14, 2, 13, 1,},
71 { 4, 8, 7, 11, 4, 8, 7, 11,},
72 { 12, 0, 15, 3, 12, 0, 15, 3,},
73 { 6, 10, 5, 9, 6, 10, 5, 9,},
74 { 14, 2, 13, 1, 14, 2, 13, 1,},
76 { 9, 17, 15, 23, 8, 16, 14, 22,},
77 { 25, 1, 31, 7, 24, 0, 30, 6,},
78 { 13, 21, 11, 19, 12, 20, 10, 18,},
79 { 29, 5, 27, 3, 28, 4, 26, 2,},
80 { 8, 16, 14, 22, 9, 17, 15, 23,},
81 { 24, 0, 30, 6, 25, 1, 31, 7,},
82 { 12, 20, 10, 18, 13, 21, 11, 19,},
83 { 28, 4, 26, 2, 29, 5, 27, 3,},
85 { 18, 34, 30, 46, 17, 33, 29, 45,},
86 { 50, 2, 62, 14, 49, 1, 61, 13,},
87 { 26, 42, 22, 38, 25, 41, 21, 37,},
88 { 58, 10, 54, 6, 57, 9, 53, 5,},
89 { 16, 32, 28, 44, 19, 35, 31, 47,},
90 { 48, 0, 60, 12, 51, 3, 63, 15,},
91 { 24, 40, 20, 36, 27, 43, 23, 39,},
92 { 56, 8, 52, 4, 59, 11, 55, 7,},
94 { 18, 34, 30, 46, 17, 33, 29, 45,},
95 { 50, 2, 62, 14, 49, 1, 61, 13,},
96 { 26, 42, 22, 38, 25, 41, 21, 37,},
97 { 58, 10, 54, 6, 57, 9, 53, 5,},
98 { 16, 32, 28, 44, 19, 35, 31, 47,},
99 { 48, 0, 60, 12, 51, 3, 63, 15,},
100 { 24, 40, 20, 36, 27, 43, 23, 39,},
101 { 56, 8, 52, 4, 59, 11, 55, 7,},
103 { 36, 68, 60, 92, 34, 66, 58, 90,},
104 { 100, 4,124, 28, 98, 2,122, 26,},
105 { 52, 84, 44, 76, 50, 82, 42, 74,},
106 { 116, 20,108, 12,114, 18,106, 10,},
107 { 32, 64, 56, 88, 38, 70, 62, 94,},
108 { 96, 0,120, 24,102, 6,126, 30,},
109 { 48, 80, 40, 72, 54, 86, 46, 78,},
110 { 112, 16,104, 8,118, 22,110, 14,},
114 static void fillPlane(uint8_t *plane
, int stride
, int width
, int height
, int y
,
118 uint8_t *ptr
= plane
+ stride
* y
;
119 for (i
= 0; i
< height
; i
++) {
120 memset(ptr
, val
, width
);
125 void ff_copyPlane(const uint8_t *src
, int srcStride
,
126 int srcSliceY
, int srcSliceH
, int width
,
127 uint8_t *dst
, int dstStride
)
129 dst
+= dstStride
* srcSliceY
;
130 if (dstStride
== srcStride
&& srcStride
> 0) {
131 memcpy(dst
, src
, srcSliceH
* dstStride
);
134 for (i
= 0; i
< srcSliceH
; i
++) {
135 memcpy(dst
, src
, width
);
142 static int planarToNv12Wrapper(SwsInternal
*c
, const uint8_t *const src
[],
143 const int srcStride
[], int srcSliceY
,
144 int srcSliceH
, uint8_t *const dstParam
[],
145 const int dstStride
[])
147 uint8_t *dst
= dstParam
[1] + dstStride
[1] * srcSliceY
/ 2;
149 ff_copyPlane(src
[0], srcStride
[0], srcSliceY
, srcSliceH
, c
->opts
.src_w
,
150 dstParam
[0], dstStride
[0]);
152 if (c
->opts
.dst_format
== AV_PIX_FMT_NV12
)
153 interleaveBytes(src
[1], src
[2], dst
, c
->chrSrcW
, (srcSliceH
+ 1) / 2,
154 srcStride
[1], srcStride
[2], dstStride
[1]);
156 interleaveBytes(src
[2], src
[1], dst
, c
->chrSrcW
, (srcSliceH
+ 1) / 2,
157 srcStride
[2], srcStride
[1], dstStride
[1]);
162 static int nv12ToPlanarWrapper(SwsInternal
*c
, const uint8_t *const src
[],
163 const int srcStride
[], int srcSliceY
,
164 int srcSliceH
, uint8_t *const dstParam
[],
165 const int dstStride
[])
167 uint8_t *dst1
= dstParam
[1] + dstStride
[1] * srcSliceY
/ 2;
168 uint8_t *dst2
= dstParam
[2] + dstStride
[2] * srcSliceY
/ 2;
170 ff_copyPlane(src
[0], srcStride
[0], srcSliceY
, srcSliceH
, c
->opts
.src_w
,
171 dstParam
[0], dstStride
[0]);
173 if (c
->opts
.src_format
== AV_PIX_FMT_NV12
)
174 deinterleaveBytes(src
[1], dst1
, dst2
, c
->chrSrcW
, (srcSliceH
+ 1) / 2,
175 srcStride
[1], dstStride
[1], dstStride
[2]);
177 deinterleaveBytes(src
[1], dst2
, dst1
, c
->chrSrcW
, (srcSliceH
+ 1) / 2,
178 srcStride
[1], dstStride
[2], dstStride
[1]);
183 static int planarToNv24Wrapper(SwsInternal
*c
, const uint8_t *const src
[],
184 const int srcStride
[], int srcSliceY
,
185 int srcSliceH
, uint8_t *const dstParam
[],
186 const int dstStride
[])
188 uint8_t *dst
= dstParam
[1] + dstStride
[1] * srcSliceY
;
190 ff_copyPlane(src
[0], srcStride
[0], srcSliceY
, srcSliceH
, c
->opts
.src_w
,
191 dstParam
[0], dstStride
[0]);
193 if (c
->opts
.dst_format
== AV_PIX_FMT_NV24
)
194 interleaveBytes(src
[1], src
[2], dst
, c
->chrSrcW
, srcSliceH
,
195 srcStride
[1], srcStride
[2], dstStride
[1]);
197 interleaveBytes(src
[2], src
[1], dst
, c
->chrSrcW
, srcSliceH
,
198 srcStride
[2], srcStride
[1], dstStride
[1]);
203 static int nv24ToPlanarWrapper(SwsInternal
*c
, const uint8_t *const src
[],
204 const int srcStride
[], int srcSliceY
,
205 int srcSliceH
, uint8_t *const dstParam
[],
206 const int dstStride
[])
208 uint8_t *dst1
= dstParam
[1] + dstStride
[1] * srcSliceY
;
209 uint8_t *dst2
= dstParam
[2] + dstStride
[2] * srcSliceY
;
211 ff_copyPlane(src
[0], srcStride
[0], srcSliceY
, srcSliceH
, c
->opts
.src_w
,
212 dstParam
[0], dstStride
[0]);
214 if (c
->opts
.src_format
== AV_PIX_FMT_NV24
)
215 deinterleaveBytes(src
[1], dst1
, dst2
, c
->chrSrcW
, srcSliceH
,
216 srcStride
[1], dstStride
[1], dstStride
[2]);
218 deinterleaveBytes(src
[1], dst2
, dst1
, c
->chrSrcW
, srcSliceH
,
219 srcStride
[1], dstStride
[2], dstStride
[1]);
224 static void nv24_to_yuv420p_chroma(uint8_t *dst1
, int dstStride1
,
225 uint8_t *dst2
, int dstStride2
,
226 const uint8_t *src
, int srcStride
,
229 const uint8_t *src1
= src
;
230 const uint8_t *src2
= src
+ srcStride
;
231 // average 4 pixels into 1 (interleaved U and V)
232 for (int y
= 0; y
< h
; y
+= 2) {
235 for (int x
= 0; x
< w
; x
++) {
236 dst1
[x
] = (src1
[4 * x
+ 0] + src1
[4 * x
+ 2] +
237 src2
[4 * x
+ 0] + src2
[4 * x
+ 2]) >> 2;
238 dst2
[x
] = (src1
[4 * x
+ 1] + src1
[4 * x
+ 3] +
239 src2
[4 * x
+ 1] + src2
[4 * x
+ 3]) >> 2;
241 src1
+= srcStride
* 2;
242 src2
+= srcStride
* 2;
248 static int nv24ToYuv420Wrapper(SwsInternal
*c
, const uint8_t *const src
[],
249 const int srcStride
[], int srcSliceY
, int srcSliceH
,
250 uint8_t *const dstParam
[], const int dstStride
[])
252 uint8_t *dst1
= dstParam
[1] + dstStride
[1] * srcSliceY
/ 2;
253 uint8_t *dst2
= dstParam
[2] + dstStride
[2] * srcSliceY
/ 2;
255 ff_copyPlane(src
[0], srcStride
[0], srcSliceY
, srcSliceH
, c
->opts
.src_w
,
256 dstParam
[0], dstStride
[0]);
258 if (c
->opts
.src_format
== AV_PIX_FMT_NV24
)
259 nv24_to_yuv420p_chroma(dst1
, dstStride
[1], dst2
, dstStride
[2],
260 src
[1], srcStride
[1], c
->opts
.src_w
/ 2, srcSliceH
);
262 nv24_to_yuv420p_chroma(dst2
, dstStride
[2], dst1
, dstStride
[1],
263 src
[1], srcStride
[1], c
->opts
.src_w
/ 2, srcSliceH
);
268 static int planarToP01xWrapper(SwsInternal
*c
, const uint8_t *const src8
[],
269 const int srcStride
[], int srcSliceY
,
270 int srcSliceH
, uint8_t *const dstParam8
[],
271 const int dstStride
[])
273 const AVPixFmtDescriptor
*src_format
= av_pix_fmt_desc_get(c
->opts
.src_format
);
274 const AVPixFmtDescriptor
*dst_format
= av_pix_fmt_desc_get(c
->opts
.dst_format
);
275 const uint16_t **src
= (const uint16_t**)src8
;
276 uint16_t *dstY
= (uint16_t*)(dstParam8
[0] + dstStride
[0] * srcSliceY
);
277 uint16_t *dstUV
= (uint16_t*)(dstParam8
[1] + dstStride
[1] * srcSliceY
/ 2);
280 /* Calculate net shift required for values. */
281 const int shift
[3] = {
282 dst_format
->comp
[0].depth
+ dst_format
->comp
[0].shift
-
283 src_format
->comp
[0].depth
- src_format
->comp
[0].shift
,
284 dst_format
->comp
[1].depth
+ dst_format
->comp
[1].shift
-
285 src_format
->comp
[1].depth
- src_format
->comp
[1].shift
,
286 dst_format
->comp
[2].depth
+ dst_format
->comp
[2].shift
-
287 src_format
->comp
[2].depth
- src_format
->comp
[2].shift
,
290 av_assert0(!(srcStride
[0] % 2 || srcStride
[1] % 2 || srcStride
[2] % 2 ||
291 dstStride
[0] % 2 || dstStride
[1] % 2));
293 for (y
= 0; y
< srcSliceH
; y
++) {
294 uint16_t *tdstY
= dstY
;
295 const uint16_t *tsrc0
= src
[0];
296 for (x
= c
->opts
.src_w
; x
> 0; x
--) {
297 *tdstY
++ = *tsrc0
++ << shift
[0];
299 src
[0] += srcStride
[0] / 2;
300 dstY
+= dstStride
[0] / 2;
303 uint16_t *tdstUV
= dstUV
;
304 const uint16_t *tsrc1
= src
[1];
305 const uint16_t *tsrc2
= src
[2];
306 for (x
= c
->opts
.src_w
/ 2; x
> 0; x
--) {
307 *tdstUV
++ = *tsrc1
++ << shift
[1];
308 *tdstUV
++ = *tsrc2
++ << shift
[2];
310 src
[1] += srcStride
[1] / 2;
311 src
[2] += srcStride
[2] / 2;
312 dstUV
+= dstStride
[1] / 2;
319 #if AV_HAVE_BIGENDIAN
320 #define output_pixel(p, v) do { \
321 uint16_t *pp = (p); \
325 #define output_pixel(p, v) (*p) = (v)
328 static int planar8ToP01xleWrapper(SwsInternal
*c
, const uint8_t *const src
[],
329 const int srcStride
[], int srcSliceY
,
330 int srcSliceH
, uint8_t *const dstParam8
[],
331 const int dstStride
[])
333 const uint8_t *src0
= src
[0], *src1
= src
[1], *src2
= src
[2];
334 uint16_t *dstY
= (uint16_t*)(dstParam8
[0] + dstStride
[0] * srcSliceY
);
335 uint16_t *dstUV
= (uint16_t*)(dstParam8
[1] + dstStride
[1] * srcSliceY
/ 2);
338 av_assert0(!(dstStride
[0] % 2 || dstStride
[1] % 2));
340 for (y
= 0; y
< srcSliceH
; y
++) {
341 uint16_t *tdstY
= dstY
;
342 const uint8_t *tsrc0
= src0
;
343 for (x
= c
->opts
.src_w
; x
> 0; x
--) {
345 output_pixel(tdstY
++, t
<< 8);
347 src0
+= srcStride
[0];
348 dstY
+= dstStride
[0] / 2;
351 uint16_t *tdstUV
= dstUV
;
352 const uint8_t *tsrc1
= src1
;
353 const uint8_t *tsrc2
= src2
;
354 for (x
= c
->opts
.src_w
/ 2; x
> 0; x
--) {
356 output_pixel(tdstUV
++, t
<< 8);
358 output_pixel(tdstUV
++, t
<< 8);
360 src1
+= srcStride
[1];
361 src2
+= srcStride
[2];
362 dstUV
+= dstStride
[1] / 2;
371 static int planarToYuy2Wrapper(SwsInternal
*c
, const uint8_t *const src
[],
372 const int srcStride
[], int srcSliceY
, int srcSliceH
,
373 uint8_t *const dstParam
[], const int dstStride
[])
375 uint8_t *dst
= dstParam
[0] + dstStride
[0] * srcSliceY
;
377 yv12toyuy2(src
[0], src
[1], src
[2], dst
, c
->opts
.src_w
, srcSliceH
, srcStride
[0],
378 srcStride
[1], dstStride
[0]);
383 static int planarToUyvyWrapper(SwsInternal
*c
, const uint8_t *const src
[],
384 const int srcStride
[], int srcSliceY
, int srcSliceH
,
385 uint8_t *const dstParam
[], const int dstStride
[])
387 uint8_t *dst
= dstParam
[0] + dstStride
[0] * srcSliceY
;
389 yv12touyvy(src
[0], src
[1], src
[2], dst
, c
->opts
.src_w
, srcSliceH
, srcStride
[0],
390 srcStride
[1], dstStride
[0]);
395 static int yuv422pToYuy2Wrapper(SwsInternal
*c
, const uint8_t *const src
[],
396 const int srcStride
[], int srcSliceY
, int srcSliceH
,
397 uint8_t *const dstParam
[], const int dstStride
[])
399 uint8_t *dst
= dstParam
[0] + dstStride
[0] * srcSliceY
;
401 yuv422ptoyuy2(src
[0], src
[1], src
[2], dst
, c
->opts
.src_w
, srcSliceH
, srcStride
[0],
402 srcStride
[1], dstStride
[0]);
407 static int yuv422pToUyvyWrapper(SwsInternal
*c
, const uint8_t *const src
[],
408 const int srcStride
[], int srcSliceY
, int srcSliceH
,
409 uint8_t *const dstParam
[], const int dstStride
[])
411 uint8_t *dst
= dstParam
[0] + dstStride
[0] * srcSliceY
;
413 yuv422ptouyvy(src
[0], src
[1], src
[2], dst
, c
->opts
.src_w
, srcSliceH
, srcStride
[0],
414 srcStride
[1], dstStride
[0]);
419 static int yuyvToYuv420Wrapper(SwsInternal
*c
, const uint8_t *const src
[],
420 const int srcStride
[], int srcSliceY
, int srcSliceH
,
421 uint8_t *const dstParam
[], const int dstStride
[])
423 uint8_t *ydst
= dstParam
[0] + dstStride
[0] * srcSliceY
;
424 uint8_t *udst
= dstParam
[1] + dstStride
[1] * srcSliceY
/ 2;
425 uint8_t *vdst
= dstParam
[2] + dstStride
[2] * srcSliceY
/ 2;
427 yuyvtoyuv420(ydst
, udst
, vdst
, src
[0], c
->opts
.src_w
, srcSliceH
, dstStride
[0],
428 dstStride
[1], srcStride
[0]);
431 fillPlane(dstParam
[3], dstStride
[3], c
->opts
.src_w
, srcSliceH
, srcSliceY
, 255);
436 static int yuyvToYuv422Wrapper(SwsInternal
*c
, const uint8_t *const src
[],
437 const int srcStride
[], int srcSliceY
, int srcSliceH
,
438 uint8_t *const dstParam
[], const int dstStride
[])
440 uint8_t *ydst
= dstParam
[0] + dstStride
[0] * srcSliceY
;
441 uint8_t *udst
= dstParam
[1] + dstStride
[1] * srcSliceY
;
442 uint8_t *vdst
= dstParam
[2] + dstStride
[2] * srcSliceY
;
444 yuyvtoyuv422(ydst
, udst
, vdst
, src
[0], c
->opts
.src_w
, srcSliceH
, dstStride
[0],
445 dstStride
[1], srcStride
[0]);
450 static int uyvyToYuv420Wrapper(SwsInternal
*c
, const uint8_t *const src
[],
451 const int srcStride
[], int srcSliceY
, int srcSliceH
,
452 uint8_t *const dstParam
[], const int dstStride
[])
454 uint8_t *ydst
= dstParam
[0] + dstStride
[0] * srcSliceY
;
455 uint8_t *udst
= dstParam
[1] + dstStride
[1] * srcSliceY
/ 2;
456 uint8_t *vdst
= dstParam
[2] + dstStride
[2] * srcSliceY
/ 2;
458 uyvytoyuv420(ydst
, udst
, vdst
, src
[0], c
->opts
.src_w
, srcSliceH
, dstStride
[0],
459 dstStride
[1], srcStride
[0]);
462 fillPlane(dstParam
[3], dstStride
[3], c
->opts
.src_w
, srcSliceH
, srcSliceY
, 255);
467 static int uyvyToYuv422Wrapper(SwsInternal
*c
, const uint8_t *const src
[],
468 const int srcStride
[], int srcSliceY
, int srcSliceH
,
469 uint8_t *const dstParam
[], const int dstStride
[])
471 uint8_t *ydst
= dstParam
[0] + dstStride
[0] * srcSliceY
;
472 uint8_t *udst
= dstParam
[1] + dstStride
[1] * srcSliceY
;
473 uint8_t *vdst
= dstParam
[2] + dstStride
[2] * srcSliceY
;
475 uyvytoyuv422(ydst
, udst
, vdst
, src
[0], c
->opts
.src_w
, srcSliceH
, dstStride
[0],
476 dstStride
[1], srcStride
[0]);
481 static void gray8aToPacked32(const uint8_t *src
, uint8_t *dst
, int num_pixels
,
482 const uint8_t *palette
)
485 for (i
= 0; i
< num_pixels
; i
++)
486 ((uint32_t *) dst
)[i
] = ((const uint32_t *) palette
)[src
[i
<< 1]] | (src
[(i
<< 1) + 1] << 24);
489 static void gray8aToPacked32_1(const uint8_t *src
, uint8_t *dst
, int num_pixels
,
490 const uint8_t *palette
)
494 for (i
= 0; i
< num_pixels
; i
++)
495 ((uint32_t *) dst
)[i
] = ((const uint32_t *) palette
)[src
[i
<< 1]] | src
[(i
<< 1) + 1];
498 static void gray8aToPacked24(const uint8_t *src
, uint8_t *dst
, int num_pixels
,
499 const uint8_t *palette
)
503 for (i
= 0; i
< num_pixels
; i
++) {
505 dst
[0] = palette
[src
[i
<< 1] * 4 + 0];
506 dst
[1] = palette
[src
[i
<< 1] * 4 + 1];
507 dst
[2] = palette
[src
[i
<< 1] * 4 + 2];
512 static void gray8aToPlanar8(const uint8_t *src
, uint8_t *dst0
, uint8_t *dst1
,
513 uint8_t *dst2
, uint8_t *dstA
, int num_pixels
,
514 const uint8_t *palette
)
516 for (int i
= 0; i
< num_pixels
; i
++) {
517 const uint8_t *rgb
= &palette
[src
[i
<< 1] * 4];
522 dstA
[i
] = src
[(i
<< 1) + 1];
526 static void pal8ToPlanar8(const uint8_t *src
, uint8_t *dst0
, uint8_t *dst1
,
527 uint8_t *dst2
, uint8_t *dstA
, int num_pixels
,
528 const uint8_t *palette
)
530 for (int i
= 0; i
< num_pixels
; i
++) {
531 const uint8_t *rgba
= &palette
[src
[i
] * 4];
540 static int bswap_16bpc(SwsInternal
*c
, const uint8_t *const src
[],
541 const int srcStride
[], int srcSliceY
, int srcSliceH
,
542 uint8_t *const dst
[], const int dstStride
[])
546 for (p
= 0; p
< 4; p
++) {
547 int srcstr
= srcStride
[p
] / 2;
548 int dststr
= dstStride
[p
] / 2;
549 uint16_t *dstPtr
= (uint16_t *) dst
[p
];
550 const uint16_t *srcPtr
= (const uint16_t *) src
[p
];
551 int min_stride
= FFMIN(FFABS(srcstr
), FFABS(dststr
));
552 if(!dstPtr
|| !srcPtr
)
554 dstPtr
+= (srcSliceY
>> c
->chrDstVSubSample
) * dststr
;
555 for (i
= 0; i
< (srcSliceH
>> c
->chrDstVSubSample
); i
++) {
556 for (j
= 0; j
< min_stride
; j
++) {
557 dstPtr
[j
] = av_bswap16(srcPtr
[j
]);
567 static int bswap_32bpc(SwsInternal
*c
, const uint8_t *const src
[],
568 const int srcStride
[], int srcSliceY
, int srcSliceH
,
569 uint8_t *const dst
[], const int dstStride
[])
573 for (p
= 0; p
< 4; p
++) {
574 int srcstr
= srcStride
[p
] / 4;
575 int dststr
= dstStride
[p
] / 4;
576 uint32_t *dstPtr
= (uint32_t *) dst
[p
];
577 const uint32_t *srcPtr
= (const uint32_t *) src
[p
];
578 int min_stride
= FFMIN(FFABS(srcstr
), FFABS(dststr
));
579 if(!dstPtr
|| !srcPtr
)
581 dstPtr
+= (srcSliceY
>> c
->chrDstVSubSample
) * dststr
;
582 for (i
= 0; i
< (srcSliceH
>> c
->chrDstVSubSample
); i
++) {
583 for (j
= 0; j
< min_stride
; j
++) {
584 dstPtr
[j
] = av_bswap32(srcPtr
[j
]);
595 static int palToRgbWrapper(SwsInternal
*c
, const uint8_t *const src
[], const int srcStride
[],
596 int srcSliceY
, int srcSliceH
, uint8_t *const dst
[],
597 const int dstStride
[])
599 const enum AVPixelFormat srcFormat
= c
->opts
.src_format
;
600 const enum AVPixelFormat dstFormat
= c
->opts
.dst_format
;
601 void (*conv
)(const uint8_t *src
, uint8_t *dst
, int num_pixels
,
602 const uint8_t *palette
) = NULL
;
604 uint8_t *dstPtr
= dst
[0] + dstStride
[0] * srcSliceY
;
605 const uint8_t *srcPtr
= src
[0];
607 if (srcFormat
== AV_PIX_FMT_YA8
) {
609 case AV_PIX_FMT_RGB32
: conv
= gray8aToPacked32
; break;
610 case AV_PIX_FMT_BGR32
: conv
= gray8aToPacked32
; break;
611 case AV_PIX_FMT_BGR32_1
: conv
= gray8aToPacked32_1
; break;
612 case AV_PIX_FMT_RGB32_1
: conv
= gray8aToPacked32_1
; break;
613 case AV_PIX_FMT_RGB24
: conv
= gray8aToPacked24
; break;
614 case AV_PIX_FMT_BGR24
: conv
= gray8aToPacked24
; break;
616 } else if (usePal(srcFormat
)) {
618 case AV_PIX_FMT_RGB32
: conv
= sws_convertPalette8ToPacked32
; break;
619 case AV_PIX_FMT_BGR32
: conv
= sws_convertPalette8ToPacked32
; break;
620 case AV_PIX_FMT_BGR32_1
: conv
= sws_convertPalette8ToPacked32
; break;
621 case AV_PIX_FMT_RGB32_1
: conv
= sws_convertPalette8ToPacked32
; break;
622 case AV_PIX_FMT_RGB24
: conv
= sws_convertPalette8ToPacked24
; break;
623 case AV_PIX_FMT_BGR24
: conv
= sws_convertPalette8ToPacked24
; break;
628 av_log(c
, AV_LOG_ERROR
, "internal error %s -> %s converter\n",
629 av_get_pix_fmt_name(srcFormat
), av_get_pix_fmt_name(dstFormat
));
631 for (i
= 0; i
< srcSliceH
; i
++) {
632 conv(srcPtr
, dstPtr
, c
->opts
.src_w
, (uint8_t *) c
->pal_rgb
);
633 srcPtr
+= srcStride
[0];
634 dstPtr
+= dstStride
[0];
641 static int palToGbrpWrapper(SwsInternal
*c
, const uint8_t *const src
[],
642 const int srcStride
[], int srcSliceY
, int srcSliceH
,
643 uint8_t *const dst
[], const int dstStride
[])
645 const enum AVPixelFormat srcFormat
= c
->opts
.src_format
;
646 const enum AVPixelFormat dstFormat
= c
->opts
.dst_format
;
647 void (*conv
)(const uint8_t *src
, uint8_t *dstG
, uint8_t *dstB
, uint8_t *dstR
,
648 uint8_t *dstA
, int num_pixels
, const uint8_t *palette
) = NULL
;
650 const int num_planes
= isALPHA(dstFormat
) ? 4 : 3;
651 const uint8_t *srcPtr
= src
[0];
652 uint8_t *dstPtr
[4] = {0};
653 for (int i
= 0; i
< num_planes
; i
++)
654 dstPtr
[i
] = dst
[i
] + dstStride
[i
] * srcSliceY
;
656 if (srcFormat
== AV_PIX_FMT_YA8
) {
658 case AV_PIX_FMT_GBRP
: conv
= gray8aToPlanar8
; break;
659 case AV_PIX_FMT_GBRAP
: conv
= gray8aToPlanar8
; break;
661 } else if (usePal(srcFormat
)) {
663 case AV_PIX_FMT_GBRP
: conv
= pal8ToPlanar8
; break;
664 case AV_PIX_FMT_GBRAP
: conv
= pal8ToPlanar8
; break;
669 for (int y
= 0; y
< srcSliceH
; y
++) {
670 conv(srcPtr
, dstPtr
[0], dstPtr
[1], dstPtr
[2], dstPtr
[3], c
->opts
.src_w
,
671 (uint8_t *) c
->pal_rgb
);
672 srcPtr
+= srcStride
[0];
673 for (int i
= 0; i
< num_planes
; i
++)
674 dstPtr
[i
] += dstStride
[i
];
680 static void packed16togbra16(const uint8_t *src
, int srcStride
,
681 uint16_t *dst
[], const int dstStride
[], int srcSliceH
,
682 int src_alpha
, int swap
, int shift
, int width
)
685 int dst_alpha
= dst
[3] != NULL
;
686 for (h
= 0; h
< srcSliceH
; h
++) {
687 uint16_t *src_line
= (uint16_t *)(src
+ srcStride
* h
);
690 if (src_alpha
&& dst_alpha
) {
691 for (x
= 0; x
< width
; x
++) {
692 dst
[0][x
] = av_bswap16(av_bswap16(*src_line
++) >> shift
);
693 dst
[1][x
] = av_bswap16(av_bswap16(*src_line
++) >> shift
);
694 dst
[2][x
] = av_bswap16(av_bswap16(*src_line
++) >> shift
);
695 dst
[3][x
] = av_bswap16(av_bswap16(*src_line
++) >> shift
);
697 } else if (dst_alpha
) {
698 for (x
= 0; x
< width
; x
++) {
699 dst
[0][x
] = av_bswap16(av_bswap16(*src_line
++) >> shift
);
700 dst
[1][x
] = av_bswap16(av_bswap16(*src_line
++) >> shift
);
701 dst
[2][x
] = av_bswap16(av_bswap16(*src_line
++) >> shift
);
704 } else if (src_alpha
) {
705 for (x
= 0; x
< width
; x
++) {
706 dst
[0][x
] = av_bswap16(av_bswap16(*src_line
++) >> shift
);
707 dst
[1][x
] = av_bswap16(av_bswap16(*src_line
++) >> shift
);
708 dst
[2][x
] = av_bswap16(av_bswap16(*src_line
++) >> shift
);
712 for (x
= 0; x
< width
; x
++) {
713 dst
[0][x
] = av_bswap16(av_bswap16(*src_line
++) >> shift
);
714 dst
[1][x
] = av_bswap16(av_bswap16(*src_line
++) >> shift
);
715 dst
[2][x
] = av_bswap16(av_bswap16(*src_line
++) >> shift
);
720 if (src_alpha
&& dst_alpha
) {
721 for (x
= 0; x
< width
; x
++) {
722 dst
[0][x
] = av_bswap16(*src_line
++ >> shift
);
723 dst
[1][x
] = av_bswap16(*src_line
++ >> shift
);
724 dst
[2][x
] = av_bswap16(*src_line
++ >> shift
);
725 dst
[3][x
] = av_bswap16(*src_line
++ >> shift
);
727 } else if (dst_alpha
) {
728 for (x
= 0; x
< width
; x
++) {
729 dst
[0][x
] = av_bswap16(*src_line
++ >> shift
);
730 dst
[1][x
] = av_bswap16(*src_line
++ >> shift
);
731 dst
[2][x
] = av_bswap16(*src_line
++ >> shift
);
734 } else if (src_alpha
) {
735 for (x
= 0; x
< width
; x
++) {
736 dst
[0][x
] = av_bswap16(*src_line
++ >> shift
);
737 dst
[1][x
] = av_bswap16(*src_line
++ >> shift
);
738 dst
[2][x
] = av_bswap16(*src_line
++ >> shift
);
742 for (x
= 0; x
< width
; x
++) {
743 dst
[0][x
] = av_bswap16(*src_line
++ >> shift
);
744 dst
[1][x
] = av_bswap16(*src_line
++ >> shift
);
745 dst
[2][x
] = av_bswap16(*src_line
++ >> shift
);
750 if (src_alpha
&& dst_alpha
) {
751 for (x
= 0; x
< width
; x
++) {
752 dst
[0][x
] = av_bswap16(*src_line
++) >> shift
;
753 dst
[1][x
] = av_bswap16(*src_line
++) >> shift
;
754 dst
[2][x
] = av_bswap16(*src_line
++) >> shift
;
755 dst
[3][x
] = av_bswap16(*src_line
++) >> shift
;
757 } else if (dst_alpha
) {
758 for (x
= 0; x
< width
; x
++) {
759 dst
[0][x
] = av_bswap16(*src_line
++) >> shift
;
760 dst
[1][x
] = av_bswap16(*src_line
++) >> shift
;
761 dst
[2][x
] = av_bswap16(*src_line
++) >> shift
;
764 } else if (src_alpha
) {
765 for (x
= 0; x
< width
; x
++) {
766 dst
[0][x
] = av_bswap16(*src_line
++) >> shift
;
767 dst
[1][x
] = av_bswap16(*src_line
++) >> shift
;
768 dst
[2][x
] = av_bswap16(*src_line
++) >> shift
;
772 for (x
= 0; x
< width
; x
++) {
773 dst
[0][x
] = av_bswap16(*src_line
++) >> shift
;
774 dst
[1][x
] = av_bswap16(*src_line
++) >> shift
;
775 dst
[2][x
] = av_bswap16(*src_line
++) >> shift
;
780 if (src_alpha
&& dst_alpha
) {
781 for (x
= 0; x
< width
; x
++) {
782 dst
[0][x
] = *src_line
++ >> shift
;
783 dst
[1][x
] = *src_line
++ >> shift
;
784 dst
[2][x
] = *src_line
++ >> shift
;
785 dst
[3][x
] = *src_line
++ >> shift
;
787 } else if (dst_alpha
) {
788 for (x
= 0; x
< width
; x
++) {
789 dst
[0][x
] = *src_line
++ >> shift
;
790 dst
[1][x
] = *src_line
++ >> shift
;
791 dst
[2][x
] = *src_line
++ >> shift
;
794 } else if (src_alpha
) {
795 for (x
= 0; x
< width
; x
++) {
796 dst
[0][x
] = *src_line
++ >> shift
;
797 dst
[1][x
] = *src_line
++ >> shift
;
798 dst
[2][x
] = *src_line
++ >> shift
;
802 for (x
= 0; x
< width
; x
++) {
803 dst
[0][x
] = *src_line
++ >> shift
;
804 dst
[1][x
] = *src_line
++ >> shift
;
805 dst
[2][x
] = *src_line
++ >> shift
;
809 for (i
= 0; i
< 4; i
++)
810 dst
[i
] += dstStride
[i
] >> 1;
814 static void packed30togbra10(const uint8_t *src
, int srcStride
,
815 uint16_t *dst
[], const int dstStride
[], int srcSliceH
,
816 int swap
, int bpc
, int width
)
819 int dst_alpha
= dst
[3] != NULL
;
820 int scale_high
= bpc
- 10, scale_low
= 10 - scale_high
;
821 for (h
= 0; h
< srcSliceH
; h
++) {
822 uint32_t *src_line
= (uint32_t *)(src
+ srcStride
* h
);
829 for (x
= 0; x
< width
; x
++) {
830 unsigned p
= AV_RL32(src_line
);
831 component
= (p
>> 20) & 0x3FF;
832 dst
[0][x
] = av_bswap16(component
<< scale_high
| component
>> scale_low
);
833 component
= (p
>> 10) & 0x3FF;
834 dst
[1][x
] = av_bswap16(component
<< scale_high
| component
>> scale_low
);
835 component
= p
& 0x3FF;
836 dst
[2][x
] = av_bswap16(component
<< scale_high
| component
>> scale_low
);
841 for (x
= 0; x
< width
; x
++) {
842 unsigned p
= AV_RL32(src_line
);
843 component
= (p
>> 20) & 0x3FF;
844 dst
[0][x
] = av_bswap16(component
<< scale_high
| component
>> scale_low
);
845 component
= (p
>> 10) & 0x3FF;
846 dst
[1][x
] = av_bswap16(component
<< scale_high
| component
>> scale_low
);
847 component
= p
& 0x3FF;
848 dst
[2][x
] = av_bswap16(component
<< scale_high
| component
>> scale_low
);
855 for (x
= 0; x
< width
; x
++) {
856 unsigned p
= AV_RL32(src_line
);
857 component
= (p
>> 20) & 0x3FF;
858 dst
[0][x
] = component
<< scale_high
| component
>> scale_low
;
859 component
= (p
>> 10) & 0x3FF;
860 dst
[1][x
] = component
<< scale_high
| component
>> scale_low
;
861 component
= p
& 0x3FF;
862 dst
[2][x
] = component
<< scale_high
| component
>> scale_low
;
867 for (x
= 0; x
< width
; x
++) {
868 unsigned p
= AV_RL32(src_line
);
869 component
= (p
>> 20) & 0x3FF;
870 dst
[0][x
] = component
<< scale_high
| component
>> scale_low
;
871 component
= (p
>> 10) & 0x3FF;
872 dst
[1][x
] = component
<< scale_high
| component
>> scale_low
;
873 component
= p
& 0x3FF;
874 dst
[2][x
] = component
<< scale_high
| component
>> scale_low
;
880 for (i
= 0; i
< 4; i
++)
881 dst
[i
] += dstStride
[i
] >> 1;
885 static int Rgb16ToPlanarRgb16Wrapper(SwsInternal
*c
, const uint8_t *const src
[],
886 const int srcStride
[], int srcSliceY
, int srcSliceH
,
887 uint8_t *const dst
[], const int dstStride
[])
889 uint16_t *dst2013
[] = { (uint16_t *)dst
[2], (uint16_t *)dst
[0], (uint16_t *)dst
[1], (uint16_t *)dst
[3] };
890 uint16_t *dst1023
[] = { (uint16_t *)dst
[1], (uint16_t *)dst
[0], (uint16_t *)dst
[2], (uint16_t *)dst
[3] };
891 int stride2013
[] = { dstStride
[2], dstStride
[0], dstStride
[1], dstStride
[3] };
892 int stride1023
[] = { dstStride
[1], dstStride
[0], dstStride
[2], dstStride
[3] };
893 const AVPixFmtDescriptor
*src_format
= av_pix_fmt_desc_get(c
->opts
.src_format
);
894 const AVPixFmtDescriptor
*dst_format
= av_pix_fmt_desc_get(c
->opts
.dst_format
);
895 int bpc
= dst_format
->comp
[0].depth
;
896 int alpha
= src_format
->flags
& AV_PIX_FMT_FLAG_ALPHA
;
900 if ( HAVE_BIGENDIAN
&& !(src_format
->flags
& AV_PIX_FMT_FLAG_BE
) ||
901 !HAVE_BIGENDIAN
&& src_format
->flags
& AV_PIX_FMT_FLAG_BE
)
903 if ( HAVE_BIGENDIAN
&& !(dst_format
->flags
& AV_PIX_FMT_FLAG_BE
) ||
904 !HAVE_BIGENDIAN
&& dst_format
->flags
& AV_PIX_FMT_FLAG_BE
)
907 if ((dst_format
->flags
& (AV_PIX_FMT_FLAG_PLANAR
| AV_PIX_FMT_FLAG_RGB
)) !=
908 (AV_PIX_FMT_FLAG_PLANAR
| AV_PIX_FMT_FLAG_RGB
) || bpc
< 9) {
909 av_log(c
, AV_LOG_ERROR
, "unsupported conversion to planar RGB %s -> %s\n",
910 src_format
->name
, dst_format
->name
);
915 dst2013
[i
] += stride2013
[i
] * srcSliceY
/ 2;
916 dst1023
[i
] += stride1023
[i
] * srcSliceY
/ 2;
919 switch (c
->opts
.src_format
) {
920 case AV_PIX_FMT_RGB48LE
:
921 case AV_PIX_FMT_RGB48BE
:
922 case AV_PIX_FMT_RGBA64LE
:
923 case AV_PIX_FMT_RGBA64BE
:
924 packed16togbra16(src
[0], srcStride
[0],
925 dst2013
, stride2013
, srcSliceH
, alpha
, swap
,
926 16 - bpc
, c
->opts
.src_w
);
928 case AV_PIX_FMT_X2RGB10LE
:
929 av_assert0(bpc
>= 10);
930 packed30togbra10(src
[0], srcStride
[0],
931 dst2013
, stride2013
, srcSliceH
, swap
,
934 case AV_PIX_FMT_BGR48LE
:
935 case AV_PIX_FMT_BGR48BE
:
936 case AV_PIX_FMT_BGRA64LE
:
937 case AV_PIX_FMT_BGRA64BE
:
938 packed16togbra16(src
[0], srcStride
[0],
939 dst1023
, stride1023
, srcSliceH
, alpha
, swap
,
940 16 - bpc
, c
->opts
.src_w
);
942 case AV_PIX_FMT_X2BGR10LE
:
943 av_assert0(bpc
>= 10);
944 packed30togbra10(src
[0], srcStride
[0],
945 dst1023
, stride1023
, srcSliceH
, swap
,
949 av_log(c
, AV_LOG_ERROR
,
950 "unsupported conversion to planar RGB %s -> %s\n",
951 src_format
->name
, dst_format
->name
);
957 static void gbr16ptopacked16(const uint16_t *src
[], const int srcStride
[],
958 uint8_t *dst
, int dstStride
, int srcSliceH
,
959 int alpha
, int swap
, int bpp
, int width
)
962 int src_alpha
= src
[3] != NULL
;
963 int scale_high
= 16 - bpp
, scale_low
= (bpp
- 8) * 2;
964 for (h
= 0; h
< srcSliceH
; h
++) {
965 uint16_t *dest
= (uint16_t *)(dst
+ dstStride
* h
);
970 if (alpha
&& !src_alpha
) {
971 for (x
= 0; x
< width
; x
++) {
972 component
= av_bswap16(src
[0][x
]);
973 *dest
++ = av_bswap16(component
<< scale_high
| component
>> scale_low
);
974 component
= av_bswap16(src
[1][x
]);
975 *dest
++ = av_bswap16(component
<< scale_high
| component
>> scale_low
);
976 component
= av_bswap16(src
[2][x
]);
977 *dest
++ = av_bswap16(component
<< scale_high
| component
>> scale_low
);
980 } else if (alpha
&& src_alpha
) {
981 for (x
= 0; x
< width
; x
++) {
982 component
= av_bswap16(src
[0][x
]);
983 *dest
++ = av_bswap16(component
<< scale_high
| component
>> scale_low
);
984 component
= av_bswap16(src
[1][x
]);
985 *dest
++ = av_bswap16(component
<< scale_high
| component
>> scale_low
);
986 component
= av_bswap16(src
[2][x
]);
987 *dest
++ = av_bswap16(component
<< scale_high
| component
>> scale_low
);
988 component
= av_bswap16(src
[3][x
]);
989 *dest
++ = av_bswap16(component
<< scale_high
| component
>> scale_low
);
992 for (x
= 0; x
< width
; x
++) {
993 component
= av_bswap16(src
[0][x
]);
994 *dest
++ = av_bswap16(component
<< scale_high
| component
>> scale_low
);
995 component
= av_bswap16(src
[1][x
]);
996 *dest
++ = av_bswap16(component
<< scale_high
| component
>> scale_low
);
997 component
= av_bswap16(src
[2][x
]);
998 *dest
++ = av_bswap16(component
<< scale_high
| component
>> scale_low
);
1003 if (alpha
&& !src_alpha
) {
1004 for (x
= 0; x
< width
; x
++) {
1005 *dest
++ = av_bswap16(src
[0][x
] << scale_high
| src
[0][x
] >> scale_low
);
1006 *dest
++ = av_bswap16(src
[1][x
] << scale_high
| src
[1][x
] >> scale_low
);
1007 *dest
++ = av_bswap16(src
[2][x
] << scale_high
| src
[2][x
] >> scale_low
);
1010 } else if (alpha
&& src_alpha
) {
1011 for (x
= 0; x
< width
; x
++) {
1012 *dest
++ = av_bswap16(src
[0][x
] << scale_high
| src
[0][x
] >> scale_low
);
1013 *dest
++ = av_bswap16(src
[1][x
] << scale_high
| src
[1][x
] >> scale_low
);
1014 *dest
++ = av_bswap16(src
[2][x
] << scale_high
| src
[2][x
] >> scale_low
);
1015 *dest
++ = av_bswap16(src
[3][x
] << scale_high
| src
[3][x
] >> scale_low
);
1018 for (x
= 0; x
< width
; x
++) {
1019 *dest
++ = av_bswap16(src
[0][x
] << scale_high
| src
[0][x
] >> scale_low
);
1020 *dest
++ = av_bswap16(src
[1][x
] << scale_high
| src
[1][x
] >> scale_low
);
1021 *dest
++ = av_bswap16(src
[2][x
] << scale_high
| src
[2][x
] >> scale_low
);
1026 if (alpha
&& !src_alpha
) {
1027 for (x
= 0; x
< width
; x
++) {
1028 *dest
++ = av_bswap16(src
[0][x
]) << scale_high
| av_bswap16(src
[0][x
]) >> scale_low
;
1029 *dest
++ = av_bswap16(src
[1][x
]) << scale_high
| av_bswap16(src
[1][x
]) >> scale_low
;
1030 *dest
++ = av_bswap16(src
[2][x
]) << scale_high
| av_bswap16(src
[2][x
]) >> scale_low
;
1033 } else if (alpha
&& src_alpha
) {
1034 for (x
= 0; x
< width
; x
++) {
1035 *dest
++ = av_bswap16(src
[0][x
]) << scale_high
| av_bswap16(src
[0][x
]) >> scale_low
;
1036 *dest
++ = av_bswap16(src
[1][x
]) << scale_high
| av_bswap16(src
[1][x
]) >> scale_low
;
1037 *dest
++ = av_bswap16(src
[2][x
]) << scale_high
| av_bswap16(src
[2][x
]) >> scale_low
;
1038 *dest
++ = av_bswap16(src
[3][x
]) << scale_high
| av_bswap16(src
[3][x
]) >> scale_low
;
1041 for (x
= 0; x
< width
; x
++) {
1042 *dest
++ = av_bswap16(src
[0][x
]) << scale_high
| av_bswap16(src
[0][x
]) >> scale_low
;
1043 *dest
++ = av_bswap16(src
[1][x
]) << scale_high
| av_bswap16(src
[1][x
]) >> scale_low
;
1044 *dest
++ = av_bswap16(src
[2][x
]) << scale_high
| av_bswap16(src
[2][x
]) >> scale_low
;
1049 if (alpha
&& !src_alpha
) {
1050 for (x
= 0; x
< width
; x
++) {
1051 *dest
++ = src
[0][x
] << scale_high
| src
[0][x
] >> scale_low
;
1052 *dest
++ = src
[1][x
] << scale_high
| src
[1][x
] >> scale_low
;
1053 *dest
++ = src
[2][x
] << scale_high
| src
[2][x
] >> scale_low
;
1056 } else if (alpha
&& src_alpha
) {
1057 for (x
= 0; x
< width
; x
++) {
1058 *dest
++ = src
[0][x
] << scale_high
| src
[0][x
] >> scale_low
;
1059 *dest
++ = src
[1][x
] << scale_high
| src
[1][x
] >> scale_low
;
1060 *dest
++ = src
[2][x
] << scale_high
| src
[2][x
] >> scale_low
;
1061 *dest
++ = src
[3][x
] << scale_high
| src
[3][x
] >> scale_low
;
1064 for (x
= 0; x
< width
; x
++) {
1065 *dest
++ = src
[0][x
] << scale_high
| src
[0][x
] >> scale_low
;
1066 *dest
++ = src
[1][x
] << scale_high
| src
[1][x
] >> scale_low
;
1067 *dest
++ = src
[2][x
] << scale_high
| src
[2][x
] >> scale_low
;
1071 for (i
= 0; i
< 3 + src_alpha
; i
++)
1072 src
[i
] += srcStride
[i
] >> 1;
1076 static void gbr16ptopacked30(const uint16_t *src
[], const int srcStride
[],
1077 uint8_t *dst
, int dstStride
, int srcSliceH
,
1078 int swap
, int bpp
, int width
)
1081 int shift
= bpp
- 10;
1082 av_assert0(bpp
>= 0);
1083 for (h
= 0; h
< srcSliceH
; h
++) {
1084 uint8_t *dest
= dst
+ dstStride
* h
;
1089 for (x
= 0; x
< width
; x
++) {
1090 unsigned C0
= av_bswap16(src
[0][x
]) >> shift
;
1091 unsigned C1
= av_bswap16(src
[1][x
]) >> shift
;
1092 unsigned C2
= av_bswap16(src
[2][x
]) >> shift
;
1093 AV_WL32(dest
+ 4 * x
, (3U << 30) + (C0
<< 20) + (C1
<< 10) + C2
);
1097 for (x
= 0; x
< width
; x
++) {
1098 unsigned C0
= src
[0][x
] >> shift
;
1099 unsigned C1
= src
[1][x
] >> shift
;
1100 unsigned C2
= src
[2][x
] >> shift
;
1101 AV_WL32(dest
+ 4 * x
, (3U << 30) + (C0
<< 20) + (C1
<< 10) + C2
);
1105 for (i
= 0; i
< 3; i
++)
1106 src
[i
] += srcStride
[i
] >> 1;
1111 static int planarRgb16ToRgb16Wrapper(SwsInternal
*c
, const uint8_t *const src
[],
1112 const int srcStride
[], int srcSliceY
, int srcSliceH
,
1113 uint8_t *const dst
[], const int dstStride
[])
1115 const uint16_t *src102
[] = { (uint16_t *)src
[1], (uint16_t *)src
[0], (uint16_t *)src
[2], (uint16_t *)src
[3] };
1116 const uint16_t *src201
[] = { (uint16_t *)src
[2], (uint16_t *)src
[0], (uint16_t *)src
[1], (uint16_t *)src
[3] };
1117 int stride102
[] = { srcStride
[1], srcStride
[0], srcStride
[2], srcStride
[3] };
1118 int stride201
[] = { srcStride
[2], srcStride
[0], srcStride
[1], srcStride
[3] };
1119 const AVPixFmtDescriptor
*src_format
= av_pix_fmt_desc_get(c
->opts
.src_format
);
1120 const AVPixFmtDescriptor
*dst_format
= av_pix_fmt_desc_get(c
->opts
.dst_format
);
1121 int bits_per_sample
= src_format
->comp
[0].depth
;
1123 if ( HAVE_BIGENDIAN
&& !(src_format
->flags
& AV_PIX_FMT_FLAG_BE
) ||
1124 !HAVE_BIGENDIAN
&& src_format
->flags
& AV_PIX_FMT_FLAG_BE
)
1126 if ( HAVE_BIGENDIAN
&& !(dst_format
->flags
& AV_PIX_FMT_FLAG_BE
) ||
1127 !HAVE_BIGENDIAN
&& dst_format
->flags
& AV_PIX_FMT_FLAG_BE
)
1130 if ((src_format
->flags
& (AV_PIX_FMT_FLAG_PLANAR
| AV_PIX_FMT_FLAG_RGB
)) !=
1131 (AV_PIX_FMT_FLAG_PLANAR
| AV_PIX_FMT_FLAG_RGB
) ||
1132 bits_per_sample
<= 8) {
1133 av_log(c
, AV_LOG_ERROR
, "unsupported planar RGB conversion %s -> %s\n",
1134 src_format
->name
, dst_format
->name
);
1137 switch (c
->opts
.dst_format
) {
1138 case AV_PIX_FMT_BGR48LE
:
1139 case AV_PIX_FMT_BGR48BE
:
1140 gbr16ptopacked16(src102
, stride102
,
1141 dst
[0] + srcSliceY
* dstStride
[0], dstStride
[0],
1142 srcSliceH
, 0, swap
, bits_per_sample
, c
->opts
.src_w
);
1144 case AV_PIX_FMT_RGB48LE
:
1145 case AV_PIX_FMT_RGB48BE
:
1146 gbr16ptopacked16(src201
, stride201
,
1147 dst
[0] + srcSliceY
* dstStride
[0], dstStride
[0],
1148 srcSliceH
, 0, swap
, bits_per_sample
, c
->opts
.src_w
);
1150 case AV_PIX_FMT_RGBA64LE
:
1151 case AV_PIX_FMT_RGBA64BE
:
1152 gbr16ptopacked16(src201
, stride201
,
1153 dst
[0] + srcSliceY
* dstStride
[0], dstStride
[0],
1154 srcSliceH
, 1, swap
, bits_per_sample
, c
->opts
.src_w
);
1156 case AV_PIX_FMT_BGRA64LE
:
1157 case AV_PIX_FMT_BGRA64BE
:
1158 gbr16ptopacked16(src102
, stride102
,
1159 dst
[0] + srcSliceY
* dstStride
[0], dstStride
[0],
1160 srcSliceH
, 1, swap
, bits_per_sample
, c
->opts
.src_w
);
1162 case AV_PIX_FMT_X2RGB10LE
:
1163 gbr16ptopacked30(src201
, stride201
,
1164 dst
[0] + srcSliceY
* dstStride
[0], dstStride
[0],
1165 srcSliceH
, swap
, bits_per_sample
, c
->opts
.src_w
);
1167 case AV_PIX_FMT_X2BGR10LE
:
1168 gbr16ptopacked30(src102
, stride102
,
1169 dst
[0] + srcSliceY
* dstStride
[0], dstStride
[0],
1170 srcSliceH
, swap
, bits_per_sample
, c
->opts
.src_w
);
1173 av_log(c
, AV_LOG_ERROR
,
1174 "unsupported planar RGB conversion %s -> %s\n",
1175 src_format
->name
, dst_format
->name
);
1181 static void gbr24ptopacked24(const uint8_t *src
[], const int srcStride
[],
1182 uint8_t *dst
, int dstStride
, int srcSliceH
,
1186 for (h
= 0; h
< srcSliceH
; h
++) {
1187 uint8_t *dest
= dst
+ dstStride
* h
;
1188 for (x
= 0; x
< width
; x
++) {
1189 *dest
++ = src
[0][x
];
1190 *dest
++ = src
[1][x
];
1191 *dest
++ = src
[2][x
];
1194 for (i
= 0; i
< 3; i
++)
1195 src
[i
] += srcStride
[i
];
1199 static void gbr24ptopacked32(const uint8_t *src
[], const int srcStride
[],
1200 uint8_t *dst
, int dstStride
, int srcSliceH
,
1201 int alpha_first
, int width
)
1204 for (h
= 0; h
< srcSliceH
; h
++) {
1205 uint8_t *dest
= dst
+ dstStride
* h
;
1208 for (x
= 0; x
< width
; x
++) {
1210 *dest
++ = src
[0][x
];
1211 *dest
++ = src
[1][x
];
1212 *dest
++ = src
[2][x
];
1215 for (x
= 0; x
< width
; x
++) {
1216 *dest
++ = src
[0][x
];
1217 *dest
++ = src
[1][x
];
1218 *dest
++ = src
[2][x
];
1223 for (i
= 0; i
< 3; i
++)
1224 src
[i
] += srcStride
[i
];
1228 static void gbraptopacked32(const uint8_t *src
[], const int srcStride
[],
1229 uint8_t *dst
, int dstStride
, int srcSliceH
,
1230 int alpha_first
, int width
)
1233 for (h
= 0; h
< srcSliceH
; h
++) {
1234 uint8_t *dest
= dst
+ dstStride
* h
;
1237 for (x
= 0; x
< width
; x
++) {
1238 *dest
++ = src
[3][x
];
1239 *dest
++ = src
[0][x
];
1240 *dest
++ = src
[1][x
];
1241 *dest
++ = src
[2][x
];
1244 for (x
= 0; x
< width
; x
++) {
1245 *dest
++ = src
[0][x
];
1246 *dest
++ = src
[1][x
];
1247 *dest
++ = src
[2][x
];
1248 *dest
++ = src
[3][x
];
1252 for (i
= 0; i
< 4; i
++)
1253 src
[i
] += srcStride
[i
];
1257 static int planarRgbaToRgbWrapper(SwsInternal
*c
, const uint8_t *const src
[],
1258 const int srcStride
[], int srcSliceY
, int srcSliceH
,
1259 uint8_t *const dst
[], const int dstStride
[])
1261 int alpha_first
= 0;
1262 const uint8_t *src102
[] = { src
[1], src
[0], src
[2], src
[3] };
1263 const uint8_t *src201
[] = { src
[2], src
[0], src
[1], src
[3] };
1264 int stride102
[] = { srcStride
[1], srcStride
[0], srcStride
[2], srcStride
[3] };
1265 int stride201
[] = { srcStride
[2], srcStride
[0], srcStride
[1], srcStride
[3] };
1267 if (c
->opts
.src_format
!= AV_PIX_FMT_GBRAP
) {
1268 av_log(c
, AV_LOG_ERROR
, "unsupported planar RGB conversion %s -> %s\n",
1269 av_get_pix_fmt_name(c
->opts
.src_format
),
1270 av_get_pix_fmt_name(c
->opts
.dst_format
));
1274 switch (c
->opts
.dst_format
) {
1275 case AV_PIX_FMT_BGR24
:
1276 gbr24ptopacked24(src102
, stride102
,
1277 dst
[0] + srcSliceY
* dstStride
[0], dstStride
[0],
1278 srcSliceH
, c
->opts
.src_w
);
1281 case AV_PIX_FMT_RGB24
:
1282 gbr24ptopacked24(src201
, stride201
,
1283 dst
[0] + srcSliceY
* dstStride
[0], dstStride
[0],
1284 srcSliceH
, c
->opts
.src_w
);
1287 case AV_PIX_FMT_ARGB
:
1289 case AV_PIX_FMT_RGBA
:
1290 gbraptopacked32(src201
, stride201
,
1291 dst
[0] + srcSliceY
* dstStride
[0], dstStride
[0],
1292 srcSliceH
, alpha_first
, c
->opts
.src_w
);
1295 case AV_PIX_FMT_ABGR
:
1297 case AV_PIX_FMT_BGRA
:
1298 gbraptopacked32(src102
, stride102
,
1299 dst
[0] + srcSliceY
* dstStride
[0], dstStride
[0],
1300 srcSliceH
, alpha_first
, c
->opts
.src_w
);
1304 av_log(c
, AV_LOG_ERROR
,
1305 "unsupported planar RGB conversion %s -> %s\n",
1306 av_get_pix_fmt_name(c
->opts
.src_format
),
1307 av_get_pix_fmt_name(c
->opts
.dst_format
));
1313 static int planarRgbToRgbWrapper(SwsInternal
*c
, const uint8_t *const src
[],
1314 const int srcStride
[], int srcSliceY
, int srcSliceH
,
1315 uint8_t *const dst
[], const int dstStride
[])
1317 int alpha_first
= 0;
1318 const uint8_t *src102
[] = { src
[1], src
[0], src
[2] };
1319 const uint8_t *src201
[] = { src
[2], src
[0], src
[1] };
1320 int stride102
[] = { srcStride
[1], srcStride
[0], srcStride
[2] };
1321 int stride201
[] = { srcStride
[2], srcStride
[0], srcStride
[1] };
1323 if (c
->opts
.src_format
!= AV_PIX_FMT_GBRP
) {
1324 av_log(c
, AV_LOG_ERROR
, "unsupported planar RGB conversion %s -> %s\n",
1325 av_get_pix_fmt_name(c
->opts
.src_format
),
1326 av_get_pix_fmt_name(c
->opts
.dst_format
));
1330 switch (c
->opts
.dst_format
) {
1331 case AV_PIX_FMT_BGR24
:
1332 gbr24ptopacked24(src102
, stride102
,
1333 dst
[0] + srcSliceY
* dstStride
[0], dstStride
[0],
1334 srcSliceH
, c
->opts
.src_w
);
1337 case AV_PIX_FMT_RGB24
:
1338 gbr24ptopacked24(src201
, stride201
,
1339 dst
[0] + srcSliceY
* dstStride
[0], dstStride
[0],
1340 srcSliceH
, c
->opts
.src_w
);
1343 case AV_PIX_FMT_ARGB
:
1345 case AV_PIX_FMT_RGBA
:
1346 gbr24ptopacked32(src201
, stride201
,
1347 dst
[0] + srcSliceY
* dstStride
[0], dstStride
[0],
1348 srcSliceH
, alpha_first
, c
->opts
.src_w
);
1351 case AV_PIX_FMT_ABGR
:
1353 case AV_PIX_FMT_BGRA
:
1354 gbr24ptopacked32(src102
, stride102
,
1355 dst
[0] + srcSliceY
* dstStride
[0], dstStride
[0],
1356 srcSliceH
, alpha_first
, c
->opts
.src_w
);
1360 av_log(c
, AV_LOG_ERROR
,
1361 "unsupported planar RGB conversion %s -> %s\n",
1362 av_get_pix_fmt_name(c
->opts
.src_format
),
1363 av_get_pix_fmt_name(c
->opts
.dst_format
));
1369 static int planarRgbToplanarRgbWrapper(SwsInternal
*c
,
1370 const uint8_t *const src
[], const int srcStride
[],
1371 int srcSliceY
, int srcSliceH
,
1372 uint8_t *const dst
[], const int dstStride
[])
1374 ff_copyPlane(src
[0], srcStride
[0], srcSliceY
, srcSliceH
, c
->opts
.src_w
,
1375 dst
[0], dstStride
[0]);
1376 ff_copyPlane(src
[1], srcStride
[1], srcSliceY
, srcSliceH
, c
->opts
.src_w
,
1377 dst
[1], dstStride
[1]);
1378 ff_copyPlane(src
[2], srcStride
[2], srcSliceY
, srcSliceH
, c
->opts
.src_w
,
1379 dst
[2], dstStride
[2]);
1381 fillPlane(dst
[3], dstStride
[3], c
->opts
.src_w
, srcSliceH
, srcSliceY
, 255);
1386 static void packedtogbr24p(const uint8_t *src
, int srcStride
,
1387 uint8_t *const dst
[], const int dstStride
[], int srcSliceH
,
1388 int alpha_first
, int inc_size
, int width
)
1400 for (h
= 0; h
< srcSliceH
; h
++) {
1401 for (x
= 0; x
< width
; x
++) {
1402 dest
[0][x
] = src
[0];
1403 dest
[1][x
] = src
[1];
1404 dest
[2][x
] = src
[2];
1408 src
+= srcStride
- width
* inc_size
;
1409 dest
[0] += dstStride
[0];
1410 dest
[1] += dstStride
[1];
1411 dest
[2] += dstStride
[2];
1415 static int rgbToPlanarRgbWrapper(SwsInternal
*c
, const uint8_t *const src
[],
1416 const int srcStride
[], int srcSliceY
, int srcSliceH
,
1417 uint8_t *const dst
[], const int dstStride
[])
1419 int alpha_first
= 0;
1420 int stride102
[] = { dstStride
[1], dstStride
[0], dstStride
[2] };
1421 int stride201
[] = { dstStride
[2], dstStride
[0], dstStride
[1] };
1422 uint8_t *dst102
[] = { dst
[1] + srcSliceY
* dstStride
[1],
1423 dst
[0] + srcSliceY
* dstStride
[0],
1424 dst
[2] + srcSliceY
* dstStride
[2] };
1425 uint8_t *dst201
[] = { dst
[2] + srcSliceY
* dstStride
[2],
1426 dst
[0] + srcSliceY
* dstStride
[0],
1427 dst
[1] + srcSliceY
* dstStride
[1] };
1429 switch (c
->opts
.src_format
) {
1430 case AV_PIX_FMT_RGB24
:
1431 packedtogbr24p((const uint8_t *) src
[0], srcStride
[0], dst201
,
1432 stride201
, srcSliceH
, alpha_first
, 3, c
->opts
.src_w
);
1434 case AV_PIX_FMT_BGR24
:
1435 packedtogbr24p((const uint8_t *) src
[0], srcStride
[0], dst102
,
1436 stride102
, srcSliceH
, alpha_first
, 3, c
->opts
.src_w
);
1438 case AV_PIX_FMT_ARGB
:
1440 case AV_PIX_FMT_RGBA
:
1441 packedtogbr24p((const uint8_t *) src
[0], srcStride
[0], dst201
,
1442 stride201
, srcSliceH
, alpha_first
, 4, c
->opts
.src_w
);
1444 case AV_PIX_FMT_ABGR
:
1446 case AV_PIX_FMT_BGRA
:
1447 packedtogbr24p((const uint8_t *) src
[0], srcStride
[0], dst102
,
1448 stride102
, srcSliceH
, alpha_first
, 4, c
->opts
.src_w
);
1451 av_log(c
, AV_LOG_ERROR
,
1452 "unsupported planar RGB conversion %s -> %s\n",
1453 av_get_pix_fmt_name(c
->opts
.src_format
),
1454 av_get_pix_fmt_name(c
->opts
.dst_format
));
1460 static void packed24togbrap(const uint8_t *src
, int srcStride
,
1461 uint8_t *const dst
[], const int dstStride
[],
1462 int srcSliceH
, int width
)
1472 for (h
= 0; h
< srcSliceH
; h
++) {
1473 for (x
= 0; x
< width
; x
++) {
1474 dest
[0][x
] = src
[x
* 3 + 0];
1475 dest
[1][x
] = src
[x
* 3 + 1];
1476 dest
[2][x
] = src
[x
* 3 + 2];
1480 dest
[0] += dstStride
[0];
1481 dest
[1] += dstStride
[1];
1482 dest
[2] += dstStride
[2];
1483 dest
[3] += dstStride
[3];
1487 static void packed32togbrap(const uint8_t *src
, int srcStride
,
1488 uint8_t *const dst
[], const int dstStride
[],
1489 int srcSliceH
, int alpha_first
, int width
)
1499 for (h
= 0; h
< srcSliceH
; h
++) {
1501 for (x
= 0; x
< width
; x
++) {
1502 dest
[0][x
] = src
[x
* 4 + 1];
1503 dest
[1][x
] = src
[x
* 4 + 2];
1504 dest
[2][x
] = src
[x
* 4 + 3];
1505 dest
[3][x
] = src
[x
* 4 + 0];
1508 for (x
= 0; x
< width
; x
++) {
1509 dest
[0][x
] = src
[x
* 4 + 0];
1510 dest
[1][x
] = src
[x
* 4 + 1];
1511 dest
[2][x
] = src
[x
* 4 + 2];
1512 dest
[3][x
] = src
[x
* 4 + 3];
1516 dest
[0] += dstStride
[0];
1517 dest
[1] += dstStride
[1];
1518 dest
[2] += dstStride
[2];
1519 dest
[3] += dstStride
[3];
1523 static int rgbToPlanarRgbaWrapper(SwsInternal
*c
, const uint8_t *const src
[],
1524 const int srcStride
[], int srcSliceY
, int srcSliceH
,
1525 uint8_t *const dst
[], const int dstStride
[])
1527 int alpha_first
= 0;
1528 int stride102
[] = { dstStride
[1], dstStride
[0], dstStride
[2], dstStride
[3] };
1529 int stride201
[] = { dstStride
[2], dstStride
[0], dstStride
[1], dstStride
[3] };
1530 uint8_t *dst102
[] = { dst
[1] + srcSliceY
* dstStride
[1],
1531 dst
[0] + srcSliceY
* dstStride
[0],
1532 dst
[2] + srcSliceY
* dstStride
[2],
1533 dst
[3] + srcSliceY
* dstStride
[3] };
1534 uint8_t *dst201
[] = { dst
[2] + srcSliceY
* dstStride
[2],
1535 dst
[0] + srcSliceY
* dstStride
[0],
1536 dst
[1] + srcSliceY
* dstStride
[1],
1537 dst
[3] + srcSliceY
* dstStride
[3] };
1539 switch (c
->opts
.src_format
) {
1540 case AV_PIX_FMT_RGB24
:
1541 packed24togbrap((const uint8_t *) src
[0], srcStride
[0], dst201
,
1542 stride201
, srcSliceH
, c
->opts
.src_w
);
1544 case AV_PIX_FMT_BGR24
:
1545 packed24togbrap((const uint8_t *) src
[0], srcStride
[0], dst102
,
1546 stride102
, srcSliceH
, c
->opts
.src_w
);
1548 case AV_PIX_FMT_ARGB
:
1550 case AV_PIX_FMT_RGBA
:
1551 packed32togbrap((const uint8_t *) src
[0], srcStride
[0], dst201
,
1552 stride201
, srcSliceH
, alpha_first
, c
->opts
.src_w
);
1554 case AV_PIX_FMT_ABGR
:
1556 case AV_PIX_FMT_BGRA
:
1557 packed32togbrap((const uint8_t *) src
[0], srcStride
[0], dst102
,
1558 stride102
, srcSliceH
, alpha_first
, c
->opts
.src_w
);
1561 av_log(c
, AV_LOG_ERROR
,
1562 "unsupported planar RGB conversion %s -> %s\n",
1563 av_get_pix_fmt_name(c
->opts
.src_format
),
1564 av_get_pix_fmt_name(c
->opts
.dst_format
));
1572 #define BAYER_RENAME(x) bayer_gbrg8_to_##x
1573 #include "bayer_template.c"
1577 #define BAYER_RENAME(x) bayer_gbrg16le_to_##x
1578 #include "bayer_template.c"
1582 #define BAYER_RENAME(x) bayer_gbrg16be_to_##x
1583 #include "bayer_template.c"
1587 #define BAYER_RENAME(x) bayer_grbg8_to_##x
1588 #include "bayer_template.c"
1592 #define BAYER_RENAME(x) bayer_grbg16le_to_##x
1593 #include "bayer_template.c"
1597 #define BAYER_RENAME(x) bayer_grbg16be_to_##x
1598 #include "bayer_template.c"
1602 #define BAYER_RENAME(x) bayer_bggr8_to_##x
1603 #include "bayer_template.c"
1607 #define BAYER_RENAME(x) bayer_bggr16le_to_##x
1608 #include "bayer_template.c"
1612 #define BAYER_RENAME(x) bayer_bggr16be_to_##x
1613 #include "bayer_template.c"
1617 #define BAYER_RENAME(x) bayer_rggb8_to_##x
1618 #include "bayer_template.c"
1622 #define BAYER_RENAME(x) bayer_rggb16le_to_##x
1623 #include "bayer_template.c"
1627 #define BAYER_RENAME(x) bayer_rggb16be_to_##x
1628 #include "bayer_template.c"
1630 static int bayer_to_rgb24_wrapper(SwsInternal
*c
, const uint8_t *const src
[],
1631 const int srcStride
[], int srcSliceY
, int srcSliceH
,
1632 uint8_t *const dst
[], const int dstStride
[])
1634 uint8_t *dstPtr
= dst
[0] + srcSliceY
* dstStride
[0];
1635 const uint8_t *srcPtr
= src
[0];
1637 void (*copy
) (const uint8_t *src
, int src_stride
, uint8_t *dst
, int dst_stride
, int width
);
1638 void (*interpolate
)(const uint8_t *src
, int src_stride
, uint8_t *dst
, int dst_stride
, int width
);
1640 switch(c
->opts
.src_format
) {
1641 #define CASE(pixfmt, prefix) \
1642 case pixfmt: copy = bayer_##prefix##_to_rgb24_copy; \
1643 interpolate = bayer_##prefix##_to_rgb24_interpolate; \
1645 CASE(AV_PIX_FMT_BAYER_BGGR8
, bggr8
)
1646 CASE(AV_PIX_FMT_BAYER_BGGR16LE
, bggr16le
)
1647 CASE(AV_PIX_FMT_BAYER_BGGR16BE
, bggr16be
)
1648 CASE(AV_PIX_FMT_BAYER_RGGB8
, rggb8
)
1649 CASE(AV_PIX_FMT_BAYER_RGGB16LE
, rggb16le
)
1650 CASE(AV_PIX_FMT_BAYER_RGGB16BE
, rggb16be
)
1651 CASE(AV_PIX_FMT_BAYER_GBRG8
, gbrg8
)
1652 CASE(AV_PIX_FMT_BAYER_GBRG16LE
, gbrg16le
)
1653 CASE(AV_PIX_FMT_BAYER_GBRG16BE
, gbrg16be
)
1654 CASE(AV_PIX_FMT_BAYER_GRBG8
, grbg8
)
1655 CASE(AV_PIX_FMT_BAYER_GRBG16LE
, grbg16le
)
1656 CASE(AV_PIX_FMT_BAYER_GRBG16BE
, grbg16be
)
1661 av_assert0(srcSliceH
> 1);
1663 copy(srcPtr
, srcStride
[0], dstPtr
, dstStride
[0], c
->opts
.src_w
);
1664 srcPtr
+= 2 * srcStride
[0];
1665 dstPtr
+= 2 * dstStride
[0];
1667 for (i
= 2; i
< srcSliceH
- 2; i
+= 2) {
1668 interpolate(srcPtr
, srcStride
[0], dstPtr
, dstStride
[0], c
->opts
.src_w
);
1669 srcPtr
+= 2 * srcStride
[0];
1670 dstPtr
+= 2 * dstStride
[0];
1673 if (i
+ 1 == srcSliceH
) {
1674 copy(srcPtr
, -srcStride
[0], dstPtr
, -dstStride
[0], c
->opts
.src_w
);
1675 } else if (i
< srcSliceH
)
1676 copy(srcPtr
, srcStride
[0], dstPtr
, dstStride
[0], c
->opts
.src_w
);
1680 static int bayer_to_rgb48_wrapper(SwsInternal
*c
, const uint8_t *const src
[],
1681 const int srcStride
[], int srcSliceY
, int srcSliceH
,
1682 uint8_t *const dst
[], const int dstStride
[])
1684 uint8_t *dstPtr
= dst
[0] + srcSliceY
* dstStride
[0];
1685 const uint8_t *srcPtr
= src
[0];
1687 void (*copy
) (const uint8_t *src
, int src_stride
, uint8_t *dst
, int dst_stride
, int width
);
1688 void (*interpolate
)(const uint8_t *src
, int src_stride
, uint8_t *dst
, int dst_stride
, int width
);
1690 switch(c
->opts
.src_format
) {
1691 #define CASE(pixfmt, prefix) \
1692 case pixfmt: copy = bayer_##prefix##_to_rgb48_copy; \
1693 interpolate = bayer_##prefix##_to_rgb48_interpolate; \
1695 CASE(AV_PIX_FMT_BAYER_BGGR8
, bggr8
)
1696 CASE(AV_PIX_FMT_BAYER_BGGR16LE
, bggr16le
)
1697 CASE(AV_PIX_FMT_BAYER_BGGR16BE
, bggr16be
)
1698 CASE(AV_PIX_FMT_BAYER_RGGB8
, rggb8
)
1699 CASE(AV_PIX_FMT_BAYER_RGGB16LE
, rggb16le
)
1700 CASE(AV_PIX_FMT_BAYER_RGGB16BE
, rggb16be
)
1701 CASE(AV_PIX_FMT_BAYER_GBRG8
, gbrg8
)
1702 CASE(AV_PIX_FMT_BAYER_GBRG16LE
, gbrg16le
)
1703 CASE(AV_PIX_FMT_BAYER_GBRG16BE
, gbrg16be
)
1704 CASE(AV_PIX_FMT_BAYER_GRBG8
, grbg8
)
1705 CASE(AV_PIX_FMT_BAYER_GRBG16LE
, grbg16le
)
1706 CASE(AV_PIX_FMT_BAYER_GRBG16BE
, grbg16be
)
1711 av_assert0(srcSliceH
> 1);
1713 copy(srcPtr
, srcStride
[0], dstPtr
, dstStride
[0], c
->opts
.src_w
);
1714 srcPtr
+= 2 * srcStride
[0];
1715 dstPtr
+= 2 * dstStride
[0];
1717 for (i
= 2; i
< srcSliceH
- 2; i
+= 2) {
1718 interpolate(srcPtr
, srcStride
[0], dstPtr
, dstStride
[0], c
->opts
.src_w
);
1719 srcPtr
+= 2 * srcStride
[0];
1720 dstPtr
+= 2 * dstStride
[0];
1723 if (i
+ 1 == srcSliceH
) {
1724 copy(srcPtr
, -srcStride
[0], dstPtr
, -dstStride
[0], c
->opts
.src_w
);
1725 } else if (i
< srcSliceH
)
1726 copy(srcPtr
, srcStride
[0], dstPtr
, dstStride
[0], c
->opts
.src_w
);
1730 static int bayer_to_yv12_wrapper(SwsInternal
*c
, const uint8_t *const src
[],
1731 const int srcStride
[], int srcSliceY
, int srcSliceH
,
1732 uint8_t *const dst
[], const int dstStride
[])
1734 const uint8_t *srcPtr
= src
[0];
1735 uint8_t *dstY
= dst
[0] + srcSliceY
* dstStride
[0];
1736 uint8_t *dstU
= dst
[1] + srcSliceY
* dstStride
[1] / 2;
1737 uint8_t *dstV
= dst
[2] + srcSliceY
* dstStride
[2] / 2;
1739 void (*copy
) (const uint8_t *src
, int src_stride
, uint8_t *dstY
, uint8_t *dstU
, uint8_t *dstV
, int luma_stride
, int width
, const int32_t *rgb2yuv
);
1740 void (*interpolate
)(const uint8_t *src
, int src_stride
, uint8_t *dstY
, uint8_t *dstU
, uint8_t *dstV
, int luma_stride
, int width
, const int32_t *rgb2yuv
);
1742 switch(c
->opts
.src_format
) {
1743 #define CASE(pixfmt, prefix) \
1744 case pixfmt: copy = bayer_##prefix##_to_yv12_copy; \
1745 interpolate = bayer_##prefix##_to_yv12_interpolate; \
1747 CASE(AV_PIX_FMT_BAYER_BGGR8
, bggr8
)
1748 CASE(AV_PIX_FMT_BAYER_BGGR16LE
, bggr16le
)
1749 CASE(AV_PIX_FMT_BAYER_BGGR16BE
, bggr16be
)
1750 CASE(AV_PIX_FMT_BAYER_RGGB8
, rggb8
)
1751 CASE(AV_PIX_FMT_BAYER_RGGB16LE
, rggb16le
)
1752 CASE(AV_PIX_FMT_BAYER_RGGB16BE
, rggb16be
)
1753 CASE(AV_PIX_FMT_BAYER_GBRG8
, gbrg8
)
1754 CASE(AV_PIX_FMT_BAYER_GBRG16LE
, gbrg16le
)
1755 CASE(AV_PIX_FMT_BAYER_GBRG16BE
, gbrg16be
)
1756 CASE(AV_PIX_FMT_BAYER_GRBG8
, grbg8
)
1757 CASE(AV_PIX_FMT_BAYER_GRBG16LE
, grbg16le
)
1758 CASE(AV_PIX_FMT_BAYER_GRBG16BE
, grbg16be
)
1763 av_assert0(srcSliceH
> 1);
1765 copy(srcPtr
, srcStride
[0], dstY
, dstU
, dstV
, dstStride
[0], c
->opts
.src_w
, c
->input_rgb2yuv_table
);
1766 srcPtr
+= 2 * srcStride
[0];
1767 dstY
+= 2 * dstStride
[0];
1768 dstU
+= dstStride
[1];
1769 dstV
+= dstStride
[1];
1771 for (i
= 2; i
< srcSliceH
- 2; i
+= 2) {
1772 interpolate(srcPtr
, srcStride
[0], dstY
, dstU
, dstV
, dstStride
[0], c
->opts
.src_w
, c
->input_rgb2yuv_table
);
1773 srcPtr
+= 2 * srcStride
[0];
1774 dstY
+= 2 * dstStride
[0];
1775 dstU
+= dstStride
[1];
1776 dstV
+= dstStride
[1];
1779 if (i
+ 1 == srcSliceH
) {
1780 copy(srcPtr
, -srcStride
[0], dstY
, dstU
, dstV
, -dstStride
[0], c
->opts
.src_w
, c
->input_rgb2yuv_table
);
1781 } else if (i
< srcSliceH
)
1782 copy(srcPtr
, srcStride
[0], dstY
, dstU
, dstV
, dstStride
[0], c
->opts
.src_w
, c
->input_rgb2yuv_table
);
1786 #define isRGBA32(x) ( \
1787 (x) == AV_PIX_FMT_ARGB \
1788 || (x) == AV_PIX_FMT_RGBA \
1789 || (x) == AV_PIX_FMT_BGRA \
1790 || (x) == AV_PIX_FMT_ABGR \
1793 #define isRGBA64(x) ( \
1794 (x) == AV_PIX_FMT_RGBA64LE \
1795 || (x) == AV_PIX_FMT_RGBA64BE \
1796 || (x) == AV_PIX_FMT_BGRA64LE \
1797 || (x) == AV_PIX_FMT_BGRA64BE \
1800 #define isRGB48(x) ( \
1801 (x) == AV_PIX_FMT_RGB48LE \
1802 || (x) == AV_PIX_FMT_RGB48BE \
1803 || (x) == AV_PIX_FMT_BGR48LE \
1804 || (x) == AV_PIX_FMT_BGR48BE \
1807 #define isAYUV(x) ( \
1808 (x) == AV_PIX_FMT_AYUV \
1809 || (x) == AV_PIX_FMT_VUYA \
1810 || (x) == AV_PIX_FMT_VUYX \
1811 || (x) == AV_PIX_FMT_UYVA \
1814 #define isX2RGB(x) ( \
1815 (x) == AV_PIX_FMT_X2RGB10LE \
1816 || (x) == AV_PIX_FMT_X2BGR10LE \
1819 /* {RGB,BGR}{15,16,24,32,32_1} -> {RGB,BGR}{15,16,24,32} */
1820 typedef void (* rgbConvFn
) (const uint8_t *, uint8_t *, int);
1821 static rgbConvFn
findRgbConvFn(SwsInternal
*c
)
1823 const enum AVPixelFormat srcFormat
= c
->opts
.src_format
;
1824 const enum AVPixelFormat dstFormat
= c
->opts
.dst_format
;
1825 const int srcId
= c
->srcFormatBpp
;
1826 const int dstId
= c
->dstFormatBpp
;
1827 rgbConvFn conv
= NULL
;
1829 #define IS_NOT_NE(bpp, desc) \
1830 (((bpp + 7) >> 3) == 2 && \
1831 (!(desc->flags & AV_PIX_FMT_FLAG_BE) != !HAVE_BIGENDIAN))
1833 #define CONV_IS(src, dst) (srcFormat == AV_PIX_FMT_##src && dstFormat == AV_PIX_FMT_##dst)
1835 if (isRGBA32(srcFormat
) && isRGBA32(dstFormat
)) {
1836 if ( CONV_IS(ABGR
, RGBA
)
1837 || CONV_IS(ARGB
, BGRA
)
1838 || CONV_IS(BGRA
, ARGB
)
1839 || CONV_IS(RGBA
, ABGR
)) conv
= shuffle_bytes_3210
;
1840 else if (CONV_IS(ABGR
, ARGB
)
1841 || CONV_IS(ARGB
, ABGR
)) conv
= shuffle_bytes_0321
;
1842 else if (CONV_IS(ABGR
, BGRA
)
1843 || CONV_IS(ARGB
, RGBA
)) conv
= shuffle_bytes_1230
;
1844 else if (CONV_IS(BGRA
, RGBA
)
1845 || CONV_IS(RGBA
, BGRA
)) conv
= shuffle_bytes_2103
;
1846 else if (CONV_IS(BGRA
, ABGR
)
1847 || CONV_IS(RGBA
, ARGB
)) conv
= shuffle_bytes_3012
;
1848 } else if (isRGB48(srcFormat
) && isRGB48(dstFormat
)) {
1849 if (CONV_IS(RGB48LE
, BGR48LE
)
1850 || CONV_IS(BGR48LE
, RGB48LE
)
1851 || CONV_IS(RGB48BE
, BGR48BE
)
1852 || CONV_IS(BGR48BE
, RGB48BE
)) conv
= rgb48tobgr48_nobswap
;
1853 else if (CONV_IS(RGB48LE
, BGR48BE
)
1854 || CONV_IS(BGR48LE
, RGB48BE
)
1855 || CONV_IS(RGB48BE
, BGR48LE
)
1856 || CONV_IS(BGR48BE
, RGB48LE
)) conv
= rgb48tobgr48_bswap
;
1857 } else if (isRGB48(srcFormat
) && isRGBA64(dstFormat
)) {
1858 if (CONV_IS(RGB48LE
, BGRA64LE
)
1859 || CONV_IS(BGR48LE
, RGBA64LE
)
1860 || CONV_IS(RGB48BE
, BGRA64BE
)
1861 || CONV_IS(BGR48BE
, RGBA64BE
)) conv
= rgb48tobgr64_nobswap
;
1862 else if (CONV_IS(RGB48LE
, BGRA64BE
)
1863 || CONV_IS(BGR48LE
, RGBA64BE
)
1864 || CONV_IS(RGB48BE
, BGRA64LE
)
1865 || CONV_IS(BGR48BE
, RGBA64LE
)) conv
= rgb48tobgr64_bswap
;
1866 if (CONV_IS(RGB48LE
, RGBA64LE
)
1867 || CONV_IS(BGR48LE
, BGRA64LE
)
1868 || CONV_IS(RGB48BE
, RGBA64BE
)
1869 || CONV_IS(BGR48BE
, BGRA64BE
)) conv
= rgb48to64_nobswap
;
1870 else if (CONV_IS(RGB48LE
, RGBA64BE
)
1871 || CONV_IS(BGR48LE
, BGRA64BE
)
1872 || CONV_IS(RGB48BE
, RGBA64LE
)
1873 || CONV_IS(BGR48BE
, BGRA64LE
)) conv
= rgb48to64_bswap
;
1874 } else if (isRGBA64(srcFormat
) && isRGB48(dstFormat
)) {
1875 if (CONV_IS(RGBA64LE
, BGR48LE
)
1876 || CONV_IS(BGRA64LE
, RGB48LE
)
1877 || CONV_IS(RGBA64BE
, BGR48BE
)
1878 || CONV_IS(BGRA64BE
, RGB48BE
)) conv
= rgb64tobgr48_nobswap
;
1879 else if (CONV_IS(RGBA64LE
, BGR48BE
)
1880 || CONV_IS(BGRA64LE
, RGB48BE
)
1881 || CONV_IS(RGBA64BE
, BGR48LE
)
1882 || CONV_IS(BGRA64BE
, RGB48LE
)) conv
= rgb64tobgr48_bswap
;
1883 else if (CONV_IS(RGBA64LE
, RGB48LE
)
1884 || CONV_IS(BGRA64LE
, BGR48LE
)
1885 || CONV_IS(RGBA64BE
, RGB48BE
)
1886 || CONV_IS(BGRA64BE
, BGR48BE
)) conv
= rgb64to48_nobswap
;
1887 else if (CONV_IS(RGBA64LE
, RGB48BE
)
1888 || CONV_IS(BGRA64LE
, BGR48BE
)
1889 || CONV_IS(RGBA64BE
, RGB48LE
)
1890 || CONV_IS(BGRA64BE
, BGR48LE
)) conv
= rgb64to48_bswap
;
1891 } else if (isX2RGB(srcFormat
) && isRGB48(dstFormat
)) {
1892 if (CONV_IS(X2RGB10LE
, RGB48LE
)
1893 || CONV_IS(X2BGR10LE
, BGR48LE
)) conv
= HAVE_BIGENDIAN
? x2rgb10to48_bswap
1894 : x2rgb10to48_nobswap
;
1895 else if (CONV_IS(X2RGB10LE
, RGB48BE
)
1896 || CONV_IS(X2BGR10LE
, BGR48BE
)) conv
= HAVE_BIGENDIAN
? x2rgb10to48_nobswap
1897 : x2rgb10to48_bswap
;
1898 else if (CONV_IS(X2RGB10LE
, BGR48LE
)
1899 || CONV_IS(X2BGR10LE
, RGB48LE
)) conv
= HAVE_BIGENDIAN
? x2rgb10tobgr48_bswap
1900 : x2rgb10tobgr48_nobswap
;
1901 else if (CONV_IS(X2RGB10LE
, BGR48BE
)
1902 || CONV_IS(X2BGR10LE
, RGB48BE
)) conv
= HAVE_BIGENDIAN
? x2rgb10tobgr48_nobswap
1903 : x2rgb10tobgr48_bswap
;
1904 else if (CONV_IS(X2RGB10LE
, RGBA64LE
)
1905 || CONV_IS(X2BGR10LE
, BGRA64LE
)) conv
= HAVE_BIGENDIAN
? x2rgb10to64_bswap
1906 : x2rgb10to64_nobswap
;
1907 else if (CONV_IS(X2RGB10LE
, RGBA64BE
)
1908 || CONV_IS(X2BGR10LE
, BGRA64BE
)) conv
= HAVE_BIGENDIAN
? x2rgb10to64_nobswap
1909 : x2rgb10to64_bswap
;
1910 else if (CONV_IS(X2RGB10LE
, BGRA64LE
)
1911 || CONV_IS(X2BGR10LE
, RGBA64LE
)) conv
= HAVE_BIGENDIAN
? x2rgb10tobgr64_bswap
1912 : x2rgb10tobgr64_nobswap
;
1913 else if (CONV_IS(X2RGB10LE
, BGRA64BE
)
1914 || CONV_IS(X2BGR10LE
, RGBA64BE
)) conv
= HAVE_BIGENDIAN
? x2rgb10tobgr64_nobswap
1915 : x2rgb10tobgr64_bswap
;
1916 } else if (isAYUV(srcFormat
) && isAYUV(dstFormat
)) {
1917 /* VUYX only for dst, to avoid copying undefined bytes */
1918 if ( CONV_IS(AYUV
, VUYA
)
1919 || CONV_IS(AYUV
, VUYX
)
1920 || CONV_IS(VUYA
, AYUV
)) conv
= shuffle_bytes_3210
;
1921 else if (CONV_IS(AYUV
, UYVA
)) conv
= shuffle_bytes_2130
;
1922 else if (CONV_IS(VUYA
, UYVA
)) conv
= shuffle_bytes_1203
;
1923 else if (CONV_IS(UYVA
, AYUV
)) conv
= shuffle_bytes_3102
;
1924 else if (CONV_IS(UYVA
, VUYA
)
1925 || CONV_IS(UYVA
, VUYX
)) conv
= shuffle_bytes_2013
;
1928 if ((isBGRinInt(srcFormat
) && isBGRinInt(dstFormat
)) ||
1929 (isRGBinInt(srcFormat
) && isRGBinInt(dstFormat
))) {
1930 switch (srcId
| (dstId
<< 16)) {
1931 case 0x000F000C: conv
= rgb12to15
; break;
1932 case 0x000F0010: conv
= rgb16to15
; break;
1933 case 0x000F0018: conv
= rgb24to15
; break;
1934 case 0x000F0020: conv
= rgb32to15
; break;
1935 case 0x0010000F: conv
= rgb15to16
; break;
1936 case 0x00100018: conv
= rgb24to16
; break;
1937 case 0x00100020: conv
= rgb32to16
; break;
1938 case 0x0018000F: conv
= rgb15to24
; break;
1939 case 0x00180010: conv
= rgb16to24
; break;
1940 case 0x00180020: conv
= rgb32to24
; break;
1941 case 0x0020000F: conv
= rgb15to32
; break;
1942 case 0x00200010: conv
= rgb16to32
; break;
1943 case 0x00200018: conv
= rgb24to32
; break;
1945 } else if ((isBGRinInt(srcFormat
) && isRGBinInt(dstFormat
)) ||
1946 (isRGBinInt(srcFormat
) && isBGRinInt(dstFormat
))) {
1947 switch (srcId
| (dstId
<< 16)) {
1948 case 0x000C000C: conv
= rgb12tobgr12
; break;
1949 case 0x000F000F: conv
= rgb15tobgr15
; break;
1950 case 0x000F0010: conv
= rgb16tobgr15
; break;
1951 case 0x000F0018: conv
= rgb24tobgr15
; break;
1952 case 0x000F0020: conv
= rgb32tobgr15
; break;
1953 case 0x0010000F: conv
= rgb15tobgr16
; break;
1954 case 0x00100010: conv
= rgb16tobgr16
; break;
1955 case 0x00100018: conv
= rgb24tobgr16
; break;
1956 case 0x00100020: conv
= rgb32tobgr16
; break;
1957 case 0x0018000F: conv
= rgb15tobgr24
; break;
1958 case 0x00180010: conv
= rgb16tobgr24
; break;
1959 case 0x00180018: conv
= rgb24tobgr24
; break;
1960 case 0x00180020: conv
= rgb32tobgr24
; break;
1961 case 0x0020000F: conv
= rgb15tobgr32
; break;
1962 case 0x00200010: conv
= rgb16tobgr32
; break;
1963 case 0x00200018: conv
= rgb24tobgr32
; break;
1967 if ((dstFormat
== AV_PIX_FMT_RGB32_1
|| dstFormat
== AV_PIX_FMT_BGR32_1
) && !isRGBA32(srcFormat
) && ALT32_CORR
<0)
1970 // Maintain symmetry between endianness
1971 if (c
->opts
.flags
& SWS_BITEXACT
)
1972 if ((dstFormat
== AV_PIX_FMT_RGB32
|| dstFormat
== AV_PIX_FMT_BGR32
) && !isRGBA32(srcFormat
) && ALT32_CORR
>0)
1978 /* {RGB,BGR}{15,16,24,32,32_1} -> {RGB,BGR}{15,16,24,32} */
1979 static int rgbToRgbWrapper(SwsInternal
*c
, const uint8_t *const src
[], const int srcStride
[],
1980 int srcSliceY
, int srcSliceH
, uint8_t *const dst
[],
1981 const int dstStride
[])
1984 const enum AVPixelFormat srcFormat
= c
->opts
.src_format
;
1985 const enum AVPixelFormat dstFormat
= c
->opts
.dst_format
;
1986 const AVPixFmtDescriptor
*desc_src
= av_pix_fmt_desc_get(c
->opts
.src_format
);
1987 const AVPixFmtDescriptor
*desc_dst
= av_pix_fmt_desc_get(c
->opts
.dst_format
);
1988 const int srcBpp
= (c
->srcFormatBpp
+ 7) >> 3;
1989 const int dstBpp
= (c
->dstFormatBpp
+ 7) >> 3;
1990 rgbConvFn conv
= findRgbConvFn(c
);
1993 av_log(c
, AV_LOG_ERROR
, "internal error %s -> %s converter\n",
1994 av_get_pix_fmt_name(srcFormat
), av_get_pix_fmt_name(dstFormat
));
1996 const uint8_t *srcPtr
= src
[0];
1997 uint8_t *dstPtr
= dst
[0];
1998 int src_bswap
= IS_NOT_NE(c
->srcFormatBpp
, desc_src
);
1999 int dst_bswap
= IS_NOT_NE(c
->dstFormatBpp
, desc_dst
);
2001 if ((srcFormat
== AV_PIX_FMT_RGB32_1
|| srcFormat
== AV_PIX_FMT_BGR32_1
) &&
2002 !isRGBA32(dstFormat
))
2003 srcPtr
+= ALT32_CORR
;
2005 if ((dstFormat
== AV_PIX_FMT_RGB32_1
|| dstFormat
== AV_PIX_FMT_BGR32_1
) &&
2006 !isRGBA32(srcFormat
)) {
2008 av_assert0(ALT32_CORR
== 1);
2009 for (i
= 0; i
< srcSliceH
; i
++)
2010 dstPtr
[dstStride
[0] * (srcSliceY
+ i
)] = 255;
2011 dstPtr
+= ALT32_CORR
;
2014 if (dstStride
[0] * srcBpp
== srcStride
[0] * dstBpp
&& srcStride
[0] > 0 &&
2015 !(srcStride
[0] % srcBpp
) && !dst_bswap
&& !src_bswap
)
2016 conv(srcPtr
, dstPtr
+ dstStride
[0] * srcSliceY
,
2017 (srcSliceH
- 1) * srcStride
[0] + c
->opts
.src_w
* srcBpp
);
2020 dstPtr
+= dstStride
[0] * srcSliceY
;
2022 for (i
= 0; i
< srcSliceH
; i
++) {
2024 for(j
=0; j
<c
->opts
.src_w
; j
++)
2025 ((uint16_t*)c
->formatConvBuffer
)[j
] = av_bswap16(((uint16_t*)srcPtr
)[j
]);
2026 conv(c
->formatConvBuffer
, dstPtr
, c
->opts
.src_w
* srcBpp
);
2028 conv(srcPtr
, dstPtr
, c
->opts
.src_w
* srcBpp
);
2030 for(j
=0; j
<c
->opts
.src_w
; j
++)
2031 ((uint16_t*)dstPtr
)[j
] = av_bswap16(((uint16_t*)dstPtr
)[j
]);
2032 srcPtr
+= srcStride
[0];
2033 dstPtr
+= dstStride
[0];
2040 static int bgr24ToYv12Wrapper(SwsInternal
*c
, const uint8_t *const src
[],
2041 const int srcStride
[], int srcSliceY
, int srcSliceH
,
2042 uint8_t *const dst
[], const int dstStride
[])
2046 dst
[0] + srcSliceY
* dstStride
[0],
2047 dst
[1] + (srcSliceY
>> 1) * dstStride
[1],
2048 dst
[2] + (srcSliceY
>> 1) * dstStride
[2],
2049 c
->opts
.src_w
, srcSliceH
,
2050 dstStride
[0], dstStride
[1], srcStride
[0],
2051 c
->input_rgb2yuv_table
);
2053 fillPlane(dst
[3], dstStride
[3], c
->opts
.src_w
, srcSliceH
, srcSliceY
, 255);
2057 static int yvu9ToYv12Wrapper(SwsInternal
*c
, const uint8_t *const src
[],
2058 const int srcStride
[], int srcSliceY
, int srcSliceH
,
2059 uint8_t *const dst
[], const int dstStride
[])
2061 ff_copyPlane(src
[0], srcStride
[0], srcSliceY
, srcSliceH
, c
->opts
.src_w
,
2062 dst
[0], dstStride
[0]);
2064 planar2x(src
[1], dst
[1] + dstStride
[1] * (srcSliceY
>> 1), c
->chrSrcW
,
2065 srcSliceH
>> 2, srcStride
[1], dstStride
[1]);
2066 planar2x(src
[2], dst
[2] + dstStride
[2] * (srcSliceY
>> 1), c
->chrSrcW
,
2067 srcSliceH
>> 2, srcStride
[2], dstStride
[2]);
2069 fillPlane(dst
[3], dstStride
[3], c
->opts
.src_w
, srcSliceH
, srcSliceY
, 255);
2073 static int uint_y_to_float_y_wrapper(SwsInternal
*c
, const uint8_t *const src
[],
2074 const int srcStride
[], int srcSliceY
,
2075 int srcSliceH
, uint8_t *const dst
[], const int dstStride
[])
2078 ptrdiff_t dstStrideFloat
= dstStride
[0] >> 2;
2079 const uint8_t *srcPtr
= src
[0];
2080 float *dstPtr
= (float *)(dst
[0] + dstStride
[0] * srcSliceY
);
2082 for (y
= 0; y
< srcSliceH
; ++y
){
2083 for (x
= 0; x
< c
->opts
.src_w
; ++x
){
2084 dstPtr
[x
] = c
->uint2float_lut
[srcPtr
[x
]];
2086 srcPtr
+= srcStride
[0];
2087 dstPtr
+= dstStrideFloat
;
2093 static int float_y_to_uint_y_wrapper(SwsInternal
*c
,
2094 const uint8_t *const src
[],
2095 const int srcStride
[], int srcSliceY
,
2096 int srcSliceH
, uint8_t *const dst
[],
2097 const int dstStride
[])
2100 ptrdiff_t srcStrideFloat
= srcStride
[0] >> 2;
2101 const float *srcPtr
= (const float *)src
[0];
2102 uint8_t *dstPtr
= dst
[0] + dstStride
[0] * srcSliceY
;
2104 for (y
= 0; y
< srcSliceH
; ++y
){
2105 for (x
= 0; x
< c
->opts
.src_w
; ++x
){
2106 dstPtr
[x
] = av_clip_uint8(lrintf(255.0f
* srcPtr
[x
]));
2108 srcPtr
+= srcStrideFloat
;
2109 dstPtr
+= dstStride
[0];
2115 /* unscaled copy like stuff (assumes nearly identical formats) */
2116 static int packedCopyWrapper(SwsInternal
*c
, const uint8_t *const src
[],
2117 const int srcStride
[], int srcSliceY
, int srcSliceH
,
2118 uint8_t *const dst
[], const int dstStride
[])
2120 if (dstStride
[0] == srcStride
[0] && srcStride
[0] > 0)
2121 memcpy(dst
[0] + dstStride
[0] * srcSliceY
, src
[0], srcSliceH
* dstStride
[0]);
2124 const uint8_t *srcPtr
= src
[0];
2125 uint8_t *dstPtr
= dst
[0] + dstStride
[0] * srcSliceY
;
2128 /* universal length finder */
2129 while (length
+ c
->opts
.src_w
<= FFABS(dstStride
[0]) &&
2130 length
+ c
->opts
.src_w
<= FFABS(srcStride
[0]))
2131 length
+= c
->opts
.src_w
;
2132 av_assert1(length
!= 0);
2134 for (i
= 0; i
< srcSliceH
; i
++) {
2135 memcpy(dstPtr
, srcPtr
, length
);
2136 srcPtr
+= srcStride
[0];
2137 dstPtr
+= dstStride
[0];
2143 #define DITHER_COPY(dst, dstStride, src, srcStride, bswap, dbswap)\
2144 unsigned shift= src_depth-dst_depth, tmp;\
2145 unsigned bias = 1 << (shift - 1);\
2146 if (c->opts.dither == SWS_DITHER_NONE) {\
2147 for (i = 0; i < height; i++) {\
2148 for (j = 0; j < length-7; j+=8) {\
2149 tmp = (bswap(src[j+0]) + bias)>>shift; dst[j+0] = dbswap(tmp - (tmp>>dst_depth));\
2150 tmp = (bswap(src[j+1]) + bias)>>shift; dst[j+1] = dbswap(tmp - (tmp>>dst_depth));\
2151 tmp = (bswap(src[j+2]) + bias)>>shift; dst[j+2] = dbswap(tmp - (tmp>>dst_depth));\
2152 tmp = (bswap(src[j+3]) + bias)>>shift; dst[j+3] = dbswap(tmp - (tmp>>dst_depth));\
2153 tmp = (bswap(src[j+4]) + bias)>>shift; dst[j+4] = dbswap(tmp - (tmp>>dst_depth));\
2154 tmp = (bswap(src[j+5]) + bias)>>shift; dst[j+5] = dbswap(tmp - (tmp>>dst_depth));\
2155 tmp = (bswap(src[j+6]) + bias)>>shift; dst[j+6] = dbswap(tmp - (tmp>>dst_depth));\
2156 tmp = (bswap(src[j+7]) + bias)>>shift; dst[j+7] = dbswap(tmp - (tmp>>dst_depth));\
2158 for (; j < length; j++) {\
2159 tmp = (bswap(src[j]) + bias)>>shift; dst[j] = dbswap(tmp - (tmp>>dst_depth));\
2164 } else if (shiftonly) {\
2165 for (i = 0; i < height; i++) {\
2166 const uint8_t *dither= dithers[shift-1][i&7];\
2167 for (j = 0; j < length-7; j+=8) {\
2168 tmp = (bswap(src[j+0]) + dither[0])>>shift; dst[j+0] = dbswap(tmp - (tmp>>dst_depth));\
2169 tmp = (bswap(src[j+1]) + dither[1])>>shift; dst[j+1] = dbswap(tmp - (tmp>>dst_depth));\
2170 tmp = (bswap(src[j+2]) + dither[2])>>shift; dst[j+2] = dbswap(tmp - (tmp>>dst_depth));\
2171 tmp = (bswap(src[j+3]) + dither[3])>>shift; dst[j+3] = dbswap(tmp - (tmp>>dst_depth));\
2172 tmp = (bswap(src[j+4]) + dither[4])>>shift; dst[j+4] = dbswap(tmp - (tmp>>dst_depth));\
2173 tmp = (bswap(src[j+5]) + dither[5])>>shift; dst[j+5] = dbswap(tmp - (tmp>>dst_depth));\
2174 tmp = (bswap(src[j+6]) + dither[6])>>shift; dst[j+6] = dbswap(tmp - (tmp>>dst_depth));\
2175 tmp = (bswap(src[j+7]) + dither[7])>>shift; dst[j+7] = dbswap(tmp - (tmp>>dst_depth));\
2177 for (; j < length; j++) {\
2178 tmp = (bswap(src[j]) + dither[j&7])>>shift; dst[j] = dbswap(tmp - (tmp>>dst_depth));\
2184 for (i = 0; i < height; i++) {\
2185 const uint8_t *dither= dithers[shift-1][i&7];\
2186 for (j = 0; j < length-7; j+=8) {\
2187 tmp = bswap(src[j+0]); dst[j+0] = dbswap((tmp - (tmp>>dst_depth) + dither[0])>>shift);\
2188 tmp = bswap(src[j+1]); dst[j+1] = dbswap((tmp - (tmp>>dst_depth) + dither[1])>>shift);\
2189 tmp = bswap(src[j+2]); dst[j+2] = dbswap((tmp - (tmp>>dst_depth) + dither[2])>>shift);\
2190 tmp = bswap(src[j+3]); dst[j+3] = dbswap((tmp - (tmp>>dst_depth) + dither[3])>>shift);\
2191 tmp = bswap(src[j+4]); dst[j+4] = dbswap((tmp - (tmp>>dst_depth) + dither[4])>>shift);\
2192 tmp = bswap(src[j+5]); dst[j+5] = dbswap((tmp - (tmp>>dst_depth) + dither[5])>>shift);\
2193 tmp = bswap(src[j+6]); dst[j+6] = dbswap((tmp - (tmp>>dst_depth) + dither[6])>>shift);\
2194 tmp = bswap(src[j+7]); dst[j+7] = dbswap((tmp - (tmp>>dst_depth) + dither[7])>>shift);\
2196 for (; j < length; j++) {\
2197 tmp = bswap(src[j]); dst[j] = dbswap((tmp - (tmp>>dst_depth) + dither[j&7])>>shift);\
2204 static int planarCopyWrapper(SwsInternal
*c
, const uint8_t *const src
[],
2205 const int srcStride
[], int srcSliceY
, int srcSliceH
,
2206 uint8_t *const dst
[], const int dstStride
[])
2208 const AVPixFmtDescriptor
*desc_src
= av_pix_fmt_desc_get(c
->opts
.src_format
);
2209 const AVPixFmtDescriptor
*desc_dst
= av_pix_fmt_desc_get(c
->opts
.dst_format
);
2211 for (plane
= 0; plane
< 4 && dst
[plane
] != NULL
; plane
++) {
2212 int length
= (plane
== 0 || plane
== 3) ? c
->opts
.src_w
: AV_CEIL_RSHIFT(c
->opts
.src_w
, c
->chrDstHSubSample
);
2213 int y
= (plane
== 0 || plane
== 3) ? srcSliceY
: AV_CEIL_RSHIFT(srcSliceY
, c
->chrDstVSubSample
);
2214 int height
= (plane
== 0 || plane
== 3) ? srcSliceH
: AV_CEIL_RSHIFT(srcSliceH
, c
->chrDstVSubSample
);
2215 const uint8_t *srcPtr
= src
[plane
];
2216 uint8_t *dstPtr
= dst
[plane
] + dstStride
[plane
] * y
;
2217 int shiftonly
= plane
== 1 || plane
== 2 || (!c
->opts
.src_range
&& plane
== 0);
2218 if (plane
== 1 && isSemiPlanarYUV(c
->opts
.dst_format
))
2221 // ignore palette for GRAY8
2222 if (plane
== 1 && desc_dst
->nb_components
< 3) continue;
2223 if (!src
[plane
] || (plane
== 1 && desc_src
->nb_components
< 3)) {
2224 if (is16BPS(c
->opts
.dst_format
) || isNBPS(c
->opts
.dst_format
)) {
2225 fillPlane16(dst
[plane
], dstStride
[plane
], length
, height
, y
,
2226 plane
== 3, desc_dst
->comp
[plane
].depth
,
2227 isBE(c
->opts
.dst_format
));
2229 fillPlane(dst
[plane
], dstStride
[plane
], length
, height
, y
,
2230 (plane
== 3) ? 255 : 128);
2233 if(isNBPS(c
->opts
.src_format
) || isNBPS(c
->opts
.dst_format
)
2234 || (is16BPS(c
->opts
.src_format
) != is16BPS(c
->opts
.dst_format
))
2236 const int src_depth
= desc_src
->comp
[plane
].depth
;
2237 const int dst_depth
= desc_dst
->comp
[plane
].depth
;
2238 const uint16_t *srcPtr2
= (const uint16_t *) srcPtr
;
2239 uint16_t *dstPtr2
= (uint16_t*)dstPtr
;
2241 if (dst_depth
== 8) {
2242 av_assert1(src_depth
> 8);
2243 if(isBE(c
->opts
.src_format
) == HAVE_BIGENDIAN
){
2244 DITHER_COPY(dstPtr
, dstStride
[plane
], srcPtr2
, srcStride
[plane
]/2, , )
2246 DITHER_COPY(dstPtr
, dstStride
[plane
], srcPtr2
, srcStride
[plane
]/2, av_bswap16
, )
2248 } else if (src_depth
== 8) {
2249 for (i
= 0; i
< height
; i
++) {
2252 for (j = 0; j < length; j++)\
2253 w(&dstPtr2[j], srcPtr[j]<<(dst_depth-8));\
2255 for (j = 0; j < length; j++)\
2256 w(&dstPtr2[j], (srcPtr[j]<<(dst_depth-8)) |\
2257 (srcPtr[j]>>(2*8-dst_depth)));\
2259 if(isBE(c
->opts
.dst_format
)){
2264 dstPtr2
+= dstStride
[plane
]/2;
2265 srcPtr
+= srcStride
[plane
];
2267 } else if (src_depth
<= dst_depth
) {
2268 for (i
= 0; i
< height
; i
++) {
2270 if(isBE(c
->opts
.src_format
) == HAVE_BIGENDIAN
&&
2271 isBE(c
->opts
.dst_format
) == HAVE_BIGENDIAN
&&
2273 unsigned shift
= dst_depth
- src_depth
;
2275 #define FAST_COPY_UP(shift) \
2276 for (; j < length - 3; j += 4) { \
2277 uint64_t v = AV_RN64A(srcPtr2 + j); \
2278 AV_WN64A(dstPtr2 + j, v << shift); \
2281 #define FAST_COPY_UP(shift) \
2282 for (; j < length - 1; j += 2) { \
2283 uint32_t v = AV_RN32A(srcPtr2 + j); \
2284 AV_WN32A(dstPtr2 + j, v << shift); \
2289 case 6: FAST_COPY_UP(6); break;
2290 case 7: FAST_COPY_UP(7); break;
2293 #define COPY_UP(r,w) \
2295 for (; j < length; j++){ \
2296 unsigned int v= r(&srcPtr2[j]);\
2297 w(&dstPtr2[j], v<<(dst_depth-src_depth));\
2300 for (; j < length; j++){ \
2301 unsigned int v= r(&srcPtr2[j]);\
2302 w(&dstPtr2[j], (v<<(dst_depth-src_depth)) | \
2303 (v>>(2*src_depth-dst_depth)));\
2306 if(isBE(c
->opts
.src_format
)){
2307 if(isBE(c
->opts
.dst_format
)){
2308 COPY_UP(AV_RB16
, AV_WB16
)
2310 COPY_UP(AV_RB16
, AV_WL16
)
2313 if(isBE(c
->opts
.dst_format
)){
2314 COPY_UP(AV_RL16
, AV_WB16
)
2316 COPY_UP(AV_RL16
, AV_WL16
)
2319 dstPtr2
+= dstStride
[plane
]/2;
2320 srcPtr2
+= srcStride
[plane
]/2;
2322 } else { /* src_depth > dst_depth */
2323 if(isBE(c
->opts
.src_format
) == HAVE_BIGENDIAN
){
2324 if(isBE(c
->opts
.dst_format
) == HAVE_BIGENDIAN
){
2325 DITHER_COPY(dstPtr2
, dstStride
[plane
]/2, srcPtr2
, srcStride
[plane
]/2, , )
2327 DITHER_COPY(dstPtr2
, dstStride
[plane
]/2, srcPtr2
, srcStride
[plane
]/2, , av_bswap16
)
2330 if(isBE(c
->opts
.dst_format
) == HAVE_BIGENDIAN
){
2331 DITHER_COPY(dstPtr2
, dstStride
[plane
]/2, srcPtr2
, srcStride
[plane
]/2, av_bswap16
, )
2333 DITHER_COPY(dstPtr2
, dstStride
[plane
]/2, srcPtr2
, srcStride
[plane
]/2, av_bswap16
, av_bswap16
)
2337 } else if (is16BPS(c
->opts
.src_format
) && is16BPS(c
->opts
.dst_format
) &&
2338 isBE(c
->opts
.src_format
) != isBE(c
->opts
.dst_format
)) {
2340 for (i
= 0; i
< height
; i
++) {
2341 for (j
= 0; j
< length
; j
++)
2342 ((uint16_t *) dstPtr
)[j
] = av_bswap16(((const uint16_t *) srcPtr
)[j
]);
2343 srcPtr
+= srcStride
[plane
];
2344 dstPtr
+= dstStride
[plane
];
2346 } else if (isFloat(c
->opts
.src_format
) && isFloat(c
->opts
.dst_format
) &&
2347 isBE(c
->opts
.src_format
) != isBE(c
->opts
.dst_format
)) { /* swap float plane */
2348 for (i
= 0; i
< height
; i
++) {
2349 for (j
= 0; j
< length
; j
++)
2350 ((uint32_t *) dstPtr
)[j
] = av_bswap32(((const uint32_t *) srcPtr
)[j
]);
2351 srcPtr
+= srcStride
[plane
];
2352 dstPtr
+= dstStride
[plane
];
2354 } else if (dstStride
[plane
] == srcStride
[plane
] &&
2355 srcStride
[plane
] > 0 && srcStride
[plane
] == length
) {
2356 memcpy(dst
[plane
] + dstStride
[plane
] * y
, src
[plane
],
2357 height
* dstStride
[plane
]);
2359 if (is16BPS(c
->opts
.src_format
) && is16BPS(c
->opts
.dst_format
))
2361 else if (desc_src
->comp
[0].depth
== 1)
2362 length
>>= 3; // monowhite/black
2363 for (i
= 0; i
< height
; i
++) {
2364 memcpy(dstPtr
, srcPtr
, length
);
2365 srcPtr
+= srcStride
[plane
];
2366 dstPtr
+= dstStride
[plane
];
2375 #define IS_DIFFERENT_ENDIANESS(src_fmt, dst_fmt, pix_fmt) \
2376 ((src_fmt == pix_fmt ## BE && dst_fmt == pix_fmt ## LE) || \
2377 (src_fmt == pix_fmt ## LE && dst_fmt == pix_fmt ## BE))
2380 void ff_get_unscaled_swscale(SwsInternal
*c
)
2382 const enum AVPixelFormat srcFormat
= c
->opts
.src_format
;
2383 const enum AVPixelFormat dstFormat
= c
->opts
.dst_format
;
2384 const int flags
= c
->opts
.flags
;
2385 const int dstH
= c
->opts
.dst_h
;
2386 const int dstW
= c
->opts
.dst_w
;
2389 needsDither
= isAnyRGB(dstFormat
) &&
2390 c
->dstFormatBpp
< 24 &&
2391 (c
->dstFormatBpp
< c
->srcFormatBpp
|| (!isAnyRGB(srcFormat
)));
2394 if ((srcFormat
== AV_PIX_FMT_YUV420P
|| srcFormat
== AV_PIX_FMT_YUVA420P
) &&
2395 (dstFormat
== AV_PIX_FMT_NV12
|| dstFormat
== AV_PIX_FMT_NV21
)) {
2396 c
->convert_unscaled
= planarToNv12Wrapper
;
2399 if ((srcFormat
== AV_PIX_FMT_YUV444P
|| srcFormat
== AV_PIX_FMT_YUVA444P
) &&
2400 (dstFormat
== AV_PIX_FMT_NV24
|| dstFormat
== AV_PIX_FMT_NV42
)) {
2401 c
->convert_unscaled
= planarToNv24Wrapper
;
2404 if (dstFormat
== AV_PIX_FMT_YUV420P
&&
2405 (srcFormat
== AV_PIX_FMT_NV12
|| srcFormat
== AV_PIX_FMT_NV21
)) {
2406 c
->convert_unscaled
= nv12ToPlanarWrapper
;
2409 if (dstFormat
== AV_PIX_FMT_YUV444P
&&
2410 (srcFormat
== AV_PIX_FMT_NV24
|| srcFormat
== AV_PIX_FMT_NV42
)) {
2411 c
->convert_unscaled
= nv24ToPlanarWrapper
;
2414 if ((srcFormat
== AV_PIX_FMT_YUV420P
|| srcFormat
== AV_PIX_FMT_YUV422P
||
2415 srcFormat
== AV_PIX_FMT_YUVA420P
) && isAnyRGB(dstFormat
) &&
2416 !(flags
& SWS_ACCURATE_RND
) && (c
->opts
.dither
== SWS_DITHER_BAYER
|| c
->opts
.dither
== SWS_DITHER_AUTO
) && !(dstH
& 1)) {
2417 c
->convert_unscaled
= ff_yuv2rgb_get_func_ptr(c
);
2418 c
->dst_slice_align
= 2;
2420 /* yuv420p1x_to_p01x */
2421 if ((srcFormat
== AV_PIX_FMT_YUV420P10
|| srcFormat
== AV_PIX_FMT_YUVA420P10
||
2422 srcFormat
== AV_PIX_FMT_YUV420P12
||
2423 srcFormat
== AV_PIX_FMT_YUV420P14
||
2424 srcFormat
== AV_PIX_FMT_YUV420P16
|| srcFormat
== AV_PIX_FMT_YUVA420P16
) &&
2425 (dstFormat
== AV_PIX_FMT_P010
|| dstFormat
== AV_PIX_FMT_P016
)) {
2426 c
->convert_unscaled
= planarToP01xWrapper
;
2428 /* yuv420p_to_p01xle */
2429 if ((srcFormat
== AV_PIX_FMT_YUV420P
|| srcFormat
== AV_PIX_FMT_YUVA420P
) &&
2430 (dstFormat
== AV_PIX_FMT_P010LE
|| dstFormat
== AV_PIX_FMT_P016LE
)) {
2431 c
->convert_unscaled
= planar8ToP01xleWrapper
;
2434 if (srcFormat
== AV_PIX_FMT_YUV410P
&& !(dstH
& 3) &&
2435 (dstFormat
== AV_PIX_FMT_YUV420P
|| dstFormat
== AV_PIX_FMT_YUVA420P
) &&
2436 !(flags
& SWS_BITEXACT
)) {
2437 c
->convert_unscaled
= yvu9ToYv12Wrapper
;
2438 c
->dst_slice_align
= 4;
2442 if (srcFormat
== AV_PIX_FMT_BGR24
&&
2443 (dstFormat
== AV_PIX_FMT_YUV420P
|| dstFormat
== AV_PIX_FMT_YUVA420P
) &&
2444 !(flags
& SWS_ACCURATE_RND
) && !(dstW
&1))
2445 c
->convert_unscaled
= bgr24ToYv12Wrapper
;
2447 /* AYUV/VUYA/UYVA -> AYUV/VUYA/UYVA */
2448 if (isAYUV(srcFormat
) && isAYUV(dstFormat
) && findRgbConvFn(c
))
2449 c
->convert_unscaled
= rgbToRgbWrapper
;
2451 /* RGB/BGR -> RGB/BGR (no dither needed forms) */
2452 if (isAnyRGB(srcFormat
) && isAnyRGB(dstFormat
) && findRgbConvFn(c
)
2453 && (!needsDither
|| (c
->opts
.flags
&(SWS_FAST_BILINEAR
|SWS_POINT
))))
2454 c
->convert_unscaled
= rgbToRgbWrapper
;
2456 /* RGB to planar RGB */
2457 if ((srcFormat
== AV_PIX_FMT_GBRP
&& dstFormat
== AV_PIX_FMT_GBRAP
) ||
2458 (srcFormat
== AV_PIX_FMT_GBRP10
&& dstFormat
== AV_PIX_FMT_GBRAP10
) ||
2459 (srcFormat
== AV_PIX_FMT_GBRP12
&& dstFormat
== AV_PIX_FMT_GBRAP12
) ||
2460 (srcFormat
== AV_PIX_FMT_GBRP14
&& dstFormat
== AV_PIX_FMT_GBRAP14
) ||
2461 (srcFormat
== AV_PIX_FMT_GBRP16
&& dstFormat
== AV_PIX_FMT_GBRAP16
) ||
2462 (srcFormat
== AV_PIX_FMT_GBRAP
&& dstFormat
== AV_PIX_FMT_GBRP
) ||
2463 (srcFormat
== AV_PIX_FMT_GBRAP10
&& dstFormat
== AV_PIX_FMT_GBRP10
) ||
2464 (srcFormat
== AV_PIX_FMT_GBRAP12
&& dstFormat
== AV_PIX_FMT_GBRP12
) ||
2465 (srcFormat
== AV_PIX_FMT_GBRAP14
&& dstFormat
== AV_PIX_FMT_GBRP14
) ||
2466 (srcFormat
== AV_PIX_FMT_GBRAP16
&& dstFormat
== AV_PIX_FMT_GBRP16
))
2467 c
->convert_unscaled
= planarRgbToplanarRgbWrapper
;
2469 #define isByteRGB(f) ( \
2470 f == AV_PIX_FMT_RGB32 || \
2471 f == AV_PIX_FMT_RGB32_1 || \
2472 f == AV_PIX_FMT_RGB24 || \
2473 f == AV_PIX_FMT_BGR32 || \
2474 f == AV_PIX_FMT_BGR32_1 || \
2475 f == AV_PIX_FMT_BGR24)
2477 if (srcFormat
== AV_PIX_FMT_GBRP
&& isPlanar(srcFormat
) && isByteRGB(dstFormat
))
2478 c
->convert_unscaled
= planarRgbToRgbWrapper
;
2480 if (srcFormat
== AV_PIX_FMT_GBRAP
&& isByteRGB(dstFormat
))
2481 c
->convert_unscaled
= planarRgbaToRgbWrapper
;
2483 if ((srcFormat
== AV_PIX_FMT_RGB48LE
|| srcFormat
== AV_PIX_FMT_RGB48BE
||
2484 srcFormat
== AV_PIX_FMT_BGR48LE
|| srcFormat
== AV_PIX_FMT_BGR48BE
||
2485 srcFormat
== AV_PIX_FMT_RGBA64LE
|| srcFormat
== AV_PIX_FMT_RGBA64BE
||
2486 srcFormat
== AV_PIX_FMT_BGRA64LE
|| srcFormat
== AV_PIX_FMT_BGRA64BE
) &&
2487 (dstFormat
== AV_PIX_FMT_GBRP9LE
|| dstFormat
== AV_PIX_FMT_GBRP9BE
||
2488 dstFormat
== AV_PIX_FMT_GBRP10LE
|| dstFormat
== AV_PIX_FMT_GBRP10BE
||
2489 dstFormat
== AV_PIX_FMT_GBRP12LE
|| dstFormat
== AV_PIX_FMT_GBRP12BE
||
2490 dstFormat
== AV_PIX_FMT_GBRP14LE
|| dstFormat
== AV_PIX_FMT_GBRP14BE
||
2491 dstFormat
== AV_PIX_FMT_GBRP16LE
|| dstFormat
== AV_PIX_FMT_GBRP16BE
||
2492 dstFormat
== AV_PIX_FMT_GBRAP10LE
|| dstFormat
== AV_PIX_FMT_GBRAP10BE
||
2493 dstFormat
== AV_PIX_FMT_GBRAP12LE
|| dstFormat
== AV_PIX_FMT_GBRAP12BE
||
2494 dstFormat
== AV_PIX_FMT_GBRAP14LE
|| dstFormat
== AV_PIX_FMT_GBRAP14BE
||
2495 dstFormat
== AV_PIX_FMT_GBRAP16LE
|| dstFormat
== AV_PIX_FMT_GBRAP16BE
))
2496 c
->convert_unscaled
= Rgb16ToPlanarRgb16Wrapper
;
2498 if (av_pix_fmt_desc_get(dstFormat
)->comp
[0].depth
>= 10 &&
2499 isPlanarRGB(dstFormat
) && !isFloat(dstFormat
) &&
2500 (srcFormat
== AV_PIX_FMT_X2RGB10LE
|| srcFormat
== AV_PIX_FMT_X2BGR10LE
))
2501 c
->convert_unscaled
= Rgb16ToPlanarRgb16Wrapper
;
2503 if ((srcFormat
== AV_PIX_FMT_GBRP9LE
|| srcFormat
== AV_PIX_FMT_GBRP9BE
||
2504 srcFormat
== AV_PIX_FMT_GBRP16LE
|| srcFormat
== AV_PIX_FMT_GBRP16BE
||
2505 srcFormat
== AV_PIX_FMT_GBRP10LE
|| srcFormat
== AV_PIX_FMT_GBRP10BE
||
2506 srcFormat
== AV_PIX_FMT_GBRP12LE
|| srcFormat
== AV_PIX_FMT_GBRP12BE
||
2507 srcFormat
== AV_PIX_FMT_GBRP14LE
|| srcFormat
== AV_PIX_FMT_GBRP14BE
||
2508 srcFormat
== AV_PIX_FMT_GBRAP10LE
|| srcFormat
== AV_PIX_FMT_GBRAP10BE
||
2509 srcFormat
== AV_PIX_FMT_GBRAP12LE
|| srcFormat
== AV_PIX_FMT_GBRAP12BE
||
2510 srcFormat
== AV_PIX_FMT_GBRAP14LE
|| srcFormat
== AV_PIX_FMT_GBRAP14BE
||
2511 srcFormat
== AV_PIX_FMT_GBRAP16LE
|| srcFormat
== AV_PIX_FMT_GBRAP16BE
) &&
2512 (dstFormat
== AV_PIX_FMT_RGB48LE
|| dstFormat
== AV_PIX_FMT_RGB48BE
||
2513 dstFormat
== AV_PIX_FMT_BGR48LE
|| dstFormat
== AV_PIX_FMT_BGR48BE
||
2514 dstFormat
== AV_PIX_FMT_RGBA64LE
|| dstFormat
== AV_PIX_FMT_RGBA64BE
||
2515 dstFormat
== AV_PIX_FMT_BGRA64LE
|| dstFormat
== AV_PIX_FMT_BGRA64BE
))
2516 c
->convert_unscaled
= planarRgb16ToRgb16Wrapper
;
2518 if (av_pix_fmt_desc_get(srcFormat
)->comp
[0].depth
>= 10 &&
2519 isPlanarRGB(srcFormat
) && !isFloat(srcFormat
) &&
2520 (dstFormat
== AV_PIX_FMT_X2RGB10LE
|| dstFormat
== AV_PIX_FMT_X2BGR10LE
))
2521 c
->convert_unscaled
= planarRgb16ToRgb16Wrapper
;
2523 if (av_pix_fmt_desc_get(srcFormat
)->comp
[0].depth
== 8 &&
2524 isPackedRGB(srcFormat
) && dstFormat
== AV_PIX_FMT_GBRP
)
2525 c
->convert_unscaled
= rgbToPlanarRgbWrapper
;
2527 if (av_pix_fmt_desc_get(srcFormat
)->comp
[0].depth
== 8 &&
2528 isPackedRGB(srcFormat
) && dstFormat
== AV_PIX_FMT_GBRAP
)
2529 c
->convert_unscaled
= rgbToPlanarRgbaWrapper
;
2531 if (isBayer(srcFormat
)) {
2532 c
->dst_slice_align
= 2;
2533 if (dstFormat
== AV_PIX_FMT_RGB24
)
2534 c
->convert_unscaled
= bayer_to_rgb24_wrapper
;
2535 else if (dstFormat
== AV_PIX_FMT_RGB48
)
2536 c
->convert_unscaled
= bayer_to_rgb48_wrapper
;
2537 else if (dstFormat
== AV_PIX_FMT_YUV420P
)
2538 c
->convert_unscaled
= bayer_to_yv12_wrapper
;
2539 else if (!isBayer(dstFormat
)) {
2540 av_log(c
, AV_LOG_ERROR
, "unsupported bayer conversion\n");
2545 /* bswap 16 bits per pixel/component packed formats */
2546 if (IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_BAYER_BGGR16
) ||
2547 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_BAYER_RGGB16
) ||
2548 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_BAYER_GBRG16
) ||
2549 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_BAYER_GRBG16
) ||
2550 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_BGR444
) ||
2551 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_BGR48
) ||
2552 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_BGR555
) ||
2553 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_BGR565
) ||
2554 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_BGRA64
) ||
2555 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_GRAY9
) ||
2556 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_GRAY10
) ||
2557 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_GRAY12
) ||
2558 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_GRAY14
) ||
2559 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_GRAY16
) ||
2560 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_YA16
) ||
2561 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_AYUV64
) ||
2562 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_GBRP9
) ||
2563 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_GBRP10
) ||
2564 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_GBRP12
) ||
2565 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_GBRP14
) ||
2566 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_GBRP16
) ||
2567 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_GBRAP10
) ||
2568 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_GBRAP12
) ||
2569 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_GBRAP14
) ||
2570 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_GBRAP16
) ||
2571 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_RGB444
) ||
2572 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_RGB48
) ||
2573 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_RGB555
) ||
2574 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_RGB565
) ||
2575 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_RGBA64
) ||
2576 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_XV36
) ||
2577 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_XV48
) ||
2578 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_XYZ12
) ||
2579 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_YUV420P9
) ||
2580 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_YUV420P10
) ||
2581 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_YUV420P12
) ||
2582 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_YUV420P14
) ||
2583 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_YUV420P16
) ||
2584 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_YUV422P9
) ||
2585 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_YUV422P10
) ||
2586 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_YUV422P12
) ||
2587 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_YUV422P14
) ||
2588 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_YUV422P16
) ||
2589 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_YUV440P10
) ||
2590 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_YUV440P12
) ||
2591 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_YUV444P9
) ||
2592 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_YUV444P10
) ||
2593 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_YUV444P12
) ||
2594 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_YUV444P14
) ||
2595 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_YUV444P16
))
2596 c
->convert_unscaled
= bswap_16bpc
;
2598 /* bswap 32 bits per pixel/component formats */
2599 if (IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_GBRPF32
) ||
2600 IS_DIFFERENT_ENDIANESS(srcFormat
, dstFormat
, AV_PIX_FMT_GBRAPF32
))
2601 c
->convert_unscaled
= bswap_32bpc
;
2603 if (usePal(srcFormat
)) {
2604 switch (dstFormat
) {
2605 case AV_PIX_FMT_GBRP
:
2606 case AV_PIX_FMT_GBRAP
:
2607 c
->convert_unscaled
= palToGbrpWrapper
;
2610 if (isByteRGB(dstFormat
))
2611 c
->convert_unscaled
= palToRgbWrapper
;
2616 if (srcFormat
== AV_PIX_FMT_YUV422P
) {
2617 if (dstFormat
== AV_PIX_FMT_YUYV422
)
2618 c
->convert_unscaled
= yuv422pToYuy2Wrapper
;
2619 else if (dstFormat
== AV_PIX_FMT_UYVY422
)
2620 c
->convert_unscaled
= yuv422pToUyvyWrapper
;
2623 /* uint Y to float Y */
2624 if (srcFormat
== AV_PIX_FMT_GRAY8
&& dstFormat
== AV_PIX_FMT_GRAYF32
){
2625 c
->convert_unscaled
= uint_y_to_float_y_wrapper
;
2628 /* float Y to uint Y */
2629 if (srcFormat
== AV_PIX_FMT_GRAYF32
&& dstFormat
== AV_PIX_FMT_GRAY8
){
2630 c
->convert_unscaled
= float_y_to_uint_y_wrapper
;
2633 /* LQ converters if -sws 0 or -sws 4*/
2634 if (c
->opts
.flags
&(SWS_FAST_BILINEAR
|SWS_POINT
)) {
2636 if (srcFormat
== AV_PIX_FMT_YUV420P
|| srcFormat
== AV_PIX_FMT_YUVA420P
) {
2637 if (dstFormat
== AV_PIX_FMT_YUYV422
)
2638 c
->convert_unscaled
= planarToYuy2Wrapper
;
2639 else if (dstFormat
== AV_PIX_FMT_UYVY422
)
2640 c
->convert_unscaled
= planarToUyvyWrapper
;
2643 if (srcFormat
== AV_PIX_FMT_YUYV422
&&
2644 (dstFormat
== AV_PIX_FMT_YUV420P
|| dstFormat
== AV_PIX_FMT_YUVA420P
))
2645 c
->convert_unscaled
= yuyvToYuv420Wrapper
;
2646 if (srcFormat
== AV_PIX_FMT_UYVY422
&&
2647 (dstFormat
== AV_PIX_FMT_YUV420P
|| dstFormat
== AV_PIX_FMT_YUVA420P
))
2648 c
->convert_unscaled
= uyvyToYuv420Wrapper
;
2649 if (srcFormat
== AV_PIX_FMT_YUYV422
&& dstFormat
== AV_PIX_FMT_YUV422P
)
2650 c
->convert_unscaled
= yuyvToYuv422Wrapper
;
2651 if (srcFormat
== AV_PIX_FMT_UYVY422
&& dstFormat
== AV_PIX_FMT_YUV422P
)
2652 c
->convert_unscaled
= uyvyToYuv422Wrapper
;
2653 if (dstFormat
== AV_PIX_FMT_YUV420P
&&
2654 (srcFormat
== AV_PIX_FMT_NV24
|| srcFormat
== AV_PIX_FMT_NV42
))
2655 c
->convert_unscaled
= nv24ToYuv420Wrapper
;
2657 #define isPlanarGray(x) (isGray(x) && (x) != AV_PIX_FMT_YA8 && (x) != AV_PIX_FMT_YA16LE && (x) != AV_PIX_FMT_YA16BE)
2660 if ( srcFormat
== dstFormat
||
2661 (srcFormat
== AV_PIX_FMT_YUVA420P
&& dstFormat
== AV_PIX_FMT_YUV420P
) ||
2662 (srcFormat
== AV_PIX_FMT_YUV420P
&& dstFormat
== AV_PIX_FMT_YUVA420P
) ||
2663 (isFloat(srcFormat
) == isFloat(dstFormat
) && isFloat16(srcFormat
) == isFloat16(dstFormat
)) && ((isPlanarYUV(srcFormat
) && isPlanarGray(dstFormat
)) ||
2664 (isPlanarYUV(dstFormat
) && isPlanarGray(srcFormat
)) ||
2665 (isPlanarGray(dstFormat
) && isPlanarGray(srcFormat
)) ||
2666 (isPlanarYUV(srcFormat
) && isPlanarYUV(dstFormat
) &&
2667 c
->chrDstHSubSample
== c
->chrSrcHSubSample
&&
2668 c
->chrDstVSubSample
== c
->chrSrcVSubSample
&&
2669 isSemiPlanarYUV(srcFormat
) == isSemiPlanarYUV(dstFormat
))))
2671 if (isPacked(c
->opts
.src_format
))
2672 c
->convert_unscaled
= packedCopyWrapper
;
2673 else /* Planar YUV or gray */
2674 c
->convert_unscaled
= planarCopyWrapper
;
2678 ff_get_unscaled_swscale_ppc(c
);
2680 ff_get_unscaled_swscale_arm(c
);
2682 ff_get_unscaled_swscale_aarch64(c
);
2686 /* Convert the palette to the same packed 32-bit format as the palette */
2687 void sws_convertPalette8ToPacked32(const uint8_t *src
, uint8_t *dst
,
2688 int num_pixels
, const uint8_t *palette
)
2692 for (i
= 0; i
< num_pixels
; i
++)
2693 ((uint32_t *) dst
)[i
] = ((const uint32_t *) palette
)[src
[i
]];
2696 /* Palette format: ABCD -> dst format: ABC */
2697 void sws_convertPalette8ToPacked24(const uint8_t *src
, uint8_t *dst
,
2698 int num_pixels
, const uint8_t *palette
)
2702 for (i
= 0; i
< num_pixels
; i
++) {
2704 dst
[0] = palette
[src
[i
] * 4 + 0];
2705 dst
[1] = palette
[src
[i
] * 4 + 1];
2706 dst
[2] = palette
[src
[i
] * 4 + 2];