diff options
author | Fabrice Bellard <fabrice@bellard.org> | 2003-04-21 14:38:52 +0000 |
---|---|---|
committer | Fabrice Bellard <fabrice@bellard.org> | 2003-04-21 14:38:52 +0000 |
commit | e352ff0895df85594dd8df385a650d45b74a28e3 (patch) | |
tree | 827c0a37b47d24edb5dc3a9af83ff8a3f931ca09 /libavcodec/imgconvert.c | |
parent | 7e7e59409294af9caa63808e56c5cc824c98b4fc (diff) | |
download | ffmpeg-e352ff0895df85594dd8df385a650d45b74a28e3.tar.gz |
added all missing UV conversions
Originally committed as revision 1803 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavcodec/imgconvert.c')
-rw-r--r-- | libavcodec/imgconvert.c | 248 |
1 files changed, 213 insertions, 35 deletions
diff --git a/libavcodec/imgconvert.c b/libavcodec/imgconvert.c index c4d36aecf3..6c0128ca9d 100644 --- a/libavcodec/imgconvert.c +++ b/libavcodec/imgconvert.c @@ -463,8 +463,8 @@ int avcodec_find_best_pix_fmt(int pix_fmt_mask, int src_pix_fmt, } static void img_copy_plane(uint8_t *dst, int dst_wrap, - uint8_t *src, int src_wrap, - int width, int height) + const uint8_t *src, int src_wrap, + int width, int height) { for(;height > 0; height--) { memcpy(dst, src, width); @@ -774,13 +774,60 @@ static void img_apply_table(uint8_t *dst, int dst_wrap, } /* XXX: use generic filter ? */ +/* XXX: in most cases, the sampling position is incorrect */ + +/* 4x1 -> 1x1 */ +static void shrink41(uint8_t *dst, int dst_wrap, + const uint8_t *src, int src_wrap, + int width, int height) +{ + int w; + const uint8_t *s; + uint8_t *d; + + for(;height > 0; height--) { + s = src; + d = dst; + for(w = width;w > 0; w--) { + d[0] = (s[0] + s[1] + s[2] + s[3] + 2) >> 2; + s += 4; + d++; + } + src += src_wrap; + dst += dst_wrap; + } +} + +/* 2x1 -> 1x1 */ +static void shrink21(uint8_t *dst, int dst_wrap, + const uint8_t *src, int src_wrap, + int width, int height) +{ + int w; + const uint8_t *s; + uint8_t *d; + + for(;height > 0; height--) { + s = src; + d = dst; + for(w = width;w > 0; w--) { + d[0] = (s[0] + s[1]) >> 1; + s += 2; + d++; + } + src += src_wrap; + dst += dst_wrap; + } +} + /* 1x2 -> 1x1 */ -static void shrink2(uint8_t *dst, int dst_wrap, - uint8_t *src, int src_wrap, - int width, int height) +static void shrink12(uint8_t *dst, int dst_wrap, + const uint8_t *src, int src_wrap, + int width, int height) { int w; - uint8_t *s1, *s2, *d; + uint8_t *d; + const uint8_t *s1, *s2; for(;height > 0; height--) { s1 = src; @@ -808,11 +855,12 @@ static void shrink2(uint8_t *dst, int dst_wrap, /* 2x2 -> 1x1 */ static void shrink22(uint8_t *dst, int dst_wrap, - uint8_t *src, int src_wrap, + const uint8_t *src, int src_wrap, int width, int height) { int w; - uint8_t *s1, *s2, *d; + const uint8_t *s1, *s2; + uint8_t *d; for(;height > 0; height--) { s1 = src; @@ -838,41 +886,142 @@ static void shrink22(uint8_t *dst, int dst_wrap, } } -/* 1x1 -> 2x2 */ -static void grow22(uint8_t *dst, int dst_wrap, - uint8_t *src, int src_wrap, +/* 4x4 -> 1x1 */ +static void shrink44(uint8_t *dst, int dst_wrap, + const uint8_t *src, int src_wrap, int width, int height) { int w; - uint8_t *s1, *d; + const uint8_t *s1, *s2, *s3, *s4; + uint8_t *d; for(;height > 0; height--) { s1 = src; + s2 = s1 + src_wrap; + s3 = s2 + src_wrap; + s4 = s3 + src_wrap; d = dst; - for(w = width;w >= 4; w-=4) { - d[1] = d[0] = s1[0]; - d[3] = d[2] = s1[1]; - s1 += 2; - d += 4; - } - for(;w > 0; w--) { - d[0] = s1[0]; - s1 ++; + for(w = width;w > 0; w--) { + d[0] = (s1[0] + s1[1] + s1[2] + s1[3] + + s2[0] + s2[1] + s2[2] + s2[3] + + s3[0] + s3[1] + s3[2] + s3[3] + + s4[0] + s4[1] + s4[2] + s4[3] + 8) >> 4; + s1 += 4; + s2 += 4; + s3 += 4; + s4 += 4; d++; } + src += 4 * src_wrap; + dst += dst_wrap; + } +} + +static void grow21_line(uint8_t *dst, const uint8_t *src, + int width) +{ + int w; + const uint8_t *s1; + uint8_t *d; + + s1 = src; + d = dst; + for(w = width;w >= 4; w-=4) { + d[1] = d[0] = s1[0]; + d[3] = d[2] = s1[1]; + s1 += 2; + d += 4; + } + for(;w >= 2; w -= 2) { + d[1] = d[0] = s1[0]; + s1 ++; + d += 2; + } + /* only needed if width is not a multiple of two */ + /* XXX: veryfy that */ + if (w) { + d[0] = s1[0]; + } +} + +static void grow41_line(uint8_t *dst, const uint8_t *src, + int width) +{ + int w, v; + const uint8_t *s1; + uint8_t *d; + + s1 = src; + d = dst; + for(w = width;w >= 4; w-=4) { + v = s1[0]; + d[0] = v; + d[1] = v; + d[2] = v; + d[3] = v; + s1 ++; + d += 4; + } +} + +/* 1x1 -> 2x1 */ +static void grow21(uint8_t *dst, int dst_wrap, + const uint8_t *src, int src_wrap, + int width, int height) +{ + for(;height > 0; height--) { + grow21_line(dst, src, width); + src += src_wrap; + dst += dst_wrap; + } +} + +/* 1x1 -> 2x2 */ +static void grow22(uint8_t *dst, int dst_wrap, + const uint8_t *src, int src_wrap, + int width, int height) +{ + for(;height > 0; height--) { + grow21_line(dst, src, width); if (height%2) src += src_wrap; dst += dst_wrap; } } +/* 1x1 -> 4x1 */ +static void grow41(uint8_t *dst, int dst_wrap, + const uint8_t *src, int src_wrap, + int width, int height) +{ + for(;height > 0; height--) { + grow41_line(dst, src, width); + src += src_wrap; + dst += dst_wrap; + } +} + +/* 1x1 -> 4x4 */ +static void grow44(uint8_t *dst, int dst_wrap, + const uint8_t *src, int src_wrap, + int width, int height) +{ + for(;height > 0; height--) { + grow41_line(dst, src, width); + if ((height & 3) == 1) + src += src_wrap; + dst += dst_wrap; + } +} + /* 1x2 -> 2x1 */ static void conv411(uint8_t *dst, int dst_wrap, - uint8_t *src, int src_wrap, + const uint8_t *src, int src_wrap, int width, int height) { int w, c; - uint8_t *s1, *s2, *d; + const uint8_t *s1, *s2; + uint8_t *d; width>>=1; @@ -1188,10 +1337,12 @@ typedef struct ConvertEntry { - all FF_COLOR_RGB formats with alpha must convert to and from PIX_FMT_RGBA32 - - all PIX_FMT_YUV444P and PIX_FMT_YUVJ444P must convert to and from + - PIX_FMT_YUV444P and PIX_FMT_YUVJ444P must convert to and from PIX_FMT_RGB24. - PIX_FMT_422 must convert to and from PIX_FMT_422P. + + The other conversion functions are just optimisations for common cases. */ static ConvertEntry convert_table[PIX_FMT_NB][PIX_FMT_NB] = { [PIX_FMT_YUV420P] = { @@ -1510,9 +1661,9 @@ int img_convert(AVPicture *dst, int dst_pix_fmt, /* YUV to YUV planar */ if (is_yuv_planar(dst_pix) && is_yuv_planar(src_pix)) { - int x_shift, y_shift, w, h; + int x_shift, y_shift, w, h, xy_shift; void (*resize_func)(uint8_t *dst, int dst_wrap, - uint8_t *src, int src_wrap, + const uint8_t *src, int src_wrap, int width, int height); /* compute chroma size of the smallest dimensions */ @@ -1529,20 +1680,46 @@ int img_convert(AVPicture *dst, int dst_pix_fmt, x_shift = (dst_pix->x_chroma_shift - src_pix->x_chroma_shift); y_shift = (dst_pix->y_chroma_shift - src_pix->y_chroma_shift); - - if (x_shift == 0 && y_shift == 0) { + xy_shift = ((x_shift & 0xf) << 4) | (y_shift & 0xf); + /* there must be filters for conversion at least from and to + YUV444 format */ + switch(xy_shift) { + case 0x00: resize_func = img_copy_plane; - } else if (x_shift == 0 && y_shift == 1) { - resize_func = shrink2; - } else if (x_shift == 1 && y_shift == 1) { + break; + case 0x10: + resize_func = shrink21; + break; + case 0x20: + resize_func = shrink41; + break; + case 0x01: + resize_func = shrink12; + break; + case 0x11: resize_func = shrink22; - } else if (x_shift == -1 && y_shift == -1) { + break; + case 0x22: + resize_func = shrink44; + break; + case 0xf0: + resize_func = grow21; + break; + case 0xe0: + resize_func = grow41; + break; + case 0xff: resize_func = grow22; - } else if (x_shift == -1 && y_shift == 1) { + break; + case 0xee: + resize_func = grow44; + break; + case 0xf1: resize_func = conv411; - } else { + break; + default: /* currently not handled */ - return -1; + goto no_chroma_filter; } img_copy_plane(dst->data[0], dst->linesize[0], @@ -1578,6 +1755,7 @@ int img_convert(AVPicture *dst, int dst_pix_fmt, } return 0; } + no_chroma_filter: /* try to use an intermediate format */ if (src_pix_fmt == PIX_FMT_YUV422 || |