Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4349 | Serge | 1 | /* |
2 | * Copyright (C) 2001-2011 Michael Niedermayer |
||
3 | * |
||
4 | * This file is part of FFmpeg. |
||
5 | * |
||
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. |
||
10 | * |
||
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. |
||
15 | * |
||
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 |
||
19 | */ |
||
20 | |||
21 | #include |
||
22 | #include |
||
23 | #include |
||
24 | #include |
||
25 | #include "config.h" |
||
26 | #include "swscale.h" |
||
27 | #include "swscale_internal.h" |
||
28 | #include "rgb2rgb.h" |
||
29 | #include "libavutil/intreadwrite.h" |
||
30 | #include "libavutil/cpu.h" |
||
31 | #include "libavutil/avutil.h" |
||
32 | #include "libavutil/mathematics.h" |
||
33 | #include "libavutil/bswap.h" |
||
34 | #include "libavutil/pixdesc.h" |
||
35 | #include "libavutil/avassert.h" |
||
36 | |||
37 | DECLARE_ALIGNED(8, static const uint8_t, dithers)[8][8][8]={ |
||
38 | { |
||
39 | { 0, 1, 0, 1, 0, 1, 0, 1,}, |
||
40 | { 1, 0, 1, 0, 1, 0, 1, 0,}, |
||
41 | { 0, 1, 0, 1, 0, 1, 0, 1,}, |
||
42 | { 1, 0, 1, 0, 1, 0, 1, 0,}, |
||
43 | { 0, 1, 0, 1, 0, 1, 0, 1,}, |
||
44 | { 1, 0, 1, 0, 1, 0, 1, 0,}, |
||
45 | { 0, 1, 0, 1, 0, 1, 0, 1,}, |
||
46 | { 1, 0, 1, 0, 1, 0, 1, 0,}, |
||
47 | },{ |
||
48 | { 1, 2, 1, 2, 1, 2, 1, 2,}, |
||
49 | { 3, 0, 3, 0, 3, 0, 3, 0,}, |
||
50 | { 1, 2, 1, 2, 1, 2, 1, 2,}, |
||
51 | { 3, 0, 3, 0, 3, 0, 3, 0,}, |
||
52 | { 1, 2, 1, 2, 1, 2, 1, 2,}, |
||
53 | { 3, 0, 3, 0, 3, 0, 3, 0,}, |
||
54 | { 1, 2, 1, 2, 1, 2, 1, 2,}, |
||
55 | { 3, 0, 3, 0, 3, 0, 3, 0,}, |
||
56 | },{ |
||
57 | { 2, 4, 3, 5, 2, 4, 3, 5,}, |
||
58 | { 6, 0, 7, 1, 6, 0, 7, 1,}, |
||
59 | { 3, 5, 2, 4, 3, 5, 2, 4,}, |
||
60 | { 7, 1, 6, 0, 7, 1, 6, 0,}, |
||
61 | { 2, 4, 3, 5, 2, 4, 3, 5,}, |
||
62 | { 6, 0, 7, 1, 6, 0, 7, 1,}, |
||
63 | { 3, 5, 2, 4, 3, 5, 2, 4,}, |
||
64 | { 7, 1, 6, 0, 7, 1, 6, 0,}, |
||
65 | },{ |
||
66 | { 4, 8, 7, 11, 4, 8, 7, 11,}, |
||
67 | { 12, 0, 15, 3, 12, 0, 15, 3,}, |
||
68 | { 6, 10, 5, 9, 6, 10, 5, 9,}, |
||
69 | { 14, 2, 13, 1, 14, 2, 13, 1,}, |
||
70 | { 4, 8, 7, 11, 4, 8, 7, 11,}, |
||
71 | { 12, 0, 15, 3, 12, 0, 15, 3,}, |
||
72 | { 6, 10, 5, 9, 6, 10, 5, 9,}, |
||
73 | { 14, 2, 13, 1, 14, 2, 13, 1,}, |
||
74 | },{ |
||
75 | { 9, 17, 15, 23, 8, 16, 14, 22,}, |
||
76 | { 25, 1, 31, 7, 24, 0, 30, 6,}, |
||
77 | { 13, 21, 11, 19, 12, 20, 10, 18,}, |
||
78 | { 29, 5, 27, 3, 28, 4, 26, 2,}, |
||
79 | { 8, 16, 14, 22, 9, 17, 15, 23,}, |
||
80 | { 24, 0, 30, 6, 25, 1, 31, 7,}, |
||
81 | { 12, 20, 10, 18, 13, 21, 11, 19,}, |
||
82 | { 28, 4, 26, 2, 29, 5, 27, 3,}, |
||
83 | },{ |
||
84 | { 18, 34, 30, 46, 17, 33, 29, 45,}, |
||
85 | { 50, 2, 62, 14, 49, 1, 61, 13,}, |
||
86 | { 26, 42, 22, 38, 25, 41, 21, 37,}, |
||
87 | { 58, 10, 54, 6, 57, 9, 53, 5,}, |
||
88 | { 16, 32, 28, 44, 19, 35, 31, 47,}, |
||
89 | { 48, 0, 60, 12, 51, 3, 63, 15,}, |
||
90 | { 24, 40, 20, 36, 27, 43, 23, 39,}, |
||
91 | { 56, 8, 52, 4, 59, 11, 55, 7,}, |
||
92 | },{ |
||
93 | { 18, 34, 30, 46, 17, 33, 29, 45,}, |
||
94 | { 50, 2, 62, 14, 49, 1, 61, 13,}, |
||
95 | { 26, 42, 22, 38, 25, 41, 21, 37,}, |
||
96 | { 58, 10, 54, 6, 57, 9, 53, 5,}, |
||
97 | { 16, 32, 28, 44, 19, 35, 31, 47,}, |
||
98 | { 48, 0, 60, 12, 51, 3, 63, 15,}, |
||
99 | { 24, 40, 20, 36, 27, 43, 23, 39,}, |
||
100 | { 56, 8, 52, 4, 59, 11, 55, 7,}, |
||
101 | },{ |
||
102 | { 36, 68, 60, 92, 34, 66, 58, 90,}, |
||
103 | { 100, 4,124, 28, 98, 2,122, 26,}, |
||
104 | { 52, 84, 44, 76, 50, 82, 42, 74,}, |
||
105 | { 116, 20,108, 12,114, 18,106, 10,}, |
||
106 | { 32, 64, 56, 88, 38, 70, 62, 94,}, |
||
107 | { 96, 0,120, 24,102, 6,126, 30,}, |
||
108 | { 48, 80, 40, 72, 54, 86, 46, 78,}, |
||
109 | { 112, 16,104, 8,118, 22,110, 14,}, |
||
110 | }}; |
||
111 | |||
112 | static const uint16_t dither_scale[15][16]={ |
||
113 | { 2, 3, 3, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,}, |
||
114 | { 2, 3, 7, 7, 13, 13, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,}, |
||
115 | { 3, 3, 4, 15, 15, 29, 57, 57, 57, 113, 113, 113, 113, 113, 113, 113,}, |
||
116 | { 3, 4, 4, 5, 31, 31, 61, 121, 241, 241, 241, 241, 481, 481, 481, 481,}, |
||
117 | { 3, 4, 5, 5, 6, 63, 63, 125, 249, 497, 993, 993, 993, 993, 993, 1985,}, |
||
118 | { 3, 5, 6, 6, 6, 7, 127, 127, 253, 505, 1009, 2017, 4033, 4033, 4033, 4033,}, |
||
119 | { 3, 5, 6, 7, 7, 7, 8, 255, 255, 509, 1017, 2033, 4065, 8129,16257,16257,}, |
||
120 | { 3, 5, 6, 8, 8, 8, 8, 9, 511, 511, 1021, 2041, 4081, 8161,16321,32641,}, |
||
121 | { 3, 5, 7, 8, 9, 9, 9, 9, 10, 1023, 1023, 2045, 4089, 8177,16353,32705,}, |
||
122 | { 3, 5, 7, 8, 10, 10, 10, 10, 10, 11, 2047, 2047, 4093, 8185,16369,32737,}, |
||
123 | { 3, 5, 7, 8, 10, 11, 11, 11, 11, 11, 12, 4095, 4095, 8189,16377,32753,}, |
||
124 | { 3, 5, 7, 9, 10, 12, 12, 12, 12, 12, 12, 13, 8191, 8191,16381,32761,}, |
||
125 | { 3, 5, 7, 9, 10, 12, 13, 13, 13, 13, 13, 13, 14,16383,16383,32765,}, |
||
126 | { 3, 5, 7, 9, 10, 12, 14, 14, 14, 14, 14, 14, 14, 15,32767,32767,}, |
||
127 | { 3, 5, 7, 9, 11, 12, 14, 15, 15, 15, 15, 15, 15, 15, 16,65535,}, |
||
128 | }; |
||
129 | |||
130 | |||
131 | static void fillPlane(uint8_t *plane, int stride, int width, int height, int y, |
||
132 | uint8_t val) |
||
133 | { |
||
134 | int i; |
||
135 | uint8_t *ptr = plane + stride * y; |
||
136 | for (i = 0; i < height; i++) { |
||
137 | memset(ptr, val, width); |
||
138 | ptr += stride; |
||
139 | } |
||
140 | } |
||
141 | |||
142 | static void copyPlane(const uint8_t *src, int srcStride, |
||
143 | int srcSliceY, int srcSliceH, int width, |
||
144 | uint8_t *dst, int dstStride) |
||
145 | { |
||
146 | dst += dstStride * srcSliceY; |
||
147 | if (dstStride == srcStride && srcStride > 0) { |
||
148 | memcpy(dst, src, srcSliceH * dstStride); |
||
149 | } else { |
||
150 | int i; |
||
151 | for (i = 0; i < srcSliceH; i++) { |
||
152 | memcpy(dst, src, width); |
||
153 | src += srcStride; |
||
154 | dst += dstStride; |
||
155 | } |
||
156 | } |
||
157 | } |
||
158 | |||
159 | static int planarToNv12Wrapper(SwsContext *c, const uint8_t *src[], |
||
160 | int srcStride[], int srcSliceY, |
||
161 | int srcSliceH, uint8_t *dstParam[], |
||
162 | int dstStride[]) |
||
163 | { |
||
164 | uint8_t *dst = dstParam[1] + dstStride[1] * srcSliceY / 2; |
||
165 | |||
166 | copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW, |
||
167 | dstParam[0], dstStride[0]); |
||
168 | |||
169 | if (c->dstFormat == AV_PIX_FMT_NV12) |
||
170 | interleaveBytes(src[1], src[2], dst, c->srcW / 2, srcSliceH / 2, |
||
171 | srcStride[1], srcStride[2], dstStride[0]); |
||
172 | else |
||
173 | interleaveBytes(src[2], src[1], dst, c->srcW / 2, srcSliceH / 2, |
||
174 | srcStride[2], srcStride[1], dstStride[0]); |
||
175 | |||
176 | return srcSliceH; |
||
177 | } |
||
178 | |||
179 | static int planarToYuy2Wrapper(SwsContext *c, const uint8_t *src[], |
||
180 | int srcStride[], int srcSliceY, int srcSliceH, |
||
181 | uint8_t *dstParam[], int dstStride[]) |
||
182 | { |
||
183 | uint8_t *dst = dstParam[0] + dstStride[0] * srcSliceY; |
||
184 | |||
185 | yv12toyuy2(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0], |
||
186 | srcStride[1], dstStride[0]); |
||
187 | |||
188 | return srcSliceH; |
||
189 | } |
||
190 | |||
191 | static int planarToUyvyWrapper(SwsContext *c, const uint8_t *src[], |
||
192 | int srcStride[], int srcSliceY, int srcSliceH, |
||
193 | uint8_t *dstParam[], int dstStride[]) |
||
194 | { |
||
195 | uint8_t *dst = dstParam[0] + dstStride[0] * srcSliceY; |
||
196 | |||
197 | yv12touyvy(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0], |
||
198 | srcStride[1], dstStride[0]); |
||
199 | |||
200 | return srcSliceH; |
||
201 | } |
||
202 | |||
203 | static int yuv422pToYuy2Wrapper(SwsContext *c, const uint8_t *src[], |
||
204 | int srcStride[], int srcSliceY, int srcSliceH, |
||
205 | uint8_t *dstParam[], int dstStride[]) |
||
206 | { |
||
207 | uint8_t *dst = dstParam[0] + dstStride[0] * srcSliceY; |
||
208 | |||
209 | yuv422ptoyuy2(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0], |
||
210 | srcStride[1], dstStride[0]); |
||
211 | |||
212 | return srcSliceH; |
||
213 | } |
||
214 | |||
215 | static int yuv422pToUyvyWrapper(SwsContext *c, const uint8_t *src[], |
||
216 | int srcStride[], int srcSliceY, int srcSliceH, |
||
217 | uint8_t *dstParam[], int dstStride[]) |
||
218 | { |
||
219 | uint8_t *dst = dstParam[0] + dstStride[0] * srcSliceY; |
||
220 | |||
221 | yuv422ptouyvy(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0], |
||
222 | srcStride[1], dstStride[0]); |
||
223 | |||
224 | return srcSliceH; |
||
225 | } |
||
226 | |||
227 | static int yuyvToYuv420Wrapper(SwsContext *c, const uint8_t *src[], |
||
228 | int srcStride[], int srcSliceY, int srcSliceH, |
||
229 | uint8_t *dstParam[], int dstStride[]) |
||
230 | { |
||
231 | uint8_t *ydst = dstParam[0] + dstStride[0] * srcSliceY; |
||
232 | uint8_t *udst = dstParam[1] + dstStride[1] * srcSliceY / 2; |
||
233 | uint8_t *vdst = dstParam[2] + dstStride[2] * srcSliceY / 2; |
||
234 | |||
235 | yuyvtoyuv420(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], |
||
236 | dstStride[1], srcStride[0]); |
||
237 | |||
238 | if (dstParam[3]) |
||
239 | fillPlane(dstParam[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255); |
||
240 | |||
241 | return srcSliceH; |
||
242 | } |
||
243 | |||
244 | static int yuyvToYuv422Wrapper(SwsContext *c, const uint8_t *src[], |
||
245 | int srcStride[], int srcSliceY, int srcSliceH, |
||
246 | uint8_t *dstParam[], int dstStride[]) |
||
247 | { |
||
248 | uint8_t *ydst = dstParam[0] + dstStride[0] * srcSliceY; |
||
249 | uint8_t *udst = dstParam[1] + dstStride[1] * srcSliceY; |
||
250 | uint8_t *vdst = dstParam[2] + dstStride[2] * srcSliceY; |
||
251 | |||
252 | yuyvtoyuv422(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], |
||
253 | dstStride[1], srcStride[0]); |
||
254 | |||
255 | return srcSliceH; |
||
256 | } |
||
257 | |||
258 | static int uyvyToYuv420Wrapper(SwsContext *c, const uint8_t *src[], |
||
259 | int srcStride[], int srcSliceY, int srcSliceH, |
||
260 | uint8_t *dstParam[], int dstStride[]) |
||
261 | { |
||
262 | uint8_t *ydst = dstParam[0] + dstStride[0] * srcSliceY; |
||
263 | uint8_t *udst = dstParam[1] + dstStride[1] * srcSliceY / 2; |
||
264 | uint8_t *vdst = dstParam[2] + dstStride[2] * srcSliceY / 2; |
||
265 | |||
266 | uyvytoyuv420(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], |
||
267 | dstStride[1], srcStride[0]); |
||
268 | |||
269 | if (dstParam[3]) |
||
270 | fillPlane(dstParam[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255); |
||
271 | |||
272 | return srcSliceH; |
||
273 | } |
||
274 | |||
275 | static int uyvyToYuv422Wrapper(SwsContext *c, const uint8_t *src[], |
||
276 | int srcStride[], int srcSliceY, int srcSliceH, |
||
277 | uint8_t *dstParam[], int dstStride[]) |
||
278 | { |
||
279 | uint8_t *ydst = dstParam[0] + dstStride[0] * srcSliceY; |
||
280 | uint8_t *udst = dstParam[1] + dstStride[1] * srcSliceY; |
||
281 | uint8_t *vdst = dstParam[2] + dstStride[2] * srcSliceY; |
||
282 | |||
283 | uyvytoyuv422(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], |
||
284 | dstStride[1], srcStride[0]); |
||
285 | |||
286 | return srcSliceH; |
||
287 | } |
||
288 | |||
289 | static void gray8aToPacked32(const uint8_t *src, uint8_t *dst, int num_pixels, |
||
290 | const uint8_t *palette) |
||
291 | { |
||
292 | int i; |
||
293 | for (i = 0; i < num_pixels; i++) |
||
294 | ((uint32_t *) dst)[i] = ((const uint32_t *) palette)[src[i << 1]] | (src[(i << 1) + 1] << 24); |
||
295 | } |
||
296 | |||
297 | static void gray8aToPacked32_1(const uint8_t *src, uint8_t *dst, int num_pixels, |
||
298 | const uint8_t *palette) |
||
299 | { |
||
300 | int i; |
||
301 | |||
302 | for (i = 0; i < num_pixels; i++) |
||
303 | ((uint32_t *) dst)[i] = ((const uint32_t *) palette)[src[i << 1]] | src[(i << 1) + 1]; |
||
304 | } |
||
305 | |||
306 | static void gray8aToPacked24(const uint8_t *src, uint8_t *dst, int num_pixels, |
||
307 | const uint8_t *palette) |
||
308 | { |
||
309 | int i; |
||
310 | |||
311 | for (i = 0; i < num_pixels; i++) { |
||
312 | //FIXME slow? |
||
313 | dst[0] = palette[src[i << 1] * 4 + 0]; |
||
314 | dst[1] = palette[src[i << 1] * 4 + 1]; |
||
315 | dst[2] = palette[src[i << 1] * 4 + 2]; |
||
316 | dst += 3; |
||
317 | } |
||
318 | } |
||
319 | |||
320 | static int packed_16bpc_bswap(SwsContext *c, const uint8_t *src[], |
||
321 | int srcStride[], int srcSliceY, int srcSliceH, |
||
322 | uint8_t *dst[], int dstStride[]) |
||
323 | { |
||
324 | int i, j, p; |
||
325 | |||
326 | for (p = 0; p < 4; p++) { |
||
327 | int srcstr = srcStride[p] / 2; |
||
328 | int dststr = dstStride[p] / 2; |
||
329 | uint16_t *dstPtr = (uint16_t *) dst[p]; |
||
330 | const uint16_t *srcPtr = (const uint16_t *) src[p]; |
||
331 | int min_stride = FFMIN(FFABS(srcstr), FFABS(dststr)); |
||
332 | if(!dstPtr || !srcPtr) |
||
333 | continue; |
||
334 | for (i = 0; i < (srcSliceH >> c->chrDstVSubSample); i++) { |
||
335 | for (j = 0; j < min_stride; j++) { |
||
336 | dstPtr[j] = av_bswap16(srcPtr[j]); |
||
337 | } |
||
338 | srcPtr += srcstr; |
||
339 | dstPtr += dststr; |
||
340 | } |
||
341 | } |
||
342 | |||
343 | return srcSliceH; |
||
344 | } |
||
345 | |||
346 | static int palToRgbWrapper(SwsContext *c, const uint8_t *src[], int srcStride[], |
||
347 | int srcSliceY, int srcSliceH, uint8_t *dst[], |
||
348 | int dstStride[]) |
||
349 | { |
||
350 | const enum AVPixelFormat srcFormat = c->srcFormat; |
||
351 | const enum AVPixelFormat dstFormat = c->dstFormat; |
||
352 | void (*conv)(const uint8_t *src, uint8_t *dst, int num_pixels, |
||
353 | const uint8_t *palette) = NULL; |
||
354 | int i; |
||
355 | uint8_t *dstPtr = dst[0] + dstStride[0] * srcSliceY; |
||
356 | const uint8_t *srcPtr = src[0]; |
||
357 | |||
358 | if (srcFormat == AV_PIX_FMT_GRAY8A) { |
||
359 | switch (dstFormat) { |
||
360 | case AV_PIX_FMT_RGB32 : conv = gray8aToPacked32; break; |
||
361 | case AV_PIX_FMT_BGR32 : conv = gray8aToPacked32; break; |
||
362 | case AV_PIX_FMT_BGR32_1: conv = gray8aToPacked32_1; break; |
||
363 | case AV_PIX_FMT_RGB32_1: conv = gray8aToPacked32_1; break; |
||
364 | case AV_PIX_FMT_RGB24 : conv = gray8aToPacked24; break; |
||
365 | case AV_PIX_FMT_BGR24 : conv = gray8aToPacked24; break; |
||
366 | } |
||
367 | } else if (usePal(srcFormat)) { |
||
368 | switch (dstFormat) { |
||
369 | case AV_PIX_FMT_RGB32 : conv = sws_convertPalette8ToPacked32; break; |
||
370 | case AV_PIX_FMT_BGR32 : conv = sws_convertPalette8ToPacked32; break; |
||
371 | case AV_PIX_FMT_BGR32_1: conv = sws_convertPalette8ToPacked32; break; |
||
372 | case AV_PIX_FMT_RGB32_1: conv = sws_convertPalette8ToPacked32; break; |
||
373 | case AV_PIX_FMT_RGB24 : conv = sws_convertPalette8ToPacked24; break; |
||
374 | case AV_PIX_FMT_BGR24 : conv = sws_convertPalette8ToPacked24; break; |
||
375 | } |
||
376 | } |
||
377 | |||
378 | if (!conv) |
||
379 | av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n", |
||
380 | av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat)); |
||
381 | else { |
||
382 | for (i = 0; i < srcSliceH; i++) { |
||
383 | conv(srcPtr, dstPtr, c->srcW, (uint8_t *) c->pal_rgb); |
||
384 | srcPtr += srcStride[0]; |
||
385 | dstPtr += dstStride[0]; |
||
386 | } |
||
387 | } |
||
388 | |||
389 | return srcSliceH; |
||
390 | } |
||
391 | |||
392 | static void gbr16ptopacked16(const uint16_t *src[], int srcStride[], |
||
393 | uint8_t *dst, int dstStride, int srcSliceH, |
||
394 | int alpha, int swap, int bpp, int width) |
||
395 | { |
||
396 | int x, h, i; |
||
397 | int src_alpha = src[3] != NULL; |
||
398 | int scale_high = 16 - bpp, scale_low = (bpp - 8) * 2; |
||
399 | for (h = 0; h < srcSliceH; h++) { |
||
400 | uint16_t *dest = (uint16_t *)(dst + dstStride * h); |
||
401 | uint16_t component; |
||
402 | |||
403 | switch(swap) { |
||
404 | case 3: |
||
405 | if (alpha && !src_alpha) { |
||
406 | for (x = 0; x < width; x++) { |
||
407 | component = av_bswap16(src[0][x]); |
||
408 | *dest++ = av_bswap16(component << scale_high | component >> scale_low); |
||
409 | component = av_bswap16(src[1][x]); |
||
410 | *dest++ = av_bswap16(component << scale_high | component >> scale_low); |
||
411 | component = av_bswap16(src[2][x]); |
||
412 | *dest++ = av_bswap16(component << scale_high | component >> scale_low); |
||
413 | *dest++ = 0xffff; |
||
414 | } |
||
415 | } else if (alpha && src_alpha) { |
||
416 | for (x = 0; x < width; x++) { |
||
417 | component = av_bswap16(src[0][x]); |
||
418 | *dest++ = av_bswap16(component << scale_high | component >> scale_low); |
||
419 | component = av_bswap16(src[1][x]); |
||
420 | *dest++ = av_bswap16(component << scale_high | component >> scale_low); |
||
421 | component = av_bswap16(src[2][x]); |
||
422 | *dest++ = av_bswap16(component << scale_high | component >> scale_low); |
||
423 | component = av_bswap16(src[3][x]); |
||
424 | *dest++ = av_bswap16(component << scale_high | component >> scale_low); |
||
425 | } |
||
426 | } else { |
||
427 | for (x = 0; x < width; x++) { |
||
428 | component = av_bswap16(src[0][x]); |
||
429 | *dest++ = av_bswap16(component << scale_high | component >> scale_low); |
||
430 | component = av_bswap16(src[1][x]); |
||
431 | *dest++ = av_bswap16(component << scale_high | component >> scale_low); |
||
432 | component = av_bswap16(src[2][x]); |
||
433 | *dest++ = av_bswap16(component << scale_high | component >> scale_low); |
||
434 | } |
||
435 | } |
||
436 | break; |
||
437 | case 2: |
||
438 | if (alpha && !src_alpha) { |
||
439 | for (x = 0; x < width; x++) { |
||
440 | *dest++ = av_bswap16(src[0][x] << scale_high | src[0][x] >> scale_low); |
||
441 | *dest++ = av_bswap16(src[1][x] << scale_high | src[1][x] >> scale_low); |
||
442 | *dest++ = av_bswap16(src[2][x] << scale_high | src[2][x] >> scale_low); |
||
443 | *dest++ = 0xffff; |
||
444 | } |
||
445 | } else if (alpha && src_alpha) { |
||
446 | for (x = 0; x < width; x++) { |
||
447 | *dest++ = av_bswap16(src[0][x] << scale_high | src[0][x] >> scale_low); |
||
448 | *dest++ = av_bswap16(src[1][x] << scale_high | src[1][x] >> scale_low); |
||
449 | *dest++ = av_bswap16(src[2][x] << scale_high | src[2][x] >> scale_low); |
||
450 | *dest++ = av_bswap16(src[3][x] << scale_high | src[3][x] >> scale_low); |
||
451 | } |
||
452 | } else { |
||
453 | for (x = 0; x < width; x++) { |
||
454 | *dest++ = av_bswap16(src[0][x] << scale_high | src[0][x] >> scale_low); |
||
455 | *dest++ = av_bswap16(src[1][x] << scale_high | src[1][x] >> scale_low); |
||
456 | *dest++ = av_bswap16(src[2][x] << scale_high | src[2][x] >> scale_low); |
||
457 | } |
||
458 | } |
||
459 | break; |
||
460 | case 1: |
||
461 | if (alpha && !src_alpha) { |
||
462 | for (x = 0; x < width; x++) { |
||
463 | *dest++ = av_bswap16(src[0][x]) << scale_high | av_bswap16(src[0][x]) >> scale_low; |
||
464 | *dest++ = av_bswap16(src[1][x]) << scale_high | av_bswap16(src[1][x]) >> scale_low; |
||
465 | *dest++ = av_bswap16(src[2][x]) << scale_high | av_bswap16(src[2][x]) >> scale_low; |
||
466 | *dest++ = 0xffff; |
||
467 | } |
||
468 | } else if (alpha && src_alpha) { |
||
469 | for (x = 0; x < width; x++) { |
||
470 | *dest++ = av_bswap16(src[0][x]) << scale_high | av_bswap16(src[0][x]) >> scale_low; |
||
471 | *dest++ = av_bswap16(src[1][x]) << scale_high | av_bswap16(src[1][x]) >> scale_low; |
||
472 | *dest++ = av_bswap16(src[2][x]) << scale_high | av_bswap16(src[2][x]) >> scale_low; |
||
473 | *dest++ = av_bswap16(src[3][x]) << scale_high | av_bswap16(src[3][x]) >> scale_low; |
||
474 | } |
||
475 | } else { |
||
476 | for (x = 0; x < width; x++) { |
||
477 | *dest++ = av_bswap16(src[0][x]) << scale_high | av_bswap16(src[0][x]) >> scale_low; |
||
478 | *dest++ = av_bswap16(src[1][x]) << scale_high | av_bswap16(src[1][x]) >> scale_low; |
||
479 | *dest++ = av_bswap16(src[2][x]) << scale_high | av_bswap16(src[2][x]) >> scale_low; |
||
480 | } |
||
481 | } |
||
482 | break; |
||
483 | default: |
||
484 | if (alpha && !src_alpha) { |
||
485 | for (x = 0; x < width; x++) { |
||
486 | *dest++ = src[0][x] << scale_high | src[0][x] >> scale_low; |
||
487 | *dest++ = src[1][x] << scale_high | src[1][x] >> scale_low; |
||
488 | *dest++ = src[2][x] << scale_high | src[2][x] >> scale_low; |
||
489 | *dest++ = 0xffff; |
||
490 | } |
||
491 | } else if (alpha && src_alpha) { |
||
492 | for (x = 0; x < width; x++) { |
||
493 | *dest++ = src[0][x] << scale_high | src[0][x] >> scale_low; |
||
494 | *dest++ = src[1][x] << scale_high | src[1][x] >> scale_low; |
||
495 | *dest++ = src[2][x] << scale_high | src[2][x] >> scale_low; |
||
496 | *dest++ = src[3][x] << scale_high | src[3][x] >> scale_low; |
||
497 | } |
||
498 | } else { |
||
499 | for (x = 0; x < width; x++) { |
||
500 | *dest++ = src[0][x] << scale_high | src[0][x] >> scale_low; |
||
501 | *dest++ = src[1][x] << scale_high | src[1][x] >> scale_low; |
||
502 | *dest++ = src[2][x] << scale_high | src[2][x] >> scale_low; |
||
503 | } |
||
504 | } |
||
505 | } |
||
506 | for (i = 0; i < 3 + src_alpha; i++) |
||
507 | src[i] += srcStride[i] >> 1; |
||
508 | } |
||
509 | } |
||
510 | |||
511 | static int planarRgb16ToRgb16Wrapper(SwsContext *c, const uint8_t *src[], |
||
512 | int srcStride[], int srcSliceY, int srcSliceH, |
||
513 | uint8_t *dst[], int dstStride[]) |
||
514 | { |
||
515 | const uint16_t *src102[] = { (uint16_t *)src[1], (uint16_t *)src[0], (uint16_t *)src[2], (uint16_t *)src[3] }; |
||
516 | const uint16_t *src201[] = { (uint16_t *)src[2], (uint16_t *)src[0], (uint16_t *)src[1], (uint16_t *)src[3] }; |
||
517 | int stride102[] = { srcStride[1], srcStride[0], srcStride[2], srcStride[3] }; |
||
518 | int stride201[] = { srcStride[2], srcStride[0], srcStride[1], srcStride[3] }; |
||
519 | const AVPixFmtDescriptor *src_format = av_pix_fmt_desc_get(c->srcFormat); |
||
520 | const AVPixFmtDescriptor *dst_format = av_pix_fmt_desc_get(c->dstFormat); |
||
521 | int bits_per_sample = src_format->comp[0].depth_minus1 + 1; |
||
522 | int swap = 0; |
||
523 | if ( HAVE_BIGENDIAN && !(src_format->flags & AV_PIX_FMT_FLAG_BE) || |
||
524 | !HAVE_BIGENDIAN && src_format->flags & AV_PIX_FMT_FLAG_BE) |
||
525 | swap++; |
||
526 | if ( HAVE_BIGENDIAN && !(dst_format->flags & AV_PIX_FMT_FLAG_BE) || |
||
527 | !HAVE_BIGENDIAN && dst_format->flags & AV_PIX_FMT_FLAG_BE) |
||
528 | swap += 2; |
||
529 | |||
530 | if ((src_format->flags & (AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB)) != |
||
531 | (AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB) || |
||
532 | bits_per_sample <= 8) { |
||
533 | av_log(c, AV_LOG_ERROR, "unsupported planar RGB conversion %s -> %s\n", |
||
534 | src_format->name, dst_format->name); |
||
535 | return srcSliceH; |
||
536 | } |
||
537 | switch (c->dstFormat) { |
||
538 | case AV_PIX_FMT_BGR48LE: |
||
539 | case AV_PIX_FMT_BGR48BE: |
||
540 | gbr16ptopacked16(src102, stride102, |
||
541 | dst[0] + srcSliceY * dstStride[0], dstStride[0], |
||
542 | srcSliceH, 0, swap, bits_per_sample, c->srcW); |
||
543 | break; |
||
544 | case AV_PIX_FMT_RGB48LE: |
||
545 | case AV_PIX_FMT_RGB48BE: |
||
546 | gbr16ptopacked16(src201, stride201, |
||
547 | dst[0] + srcSliceY * dstStride[0], dstStride[0], |
||
548 | srcSliceH, 0, swap, bits_per_sample, c->srcW); |
||
549 | break; |
||
550 | case AV_PIX_FMT_RGBA64LE: |
||
551 | case AV_PIX_FMT_RGBA64BE: |
||
552 | gbr16ptopacked16(src201, stride201, |
||
553 | dst[0] + srcSliceY * dstStride[0], dstStride[0], |
||
554 | srcSliceH, 1, swap, bits_per_sample, c->srcW); |
||
555 | break; |
||
556 | case AV_PIX_FMT_BGRA64LE: |
||
557 | case AV_PIX_FMT_BGRA64BE: |
||
558 | gbr16ptopacked16(src102, stride102, |
||
559 | dst[0] + srcSliceY * dstStride[0], dstStride[0], |
||
560 | srcSliceH, 1, swap, bits_per_sample, c->srcW); |
||
561 | break; |
||
562 | default: |
||
563 | av_log(c, AV_LOG_ERROR, |
||
564 | "unsupported planar RGB conversion %s -> %s\n", |
||
565 | src_format->name, dst_format->name); |
||
566 | } |
||
567 | |||
568 | return srcSliceH; |
||
569 | } |
||
570 | |||
571 | static void gbr24ptopacked24(const uint8_t *src[], int srcStride[], |
||
572 | uint8_t *dst, int dstStride, int srcSliceH, |
||
573 | int width) |
||
574 | { |
||
575 | int x, h, i; |
||
576 | for (h = 0; h < srcSliceH; h++) { |
||
577 | uint8_t *dest = dst + dstStride * h; |
||
578 | for (x = 0; x < width; x++) { |
||
579 | *dest++ = src[0][x]; |
||
580 | *dest++ = src[1][x]; |
||
581 | *dest++ = src[2][x]; |
||
582 | } |
||
583 | |||
584 | for (i = 0; i < 3; i++) |
||
585 | src[i] += srcStride[i]; |
||
586 | } |
||
587 | } |
||
588 | |||
589 | static void gbr24ptopacked32(const uint8_t *src[], int srcStride[], |
||
590 | uint8_t *dst, int dstStride, int srcSliceH, |
||
591 | int alpha_first, int width) |
||
592 | { |
||
593 | int x, h, i; |
||
594 | for (h = 0; h < srcSliceH; h++) { |
||
595 | uint8_t *dest = dst + dstStride * h; |
||
596 | |||
597 | if (alpha_first) { |
||
598 | for (x = 0; x < width; x++) { |
||
599 | *dest++ = 0xff; |
||
600 | *dest++ = src[0][x]; |
||
601 | *dest++ = src[1][x]; |
||
602 | *dest++ = src[2][x]; |
||
603 | } |
||
604 | } else { |
||
605 | for (x = 0; x < width; x++) { |
||
606 | *dest++ = src[0][x]; |
||
607 | *dest++ = src[1][x]; |
||
608 | *dest++ = src[2][x]; |
||
609 | *dest++ = 0xff; |
||
610 | } |
||
611 | } |
||
612 | |||
613 | for (i = 0; i < 3; i++) |
||
614 | src[i] += srcStride[i]; |
||
615 | } |
||
616 | } |
||
617 | |||
618 | static int planarRgbToRgbWrapper(SwsContext *c, const uint8_t *src[], |
||
619 | int srcStride[], int srcSliceY, int srcSliceH, |
||
620 | uint8_t *dst[], int dstStride[]) |
||
621 | { |
||
622 | int alpha_first = 0; |
||
623 | const uint8_t *src102[] = { src[1], src[0], src[2] }; |
||
624 | const uint8_t *src201[] = { src[2], src[0], src[1] }; |
||
625 | int stride102[] = { srcStride[1], srcStride[0], srcStride[2] }; |
||
626 | int stride201[] = { srcStride[2], srcStride[0], srcStride[1] }; |
||
627 | |||
628 | if (c->srcFormat != AV_PIX_FMT_GBRP) { |
||
629 | av_log(c, AV_LOG_ERROR, "unsupported planar RGB conversion %s -> %s\n", |
||
630 | av_get_pix_fmt_name(c->srcFormat), |
||
631 | av_get_pix_fmt_name(c->dstFormat)); |
||
632 | return srcSliceH; |
||
633 | } |
||
634 | |||
635 | switch (c->dstFormat) { |
||
636 | case AV_PIX_FMT_BGR24: |
||
637 | gbr24ptopacked24(src102, stride102, |
||
638 | dst[0] + srcSliceY * dstStride[0], dstStride[0], |
||
639 | srcSliceH, c->srcW); |
||
640 | break; |
||
641 | |||
642 | case AV_PIX_FMT_RGB24: |
||
643 | gbr24ptopacked24(src201, stride201, |
||
644 | dst[0] + srcSliceY * dstStride[0], dstStride[0], |
||
645 | srcSliceH, c->srcW); |
||
646 | break; |
||
647 | |||
648 | case AV_PIX_FMT_ARGB: |
||
649 | alpha_first = 1; |
||
650 | case AV_PIX_FMT_RGBA: |
||
651 | gbr24ptopacked32(src201, stride201, |
||
652 | dst[0] + srcSliceY * dstStride[0], dstStride[0], |
||
653 | srcSliceH, alpha_first, c->srcW); |
||
654 | break; |
||
655 | |||
656 | case AV_PIX_FMT_ABGR: |
||
657 | alpha_first = 1; |
||
658 | case AV_PIX_FMT_BGRA: |
||
659 | gbr24ptopacked32(src102, stride102, |
||
660 | dst[0] + srcSliceY * dstStride[0], dstStride[0], |
||
661 | srcSliceH, alpha_first, c->srcW); |
||
662 | break; |
||
663 | |||
664 | default: |
||
665 | av_log(c, AV_LOG_ERROR, |
||
666 | "unsupported planar RGB conversion %s -> %s\n", |
||
667 | av_get_pix_fmt_name(c->srcFormat), |
||
668 | av_get_pix_fmt_name(c->dstFormat)); |
||
669 | } |
||
670 | |||
671 | return srcSliceH; |
||
672 | } |
||
673 | |||
674 | static int planarRgbToplanarRgbWrapper(SwsContext *c, const uint8_t *src[], |
||
675 | int srcStride[], int srcSliceY, int srcSliceH, |
||
676 | uint8_t *dst[], int dstStride[]) |
||
677 | { |
||
678 | copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW, |
||
679 | dst[0], dstStride[0]); |
||
680 | copyPlane(src[1], srcStride[1], srcSliceY, srcSliceH, c->srcW, |
||
681 | dst[1], dstStride[1]); |
||
682 | copyPlane(src[2], srcStride[2], srcSliceY, srcSliceH, c->srcW, |
||
683 | dst[2], dstStride[2]); |
||
684 | if (dst[3]) |
||
685 | fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255); |
||
686 | |||
687 | return srcSliceH; |
||
688 | } |
||
689 | |||
690 | static void packedtogbr24p(const uint8_t *src, int srcStride, |
||
691 | uint8_t *dst[], int dstStride[], int srcSliceH, |
||
692 | int alpha_first, int inc_size, int width) |
||
693 | { |
||
694 | uint8_t *dest[3]; |
||
695 | int x, h; |
||
696 | |||
697 | dest[0] = dst[0]; |
||
698 | dest[1] = dst[1]; |
||
699 | dest[2] = dst[2]; |
||
700 | |||
701 | if (alpha_first) |
||
702 | src++; |
||
703 | |||
704 | for (h = 0; h < srcSliceH; h++) { |
||
705 | for (x = 0; x < width; x++) { |
||
706 | dest[0][x] = src[0]; |
||
707 | dest[1][x] = src[1]; |
||
708 | dest[2][x] = src[2]; |
||
709 | |||
710 | src += inc_size; |
||
711 | } |
||
712 | src += srcStride - width * inc_size; |
||
713 | dest[0] += dstStride[0]; |
||
714 | dest[1] += dstStride[1]; |
||
715 | dest[2] += dstStride[2]; |
||
716 | } |
||
717 | } |
||
718 | |||
719 | static int rgbToPlanarRgbWrapper(SwsContext *c, const uint8_t *src[], |
||
720 | int srcStride[], int srcSliceY, int srcSliceH, |
||
721 | uint8_t *dst[], int dstStride[]) |
||
722 | { |
||
723 | int alpha_first = 0; |
||
724 | int stride102[] = { dstStride[1], dstStride[0], dstStride[2] }; |
||
725 | int stride201[] = { dstStride[2], dstStride[0], dstStride[1] }; |
||
726 | uint8_t *dst102[] = { dst[1] + srcSliceY * dstStride[1], |
||
727 | dst[0] + srcSliceY * dstStride[0], |
||
728 | dst[2] + srcSliceY * dstStride[2] }; |
||
729 | uint8_t *dst201[] = { dst[2] + srcSliceY * dstStride[2], |
||
730 | dst[0] + srcSliceY * dstStride[0], |
||
731 | dst[1] + srcSliceY * dstStride[1] }; |
||
732 | |||
733 | switch (c->srcFormat) { |
||
734 | case AV_PIX_FMT_RGB24: |
||
735 | packedtogbr24p((const uint8_t *) src[0], srcStride[0], dst201, |
||
736 | stride201, srcSliceH, alpha_first, 3, c->srcW); |
||
737 | break; |
||
738 | case AV_PIX_FMT_BGR24: |
||
739 | packedtogbr24p((const uint8_t *) src[0], srcStride[0], dst102, |
||
740 | stride102, srcSliceH, alpha_first, 3, c->srcW); |
||
741 | break; |
||
742 | case AV_PIX_FMT_ARGB: |
||
743 | alpha_first = 1; |
||
744 | case AV_PIX_FMT_RGBA: |
||
745 | packedtogbr24p((const uint8_t *) src[0], srcStride[0], dst201, |
||
746 | stride201, srcSliceH, alpha_first, 4, c->srcW); |
||
747 | break; |
||
748 | case AV_PIX_FMT_ABGR: |
||
749 | alpha_first = 1; |
||
750 | case AV_PIX_FMT_BGRA: |
||
751 | packedtogbr24p((const uint8_t *) src[0], srcStride[0], dst102, |
||
752 | stride102, srcSliceH, alpha_first, 4, c->srcW); |
||
753 | break; |
||
754 | default: |
||
755 | av_log(c, AV_LOG_ERROR, |
||
756 | "unsupported planar RGB conversion %s -> %s\n", |
||
757 | av_get_pix_fmt_name(c->srcFormat), |
||
758 | av_get_pix_fmt_name(c->dstFormat)); |
||
759 | } |
||
760 | |||
761 | return srcSliceH; |
||
762 | } |
||
763 | |||
764 | #define isRGBA32(x) ( \ |
||
765 | (x) == AV_PIX_FMT_ARGB \ |
||
766 | || (x) == AV_PIX_FMT_RGBA \ |
||
767 | || (x) == AV_PIX_FMT_BGRA \ |
||
768 | || (x) == AV_PIX_FMT_ABGR \ |
||
769 | ) |
||
770 | |||
771 | #define isRGBA64(x) ( \ |
||
772 | (x) == AV_PIX_FMT_RGBA64LE \ |
||
773 | || (x) == AV_PIX_FMT_RGBA64BE \ |
||
774 | || (x) == AV_PIX_FMT_BGRA64LE \ |
||
775 | || (x) == AV_PIX_FMT_BGRA64BE \ |
||
776 | ) |
||
777 | |||
778 | #define isRGB48(x) ( \ |
||
779 | (x) == AV_PIX_FMT_RGB48LE \ |
||
780 | || (x) == AV_PIX_FMT_RGB48BE \ |
||
781 | || (x) == AV_PIX_FMT_BGR48LE \ |
||
782 | || (x) == AV_PIX_FMT_BGR48BE \ |
||
783 | ) |
||
784 | |||
785 | /* {RGB,BGR}{15,16,24,32,32_1} -> {RGB,BGR}{15,16,24,32} */ |
||
786 | typedef void (* rgbConvFn) (const uint8_t *, uint8_t *, int); |
||
787 | static rgbConvFn findRgbConvFn(SwsContext *c) |
||
788 | { |
||
789 | const enum AVPixelFormat srcFormat = c->srcFormat; |
||
790 | const enum AVPixelFormat dstFormat = c->dstFormat; |
||
791 | const int srcId = c->srcFormatBpp; |
||
792 | const int dstId = c->dstFormatBpp; |
||
793 | rgbConvFn conv = NULL; |
||
794 | |||
795 | #define IS_NOT_NE(bpp, desc) \ |
||
796 | (((bpp + 7) >> 3) == 2 && \ |
||
797 | (!(desc->flags & AV_PIX_FMT_FLAG_BE) != !HAVE_BIGENDIAN)) |
||
798 | |||
799 | #define CONV_IS(src, dst) (srcFormat == AV_PIX_FMT_##src && dstFormat == AV_PIX_FMT_##dst) |
||
800 | |||
801 | if (isRGBA32(srcFormat) && isRGBA32(dstFormat)) { |
||
802 | if ( CONV_IS(ABGR, RGBA) |
||
803 | || CONV_IS(ARGB, BGRA) |
||
804 | || CONV_IS(BGRA, ARGB) |
||
805 | || CONV_IS(RGBA, ABGR)) conv = shuffle_bytes_3210; |
||
806 | else if (CONV_IS(ABGR, ARGB) |
||
807 | || CONV_IS(ARGB, ABGR)) conv = shuffle_bytes_0321; |
||
808 | else if (CONV_IS(ABGR, BGRA) |
||
809 | || CONV_IS(ARGB, RGBA)) conv = shuffle_bytes_1230; |
||
810 | else if (CONV_IS(BGRA, RGBA) |
||
811 | || CONV_IS(RGBA, BGRA)) conv = shuffle_bytes_2103; |
||
812 | else if (CONV_IS(BGRA, ABGR) |
||
813 | || CONV_IS(RGBA, ARGB)) conv = shuffle_bytes_3012; |
||
814 | } else if (isRGB48(srcFormat) && isRGB48(dstFormat)) { |
||
815 | if (CONV_IS(RGB48LE, BGR48LE) |
||
816 | || CONV_IS(BGR48LE, RGB48LE) |
||
817 | || CONV_IS(RGB48BE, BGR48BE) |
||
818 | || CONV_IS(BGR48BE, RGB48BE)) conv = rgb48tobgr48_nobswap; |
||
819 | else if (CONV_IS(RGB48LE, BGR48BE) |
||
820 | || CONV_IS(BGR48LE, RGB48BE) |
||
821 | || CONV_IS(RGB48BE, BGR48LE) |
||
822 | || CONV_IS(BGR48BE, RGB48LE)) conv = rgb48tobgr48_bswap; |
||
823 | } else if (isRGBA64(srcFormat) && isRGB48(dstFormat)) { |
||
824 | if (CONV_IS(RGBA64LE, BGR48LE) |
||
825 | || CONV_IS(BGRA64LE, RGB48LE) |
||
826 | || CONV_IS(RGBA64BE, BGR48BE) |
||
827 | || CONV_IS(BGRA64BE, RGB48BE)) conv = rgb64tobgr48_nobswap; |
||
828 | else if (CONV_IS(RGBA64LE, BGR48BE) |
||
829 | || CONV_IS(BGRA64LE, RGB48BE) |
||
830 | || CONV_IS(RGBA64BE, BGR48LE) |
||
831 | || CONV_IS(BGRA64BE, RGB48LE)) conv = rgb64tobgr48_bswap; |
||
832 | else if (CONV_IS(RGBA64LE, RGB48LE) |
||
833 | || CONV_IS(BGRA64LE, BGR48LE) |
||
834 | || CONV_IS(RGBA64BE, RGB48BE) |
||
835 | || CONV_IS(BGRA64BE, BGR48BE)) conv = rgb64to48_nobswap; |
||
836 | else if (CONV_IS(RGBA64LE, RGB48BE) |
||
837 | || CONV_IS(BGRA64LE, BGR48BE) |
||
838 | || CONV_IS(RGBA64BE, RGB48LE) |
||
839 | || CONV_IS(BGRA64BE, BGR48LE)) conv = rgb64to48_bswap; |
||
840 | } else |
||
841 | /* BGR -> BGR */ |
||
842 | if ((isBGRinInt(srcFormat) && isBGRinInt(dstFormat)) || |
||
843 | (isRGBinInt(srcFormat) && isRGBinInt(dstFormat))) { |
||
844 | switch (srcId | (dstId << 16)) { |
||
845 | case 0x000F000C: conv = rgb12to15; break; |
||
846 | case 0x000F0010: conv = rgb16to15; break; |
||
847 | case 0x000F0018: conv = rgb24to15; break; |
||
848 | case 0x000F0020: conv = rgb32to15; break; |
||
849 | case 0x0010000F: conv = rgb15to16; break; |
||
850 | case 0x00100018: conv = rgb24to16; break; |
||
851 | case 0x00100020: conv = rgb32to16; break; |
||
852 | case 0x0018000F: conv = rgb15to24; break; |
||
853 | case 0x00180010: conv = rgb16to24; break; |
||
854 | case 0x00180020: conv = rgb32to24; break; |
||
855 | case 0x0020000F: conv = rgb15to32; break; |
||
856 | case 0x00200010: conv = rgb16to32; break; |
||
857 | case 0x00200018: conv = rgb24to32; break; |
||
858 | } |
||
859 | } else if ((isBGRinInt(srcFormat) && isRGBinInt(dstFormat)) || |
||
860 | (isRGBinInt(srcFormat) && isBGRinInt(dstFormat))) { |
||
861 | switch (srcId | (dstId << 16)) { |
||
862 | case 0x000C000C: conv = rgb12tobgr12; break; |
||
863 | case 0x000F000F: conv = rgb15tobgr15; break; |
||
864 | case 0x000F0010: conv = rgb16tobgr15; break; |
||
865 | case 0x000F0018: conv = rgb24tobgr15; break; |
||
866 | case 0x000F0020: conv = rgb32tobgr15; break; |
||
867 | case 0x0010000F: conv = rgb15tobgr16; break; |
||
868 | case 0x00100010: conv = rgb16tobgr16; break; |
||
869 | case 0x00100018: conv = rgb24tobgr16; break; |
||
870 | case 0x00100020: conv = rgb32tobgr16; break; |
||
871 | case 0x0018000F: conv = rgb15tobgr24; break; |
||
872 | case 0x00180010: conv = rgb16tobgr24; break; |
||
873 | case 0x00180018: conv = rgb24tobgr24; break; |
||
874 | case 0x00180020: conv = rgb32tobgr24; break; |
||
875 | case 0x0020000F: conv = rgb15tobgr32; break; |
||
876 | case 0x00200010: conv = rgb16tobgr32; break; |
||
877 | case 0x00200018: conv = rgb24tobgr32; break; |
||
878 | } |
||
879 | } |
||
880 | |||
881 | if ((dstFormat == AV_PIX_FMT_RGB32_1 || dstFormat == AV_PIX_FMT_BGR32_1) && !isRGBA32(srcFormat) && ALT32_CORR<0) |
||
882 | return NULL; |
||
883 | |||
884 | return conv; |
||
885 | } |
||
886 | |||
887 | /* {RGB,BGR}{15,16,24,32,32_1} -> {RGB,BGR}{15,16,24,32} */ |
||
888 | static int rgbToRgbWrapper(SwsContext *c, const uint8_t *src[], int srcStride[], |
||
889 | int srcSliceY, int srcSliceH, uint8_t *dst[], |
||
890 | int dstStride[]) |
||
891 | |||
892 | { |
||
893 | const enum AVPixelFormat srcFormat = c->srcFormat; |
||
894 | const enum AVPixelFormat dstFormat = c->dstFormat; |
||
895 | const AVPixFmtDescriptor *desc_src = av_pix_fmt_desc_get(c->srcFormat); |
||
896 | const AVPixFmtDescriptor *desc_dst = av_pix_fmt_desc_get(c->dstFormat); |
||
897 | const int srcBpp = (c->srcFormatBpp + 7) >> 3; |
||
898 | const int dstBpp = (c->dstFormatBpp + 7) >> 3; |
||
899 | rgbConvFn conv = findRgbConvFn(c); |
||
900 | |||
901 | if (!conv) { |
||
902 | av_log(c, AV_LOG_ERROR, "internal error %s -> %s converter\n", |
||
903 | av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat)); |
||
904 | } else { |
||
905 | const uint8_t *srcPtr = src[0]; |
||
906 | uint8_t *dstPtr = dst[0]; |
||
907 | int src_bswap = IS_NOT_NE(c->srcFormatBpp, desc_src); |
||
908 | int dst_bswap = IS_NOT_NE(c->dstFormatBpp, desc_dst); |
||
909 | |||
910 | if ((srcFormat == AV_PIX_FMT_RGB32_1 || srcFormat == AV_PIX_FMT_BGR32_1) && |
||
911 | !isRGBA32(dstFormat)) |
||
912 | srcPtr += ALT32_CORR; |
||
913 | |||
914 | if ((dstFormat == AV_PIX_FMT_RGB32_1 || dstFormat == AV_PIX_FMT_BGR32_1) && |
||
915 | !isRGBA32(srcFormat)) { |
||
916 | int i; |
||
917 | av_assert0(ALT32_CORR == 1); |
||
918 | for (i = 0; i < srcSliceH; i++) |
||
919 | dstPtr[dstStride[0] * (srcSliceY + i)] = 255; |
||
920 | dstPtr += ALT32_CORR; |
||
921 | } |
||
922 | |||
923 | if (dstStride[0] * srcBpp == srcStride[0] * dstBpp && srcStride[0] > 0 && |
||
924 | !(srcStride[0] % srcBpp) && !dst_bswap && !src_bswap) |
||
925 | conv(srcPtr, dstPtr + dstStride[0] * srcSliceY, |
||
926 | srcSliceH * srcStride[0]); |
||
927 | else { |
||
928 | int i, j; |
||
929 | dstPtr += dstStride[0] * srcSliceY; |
||
930 | |||
931 | for (i = 0; i < srcSliceH; i++) { |
||
932 | if(src_bswap) { |
||
933 | for(j=0; j |
||
934 | ((uint16_t*)c->formatConvBuffer)[j] = av_bswap16(((uint16_t*)srcPtr)[j]); |
||
935 | conv(c->formatConvBuffer, dstPtr, c->srcW * srcBpp); |
||
936 | }else |
||
937 | conv(srcPtr, dstPtr, c->srcW * srcBpp); |
||
938 | if(dst_bswap) |
||
939 | for(j=0; j |
||
940 | ((uint16_t*)dstPtr)[j] = av_bswap16(((uint16_t*)dstPtr)[j]); |
||
941 | srcPtr += srcStride[0]; |
||
942 | dstPtr += dstStride[0]; |
||
943 | } |
||
944 | } |
||
945 | } |
||
946 | return srcSliceH; |
||
947 | } |
||
948 | |||
949 | static int bgr24ToYv12Wrapper(SwsContext *c, const uint8_t *src[], |
||
950 | int srcStride[], int srcSliceY, int srcSliceH, |
||
951 | uint8_t *dst[], int dstStride[]) |
||
952 | { |
||
953 | ff_rgb24toyv12( |
||
954 | src[0], |
||
955 | dst[0] + srcSliceY * dstStride[0], |
||
956 | dst[1] + (srcSliceY >> 1) * dstStride[1], |
||
957 | dst[2] + (srcSliceY >> 1) * dstStride[2], |
||
958 | c->srcW, srcSliceH, |
||
959 | dstStride[0], dstStride[1], srcStride[0], |
||
960 | c->input_rgb2yuv_table); |
||
961 | if (dst[3]) |
||
962 | fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255); |
||
963 | return srcSliceH; |
||
964 | } |
||
965 | |||
966 | static int yvu9ToYv12Wrapper(SwsContext *c, const uint8_t *src[], |
||
967 | int srcStride[], int srcSliceY, int srcSliceH, |
||
968 | uint8_t *dst[], int dstStride[]) |
||
969 | { |
||
970 | copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW, |
||
971 | dst[0], dstStride[0]); |
||
972 | |||
973 | planar2x(src[1], dst[1] + dstStride[1] * (srcSliceY >> 1), c->chrSrcW, |
||
974 | srcSliceH >> 2, srcStride[1], dstStride[1]); |
||
975 | planar2x(src[2], dst[2] + dstStride[2] * (srcSliceY >> 1), c->chrSrcW, |
||
976 | srcSliceH >> 2, srcStride[2], dstStride[2]); |
||
977 | if (dst[3]) |
||
978 | fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255); |
||
979 | return srcSliceH; |
||
980 | } |
||
981 | |||
982 | /* unscaled copy like stuff (assumes nearly identical formats) */ |
||
983 | static int packedCopyWrapper(SwsContext *c, const uint8_t *src[], |
||
984 | int srcStride[], int srcSliceY, int srcSliceH, |
||
985 | uint8_t *dst[], int dstStride[]) |
||
986 | { |
||
987 | if (dstStride[0] == srcStride[0] && srcStride[0] > 0) |
||
988 | memcpy(dst[0] + dstStride[0] * srcSliceY, src[0], srcSliceH * dstStride[0]); |
||
989 | else { |
||
990 | int i; |
||
991 | const uint8_t *srcPtr = src[0]; |
||
992 | uint8_t *dstPtr = dst[0] + dstStride[0] * srcSliceY; |
||
993 | int length = 0; |
||
994 | |||
995 | /* universal length finder */ |
||
996 | while (length + c->srcW <= FFABS(dstStride[0]) && |
||
997 | length + c->srcW <= FFABS(srcStride[0])) |
||
998 | length += c->srcW; |
||
999 | av_assert1(length != 0); |
||
1000 | |||
1001 | for (i = 0; i < srcSliceH; i++) { |
||
1002 | memcpy(dstPtr, srcPtr, length); |
||
1003 | srcPtr += srcStride[0]; |
||
1004 | dstPtr += dstStride[0]; |
||
1005 | } |
||
1006 | } |
||
1007 | return srcSliceH; |
||
1008 | } |
||
1009 | |||
1010 | #define DITHER_COPY(dst, dstStride, src, srcStride, bswap, dbswap)\ |
||
1011 | uint16_t scale= dither_scale[dst_depth-1][src_depth-1];\ |
||
1012 | int shift= src_depth-dst_depth + dither_scale[src_depth-2][dst_depth-1];\ |
||
1013 | for (i = 0; i < height; i++) {\ |
||
1014 | const uint8_t *dither= dithers[src_depth-9][i&7];\ |
||
1015 | for (j = 0; j < length-7; j+=8){\ |
||
1016 | dst[j+0] = dbswap((bswap(src[j+0]) + dither[0])*scale>>shift);\ |
||
1017 | dst[j+1] = dbswap((bswap(src[j+1]) + dither[1])*scale>>shift);\ |
||
1018 | dst[j+2] = dbswap((bswap(src[j+2]) + dither[2])*scale>>shift);\ |
||
1019 | dst[j+3] = dbswap((bswap(src[j+3]) + dither[3])*scale>>shift);\ |
||
1020 | dst[j+4] = dbswap((bswap(src[j+4]) + dither[4])*scale>>shift);\ |
||
1021 | dst[j+5] = dbswap((bswap(src[j+5]) + dither[5])*scale>>shift);\ |
||
1022 | dst[j+6] = dbswap((bswap(src[j+6]) + dither[6])*scale>>shift);\ |
||
1023 | dst[j+7] = dbswap((bswap(src[j+7]) + dither[7])*scale>>shift);\ |
||
1024 | }\ |
||
1025 | for (; j < length; j++)\ |
||
1026 | dst[j] = dbswap((bswap(src[j]) + dither[j&7])*scale>>shift);\ |
||
1027 | dst += dstStride;\ |
||
1028 | src += srcStride;\ |
||
1029 | } |
||
1030 | |||
1031 | static int planarCopyWrapper(SwsContext *c, const uint8_t *src[], |
||
1032 | int srcStride[], int srcSliceY, int srcSliceH, |
||
1033 | uint8_t *dst[], int dstStride[]) |
||
1034 | { |
||
1035 | const AVPixFmtDescriptor *desc_src = av_pix_fmt_desc_get(c->srcFormat); |
||
1036 | const AVPixFmtDescriptor *desc_dst = av_pix_fmt_desc_get(c->dstFormat); |
||
1037 | int plane, i, j; |
||
1038 | for (plane = 0; plane < 4; plane++) { |
||
1039 | int length = (plane == 0 || plane == 3) ? c->srcW : FF_CEIL_RSHIFT(c->srcW, c->chrDstHSubSample); |
||
1040 | int y = (plane == 0 || plane == 3) ? srcSliceY: FF_CEIL_RSHIFT(srcSliceY, c->chrDstVSubSample); |
||
1041 | int height = (plane == 0 || plane == 3) ? srcSliceH: FF_CEIL_RSHIFT(srcSliceH, c->chrDstVSubSample); |
||
1042 | const uint8_t *srcPtr = src[plane]; |
||
1043 | uint8_t *dstPtr = dst[plane] + dstStride[plane] * y; |
||
1044 | int shiftonly= plane==1 || plane==2 || (!c->srcRange && plane==0); |
||
1045 | |||
1046 | if (!dst[plane]) |
||
1047 | continue; |
||
1048 | // ignore palette for GRAY8 |
||
1049 | if (plane == 1 && !dst[2]) continue; |
||
1050 | if (!src[plane] || (plane == 1 && !src[2])) { |
||
1051 | if (is16BPS(c->dstFormat) || isNBPS(c->dstFormat)) { |
||
1052 | fillPlane16(dst[plane], dstStride[plane], length, height, y, |
||
1053 | plane == 3, desc_dst->comp[plane].depth_minus1, |
||
1054 | isBE(c->dstFormat)); |
||
1055 | } else { |
||
1056 | fillPlane(dst[plane], dstStride[plane], length, height, y, |
||
1057 | (plane == 3) ? 255 : 128); |
||
1058 | } |
||
1059 | } else { |
||
1060 | if(isNBPS(c->srcFormat) || isNBPS(c->dstFormat) |
||
1061 | || (is16BPS(c->srcFormat) != is16BPS(c->dstFormat)) |
||
1062 | ) { |
||
1063 | const int src_depth = desc_src->comp[plane].depth_minus1 + 1; |
||
1064 | const int dst_depth = desc_dst->comp[plane].depth_minus1 + 1; |
||
1065 | const uint16_t *srcPtr2 = (const uint16_t *) srcPtr; |
||
1066 | uint16_t *dstPtr2 = (uint16_t*)dstPtr; |
||
1067 | |||
1068 | if (dst_depth == 8) { |
||
1069 | if(isBE(c->srcFormat) == HAVE_BIGENDIAN){ |
||
1070 | DITHER_COPY(dstPtr, dstStride[plane], srcPtr2, srcStride[plane]/2, , ) |
||
1071 | } else { |
||
1072 | DITHER_COPY(dstPtr, dstStride[plane], srcPtr2, srcStride[plane]/2, av_bswap16, ) |
||
1073 | } |
||
1074 | } else if (src_depth == 8) { |
||
1075 | for (i = 0; i < height; i++) { |
||
1076 | #define COPY816(w)\ |
||
1077 | if(shiftonly){\ |
||
1078 | for (j = 0; j < length; j++)\ |
||
1079 | w(&dstPtr2[j], srcPtr[j]<<(dst_depth-8));\ |
||
1080 | }else{\ |
||
1081 | for (j = 0; j < length; j++)\ |
||
1082 | w(&dstPtr2[j], (srcPtr[j]<<(dst_depth-8)) |\ |
||
1083 | (srcPtr[j]>>(2*8-dst_depth)));\ |
||
1084 | } |
||
1085 | if(isBE(c->dstFormat)){ |
||
1086 | COPY816(AV_WB16) |
||
1087 | } else { |
||
1088 | COPY816(AV_WL16) |
||
1089 | } |
||
1090 | dstPtr2 += dstStride[plane]/2; |
||
1091 | srcPtr += srcStride[plane]; |
||
1092 | } |
||
1093 | } else if (src_depth <= dst_depth) { |
||
1094 | int orig_length = length; |
||
1095 | for (i = 0; i < height; i++) { |
||
1096 | if(isBE(c->srcFormat) == HAVE_BIGENDIAN && |
||
1097 | isBE(c->dstFormat) == HAVE_BIGENDIAN && |
||
1098 | shiftonly) { |
||
1099 | unsigned shift = dst_depth - src_depth; |
||
1100 | length = orig_length; |
||
1101 | #if HAVE_FAST_64BIT |
||
1102 | #define FAST_COPY_UP(shift) \ |
||
1103 | for (j = 0; j < length - 3; j += 4) { \ |
||
1104 | uint64_t v = AV_RN64A(srcPtr2 + j); \ |
||
1105 | AV_WN64A(dstPtr2 + j, v << shift); \ |
||
1106 | } \ |
||
1107 | length &= 3; |
||
1108 | #else |
||
1109 | #define FAST_COPY_UP(shift) \ |
||
1110 | for (j = 0; j < length - 1; j += 2) { \ |
||
1111 | uint32_t v = AV_RN32A(srcPtr2 + j); \ |
||
1112 | AV_WN32A(dstPtr2 + j, v << shift); \ |
||
1113 | } \ |
||
1114 | length &= 1; |
||
1115 | #endif |
||
1116 | switch (shift) |
||
1117 | { |
||
1118 | case 6: FAST_COPY_UP(6); break; |
||
1119 | case 7: FAST_COPY_UP(7); break; |
||
1120 | } |
||
1121 | } |
||
1122 | #define COPY_UP(r,w) \ |
||
1123 | if(shiftonly){\ |
||
1124 | for (j = 0; j < length; j++){ \ |
||
1125 | unsigned int v= r(&srcPtr2[j]);\ |
||
1126 | w(&dstPtr2[j], v<<(dst_depth-src_depth));\ |
||
1127 | }\ |
||
1128 | }else{\ |
||
1129 | for (j = 0; j < length; j++){ \ |
||
1130 | unsigned int v= r(&srcPtr2[j]);\ |
||
1131 | w(&dstPtr2[j], (v<<(dst_depth-src_depth)) | \ |
||
1132 | (v>>(2*src_depth-dst_depth)));\ |
||
1133 | }\ |
||
1134 | } |
||
1135 | if(isBE(c->srcFormat)){ |
||
1136 | if(isBE(c->dstFormat)){ |
||
1137 | COPY_UP(AV_RB16, AV_WB16) |
||
1138 | } else { |
||
1139 | COPY_UP(AV_RB16, AV_WL16) |
||
1140 | } |
||
1141 | } else { |
||
1142 | if(isBE(c->dstFormat)){ |
||
1143 | COPY_UP(AV_RL16, AV_WB16) |
||
1144 | } else { |
||
1145 | COPY_UP(AV_RL16, AV_WL16) |
||
1146 | } |
||
1147 | } |
||
1148 | dstPtr2 += dstStride[plane]/2; |
||
1149 | srcPtr2 += srcStride[plane]/2; |
||
1150 | } |
||
1151 | } else { |
||
1152 | if(isBE(c->srcFormat) == HAVE_BIGENDIAN){ |
||
1153 | if(isBE(c->dstFormat) == HAVE_BIGENDIAN){ |
||
1154 | DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, , ) |
||
1155 | } else { |
||
1156 | DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, , av_bswap16) |
||
1157 | } |
||
1158 | }else{ |
||
1159 | if(isBE(c->dstFormat) == HAVE_BIGENDIAN){ |
||
1160 | DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, av_bswap16, ) |
||
1161 | } else { |
||
1162 | DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, av_bswap16, av_bswap16) |
||
1163 | } |
||
1164 | } |
||
1165 | } |
||
1166 | } else if (is16BPS(c->srcFormat) && is16BPS(c->dstFormat) && |
||
1167 | isBE(c->srcFormat) != isBE(c->dstFormat)) { |
||
1168 | |||
1169 | for (i = 0; i < height; i++) { |
||
1170 | for (j = 0; j < length; j++) |
||
1171 | ((uint16_t *) dstPtr)[j] = av_bswap16(((const uint16_t *) srcPtr)[j]); |
||
1172 | srcPtr += srcStride[plane]; |
||
1173 | dstPtr += dstStride[plane]; |
||
1174 | } |
||
1175 | } else if (dstStride[plane] == srcStride[plane] && |
||
1176 | srcStride[plane] > 0 && srcStride[plane] == length) { |
||
1177 | memcpy(dst[plane] + dstStride[plane] * y, src[plane], |
||
1178 | height * dstStride[plane]); |
||
1179 | } else { |
||
1180 | if (is16BPS(c->srcFormat) && is16BPS(c->dstFormat)) |
||
1181 | length *= 2; |
||
1182 | else if (!desc_src->comp[0].depth_minus1) |
||
1183 | length >>= 3; // monowhite/black |
||
1184 | for (i = 0; i < height; i++) { |
||
1185 | memcpy(dstPtr, srcPtr, length); |
||
1186 | srcPtr += srcStride[plane]; |
||
1187 | dstPtr += dstStride[plane]; |
||
1188 | } |
||
1189 | } |
||
1190 | } |
||
1191 | } |
||
1192 | return srcSliceH; |
||
1193 | } |
||
1194 | |||
1195 | |||
1196 | #define IS_DIFFERENT_ENDIANESS(src_fmt, dst_fmt, pix_fmt) \ |
||
1197 | ((src_fmt == pix_fmt ## BE && dst_fmt == pix_fmt ## LE) || \ |
||
1198 | (src_fmt == pix_fmt ## LE && dst_fmt == pix_fmt ## BE)) |
||
1199 | |||
1200 | |||
1201 | void ff_get_unscaled_swscale(SwsContext *c) |
||
1202 | { |
||
1203 | const enum AVPixelFormat srcFormat = c->srcFormat; |
||
1204 | const enum AVPixelFormat dstFormat = c->dstFormat; |
||
1205 | const int flags = c->flags; |
||
1206 | const int dstH = c->dstH; |
||
1207 | int needsDither; |
||
1208 | |||
1209 | needsDither = isAnyRGB(dstFormat) && |
||
1210 | c->dstFormatBpp < 24 && |
||
1211 | (c->dstFormatBpp < c->srcFormatBpp || (!isAnyRGB(srcFormat))); |
||
1212 | |||
1213 | /* yv12_to_nv12 */ |
||
1214 | if ((srcFormat == AV_PIX_FMT_YUV420P || srcFormat == AV_PIX_FMT_YUVA420P) && |
||
1215 | (dstFormat == AV_PIX_FMT_NV12 || dstFormat == AV_PIX_FMT_NV21)) { |
||
1216 | c->swscale = planarToNv12Wrapper; |
||
1217 | } |
||
1218 | /* yuv2bgr */ |
||
1219 | if ((srcFormat == AV_PIX_FMT_YUV420P || srcFormat == AV_PIX_FMT_YUV422P || |
||
1220 | srcFormat == AV_PIX_FMT_YUVA420P) && isAnyRGB(dstFormat) && |
||
1221 | !(flags & SWS_ACCURATE_RND) && (c->dither == SWS_DITHER_BAYER || c->dither == SWS_DITHER_AUTO) && !(dstH & 1)) { |
||
1222 | c->swscale = ff_yuv2rgb_get_func_ptr(c); |
||
1223 | } |
||
1224 | |||
1225 | if (srcFormat == AV_PIX_FMT_YUV410P && |
||
1226 | (dstFormat == AV_PIX_FMT_YUV420P || dstFormat == AV_PIX_FMT_YUVA420P) && |
||
1227 | !(flags & SWS_BITEXACT)) { |
||
1228 | c->swscale = yvu9ToYv12Wrapper; |
||
1229 | } |
||
1230 | |||
1231 | /* bgr24toYV12 */ |
||
1232 | if (srcFormat == AV_PIX_FMT_BGR24 && |
||
1233 | (dstFormat == AV_PIX_FMT_YUV420P || dstFormat == AV_PIX_FMT_YUVA420P) && |
||
1234 | !(flags & SWS_ACCURATE_RND)) |
||
1235 | c->swscale = bgr24ToYv12Wrapper; |
||
1236 | |||
1237 | /* RGB/BGR -> RGB/BGR (no dither needed forms) */ |
||
1238 | if (isAnyRGB(srcFormat) && isAnyRGB(dstFormat) && findRgbConvFn(c) |
||
1239 | && (!needsDither || (c->flags&(SWS_FAST_BILINEAR|SWS_POINT)))) |
||
1240 | c->swscale = rgbToRgbWrapper; |
||
1241 | |||
1242 | if ((srcFormat == AV_PIX_FMT_GBRP && dstFormat == AV_PIX_FMT_GBRAP) || |
||
1243 | (srcFormat == AV_PIX_FMT_GBRAP && dstFormat == AV_PIX_FMT_GBRP)) |
||
1244 | c->swscale = planarRgbToplanarRgbWrapper; |
||
1245 | |||
1246 | #define isByteRGB(f) ( \ |
||
1247 | f == AV_PIX_FMT_RGB32 || \ |
||
1248 | f == AV_PIX_FMT_RGB32_1 || \ |
||
1249 | f == AV_PIX_FMT_RGB24 || \ |
||
1250 | f == AV_PIX_FMT_BGR32 || \ |
||
1251 | f == AV_PIX_FMT_BGR32_1 || \ |
||
1252 | f == AV_PIX_FMT_BGR24) |
||
1253 | |||
1254 | if (srcFormat == AV_PIX_FMT_GBRP && isPlanar(srcFormat) && isByteRGB(dstFormat)) |
||
1255 | c->swscale = planarRgbToRgbWrapper; |
||
1256 | |||
1257 | if ((srcFormat == AV_PIX_FMT_GBRP9LE || srcFormat == AV_PIX_FMT_GBRP9BE || |
||
1258 | srcFormat == AV_PIX_FMT_GBRP16LE || srcFormat == AV_PIX_FMT_GBRP16BE || |
||
1259 | srcFormat == AV_PIX_FMT_GBRP10LE || srcFormat == AV_PIX_FMT_GBRP10BE || |
||
1260 | srcFormat == AV_PIX_FMT_GBRP12LE || srcFormat == AV_PIX_FMT_GBRP12BE || |
||
1261 | srcFormat == AV_PIX_FMT_GBRP14LE || srcFormat == AV_PIX_FMT_GBRP14BE || |
||
1262 | srcFormat == AV_PIX_FMT_GBRAP16LE || srcFormat == AV_PIX_FMT_GBRAP16BE) && |
||
1263 | (dstFormat == AV_PIX_FMT_RGB48LE || dstFormat == AV_PIX_FMT_RGB48BE || |
||
1264 | dstFormat == AV_PIX_FMT_BGR48LE || dstFormat == AV_PIX_FMT_BGR48BE || |
||
1265 | dstFormat == AV_PIX_FMT_RGBA64LE || dstFormat == AV_PIX_FMT_RGBA64BE || |
||
1266 | dstFormat == AV_PIX_FMT_BGRA64LE || dstFormat == AV_PIX_FMT_BGRA64BE)) |
||
1267 | c->swscale = planarRgb16ToRgb16Wrapper; |
||
1268 | |||
1269 | if (av_pix_fmt_desc_get(srcFormat)->comp[0].depth_minus1 == 7 && |
||
1270 | isPackedRGB(srcFormat) && dstFormat == AV_PIX_FMT_GBRP) |
||
1271 | c->swscale = rgbToPlanarRgbWrapper; |
||
1272 | |||
1273 | /* bswap 16 bits per pixel/component packed formats */ |
||
1274 | if (IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGR444) || |
||
1275 | IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGR48) || |
||
1276 | IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGRA64) || |
||
1277 | IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGR555) || |
||
1278 | IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_BGR565) || |
||
1279 | IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GRAY16) || |
||
1280 | IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRP9) || |
||
1281 | IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRP10) || |
||
1282 | IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRP12) || |
||
1283 | IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRP14) || |
||
1284 | IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRP16) || |
||
1285 | IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRAP16) || |
||
1286 | IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB444) || |
||
1287 | IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB48) || |
||
1288 | IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGBA64) || |
||
1289 | IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB555) || |
||
1290 | IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB565) || |
||
1291 | IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_XYZ12) || |
||
1292 | IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV420P9) || |
||
1293 | IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV420P10) || |
||
1294 | IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV420P12) || |
||
1295 | IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV420P14) || |
||
1296 | IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV420P16) || |
||
1297 | IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV422P9) || |
||
1298 | IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV422P10) || |
||
1299 | IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV422P12) || |
||
1300 | IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV422P14) || |
||
1301 | IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV422P16) || |
||
1302 | IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV444P9) || |
||
1303 | IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV444P10) || |
||
1304 | IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV444P12) || |
||
1305 | IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV444P14) || |
||
1306 | IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_YUV444P16)) |
||
1307 | c->swscale = packed_16bpc_bswap; |
||
1308 | |||
1309 | if (usePal(srcFormat) && isByteRGB(dstFormat)) |
||
1310 | c->swscale = palToRgbWrapper; |
||
1311 | |||
1312 | if (srcFormat == AV_PIX_FMT_YUV422P) { |
||
1313 | if (dstFormat == AV_PIX_FMT_YUYV422) |
||
1314 | c->swscale = yuv422pToYuy2Wrapper; |
||
1315 | else if (dstFormat == AV_PIX_FMT_UYVY422) |
||
1316 | c->swscale = yuv422pToUyvyWrapper; |
||
1317 | } |
||
1318 | |||
1319 | /* LQ converters if -sws 0 or -sws 4*/ |
||
1320 | if (c->flags&(SWS_FAST_BILINEAR|SWS_POINT)) { |
||
1321 | /* yv12_to_yuy2 */ |
||
1322 | if (srcFormat == AV_PIX_FMT_YUV420P || srcFormat == AV_PIX_FMT_YUVA420P) { |
||
1323 | if (dstFormat == AV_PIX_FMT_YUYV422) |
||
1324 | c->swscale = planarToYuy2Wrapper; |
||
1325 | else if (dstFormat == AV_PIX_FMT_UYVY422) |
||
1326 | c->swscale = planarToUyvyWrapper; |
||
1327 | } |
||
1328 | } |
||
1329 | if (srcFormat == AV_PIX_FMT_YUYV422 && |
||
1330 | (dstFormat == AV_PIX_FMT_YUV420P || dstFormat == AV_PIX_FMT_YUVA420P)) |
||
1331 | c->swscale = yuyvToYuv420Wrapper; |
||
1332 | if (srcFormat == AV_PIX_FMT_UYVY422 && |
||
1333 | (dstFormat == AV_PIX_FMT_YUV420P || dstFormat == AV_PIX_FMT_YUVA420P)) |
||
1334 | c->swscale = uyvyToYuv420Wrapper; |
||
1335 | if (srcFormat == AV_PIX_FMT_YUYV422 && dstFormat == AV_PIX_FMT_YUV422P) |
||
1336 | c->swscale = yuyvToYuv422Wrapper; |
||
1337 | if (srcFormat == AV_PIX_FMT_UYVY422 && dstFormat == AV_PIX_FMT_YUV422P) |
||
1338 | c->swscale = uyvyToYuv422Wrapper; |
||
1339 | |||
1340 | #define isPlanarGray(x) (isGray(x) && (x) != AV_PIX_FMT_GRAY8A) |
||
1341 | /* simple copy */ |
||
1342 | if ( srcFormat == dstFormat || |
||
1343 | (srcFormat == AV_PIX_FMT_YUVA420P && dstFormat == AV_PIX_FMT_YUV420P) || |
||
1344 | (srcFormat == AV_PIX_FMT_YUV420P && dstFormat == AV_PIX_FMT_YUVA420P) || |
||
1345 | (isPlanarYUV(srcFormat) && isPlanarGray(dstFormat)) || |
||
1346 | (isPlanarYUV(dstFormat) && isPlanarGray(srcFormat)) || |
||
1347 | (isPlanarGray(dstFormat) && isPlanarGray(srcFormat)) || |
||
1348 | (isPlanarYUV(srcFormat) && isPlanarYUV(dstFormat) && |
||
1349 | c->chrDstHSubSample == c->chrSrcHSubSample && |
||
1350 | c->chrDstVSubSample == c->chrSrcVSubSample && |
||
1351 | dstFormat != AV_PIX_FMT_NV12 && dstFormat != AV_PIX_FMT_NV21 && |
||
1352 | srcFormat != AV_PIX_FMT_NV12 && srcFormat != AV_PIX_FMT_NV21)) |
||
1353 | { |
||
1354 | if (isPacked(c->srcFormat)) |
||
1355 | c->swscale = packedCopyWrapper; |
||
1356 | else /* Planar YUV or gray */ |
||
1357 | c->swscale = planarCopyWrapper; |
||
1358 | } |
||
1359 | |||
1360 | if (ARCH_BFIN) |
||
1361 | ff_get_unscaled_swscale_bfin(c); |
||
1362 | if (ARCH_PPC) |
||
1363 | ff_get_unscaled_swscale_ppc(c); |
||
1364 | } |
||
1365 | |||
1366 | /* Convert the palette to the same packed 32-bit format as the palette */ |
||
1367 | void sws_convertPalette8ToPacked32(const uint8_t *src, uint8_t *dst, |
||
1368 | int num_pixels, const uint8_t *palette) |
||
1369 | { |
||
1370 | int i; |
||
1371 | |||
1372 | for (i = 0; i < num_pixels; i++) |
||
1373 | ((uint32_t *) dst)[i] = ((const uint32_t *) palette)[src[i]]; |
||
1374 | } |
||
1375 | |||
1376 | /* Palette format: ABCD -> dst format: ABC */ |
||
1377 | void sws_convertPalette8ToPacked24(const uint8_t *src, uint8_t *dst, |
||
1378 | int num_pixels, const uint8_t *palette) |
||
1379 | { |
||
1380 | int i; |
||
1381 | |||
1382 | for (i = 0; i < num_pixels; i++) { |
||
1383 | //FIXME slow? |
||
1384 | dst[0] = palette[src[i] * 4 + 0]; |
||
1385 | dst[1] = palette[src[i] * 4 + 1]; |
||
1386 | dst[2] = palette[src[i] * 4 + 2]; |
||
1387 | dst += 3; |
||
1388 | } |
||
1389 | }>>>>>>>(dst_depth-src_depth))><(dst_depth-src_depth))>>(dst_depth-src_depth));\ |