Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4349 | Serge | 1 | /* |
2 | * software RGB to RGB converter |
||
3 | * pluralize by software PAL8 to RGB converter |
||
4 | * software YUV to YUV converter |
||
5 | * software YUV to RGB converter |
||
6 | * Written by Nick Kurshev. |
||
7 | * palette & YUV & runtime CPU stuff by Michael (michaelni@gmx.at) |
||
8 | * lot of big-endian byte order fixes by Alex Beregszaszi |
||
9 | * |
||
10 | * This file is part of FFmpeg. |
||
11 | * |
||
12 | * FFmpeg is free software; you can redistribute it and/or |
||
13 | * modify it under the terms of the GNU Lesser General Public |
||
14 | * License as published by the Free Software Foundation; either |
||
15 | * version 2.1 of the License, or (at your option) any later version. |
||
16 | * |
||
17 | * FFmpeg is distributed in the hope that it will be useful, |
||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||
20 | * Lesser General Public License for more details. |
||
21 | * |
||
22 | * You should have received a copy of the GNU Lesser General Public |
||
23 | * License along with FFmpeg; if not, write to the Free Software |
||
24 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
||
25 | */ |
||
26 | |||
27 | #include |
||
28 | |||
29 | #include "libavutil/attributes.h" |
||
30 | |||
31 | static inline void rgb24tobgr32_c(const uint8_t *src, uint8_t *dst, |
||
32 | int src_size) |
||
33 | { |
||
34 | uint8_t *dest = dst; |
||
35 | const uint8_t *s = src; |
||
36 | const uint8_t *end = s + src_size; |
||
37 | |||
38 | while (s < end) { |
||
39 | #if HAVE_BIGENDIAN |
||
40 | /* RGB24 (= R, G, B) -> RGB32 (= A, B, G, R) */ |
||
41 | *dest++ = 255; |
||
42 | *dest++ = s[2]; |
||
43 | *dest++ = s[1]; |
||
44 | *dest++ = s[0]; |
||
45 | s += 3; |
||
46 | #else |
||
47 | *dest++ = *s++; |
||
48 | *dest++ = *s++; |
||
49 | *dest++ = *s++; |
||
50 | *dest++ = 255; |
||
51 | #endif |
||
52 | } |
||
53 | } |
||
54 | |||
55 | static inline void rgb32tobgr24_c(const uint8_t *src, uint8_t *dst, |
||
56 | int src_size) |
||
57 | { |
||
58 | uint8_t *dest = dst; |
||
59 | const uint8_t *s = src; |
||
60 | const uint8_t *end = s + src_size; |
||
61 | |||
62 | while (s < end) { |
||
63 | #if HAVE_BIGENDIAN |
||
64 | /* RGB32 (= A, B, G, R) -> RGB24 (= R, G, B) */ |
||
65 | s++; |
||
66 | dest[2] = *s++; |
||
67 | dest[1] = *s++; |
||
68 | dest[0] = *s++; |
||
69 | dest += 3; |
||
70 | #else |
||
71 | *dest++ = *s++; |
||
72 | *dest++ = *s++; |
||
73 | *dest++ = *s++; |
||
74 | s++; |
||
75 | #endif |
||
76 | } |
||
77 | } |
||
78 | |||
79 | /* |
||
80 | * original by Strepto/Astral |
||
81 | * ported to gcc & bugfixed: A'rpi |
||
82 | * MMXEXT, 3DNOW optimization by Nick Kurshev |
||
83 | * 32-bit C version, and and&add trick by Michael Niedermayer |
||
84 | */ |
||
85 | static inline void rgb15to16_c(const uint8_t *src, uint8_t *dst, int src_size) |
||
86 | { |
||
87 | register uint8_t *d = dst; |
||
88 | register const uint8_t *s = src; |
||
89 | register const uint8_t *end = s + src_size; |
||
90 | const uint8_t *mm_end = end - 3; |
||
91 | |||
92 | while (s < mm_end) { |
||
93 | register unsigned x = *((const uint32_t *)s); |
||
94 | *((uint32_t *)d) = (x & 0x7FFF7FFF) + (x & 0x7FE07FE0); |
||
95 | d += 4; |
||
96 | s += 4; |
||
97 | } |
||
98 | if (s < end) { |
||
99 | register unsigned short x = *((const uint16_t *)s); |
||
100 | *((uint16_t *)d) = (x & 0x7FFF) + (x & 0x7FE0); |
||
101 | } |
||
102 | } |
||
103 | |||
104 | static inline void rgb16to15_c(const uint8_t *src, uint8_t *dst, int src_size) |
||
105 | { |
||
106 | register uint8_t *d = dst; |
||
107 | register const uint8_t *s = src; |
||
108 | register const uint8_t *end = s + src_size; |
||
109 | const uint8_t *mm_end = end - 3; |
||
110 | |||
111 | while (s < mm_end) { |
||
112 | register uint32_t x = *((const uint32_t *)s); |
||
113 | *((uint32_t *)d) = ((x >> 1) & 0x7FE07FE0) | (x & 0x001F001F); |
||
114 | s += 4; |
||
115 | d += 4; |
||
116 | } |
||
117 | if (s < end) { |
||
118 | register uint16_t x = *((const uint16_t *)s); |
||
119 | *((uint16_t *)d) = ((x >> 1) & 0x7FE0) | (x & 0x001F); |
||
120 | } |
||
121 | } |
||
122 | |||
123 | static inline void rgb32to16_c(const uint8_t *src, uint8_t *dst, int src_size) |
||
124 | { |
||
125 | uint16_t *d = (uint16_t *)dst; |
||
126 | const uint8_t *s = src; |
||
127 | const uint8_t *end = s + src_size; |
||
128 | |||
129 | while (s < end) { |
||
130 | register int rgb = *(const uint32_t *)s; |
||
131 | s += 4; |
||
132 | *d++ = ((rgb & 0xFF) >> 3) + |
||
133 | ((rgb & 0xFC00) >> 5) + |
||
134 | ((rgb & 0xF80000) >> 8); |
||
135 | } |
||
136 | } |
||
137 | |||
138 | static inline void rgb32tobgr16_c(const uint8_t *src, uint8_t *dst, |
||
139 | int src_size) |
||
140 | { |
||
141 | uint16_t *d = (uint16_t *)dst; |
||
142 | const uint8_t *s = src; |
||
143 | const uint8_t *end = s + src_size; |
||
144 | |||
145 | while (s < end) { |
||
146 | register int rgb = *(const uint32_t *)s; |
||
147 | s += 4; |
||
148 | *d++ = ((rgb & 0xF8) << 8) + |
||
149 | ((rgb & 0xFC00) >> 5) + |
||
150 | ((rgb & 0xF80000) >> 19); |
||
151 | } |
||
152 | } |
||
153 | |||
154 | static inline void rgb32to15_c(const uint8_t *src, uint8_t *dst, int src_size) |
||
155 | { |
||
156 | uint16_t *d = (uint16_t *)dst; |
||
157 | const uint8_t *s = src; |
||
158 | const uint8_t *end = s + src_size; |
||
159 | |||
160 | while (s < end) { |
||
161 | register int rgb = *(const uint32_t *)s; |
||
162 | s += 4; |
||
163 | *d++ = ((rgb & 0xFF) >> 3) + |
||
164 | ((rgb & 0xF800) >> 6) + |
||
165 | ((rgb & 0xF80000) >> 9); |
||
166 | } |
||
167 | } |
||
168 | |||
169 | static inline void rgb32tobgr15_c(const uint8_t *src, uint8_t *dst, |
||
170 | int src_size) |
||
171 | { |
||
172 | uint16_t *d = (uint16_t *)dst; |
||
173 | const uint8_t *s = src; |
||
174 | const uint8_t *end = s + src_size; |
||
175 | |||
176 | while (s < end) { |
||
177 | register int rgb = *(const uint32_t *)s; |
||
178 | s += 4; |
||
179 | *d++ = ((rgb & 0xF8) << 7) + |
||
180 | ((rgb & 0xF800) >> 6) + |
||
181 | ((rgb & 0xF80000) >> 19); |
||
182 | } |
||
183 | } |
||
184 | |||
185 | static inline void rgb24tobgr16_c(const uint8_t *src, uint8_t *dst, |
||
186 | int src_size) |
||
187 | { |
||
188 | uint16_t *d = (uint16_t *)dst; |
||
189 | const uint8_t *s = src; |
||
190 | const uint8_t *end = s + src_size; |
||
191 | |||
192 | while (s < end) { |
||
193 | const int b = *s++; |
||
194 | const int g = *s++; |
||
195 | const int r = *s++; |
||
196 | *d++ = (b >> 3) | ((g & 0xFC) << 3) | ((r & 0xF8) << 8); |
||
197 | } |
||
198 | } |
||
199 | |||
200 | static inline void rgb24to16_c(const uint8_t *src, uint8_t *dst, int src_size) |
||
201 | { |
||
202 | uint16_t *d = (uint16_t *)dst; |
||
203 | const uint8_t *s = src; |
||
204 | const uint8_t *end = s + src_size; |
||
205 | |||
206 | while (s < end) { |
||
207 | const int r = *s++; |
||
208 | const int g = *s++; |
||
209 | const int b = *s++; |
||
210 | *d++ = (b >> 3) | ((g & 0xFC) << 3) | ((r & 0xF8) << 8); |
||
211 | } |
||
212 | } |
||
213 | |||
214 | static inline void rgb24tobgr15_c(const uint8_t *src, uint8_t *dst, |
||
215 | int src_size) |
||
216 | { |
||
217 | uint16_t *d = (uint16_t *)dst; |
||
218 | const uint8_t *s = src; |
||
219 | const uint8_t *end = s + src_size; |
||
220 | |||
221 | while (s < end) { |
||
222 | const int b = *s++; |
||
223 | const int g = *s++; |
||
224 | const int r = *s++; |
||
225 | *d++ = (b >> 3) | ((g & 0xF8) << 2) | ((r & 0xF8) << 7); |
||
226 | } |
||
227 | } |
||
228 | |||
229 | static inline void rgb24to15_c(const uint8_t *src, uint8_t *dst, int src_size) |
||
230 | { |
||
231 | uint16_t *d = (uint16_t *)dst; |
||
232 | const uint8_t *s = src; |
||
233 | const uint8_t *end = s + src_size; |
||
234 | |||
235 | while (s < end) { |
||
236 | const int r = *s++; |
||
237 | const int g = *s++; |
||
238 | const int b = *s++; |
||
239 | *d++ = (b >> 3) | ((g & 0xF8) << 2) | ((r & 0xF8) << 7); |
||
240 | } |
||
241 | } |
||
242 | |||
243 | static inline void rgb15tobgr24_c(const uint8_t *src, uint8_t *dst, |
||
244 | int src_size) |
||
245 | { |
||
246 | uint8_t *d = dst; |
||
247 | const uint16_t *s = (const uint16_t *)src; |
||
248 | const uint16_t *end = s + src_size / 2; |
||
249 | |||
250 | while (s < end) { |
||
251 | register uint16_t bgr = *s++; |
||
252 | *d++ = ((bgr&0x001F)<<3) | ((bgr&0x001F)>> 2); |
||
253 | *d++ = ((bgr&0x03E0)>>2) | ((bgr&0x03E0)>> 7); |
||
254 | *d++ = ((bgr&0x7C00)>>7) | ((bgr&0x7C00)>>12); |
||
255 | } |
||
256 | } |
||
257 | |||
258 | static inline void rgb16tobgr24_c(const uint8_t *src, uint8_t *dst, |
||
259 | int src_size) |
||
260 | { |
||
261 | uint8_t *d = (uint8_t *)dst; |
||
262 | const uint16_t *s = (const uint16_t *)src; |
||
263 | const uint16_t *end = s + src_size / 2; |
||
264 | |||
265 | while (s < end) { |
||
266 | register uint16_t bgr = *s++; |
||
267 | *d++ = ((bgr&0x001F)<<3) | ((bgr&0x001F)>> 2); |
||
268 | *d++ = ((bgr&0x07E0)>>3) | ((bgr&0x07E0)>> 9); |
||
269 | *d++ = ((bgr&0xF800)>>8) | ((bgr&0xF800)>>13); |
||
270 | } |
||
271 | } |
||
272 | |||
273 | static inline void rgb15to32_c(const uint8_t *src, uint8_t *dst, int src_size) |
||
274 | { |
||
275 | uint8_t *d = dst; |
||
276 | const uint16_t *s = (const uint16_t *)src; |
||
277 | const uint16_t *end = s + src_size / 2; |
||
278 | |||
279 | while (s < end) { |
||
280 | register uint16_t bgr = *s++; |
||
281 | #if HAVE_BIGENDIAN |
||
282 | *d++ = 255; |
||
283 | *d++ = ((bgr&0x7C00)>>7) | ((bgr&0x7C00)>>12); |
||
284 | *d++ = ((bgr&0x03E0)>>2) | ((bgr&0x03E0)>> 7); |
||
285 | *d++ = ((bgr&0x001F)<<3) | ((bgr&0x001F)>> 2); |
||
286 | #else |
||
287 | *d++ = ((bgr&0x001F)<<3) | ((bgr&0x001F)>> 2); |
||
288 | *d++ = ((bgr&0x03E0)>>2) | ((bgr&0x03E0)>> 7); |
||
289 | *d++ = ((bgr&0x7C00)>>7) | ((bgr&0x7C00)>>12); |
||
290 | *d++ = 255; |
||
291 | #endif |
||
292 | } |
||
293 | } |
||
294 | |||
295 | static inline void rgb16to32_c(const uint8_t *src, uint8_t *dst, int src_size) |
||
296 | { |
||
297 | uint8_t *d = dst; |
||
298 | const uint16_t *s = (const uint16_t *)src; |
||
299 | const uint16_t *end = s + src_size / 2; |
||
300 | |||
301 | while (s < end) { |
||
302 | register uint16_t bgr = *s++; |
||
303 | #if HAVE_BIGENDIAN |
||
304 | *d++ = 255; |
||
305 | *d++ = ((bgr&0xF800)>>8) | ((bgr&0xF800)>>13); |
||
306 | *d++ = ((bgr&0x07E0)>>3) | ((bgr&0x07E0)>> 9); |
||
307 | *d++ = ((bgr&0x001F)<<3) | ((bgr&0x001F)>> 2); |
||
308 | #else |
||
309 | *d++ = ((bgr&0x001F)<<3) | ((bgr&0x001F)>> 2); |
||
310 | *d++ = ((bgr&0x07E0)>>3) | ((bgr&0x07E0)>> 9); |
||
311 | *d++ = ((bgr&0xF800)>>8) | ((bgr&0xF800)>>13); |
||
312 | *d++ = 255; |
||
313 | #endif |
||
314 | } |
||
315 | } |
||
316 | |||
317 | static inline void shuffle_bytes_2103_c(const uint8_t *src, uint8_t *dst, |
||
318 | int src_size) |
||
319 | { |
||
320 | int idx = 15 - src_size; |
||
321 | const uint8_t *s = src - idx; |
||
322 | uint8_t *d = dst - idx; |
||
323 | |||
324 | for (; idx < 15; idx += 4) { |
||
325 | register int v = *(const uint32_t *)&s[idx], g = v & 0xff00ff00; |
||
326 | v &= 0xff00ff; |
||
327 | *(uint32_t *)&d[idx] = (v >> 16) + g + (v << 16); |
||
328 | } |
||
329 | } |
||
330 | |||
331 | static inline void rgb24tobgr24_c(const uint8_t *src, uint8_t *dst, int src_size) |
||
332 | { |
||
333 | unsigned i; |
||
334 | |||
335 | for (i = 0; i < src_size; i += 3) { |
||
336 | register uint8_t x = src[i + 2]; |
||
337 | dst[i + 1] = src[i + 1]; |
||
338 | dst[i + 2] = src[i + 0]; |
||
339 | dst[i + 0] = x; |
||
340 | } |
||
341 | } |
||
342 | |||
343 | static inline void yuvPlanartoyuy2_c(const uint8_t *ysrc, const uint8_t *usrc, |
||
344 | const uint8_t *vsrc, uint8_t *dst, |
||
345 | int width, int height, |
||
346 | int lumStride, int chromStride, |
||
347 | int dstStride, int vertLumPerChroma) |
||
348 | { |
||
349 | int y, i; |
||
350 | const int chromWidth = width >> 1; |
||
351 | |||
352 | for (y = 0; y < height; y++) { |
||
353 | #if HAVE_FAST_64BIT |
||
354 | uint64_t *ldst = (uint64_t *)dst; |
||
355 | const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc; |
||
356 | for (i = 0; i < chromWidth; i += 2) { |
||
357 | uint64_t k = yc[0] + (uc[0] << 8) + |
||
358 | (yc[1] << 16) + (unsigned)(vc[0] << 24); |
||
359 | uint64_t l = yc[2] + (uc[1] << 8) + |
||
360 | (yc[3] << 16) + (unsigned)(vc[1] << 24); |
||
361 | *ldst++ = k + (l << 32); |
||
362 | yc += 4; |
||
363 | uc += 2; |
||
364 | vc += 2; |
||
365 | } |
||
366 | |||
367 | #else |
||
368 | int *idst = (int32_t *)dst; |
||
369 | const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc; |
||
370 | |||
371 | for (i = 0; i < chromWidth; i++) { |
||
372 | #if HAVE_BIGENDIAN |
||
373 | *idst++ = (yc[0] << 24) + (uc[0] << 16) + |
||
374 | (yc[1] << 8) + (vc[0] << 0); |
||
375 | #else |
||
376 | *idst++ = yc[0] + (uc[0] << 8) + |
||
377 | (yc[1] << 16) + (vc[0] << 24); |
||
378 | #endif |
||
379 | yc += 2; |
||
380 | uc++; |
||
381 | vc++; |
||
382 | } |
||
383 | #endif |
||
384 | if ((y & (vertLumPerChroma - 1)) == vertLumPerChroma - 1) { |
||
385 | usrc += chromStride; |
||
386 | vsrc += chromStride; |
||
387 | } |
||
388 | ysrc += lumStride; |
||
389 | dst += dstStride; |
||
390 | } |
||
391 | } |
||
392 | |||
393 | /** |
||
394 | * Height should be a multiple of 2 and width should be a multiple of 16. |
||
395 | * (If this is a problem for anyone then tell me, and I will fix it.) |
||
396 | */ |
||
397 | static inline void yv12toyuy2_c(const uint8_t *ysrc, const uint8_t *usrc, |
||
398 | const uint8_t *vsrc, uint8_t *dst, |
||
399 | int width, int height, int lumStride, |
||
400 | int chromStride, int dstStride) |
||
401 | { |
||
402 | //FIXME interpolate chroma |
||
403 | yuvPlanartoyuy2_c(ysrc, usrc, vsrc, dst, width, height, lumStride, |
||
404 | chromStride, dstStride, 2); |
||
405 | } |
||
406 | |||
407 | static inline void yuvPlanartouyvy_c(const uint8_t *ysrc, const uint8_t *usrc, |
||
408 | const uint8_t *vsrc, uint8_t *dst, |
||
409 | int width, int height, |
||
410 | int lumStride, int chromStride, |
||
411 | int dstStride, int vertLumPerChroma) |
||
412 | { |
||
413 | int y, i; |
||
414 | const int chromWidth = width >> 1; |
||
415 | |||
416 | for (y = 0; y < height; y++) { |
||
417 | #if HAVE_FAST_64BIT |
||
418 | uint64_t *ldst = (uint64_t *)dst; |
||
419 | const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc; |
||
420 | for (i = 0; i < chromWidth; i += 2) { |
||
421 | uint64_t k = uc[0] + (yc[0] << 8) + |
||
422 | (vc[0] << 16) + (unsigned)(yc[1] << 24); |
||
423 | uint64_t l = uc[1] + (yc[2] << 8) + |
||
424 | (vc[1] << 16) + (unsigned)(yc[3] << 24); |
||
425 | *ldst++ = k + (l << 32); |
||
426 | yc += 4; |
||
427 | uc += 2; |
||
428 | vc += 2; |
||
429 | } |
||
430 | |||
431 | #else |
||
432 | int *idst = (int32_t *)dst; |
||
433 | const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc; |
||
434 | |||
435 | for (i = 0; i < chromWidth; i++) { |
||
436 | #if HAVE_BIGENDIAN |
||
437 | *idst++ = (uc[0] << 24) + (yc[0] << 16) + |
||
438 | (vc[0] << 8) + (yc[1] << 0); |
||
439 | #else |
||
440 | *idst++ = uc[0] + (yc[0] << 8) + |
||
441 | (vc[0] << 16) + (yc[1] << 24); |
||
442 | #endif |
||
443 | yc += 2; |
||
444 | uc++; |
||
445 | vc++; |
||
446 | } |
||
447 | #endif |
||
448 | if ((y & (vertLumPerChroma - 1)) == vertLumPerChroma - 1) { |
||
449 | usrc += chromStride; |
||
450 | vsrc += chromStride; |
||
451 | } |
||
452 | ysrc += lumStride; |
||
453 | dst += dstStride; |
||
454 | } |
||
455 | } |
||
456 | |||
457 | /** |
||
458 | * Height should be a multiple of 2 and width should be a multiple of 16 |
||
459 | * (If this is a problem for anyone then tell me, and I will fix it.) |
||
460 | */ |
||
461 | static inline void yv12touyvy_c(const uint8_t *ysrc, const uint8_t *usrc, |
||
462 | const uint8_t *vsrc, uint8_t *dst, |
||
463 | int width, int height, int lumStride, |
||
464 | int chromStride, int dstStride) |
||
465 | { |
||
466 | //FIXME interpolate chroma |
||
467 | yuvPlanartouyvy_c(ysrc, usrc, vsrc, dst, width, height, lumStride, |
||
468 | chromStride, dstStride, 2); |
||
469 | } |
||
470 | |||
471 | /** |
||
472 | * Width should be a multiple of 16. |
||
473 | */ |
||
474 | static inline void yuv422ptouyvy_c(const uint8_t *ysrc, const uint8_t *usrc, |
||
475 | const uint8_t *vsrc, uint8_t *dst, |
||
476 | int width, int height, int lumStride, |
||
477 | int chromStride, int dstStride) |
||
478 | { |
||
479 | yuvPlanartouyvy_c(ysrc, usrc, vsrc, dst, width, height, lumStride, |
||
480 | chromStride, dstStride, 1); |
||
481 | } |
||
482 | |||
483 | /** |
||
484 | * Width should be a multiple of 16. |
||
485 | */ |
||
486 | static inline void yuv422ptoyuy2_c(const uint8_t *ysrc, const uint8_t *usrc, |
||
487 | const uint8_t *vsrc, uint8_t *dst, |
||
488 | int width, int height, int lumStride, |
||
489 | int chromStride, int dstStride) |
||
490 | { |
||
491 | yuvPlanartoyuy2_c(ysrc, usrc, vsrc, dst, width, height, lumStride, |
||
492 | chromStride, dstStride, 1); |
||
493 | } |
||
494 | |||
495 | /** |
||
496 | * Height should be a multiple of 2 and width should be a multiple of 16. |
||
497 | * (If this is a problem for anyone then tell me, and I will fix it.) |
||
498 | */ |
||
499 | static inline void yuy2toyv12_c(const uint8_t *src, uint8_t *ydst, |
||
500 | uint8_t *udst, uint8_t *vdst, |
||
501 | int width, int height, int lumStride, |
||
502 | int chromStride, int srcStride) |
||
503 | { |
||
504 | int y; |
||
505 | const int chromWidth = width >> 1; |
||
506 | |||
507 | for (y = 0; y < height; y += 2) { |
||
508 | int i; |
||
509 | for (i = 0; i < chromWidth; i++) { |
||
510 | ydst[2 * i + 0] = src[4 * i + 0]; |
||
511 | udst[i] = src[4 * i + 1]; |
||
512 | ydst[2 * i + 1] = src[4 * i + 2]; |
||
513 | vdst[i] = src[4 * i + 3]; |
||
514 | } |
||
515 | ydst += lumStride; |
||
516 | src += srcStride; |
||
517 | |||
518 | for (i = 0; i < chromWidth; i++) { |
||
519 | ydst[2 * i + 0] = src[4 * i + 0]; |
||
520 | ydst[2 * i + 1] = src[4 * i + 2]; |
||
521 | } |
||
522 | udst += chromStride; |
||
523 | vdst += chromStride; |
||
524 | ydst += lumStride; |
||
525 | src += srcStride; |
||
526 | } |
||
527 | } |
||
528 | |||
529 | static inline void planar2x_c(const uint8_t *src, uint8_t *dst, int srcWidth, |
||
530 | int srcHeight, int srcStride, int dstStride) |
||
531 | { |
||
532 | int x, y; |
||
533 | |||
534 | dst[0] = src[0]; |
||
535 | |||
536 | // first line |
||
537 | for (x = 0; x < srcWidth - 1; x++) { |
||
538 | dst[2 * x + 1] = (3 * src[x] + src[x + 1]) >> 2; |
||
539 | dst[2 * x + 2] = (src[x] + 3 * src[x + 1]) >> 2; |
||
540 | } |
||
541 | dst[2 * srcWidth - 1] = src[srcWidth - 1]; |
||
542 | |||
543 | dst += dstStride; |
||
544 | |||
545 | for (y = 1; y < srcHeight; y++) { |
||
546 | const int mmxSize = 1; |
||
547 | |||
548 | dst[0] = (src[0] * 3 + src[srcStride]) >> 2; |
||
549 | dst[dstStride] = (src[0] + 3 * src[srcStride]) >> 2; |
||
550 | |||
551 | for (x = mmxSize - 1; x < srcWidth - 1; x++) { |
||
552 | dst[2 * x + 1] = (src[x + 0] * 3 + src[x + srcStride + 1]) >> 2; |
||
553 | dst[2 * x + dstStride + 2] = (src[x + 0] + 3 * src[x + srcStride + 1]) >> 2; |
||
554 | dst[2 * x + dstStride + 1] = (src[x + 1] + 3 * src[x + srcStride]) >> 2; |
||
555 | dst[2 * x + 2] = (src[x + 1] * 3 + src[x + srcStride]) >> 2; |
||
556 | } |
||
557 | dst[srcWidth * 2 - 1] = (src[srcWidth - 1] * 3 + src[srcWidth - 1 + srcStride]) >> 2; |
||
558 | dst[srcWidth * 2 - 1 + dstStride] = (src[srcWidth - 1] + 3 * src[srcWidth - 1 + srcStride]) >> 2; |
||
559 | |||
560 | dst += dstStride * 2; |
||
561 | src += srcStride; |
||
562 | } |
||
563 | |||
564 | // last line |
||
565 | dst[0] = src[0]; |
||
566 | |||
567 | for (x = 0; x < srcWidth - 1; x++) { |
||
568 | dst[2 * x + 1] = (src[x] * 3 + src[x + 1]) >> 2; |
||
569 | dst[2 * x + 2] = (src[x] + 3 * src[x + 1]) >> 2; |
||
570 | } |
||
571 | dst[2 * srcWidth - 1] = src[srcWidth - 1]; |
||
572 | } |
||
573 | |||
574 | /** |
||
575 | * Height should be a multiple of 2 and width should be a multiple of 16. |
||
576 | * (If this is a problem for anyone then tell me, and I will fix it.) |
||
577 | * Chrominance data is only taken from every second line, others are ignored. |
||
578 | * FIXME: Write HQ version. |
||
579 | */ |
||
580 | static inline void uyvytoyv12_c(const uint8_t *src, uint8_t *ydst, |
||
581 | uint8_t *udst, uint8_t *vdst, |
||
582 | int width, int height, int lumStride, |
||
583 | int chromStride, int srcStride) |
||
584 | { |
||
585 | int y; |
||
586 | const int chromWidth = width >> 1; |
||
587 | |||
588 | for (y = 0; y < height; y += 2) { |
||
589 | int i; |
||
590 | for (i = 0; i < chromWidth; i++) { |
||
591 | udst[i] = src[4 * i + 0]; |
||
592 | ydst[2 * i + 0] = src[4 * i + 1]; |
||
593 | vdst[i] = src[4 * i + 2]; |
||
594 | ydst[2 * i + 1] = src[4 * i + 3]; |
||
595 | } |
||
596 | ydst += lumStride; |
||
597 | src += srcStride; |
||
598 | |||
599 | for (i = 0; i < chromWidth; i++) { |
||
600 | ydst[2 * i + 0] = src[4 * i + 1]; |
||
601 | ydst[2 * i + 1] = src[4 * i + 3]; |
||
602 | } |
||
603 | udst += chromStride; |
||
604 | vdst += chromStride; |
||
605 | ydst += lumStride; |
||
606 | src += srcStride; |
||
607 | } |
||
608 | } |
||
609 | |||
610 | /** |
||
611 | * Height should be a multiple of 2 and width should be a multiple of 2. |
||
612 | * (If this is a problem for anyone then tell me, and I will fix it.) |
||
613 | * Chrominance data is only taken from every second line, |
||
614 | * others are ignored in the C version. |
||
615 | * FIXME: Write HQ version. |
||
616 | */ |
||
617 | void ff_rgb24toyv12_c(const uint8_t *src, uint8_t *ydst, uint8_t *udst, |
||
618 | uint8_t *vdst, int width, int height, int lumStride, |
||
619 | int chromStride, int srcStride, int32_t *rgb2yuv) |
||
620 | { |
||
621 | int32_t ry = rgb2yuv[RY_IDX], gy = rgb2yuv[GY_IDX], by = rgb2yuv[BY_IDX]; |
||
622 | int32_t ru = rgb2yuv[RU_IDX], gu = rgb2yuv[GU_IDX], bu = rgb2yuv[BU_IDX]; |
||
623 | int32_t rv = rgb2yuv[RV_IDX], gv = rgb2yuv[GV_IDX], bv = rgb2yuv[BV_IDX]; |
||
624 | int y; |
||
625 | const int chromWidth = width >> 1; |
||
626 | |||
627 | for (y = 0; y < height; y += 2) { |
||
628 | int i; |
||
629 | for (i = 0; i < chromWidth; i++) { |
||
630 | unsigned int b = src[6 * i + 0]; |
||
631 | unsigned int g = src[6 * i + 1]; |
||
632 | unsigned int r = src[6 * i + 2]; |
||
633 | |||
634 | unsigned int Y = ((ry * r + gy * g + by * b) >> RGB2YUV_SHIFT) + 16; |
||
635 | unsigned int V = ((rv * r + gv * g + bv * b) >> RGB2YUV_SHIFT) + 128; |
||
636 | unsigned int U = ((ru * r + gu * g + bu * b) >> RGB2YUV_SHIFT) + 128; |
||
637 | |||
638 | udst[i] = U; |
||
639 | vdst[i] = V; |
||
640 | ydst[2 * i] = Y; |
||
641 | |||
642 | b = src[6 * i + 3]; |
||
643 | g = src[6 * i + 4]; |
||
644 | r = src[6 * i + 5]; |
||
645 | |||
646 | Y = ((ry * r + gy * g + by * b) >> RGB2YUV_SHIFT) + 16; |
||
647 | ydst[2 * i + 1] = Y; |
||
648 | } |
||
649 | ydst += lumStride; |
||
650 | src += srcStride; |
||
651 | |||
652 | if (y+1 == height) |
||
653 | break; |
||
654 | |||
655 | for (i = 0; i < chromWidth; i++) { |
||
656 | unsigned int b = src[6 * i + 0]; |
||
657 | unsigned int g = src[6 * i + 1]; |
||
658 | unsigned int r = src[6 * i + 2]; |
||
659 | |||
660 | unsigned int Y = ((ry * r + gy * g + by * b) >> RGB2YUV_SHIFT) + 16; |
||
661 | |||
662 | ydst[2 * i] = Y; |
||
663 | |||
664 | b = src[6 * i + 3]; |
||
665 | g = src[6 * i + 4]; |
||
666 | r = src[6 * i + 5]; |
||
667 | |||
668 | Y = ((ry * r + gy * g + by * b) >> RGB2YUV_SHIFT) + 16; |
||
669 | ydst[2 * i + 1] = Y; |
||
670 | } |
||
671 | udst += chromStride; |
||
672 | vdst += chromStride; |
||
673 | ydst += lumStride; |
||
674 | src += srcStride; |
||
675 | } |
||
676 | } |
||
677 | |||
678 | static void interleaveBytes_c(const uint8_t *src1, const uint8_t *src2, |
||
679 | uint8_t *dest, int width, int height, |
||
680 | int src1Stride, int src2Stride, int dstStride) |
||
681 | { |
||
682 | int h; |
||
683 | |||
684 | for (h = 0; h < height; h++) { |
||
685 | int w; |
||
686 | for (w = 0; w < width; w++) { |
||
687 | dest[2 * w + 0] = src1[w]; |
||
688 | dest[2 * w + 1] = src2[w]; |
||
689 | } |
||
690 | dest += dstStride; |
||
691 | src1 += src1Stride; |
||
692 | src2 += src2Stride; |
||
693 | } |
||
694 | } |
||
695 | |||
696 | static inline void vu9_to_vu12_c(const uint8_t *src1, const uint8_t *src2, |
||
697 | uint8_t *dst1, uint8_t *dst2, |
||
698 | int width, int height, |
||
699 | int srcStride1, int srcStride2, |
||
700 | int dstStride1, int dstStride2) |
||
701 | { |
||
702 | int x, y; |
||
703 | int w = width / 2; |
||
704 | int h = height / 2; |
||
705 | |||
706 | for (y = 0; y < h; y++) { |
||
707 | const uint8_t *s1 = src1 + srcStride1 * (y >> 1); |
||
708 | uint8_t *d = dst1 + dstStride1 * y; |
||
709 | for (x = 0; x < w; x++) |
||
710 | d[2 * x] = d[2 * x + 1] = s1[x]; |
||
711 | } |
||
712 | for (y = 0; y < h; y++) { |
||
713 | const uint8_t *s2 = src2 + srcStride2 * (y >> 1); |
||
714 | uint8_t *d = dst2 + dstStride2 * y; |
||
715 | for (x = 0; x < w; x++) |
||
716 | d[2 * x] = d[2 * x + 1] = s2[x]; |
||
717 | } |
||
718 | } |
||
719 | |||
720 | static inline void yvu9_to_yuy2_c(const uint8_t *src1, const uint8_t *src2, |
||
721 | const uint8_t *src3, uint8_t *dst, |
||
722 | int width, int height, |
||
723 | int srcStride1, int srcStride2, |
||
724 | int srcStride3, int dstStride) |
||
725 | { |
||
726 | int x, y; |
||
727 | int w = width / 2; |
||
728 | int h = height; |
||
729 | |||
730 | for (y = 0; y < h; y++) { |
||
731 | const uint8_t *yp = src1 + srcStride1 * y; |
||
732 | const uint8_t *up = src2 + srcStride2 * (y >> 2); |
||
733 | const uint8_t *vp = src3 + srcStride3 * (y >> 2); |
||
734 | uint8_t *d = dst + dstStride * y; |
||
735 | for (x = 0; x < w; x++) { |
||
736 | const int x2 = x << 2; |
||
737 | d[8 * x + 0] = yp[x2]; |
||
738 | d[8 * x + 1] = up[x]; |
||
739 | d[8 * x + 2] = yp[x2 + 1]; |
||
740 | d[8 * x + 3] = vp[x]; |
||
741 | d[8 * x + 4] = yp[x2 + 2]; |
||
742 | d[8 * x + 5] = up[x]; |
||
743 | d[8 * x + 6] = yp[x2 + 3]; |
||
744 | d[8 * x + 7] = vp[x]; |
||
745 | } |
||
746 | } |
||
747 | } |
||
748 | |||
749 | static void extract_even_c(const uint8_t *src, uint8_t *dst, int count) |
||
750 | { |
||
751 | dst += count; |
||
752 | src += count * 2; |
||
753 | count = -count; |
||
754 | while (count < 0) { |
||
755 | dst[count] = src[2 * count]; |
||
756 | count++; |
||
757 | } |
||
758 | } |
||
759 | |||
760 | static void extract_even2_c(const uint8_t *src, uint8_t *dst0, uint8_t *dst1, |
||
761 | int count) |
||
762 | { |
||
763 | dst0 += count; |
||
764 | dst1 += count; |
||
765 | src += count * 4; |
||
766 | count = -count; |
||
767 | while (count < 0) { |
||
768 | dst0[count] = src[4 * count + 0]; |
||
769 | dst1[count] = src[4 * count + 2]; |
||
770 | count++; |
||
771 | } |
||
772 | } |
||
773 | |||
774 | static void extract_even2avg_c(const uint8_t *src0, const uint8_t *src1, |
||
775 | uint8_t *dst0, uint8_t *dst1, int count) |
||
776 | { |
||
777 | dst0 += count; |
||
778 | dst1 += count; |
||
779 | src0 += count * 4; |
||
780 | src1 += count * 4; |
||
781 | count = -count; |
||
782 | while (count < 0) { |
||
783 | dst0[count] = (src0[4 * count + 0] + src1[4 * count + 0]) >> 1; |
||
784 | dst1[count] = (src0[4 * count + 2] + src1[4 * count + 2]) >> 1; |
||
785 | count++; |
||
786 | } |
||
787 | } |
||
788 | |||
789 | static void extract_odd2_c(const uint8_t *src, uint8_t *dst0, uint8_t *dst1, |
||
790 | int count) |
||
791 | { |
||
792 | dst0 += count; |
||
793 | dst1 += count; |
||
794 | src += count * 4; |
||
795 | count = -count; |
||
796 | src++; |
||
797 | while (count < 0) { |
||
798 | dst0[count] = src[4 * count + 0]; |
||
799 | dst1[count] = src[4 * count + 2]; |
||
800 | count++; |
||
801 | } |
||
802 | } |
||
803 | |||
804 | static void extract_odd2avg_c(const uint8_t *src0, const uint8_t *src1, |
||
805 | uint8_t *dst0, uint8_t *dst1, int count) |
||
806 | { |
||
807 | dst0 += count; |
||
808 | dst1 += count; |
||
809 | src0 += count * 4; |
||
810 | src1 += count * 4; |
||
811 | count = -count; |
||
812 | src0++; |
||
813 | src1++; |
||
814 | while (count < 0) { |
||
815 | dst0[count] = (src0[4 * count + 0] + src1[4 * count + 0]) >> 1; |
||
816 | dst1[count] = (src0[4 * count + 2] + src1[4 * count + 2]) >> 1; |
||
817 | count++; |
||
818 | } |
||
819 | } |
||
820 | |||
821 | static void yuyvtoyuv420_c(uint8_t *ydst, uint8_t *udst, uint8_t *vdst, |
||
822 | const uint8_t *src, int width, int height, |
||
823 | int lumStride, int chromStride, int srcStride) |
||
824 | { |
||
825 | int y; |
||
826 | const int chromWidth = FF_CEIL_RSHIFT(width, 1); |
||
827 | |||
828 | for (y = 0; y < height; y++) { |
||
829 | extract_even_c(src, ydst, width); |
||
830 | if (y & 1) { |
||
831 | extract_odd2avg_c(src - srcStride, src, udst, vdst, chromWidth); |
||
832 | udst += chromStride; |
||
833 | vdst += chromStride; |
||
834 | } |
||
835 | |||
836 | src += srcStride; |
||
837 | ydst += lumStride; |
||
838 | } |
||
839 | } |
||
840 | |||
841 | static void yuyvtoyuv422_c(uint8_t *ydst, uint8_t *udst, uint8_t *vdst, |
||
842 | const uint8_t *src, int width, int height, |
||
843 | int lumStride, int chromStride, int srcStride) |
||
844 | { |
||
845 | int y; |
||
846 | const int chromWidth = FF_CEIL_RSHIFT(width, 1); |
||
847 | |||
848 | for (y = 0; y < height; y++) { |
||
849 | extract_even_c(src, ydst, width); |
||
850 | extract_odd2_c(src, udst, vdst, chromWidth); |
||
851 | |||
852 | src += srcStride; |
||
853 | ydst += lumStride; |
||
854 | udst += chromStride; |
||
855 | vdst += chromStride; |
||
856 | } |
||
857 | } |
||
858 | |||
859 | static void uyvytoyuv420_c(uint8_t *ydst, uint8_t *udst, uint8_t *vdst, |
||
860 | const uint8_t *src, int width, int height, |
||
861 | int lumStride, int chromStride, int srcStride) |
||
862 | { |
||
863 | int y; |
||
864 | const int chromWidth = FF_CEIL_RSHIFT(width, 1); |
||
865 | |||
866 | for (y = 0; y < height; y++) { |
||
867 | extract_even_c(src + 1, ydst, width); |
||
868 | if (y & 1) { |
||
869 | extract_even2avg_c(src - srcStride, src, udst, vdst, chromWidth); |
||
870 | udst += chromStride; |
||
871 | vdst += chromStride; |
||
872 | } |
||
873 | |||
874 | src += srcStride; |
||
875 | ydst += lumStride; |
||
876 | } |
||
877 | } |
||
878 | |||
879 | static void uyvytoyuv422_c(uint8_t *ydst, uint8_t *udst, uint8_t *vdst, |
||
880 | const uint8_t *src, int width, int height, |
||
881 | int lumStride, int chromStride, int srcStride) |
||
882 | { |
||
883 | int y; |
||
884 | const int chromWidth = FF_CEIL_RSHIFT(width, 1); |
||
885 | |||
886 | for (y = 0; y < height; y++) { |
||
887 | extract_even_c(src + 1, ydst, width); |
||
888 | extract_even2_c(src, udst, vdst, chromWidth); |
||
889 | |||
890 | src += srcStride; |
||
891 | ydst += lumStride; |
||
892 | udst += chromStride; |
||
893 | vdst += chromStride; |
||
894 | } |
||
895 | } |
||
896 | |||
897 | static av_cold void rgb2rgb_init_c(void) |
||
898 | { |
||
899 | rgb15to16 = rgb15to16_c; |
||
900 | rgb15tobgr24 = rgb15tobgr24_c; |
||
901 | rgb15to32 = rgb15to32_c; |
||
902 | rgb16tobgr24 = rgb16tobgr24_c; |
||
903 | rgb16to32 = rgb16to32_c; |
||
904 | rgb16to15 = rgb16to15_c; |
||
905 | rgb24tobgr16 = rgb24tobgr16_c; |
||
906 | rgb24tobgr15 = rgb24tobgr15_c; |
||
907 | rgb24tobgr32 = rgb24tobgr32_c; |
||
908 | rgb32to16 = rgb32to16_c; |
||
909 | rgb32to15 = rgb32to15_c; |
||
910 | rgb32tobgr24 = rgb32tobgr24_c; |
||
911 | rgb24to15 = rgb24to15_c; |
||
912 | rgb24to16 = rgb24to16_c; |
||
913 | rgb24tobgr24 = rgb24tobgr24_c; |
||
914 | shuffle_bytes_2103 = shuffle_bytes_2103_c; |
||
915 | rgb32tobgr16 = rgb32tobgr16_c; |
||
916 | rgb32tobgr15 = rgb32tobgr15_c; |
||
917 | yv12toyuy2 = yv12toyuy2_c; |
||
918 | yv12touyvy = yv12touyvy_c; |
||
919 | yuv422ptoyuy2 = yuv422ptoyuy2_c; |
||
920 | yuv422ptouyvy = yuv422ptouyvy_c; |
||
921 | yuy2toyv12 = yuy2toyv12_c; |
||
922 | planar2x = planar2x_c; |
||
923 | ff_rgb24toyv12 = ff_rgb24toyv12_c; |
||
924 | interleaveBytes = interleaveBytes_c; |
||
925 | vu9_to_vu12 = vu9_to_vu12_c; |
||
926 | yvu9_to_yuy2 = yvu9_to_yuy2_c; |
||
927 | |||
928 | uyvytoyuv420 = uyvytoyuv420_c; |
||
929 | uyvytoyuv422 = uyvytoyuv422_c; |
||
930 | yuyvtoyuv420 = yuyvtoyuv420_c; |
||
931 | yuyvtoyuv422 = yuyvtoyuv422_c; |
||
932 | }>>>>>>>>>><>>>>>>>>>>>>>>>>>>>>>>><>><>><>><>><>><>><>>><>><>><>><>><>><>><>>>><>><>><>><>><>><>><>>><>><>><>><>><>><>><>>>>><>>3)><3)>3)><3)>>3)><3)>3)><3)>>3)><3)>>3)><3)>>><>><>>><>><>>><>><>>><>><>>><>>>><>>>>>>>>> |