2 * Misc image convertion routines
3 * Copyright (c) 2001, 2002, 2003 Fabrice Bellard.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "fastmemcpy.h"
30 typedef struct PixFmtInfo
{
32 UINT8 nb_components
; /* number of components in AVPicture array */
33 UINT8 is_yuv
: 1; /* true if YUV instead of RGB color space */
34 UINT8 is_packed
: 1; /* true if multiple components in same word */
35 UINT8 is_paletted
: 1; /* true if paletted */
36 UINT8 is_alpha
: 1; /* true if alpha can be specified */
37 UINT8 is_gray
: 1; /* true if gray or monochrome format */
38 UINT8 x_chroma_shift
; /* X chroma subsampling factor is 2 ^ shift */
39 UINT8 y_chroma_shift
; /* Y chroma subsampling factor is 2 ^ shift */
42 /* this table gives more information about formats */
43 static PixFmtInfo pix_fmt_info
[PIX_FMT_NB
] = {
47 nb_components
: 3, is_yuv
: 1,
48 x_chroma_shift
: 1, y_chroma_shift
: 1,
52 nb_components
: 3, is_yuv
: 1,
53 x_chroma_shift
: 1, y_chroma_shift
: 0,
57 nb_components
: 3, is_yuv
: 1,
58 x_chroma_shift
: 0, y_chroma_shift
: 0,
62 nb_components
: 1, is_yuv
: 1, is_packed
: 1,
63 x_chroma_shift
: 1, y_chroma_shift
: 0,
67 nb_components
: 3, is_yuv
: 1,
68 x_chroma_shift
: 2, y_chroma_shift
: 2,
72 nb_components
: 3, is_yuv
: 1,
73 x_chroma_shift
: 2, y_chroma_shift
: 0,
79 nb_components
: 1, is_packed
: 1,
83 nb_components
: 1, is_packed
: 1,
87 nb_components
: 1, is_packed
: 1, is_alpha
: 1,
91 nb_components
: 1, is_packed
: 1,
95 nb_components
: 1, is_packed
: 1, is_alpha
: 1,
98 /* gray / mono formats */
101 nb_components
: 1, is_gray
: 1,
103 [PIX_FMT_MONOWHITE
] = {
105 nb_components
: 1, is_packed
: 1, is_gray
: 1,
107 [PIX_FMT_MONOBLACK
] = {
109 nb_components
: 1, is_packed
: 1, is_gray
: 1,
113 void avcodec_get_chroma_sub_sample(int pix_fmt
, int *h_shift
, int *v_shift
)
115 if (pix_fmt_info
[pix_fmt
].is_yuv
) {
116 *h_shift
= pix_fmt_info
[pix_fmt
].x_chroma_shift
;
117 *v_shift
= pix_fmt_info
[pix_fmt
].y_chroma_shift
;
124 const char *avcodec_get_pix_fmt_name(int pix_fmt
)
126 if (pix_fmt
< 0 || pix_fmt
>= PIX_FMT_NB
)
129 return pix_fmt_info
[pix_fmt
].name
;
132 /* XXX: totally non optimized */
134 static void yuv422_to_yuv420p(AVPicture
*dst
, AVPicture
*src
,
135 int width
, int height
)
137 UINT8
*lum
, *cb
, *cr
;
146 for(y
=0;y
<height
;y
+=2) {
147 for(x
=0;x
<width
;x
+=2) {
157 for(x
=0;x
<width
;x
+=2) {
167 #define ONE_HALF (1 << (SCALEBITS - 1))
168 #define FIX(x) ((int) ((x) * (1L<<SCALEBITS) + 0.5))
170 /* XXX: use generic filter ? */
172 static void shrink2(UINT8
*dst
, int dst_wrap
,
173 UINT8
*src
, int src_wrap
,
174 int width
, int height
)
179 for(;height
> 0; height
--) {
183 for(w
= width
;w
>= 4; w
-=4) {
184 d
[0] = (s1
[0] + s2
[0]) >> 1;
185 d
[1] = (s1
[1] + s2
[1]) >> 1;
186 d
[2] = (s1
[2] + s2
[2]) >> 1;
187 d
[3] = (s1
[3] + s2
[3]) >> 1;
193 d
[0] = (s1
[0] + s2
[0]) >> 1;
204 static void shrink22(UINT8
*dst
, int dst_wrap
,
205 UINT8
*src
, int src_wrap
,
206 int width
, int height
)
211 for(;height
> 0; height
--) {
215 for(w
= width
;w
>= 4; w
-=4) {
216 d
[0] = (s1
[0] + s1
[1] + s2
[0] + s2
[1] + 2) >> 1;
217 d
[1] = (s1
[2] + s1
[3] + s2
[2] + s2
[3] + 2) >> 1;
218 d
[2] = (s1
[4] + s1
[5] + s2
[4] + s2
[5] + 2) >> 1;
219 d
[3] = (s1
[6] + s1
[7] + s2
[6] + s2
[7] + 2) >> 1;
225 d
[0] = (s1
[0] + s1
[1] + s2
[0] + s2
[1] + 2) >> 1;
236 static void grow22(UINT8
*dst
, int dst_wrap
,
237 UINT8
*src
, int src_wrap
,
238 int width
, int height
)
243 for(;height
> 0; height
--) {
246 for(w
= width
;w
>= 4; w
-=4) {
264 static void conv411(UINT8
*dst
, int dst_wrap
,
265 UINT8
*src
, int src_wrap
,
266 int width
, int height
)
271 for(;height
> 0; height
--) {
275 for(w
= width
;w
> 0; w
--) {
276 c
= (s1
[0] + s2
[0]) >> 1;
288 static void img_copy(UINT8
*dst
, int dst_wrap
,
289 UINT8
*src
, int src_wrap
,
290 int width
, int height
)
292 for(;height
> 0; height
--) {
293 memcpy(dst
, src
, width
);
299 #define SCALE_BITS 10
301 #define C_Y (76309 >> (16 - SCALE_BITS))
302 #define C_RV (117504 >> (16 - SCALE_BITS))
303 #define C_BU (138453 >> (16 - SCALE_BITS))
304 #define C_GU (13954 >> (16 - SCALE_BITS))
305 #define C_GV (34903 >> (16 - SCALE_BITS))
307 #define YUV_TO_RGB2(r, g, b, y1)\
309 y = (y1 - 16) * C_Y;\
310 r = cm[(y + r_add) >> SCALE_BITS];\
311 g = cm[(y + g_add) >> SCALE_BITS];\
312 b = cm[(y + b_add) >> SCALE_BITS];\
315 /* XXX: no chroma interpolating is done */
316 #define RGB_FUNCTIONS(rgb_name) \
318 static void yuv420p_to_ ## rgb_name (AVPicture *dst, AVPicture *src, \
319 int width, int height) \
321 UINT8 *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr, *d, *d1, *d2; \
322 int w, y, cb, cr, r_add, g_add, b_add, width2; \
323 UINT8 *cm = cropTbl + MAX_NEG_CROP; \
324 unsigned int r, g, b; \
327 y1_ptr = src->data[0]; \
328 cb_ptr = src->data[1]; \
329 cr_ptr = src->data[2]; \
330 width2 = width >> 1; \
331 for(;height > 0; height -= 2) { \
333 d2 = d + dst->linesize[0]; \
334 y2_ptr = y1_ptr + src->linesize[0]; \
335 for(w = width2; w > 0; w --) { \
336 cb = cb_ptr[0] - 128; \
337 cr = cr_ptr[0] - 128; \
338 r_add = C_RV * cr + (1 << (SCALE_BITS - 1)); \
339 g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1)); \
340 b_add = C_BU * cb + (1 << (SCALE_BITS - 1)); \
342 /* output 4 pixels */ \
343 YUV_TO_RGB2(r, g, b, y1_ptr[0]); \
344 RGB_OUT(d1, r, g, b); \
346 YUV_TO_RGB2(r, g, b, y1_ptr[1]); \
347 RGB_OUT(d1 + BPP, r, g, b); \
349 YUV_TO_RGB2(r, g, b, y2_ptr[0]); \
350 RGB_OUT(d2, r, g, b); \
352 YUV_TO_RGB2(r, g, b, y2_ptr[1]); \
353 RGB_OUT(d2 + BPP, r, g, b); \
363 d += 2 * dst->linesize[0]; \
364 y1_ptr += 2 * src->linesize[0] - width; \
365 cb_ptr += src->linesize[1] - width2; \
366 cr_ptr += src->linesize[2] - width2; \
370 /* XXX: no chroma interpolating is done */ \
371 static void yuv422p_to_ ## rgb_name (AVPicture *dst, AVPicture *src, \
372 int width, int height) \
374 UINT8 *y1_ptr, *cb_ptr, *cr_ptr, *d, *d1; \
375 int w, y, cb, cr, r_add, g_add, b_add, width2; \
376 UINT8 *cm = cropTbl + MAX_NEG_CROP; \
377 unsigned int r, g, b; \
380 y1_ptr = src->data[0]; \
381 cb_ptr = src->data[1]; \
382 cr_ptr = src->data[2]; \
383 width2 = width >> 1; \
384 for(;height > 0; height --) { \
386 for(w = width2; w > 0; w --) { \
387 cb = cb_ptr[0] - 128; \
388 cr = cr_ptr[0] - 128; \
389 r_add = C_RV * cr + (1 << (SCALE_BITS - 1)); \
390 g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1)); \
391 b_add = C_BU * cb + (1 << (SCALE_BITS - 1)); \
393 /* output 2 pixels */ \
394 YUV_TO_RGB2(r, g, b, y1_ptr[0]); \
395 RGB_OUT(d, r, g, b); \
397 YUV_TO_RGB2(r, g, b, y1_ptr[1]); \
398 RGB_OUT(d + BPP, r, g, b); \
406 d += dst->linesize[0]; \
407 y1_ptr += src->linesize[0] - width; \
408 cb_ptr += src->linesize[1] - width2; \
409 cr_ptr += src->linesize[2] - width2; \
413 static void rgb_name ## _to_yuv420p(AVPicture *dst, AVPicture *src, \
414 int width, int height) \
416 int wrap, wrap3, x, y; \
417 int r, g, b, r1, g1, b1; \
418 UINT8 *lum, *cb, *cr; \
421 lum = dst->data[0]; \
428 for(y=0;y<height;y+=2) { \
429 for(x=0;x<width;x+=2) { \
430 RGB_IN(r, g, b, p); \
434 lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + \
435 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; \
436 RGB_IN(r, g, b, p + BPP); \
440 lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + \
441 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; \
445 RGB_IN(r, g, b, p); \
449 lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + \
450 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; \
452 RGB_IN(r, g, b, p + BPP); \
456 lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + \
457 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; \
459 cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + \
460 FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> \
461 (SCALEBITS + 2)) + 128; \
462 cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 - \
463 FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> \
464 (SCALEBITS + 2)) + 128; \
468 p += -wrap3 + 2 * 3; \
476 /* copy bit n to bits 0 ... n - 1 */
477 static inline unsigned int bitcopy_n(unsigned int a
, int n
)
481 return (a
& (0xff & ~mask
)) | ((-((a
>> n
) & 1)) & mask
);
484 /* rgb555 handling */
486 #define RGB_IN(r, g, b, s)\
488 unsigned int v = ((UINT16 *)(s))[0];\
489 r = bitcopy_n(v >> (10 - 3), 3);\
490 g = bitcopy_n(v >> (5 - 3), 3);\
491 b = bitcopy_n(v << 3, 3);\
494 #define RGB_OUT(d, r, g, b)\
496 ((UINT16 *)(d))[0] = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3) | 0x8000;\
501 RGB_FUNCTIONS(rgb555
)
507 /* rgb565 handling */
509 #define RGB_IN(r, g, b, s)\
511 unsigned int v = ((UINT16 *)(s))[0];\
512 r = bitcopy_n(v >> (11 - 3), 3);\
513 g = bitcopy_n(v >> (5 - 2), 2);\
514 b = bitcopy_n(v << 3, 3);\
517 #define RGB_OUT(d, r, g, b)\
519 ((UINT16 *)(d))[0] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);\
524 RGB_FUNCTIONS(rgb565
)
532 #define RGB_IN(r, g, b, s)\
539 #define RGB_OUT(d, r, g, b)\
556 #define RGB_IN(r, g, b, s)\
563 #define RGB_OUT(d, r, g, b)\
578 /* rgba32 handling */
580 #define RGB_IN(r, g, b, s)\
582 unsigned int v = ((UINT32 *)(s))[0];\
583 r = (v >> 16) & 0xff;\
584 g = (v >> 8) & 0xff;\
588 #define RGB_OUT(d, r, g, b)\
590 ((UINT32 *)(d))[0] = (0xff << 24) | (r << 16) | (g << 8) | b;\
595 RGB_FUNCTIONS(rgba32
)
602 static void rgb24_to_rgb565(AVPicture
*dst
, AVPicture
*src
,
603 int width
, int height
)
605 const unsigned char *p
;
607 int r
, g
, b
, dst_wrap
, src_wrap
;
611 src_wrap
= src
->linesize
[0] - 3 * width
;
614 dst_wrap
= dst
->linesize
[0] - 2 * width
;
616 for(y
=0;y
<height
;y
++) {
617 for(x
=0;x
<width
;x
++) {
622 ((unsigned short *)q
)[0] =
623 ((r
>> 3) << 11) | ((g
>> 2) << 5) | (b
>> 3);
632 /* NOTE: we also add a dummy alpha bit */
633 static void rgb24_to_rgb555(AVPicture
*dst
, AVPicture
*src
,
634 int width
, int height
)
636 const unsigned char *p
;
638 int r
, g
, b
, dst_wrap
, src_wrap
;
642 src_wrap
= src
->linesize
[0] - 3 * width
;
645 dst_wrap
= dst
->linesize
[0] - 2 * width
;
647 for(y
=0;y
<height
;y
++) {
648 for(x
=0;x
<width
;x
++) {
653 ((unsigned short *)q
)[0] =
654 ((r
>> 3) << 10) | ((g
>> 3) << 5) | (b
>> 3) | 0x8000;
663 static void rgb24_to_gray(AVPicture
*dst
, AVPicture
*src
,
664 int width
, int height
)
666 const unsigned char *p
;
668 int r
, g
, b
, dst_wrap
, src_wrap
;
672 src_wrap
= src
->linesize
[0] - 3 * width
;
675 dst_wrap
= dst
->linesize
[0] - width
;
677 for(y
=0;y
<height
;y
++) {
678 for(x
=0;x
<width
;x
++) {
683 q
[0] = (FIX(0.29900) * r
+ FIX(0.58700) * g
+
684 FIX(0.11400) * b
+ ONE_HALF
) >> SCALEBITS
;
693 static void gray_to_rgb24(AVPicture
*dst
, AVPicture
*src
,
694 int width
, int height
)
696 const unsigned char *p
;
698 int r
, dst_wrap
, src_wrap
;
702 src_wrap
= src
->linesize
[0] - width
;
705 dst_wrap
= dst
->linesize
[0] - 3 * width
;
707 for(y
=0;y
<height
;y
++) {
708 for(x
=0;x
<width
;x
++) {
723 static void monowhite_to_rgb24(AVPicture
*dst
, AVPicture
*src
,
724 int width
, int height
)
726 const unsigned char *p
;
728 int v
, dst_wrap
, src_wrap
;
732 src_wrap
= src
->linesize
[0] - ((width
+ 7) >> 3);
735 dst_wrap
= dst
->linesize
[0] - 3 * width
;
737 for(y
=0;y
<height
;y
++) {
741 q
[0] = q
[1] = q
[2] = -(v
>> 7); q
+= 3;
742 q
[0] = q
[1] = q
[2] = -((v
>> 6) & 1); q
+= 3;
743 q
[0] = q
[1] = q
[2] = -((v
>> 5) & 1); q
+= 3;
744 q
[0] = q
[1] = q
[2] = -((v
>> 4) & 1); q
+= 3;
745 q
[0] = q
[1] = q
[2] = -((v
>> 3) & 1); q
+= 3;
746 q
[0] = q
[1] = q
[2] = -((v
>> 2) & 1); q
+= 3;
747 q
[0] = q
[1] = q
[2] = -((v
>> 1) & 1); q
+= 3;
748 q
[0] = q
[1] = q
[2] = -((v
>> 0) & 1); q
+= 3;
754 q
[0] = q
[1] = q
[2] = -((v
>> 7) & 1); q
+= 3;
763 static void monoblack_to_rgb24(AVPicture
*dst
, AVPicture
*src
,
764 int width
, int height
)
766 const unsigned char *p
;
768 int v
, dst_wrap
, src_wrap
;
772 src_wrap
= src
->linesize
[0] - ((width
+ 7) >> 3);
775 dst_wrap
= dst
->linesize
[0] - 3 * width
;
777 for(y
=0;y
<height
;y
++) {
781 q
[0] = q
[1] = q
[2] = -(v
>> 7); q
+= 3;
782 q
[0] = q
[1] = q
[2] = -((v
>> 6) & 1); q
+= 3;
783 q
[0] = q
[1] = q
[2] = -((v
>> 5) & 1); q
+= 3;
784 q
[0] = q
[1] = q
[2] = -((v
>> 4) & 1); q
+= 3;
785 q
[0] = q
[1] = q
[2] = -((v
>> 3) & 1); q
+= 3;
786 q
[0] = q
[1] = q
[2] = -((v
>> 2) & 1); q
+= 3;
787 q
[0] = q
[1] = q
[2] = -((v
>> 1) & 1); q
+= 3;
788 q
[0] = q
[1] = q
[2] = -((v
>> 0) & 1); q
+= 3;
794 q
[0] = q
[1] = q
[2] = -((v
>> 7) & 1); q
+= 3;
803 typedef struct ConvertEntry
{
804 void (*convert
)(AVPicture
*dst
, AVPicture
*src
, int width
, int height
);
807 /* add each new convertion function in this table */
809 - all non YUV modes must convert at least to and from PIX_FMT_RGB24
811 static ConvertEntry convert_table
[PIX_FMT_NB
][PIX_FMT_NB
] = {
812 [PIX_FMT_YUV420P
] = {
814 convert
: yuv420p_to_rgb555
817 convert
: yuv420p_to_rgb565
820 convert
: yuv420p_to_bgr24
823 convert
: yuv420p_to_rgb24
826 convert
: yuv420p_to_rgba32
829 [PIX_FMT_YUV422P
] = {
831 convert
: yuv422p_to_rgb555
834 convert
: yuv422p_to_rgb565
837 convert
: yuv422p_to_bgr24
840 convert
: yuv422p_to_rgb24
843 convert
: yuv422p_to_rgba32
847 [PIX_FMT_YUV420P
] = {
848 convert
: yuv422_to_yuv420p
,
853 [PIX_FMT_YUV420P
] = {
854 convert
: rgb24_to_yuv420p
857 convert
: rgb24_to_rgb565
860 convert
: rgb24_to_rgb555
863 convert
: rgb24_to_gray
867 [PIX_FMT_YUV420P
] = {
868 convert
: rgba32_to_yuv420p
872 [PIX_FMT_YUV420P
] = {
873 convert
: bgr24_to_yuv420p
877 [PIX_FMT_YUV420P
] = {
878 convert
: rgb555_to_yuv420p
882 [PIX_FMT_YUV420P
] = {
883 convert
: rgb565_to_yuv420p
888 convert
: gray_to_rgb24
891 [PIX_FMT_MONOWHITE
] = {
893 convert
: monowhite_to_rgb24
896 [PIX_FMT_MONOBLACK
] = {
898 convert
: monoblack_to_rgb24
903 static int avpicture_alloc(AVPicture
*picture
,
904 int pix_fmt
, int width
, int height
)
909 size
= avpicture_get_size(pix_fmt
, width
, height
);
912 ptr
= av_malloc(size
);
915 avpicture_fill(picture
, ptr
, pix_fmt
, width
, height
);
918 memset(picture
, 0, sizeof(AVPicture
));
922 static void avpicture_free(AVPicture
*picture
)
924 free(picture
->data
[0]);
927 /* XXX: always use linesize. Return -1 if not supported */
928 int img_convert(AVPicture
*dst
, int dst_pix_fmt
,
929 AVPicture
*src
, int src_pix_fmt
,
930 int src_width
, int src_height
)
932 int i
, ret
, dst_width
, dst_height
;
933 PixFmtInfo
*src_pix
, *dst_pix
;
935 AVPicture tmp1
, *tmp
= &tmp1
;
937 if (src_pix_fmt
< 0 || src_pix_fmt
>= PIX_FMT_NB
||
938 dst_pix_fmt
< 0 || dst_pix_fmt
>= PIX_FMT_NB
)
940 if (src_width
<= 0 || src_height
<= 0)
943 dst_width
= src_width
;
944 dst_height
= src_height
;
946 dst_pix
= &pix_fmt_info
[dst_pix_fmt
];
947 src_pix
= &pix_fmt_info
[src_pix_fmt
];
948 if (src_pix_fmt
== dst_pix_fmt
) {
949 /* same format: just copy */
950 for(i
= 0; i
< dst_pix
->nb_components
; i
++) {
954 if (dst_pix
->is_yuv
&& (i
== 1 || i
== 2)) {
955 w
>>= dst_pix
->x_chroma_shift
;
956 h
>>= dst_pix
->y_chroma_shift
;
958 img_copy(dst
->data
[i
], dst
->linesize
[i
],
959 src
->data
[i
], src
->linesize
[i
],
965 ce
= &convert_table
[src_pix_fmt
][dst_pix_fmt
];
967 /* specific convertion routine */
968 ce
->convert(dst
, src
, dst_width
, dst_height
);
972 /* if both format are not YUV, try to use RGB24 as common
974 if (!dst_pix
->is_yuv
&& !src_pix
->is_yuv
) {
975 if (avpicture_alloc(tmp
, PIX_FMT_RGB24
, dst_width
, dst_height
) < 0)
978 if (img_convert(tmp
, PIX_FMT_RGB24
,
979 src
, src_pix_fmt
, src_width
, src_height
) < 0)
981 if (img_convert(dst
, dst_pix_fmt
,
982 tmp
, PIX_FMT_RGB24
, dst_width
, dst_height
) < 0)
991 if (dst_pix
->is_yuv
&& src_pix_fmt
== PIX_FMT_GRAY8
) {
995 img_copy(dst
->data
[0], dst
->linesize
[0],
996 src
->data
[0], src
->linesize
[0],
997 dst_width
, dst_height
);
998 /* fill U and V with 128 */
1001 w
>>= dst_pix
->x_chroma_shift
;
1002 h
>>= dst_pix
->y_chroma_shift
;
1003 for(i
= 1; i
<= 2; i
++) {
1005 for(y
= 0; y
<h
; y
++) {
1007 d
+= dst
->linesize
[i
];
1014 if (src_pix
->is_yuv
&& dst_pix_fmt
== PIX_FMT_GRAY8
) {
1015 img_copy(dst
->data
[0], dst
->linesize
[0],
1016 src
->data
[0], src
->linesize
[0],
1017 dst_width
, dst_height
);
1022 if (dst_pix
->is_yuv
&& src_pix
->is_yuv
) {
1023 int x_shift
, y_shift
, w
, h
;
1024 void (*resize_func
)(UINT8
*dst
, int dst_wrap
,
1025 UINT8
*src
, int src_wrap
,
1026 int width
, int height
);
1028 /* compute chroma size of the smallest dimensions */
1031 if (dst_pix
->x_chroma_shift
>= src_pix
->x_chroma_shift
)
1032 w
>>= dst_pix
->x_chroma_shift
;
1034 w
>>= src_pix
->x_chroma_shift
;
1035 if (dst_pix
->y_chroma_shift
>= src_pix
->y_chroma_shift
)
1036 h
>>= dst_pix
->y_chroma_shift
;
1038 h
>>= src_pix
->y_chroma_shift
;
1040 x_shift
= (dst_pix
->x_chroma_shift
- src_pix
->x_chroma_shift
);
1041 y_shift
= (dst_pix
->y_chroma_shift
- src_pix
->y_chroma_shift
);
1042 if (x_shift
== 0 && y_shift
== 0) {
1043 resize_func
= img_copy
; /* should never happen */
1044 } else if (x_shift
== 0 && y_shift
== 1) {
1045 resize_func
= shrink2
;
1046 } else if (x_shift
== 1 && y_shift
== 1) {
1047 resize_func
= shrink22
;
1048 } else if (x_shift
== -1 && y_shift
== -1) {
1049 resize_func
= grow22
;
1050 } else if (x_shift
== -1 && y_shift
== 1) {
1051 resize_func
= conv411
;
1053 /* currently not handled */
1057 img_copy(dst
->data
[0], dst
->linesize
[0],
1058 src
->data
[0], src
->linesize
[0],
1059 dst_width
, dst_height
);
1060 for(i
= 1;i
<= 2; i
++)
1061 resize_func(dst
->data
[1], dst
->linesize
[1],
1062 src
->data
[1], src
->linesize
[1],
1066 /* cannot convert yet */
1073 #define DEINT_INPLACE_LINE_LUM \
1074 movd_m2r(lum_m4[0],mm0);\
1075 movd_m2r(lum_m3[0],mm1);\
1076 movd_m2r(lum_m2[0],mm2);\
1077 movd_m2r(lum_m1[0],mm3);\
1078 movd_m2r(lum[0],mm4);\
1079 punpcklbw_r2r(mm7,mm0);\
1080 movd_r2m(mm2,lum_m4[0]);\
1081 punpcklbw_r2r(mm7,mm1);\
1082 punpcklbw_r2r(mm7,mm2);\
1083 punpcklbw_r2r(mm7,mm3);\
1084 punpcklbw_r2r(mm7,mm4);\
1085 paddw_r2r(mm3,mm1);\
1087 paddw_r2r(mm4,mm0);\
1089 paddw_r2r(mm6,mm2);\
1090 paddw_r2r(mm2,mm1);\
1091 psubusw_r2r(mm0,mm1);\
1093 packuswb_r2r(mm7,mm1);\
1094 movd_r2m(mm1,lum_m2[0]);
1096 #define DEINT_LINE_LUM \
1097 movd_m2r(lum_m4[0],mm0);\
1098 movd_m2r(lum_m3[0],mm1);\
1099 movd_m2r(lum_m2[0],mm2);\
1100 movd_m2r(lum_m1[0],mm3);\
1101 movd_m2r(lum[0],mm4);\
1102 punpcklbw_r2r(mm7,mm0);\
1103 punpcklbw_r2r(mm7,mm1);\
1104 punpcklbw_r2r(mm7,mm2);\
1105 punpcklbw_r2r(mm7,mm3);\
1106 punpcklbw_r2r(mm7,mm4);\
1107 paddw_r2r(mm3,mm1);\
1109 paddw_r2r(mm4,mm0);\
1111 paddw_r2r(mm6,mm2);\
1112 paddw_r2r(mm2,mm1);\
1113 psubusw_r2r(mm0,mm1);\
1115 packuswb_r2r(mm7,mm1);\
1116 movd_r2m(mm1,dst[0]);
1119 /* filter parameters: [-1 4 2 4 -1] // 8 */
1120 static void deinterlace_line(UINT8
*dst
, UINT8
*lum_m4
, UINT8
*lum_m3
, UINT8
*lum_m2
, UINT8
*lum_m1
, UINT8
*lum
,
1124 UINT8
*cm
= cropTbl
+ MAX_NEG_CROP
;
1127 for(;size
> 0;size
--) {
1129 sum
+= lum_m3
[0] << 2;
1130 sum
+= lum_m2
[0] << 1;
1131 sum
+= lum_m1
[0] << 2;
1133 dst
[0] = cm
[(sum
+ 4) >> 3];
1143 for (;size
> 3; size
-=4) {
1154 static void deinterlace_line_inplace(UINT8
*lum_m4
, UINT8
*lum_m3
, UINT8
*lum_m2
, UINT8
*lum_m1
, UINT8
*lum
,
1158 UINT8
*cm
= cropTbl
+ MAX_NEG_CROP
;
1161 for(;size
> 0;size
--) {
1163 sum
+= lum_m3
[0] << 2;
1164 sum
+= lum_m2
[0] << 1;
1165 lum_m4
[0]=lum_m2
[0];
1166 sum
+= lum_m1
[0] << 2;
1168 lum_m2
[0] = cm
[(sum
+ 4) >> 3];
1177 for (;size
> 3; size
-=4) {
1178 DEINT_INPLACE_LINE_LUM
1188 /* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The
1189 top field is copied as is, but the bottom field is deinterlaced
1190 against the top field. */
1191 static void deinterlace_bottom_field(UINT8
*dst
, int dst_wrap
,
1192 UINT8
*src1
, int src_wrap
,
1193 int width
, int height
)
1195 UINT8
*src_m2
, *src_m1
, *src_0
, *src_p1
, *src_p2
;
1200 src_0
=&src_m1
[src_wrap
];
1201 src_p1
=&src_0
[src_wrap
];
1202 src_p2
=&src_p1
[src_wrap
];
1203 for(y
=0;y
<(height
-2);y
+=2) {
1204 memcpy(dst
,src_m1
,width
);
1206 deinterlace_line(dst
,src_m2
,src_m1
,src_0
,src_p1
,src_p2
,width
);
1210 src_p1
+= 2*src_wrap
;
1211 src_p2
+= 2*src_wrap
;
1214 memcpy(dst
,src_m1
,width
);
1217 deinterlace_line(dst
,src_m2
,src_m1
,src_0
,src_0
,src_0
,width
);
1220 static void deinterlace_bottom_field_inplace(UINT8
*src1
, int src_wrap
,
1221 int width
, int height
)
1223 UINT8
*src_m1
, *src_0
, *src_p1
, *src_p2
;
1226 buf
= (UINT8
*)av_malloc(width
);
1229 memcpy(buf
,src_m1
,width
);
1230 src_0
=&src_m1
[src_wrap
];
1231 src_p1
=&src_0
[src_wrap
];
1232 src_p2
=&src_p1
[src_wrap
];
1233 for(y
=0;y
<(height
-2);y
+=2) {
1234 deinterlace_line_inplace(buf
,src_m1
,src_0
,src_p1
,src_p2
,width
);
1237 src_p1
+= 2*src_wrap
;
1238 src_p2
+= 2*src_wrap
;
1241 deinterlace_line_inplace(buf
,src_m1
,src_0
,src_0
,src_0
,width
);
1246 /* deinterlace - if not supported return -1 */
1247 int avpicture_deinterlace(AVPicture
*dst
, AVPicture
*src
,
1248 int pix_fmt
, int width
, int height
)
1252 if (pix_fmt
!= PIX_FMT_YUV420P
&&
1253 pix_fmt
!= PIX_FMT_YUV422P
&&
1254 pix_fmt
!= PIX_FMT_YUV444P
)
1256 if ((width
& 3) != 0 || (height
& 3) != 0)
1267 movq_m2r(rounder
,mm6
);
1275 case PIX_FMT_YUV420P
:
1279 case PIX_FMT_YUV422P
:
1287 deinterlace_bottom_field_inplace(src
->data
[i
], src
->linesize
[i
],
1290 deinterlace_bottom_field(dst
->data
[i
],dst
->linesize
[i
],
1291 src
->data
[i
], src
->linesize
[i
],