summaryrefslogtreecommitdiff
path: root/libavcodec/imgconvert.c
diff options
context:
space:
mode:
authorFabrice Bellard <fabrice@bellard.org>2003-04-21 14:38:52 +0000
committerFabrice Bellard <fabrice@bellard.org>2003-04-21 14:38:52 +0000
commite352ff0895df85594dd8df385a650d45b74a28e3 (patch)
tree827c0a37b47d24edb5dc3a9af83ff8a3f931ca09 /libavcodec/imgconvert.c
parent7e7e59409294af9caa63808e56c5cc824c98b4fc (diff)
downloadffmpeg-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.c248
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 ||