X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fimgconvert.c;h=88b8e3f32861c83b85dabadbb9926cbfbb54c418;hb=690bfceb204147d28d8a51b573b518d8e059462d;hp=7fe88c8344b5a7e32998cdb43ef5ac57ae702986;hpb=c3b95b1d3d506da97faa83b5a866ca605cb57316;p=ffmpeg diff --git a/libavcodec/imgconvert.c b/libavcodec/imgconvert.c index 7fe88c8344b..88b8e3f3286 100644 --- a/libavcodec/imgconvert.c +++ b/libavcodec/imgconvert.c @@ -1,5 +1,5 @@ /* - * Misc image convertion routines + * Misc image conversion routines * Copyright (c) 2001, 2002, 2003 Fabrice Bellard. * * This file is part of FFmpeg. @@ -21,7 +21,7 @@ /** * @file imgconvert.c - * Misc image convertion routines. + * misc image conversion routines */ /* TODO: @@ -32,6 +32,7 @@ #include "avcodec.h" #include "dsputil.h" +#include "colorspace.h" #ifdef HAVE_MMX #include "i386/mmx.h" @@ -119,6 +120,24 @@ static const PixFmtInfo pix_fmt_info[PIX_FMT_NB] = { .depth = 8, .x_chroma_shift = 2, .y_chroma_shift = 0, }, + [PIX_FMT_YUV440P] = { + .name = "yuv440p", + .nb_channels = 3, + .color_type = FF_COLOR_YUV, + .pixel_type = FF_PIXEL_PLANAR, + .depth = 8, + .x_chroma_shift = 0, .y_chroma_shift = 1, + }, + + /* YUV formats with alpha plane */ + [PIX_FMT_YUVA420P] = { + .name = "yuva420p", + .nb_channels = 4, + .color_type = FF_COLOR_YUV, + .pixel_type = FF_PIXEL_PLANAR, + .depth = 8, + .x_chroma_shift = 1, .y_chroma_shift = 1, + }, /* JPEG YUV */ [PIX_FMT_YUVJ420P] = { @@ -145,6 +164,14 @@ static const PixFmtInfo pix_fmt_info[PIX_FMT_NB] = { .depth = 8, .x_chroma_shift = 0, .y_chroma_shift = 0, }, + [PIX_FMT_YUVJ440P] = { + .name = "yuvj440p", + .nb_channels = 3, + .color_type = FF_COLOR_YUV_JPEG, + .pixel_type = FF_PIXEL_PLANAR, + .depth = 8, + .x_chroma_shift = 0, .y_chroma_shift = 1, + }, /* RGB formats */ [PIX_FMT_RGB24] = { @@ -399,64 +426,53 @@ void avcodec_pix_fmt_string (char *buf, int buf_size, int pix_fmt) ); } -int avpicture_fill(AVPicture *picture, uint8_t *ptr, - int pix_fmt, int width, int height) +int ff_fill_linesize(AVPicture *picture, int pix_fmt, int width) { - int size, w2, h2, size2; + int w2; const PixFmtInfo *pinfo; - if(avcodec_check_dimensions(NULL, width, height)) - goto fail; + memset(picture->linesize, 0, sizeof(picture->linesize)); pinfo = &pix_fmt_info[pix_fmt]; - size = width * height; switch(pix_fmt) { case PIX_FMT_YUV420P: case PIX_FMT_YUV422P: case PIX_FMT_YUV444P: case PIX_FMT_YUV410P: case PIX_FMT_YUV411P: + case PIX_FMT_YUV440P: case PIX_FMT_YUVJ420P: case PIX_FMT_YUVJ422P: case PIX_FMT_YUVJ444P: + case PIX_FMT_YUVJ440P: w2 = (width + (1 << pinfo->x_chroma_shift) - 1) >> pinfo->x_chroma_shift; - h2 = (height + (1 << pinfo->y_chroma_shift) - 1) >> pinfo->y_chroma_shift; - size2 = w2 * h2; - picture->data[0] = ptr; - picture->data[1] = picture->data[0] + size; - picture->data[2] = picture->data[1] + size2; picture->linesize[0] = width; picture->linesize[1] = w2; picture->linesize[2] = w2; - return size + 2 * size2; + break; + case PIX_FMT_YUVA420P: + w2 = (width + (1 << pinfo->x_chroma_shift) - 1) >> pinfo->x_chroma_shift; + picture->linesize[0] = width; + picture->linesize[1] = w2; + picture->linesize[2] = w2; + picture->linesize[3] = width; + break; case PIX_FMT_NV12: case PIX_FMT_NV21: w2 = (width + (1 << pinfo->x_chroma_shift) - 1) >> pinfo->x_chroma_shift; - h2 = (height + (1 << pinfo->y_chroma_shift) - 1) >> pinfo->y_chroma_shift; - size2 = w2 * h2 * 2; - picture->data[0] = ptr; - picture->data[1] = picture->data[0] + size; - picture->data[2] = NULL; picture->linesize[0] = width; picture->linesize[1] = w2; - picture->linesize[2] = 0; - return size + 2 * size2; + break; case PIX_FMT_RGB24: case PIX_FMT_BGR24: - picture->data[0] = ptr; - picture->data[1] = NULL; - picture->data[2] = NULL; picture->linesize[0] = width * 3; - return size * 3; + break; case PIX_FMT_RGB32: case PIX_FMT_BGR32: case PIX_FMT_RGB32_1: case PIX_FMT_BGR32_1: - picture->data[0] = ptr; - picture->data[1] = NULL; - picture->data[2] = NULL; picture->linesize[0] = width * 4; - return size * 4; + break; case PIX_FMT_GRAY16BE: case PIX_FMT_GRAY16LE: case PIX_FMT_BGR555: @@ -464,57 +480,119 @@ int avpicture_fill(AVPicture *picture, uint8_t *ptr, case PIX_FMT_RGB555: case PIX_FMT_RGB565: case PIX_FMT_YUYV422: - picture->data[0] = ptr; - picture->data[1] = NULL; - picture->data[2] = NULL; picture->linesize[0] = width * 2; - return size * 2; + break; case PIX_FMT_UYVY422: - picture->data[0] = ptr; - picture->data[1] = NULL; - picture->data[2] = NULL; picture->linesize[0] = width * 2; - return size * 2; + break; case PIX_FMT_UYYVYY411: - picture->data[0] = ptr; - picture->data[1] = NULL; - picture->data[2] = NULL; picture->linesize[0] = width + width/2; - return size + size/2; + break; case PIX_FMT_RGB8: case PIX_FMT_BGR8: case PIX_FMT_RGB4_BYTE: case PIX_FMT_BGR4_BYTE: case PIX_FMT_GRAY8: - picture->data[0] = ptr; - picture->data[1] = NULL; - picture->data[2] = NULL; picture->linesize[0] = width; - return size; + break; case PIX_FMT_RGB4: case PIX_FMT_BGR4: + picture->linesize[0] = width / 2; + break; + case PIX_FMT_MONOWHITE: + case PIX_FMT_MONOBLACK: + picture->linesize[0] = (width + 7) >> 3; + break; + case PIX_FMT_PAL8: + picture->linesize[0] = width; + picture->linesize[1] = 4; + break; + default: + return -1; + } + return 0; +} + +int ff_fill_pointer(AVPicture *picture, uint8_t *ptr, int pix_fmt, + int height) +{ + int size, h2, size2; + const PixFmtInfo *pinfo; + + pinfo = &pix_fmt_info[pix_fmt]; + size = picture->linesize[0] * height; + switch(pix_fmt) { + case PIX_FMT_YUV420P: + case PIX_FMT_YUV422P: + case PIX_FMT_YUV444P: + case PIX_FMT_YUV410P: + case PIX_FMT_YUV411P: + case PIX_FMT_YUV440P: + case PIX_FMT_YUVJ420P: + case PIX_FMT_YUVJ422P: + case PIX_FMT_YUVJ444P: + case PIX_FMT_YUVJ440P: + h2 = (height + (1 << pinfo->y_chroma_shift) - 1) >> pinfo->y_chroma_shift; + size2 = picture->linesize[1] * h2; picture->data[0] = ptr; - picture->data[1] = NULL; + picture->data[1] = picture->data[0] + size; + picture->data[2] = picture->data[1] + size2; + picture->data[3] = NULL; + return size + 2 * size2; + case PIX_FMT_YUVA420P: + h2 = (height + (1 << pinfo->y_chroma_shift) - 1) >> pinfo->y_chroma_shift; + size2 = picture->linesize[1] * h2; + picture->data[0] = ptr; + picture->data[1] = picture->data[0] + size; + picture->data[2] = picture->data[1] + size2; + picture->data[3] = picture->data[1] + size2 + size2; + return 2 * size + 2 * size2; + case PIX_FMT_NV12: + case PIX_FMT_NV21: + h2 = (height + (1 << pinfo->y_chroma_shift) - 1) >> pinfo->y_chroma_shift; + size2 = picture->linesize[1] * h2 * 2; + picture->data[0] = ptr; + picture->data[1] = picture->data[0] + size; picture->data[2] = NULL; - picture->linesize[0] = width / 2; - return size / 2; + picture->data[3] = NULL; + return size + 2 * size2; + case PIX_FMT_RGB24: + case PIX_FMT_BGR24: + case PIX_FMT_RGB32: + case PIX_FMT_BGR32: + case PIX_FMT_RGB32_1: + case PIX_FMT_BGR32_1: + case PIX_FMT_GRAY16BE: + case PIX_FMT_GRAY16LE: + case PIX_FMT_BGR555: + case PIX_FMT_BGR565: + case PIX_FMT_RGB555: + case PIX_FMT_RGB565: + case PIX_FMT_YUYV422: + case PIX_FMT_UYVY422: + case PIX_FMT_UYYVYY411: + case PIX_FMT_RGB8: + case PIX_FMT_BGR8: + case PIX_FMT_RGB4_BYTE: + case PIX_FMT_BGR4_BYTE: + case PIX_FMT_GRAY8: + case PIX_FMT_RGB4: + case PIX_FMT_BGR4: case PIX_FMT_MONOWHITE: case PIX_FMT_MONOBLACK: picture->data[0] = ptr; picture->data[1] = NULL; picture->data[2] = NULL; - picture->linesize[0] = (width + 7) >> 3; - return picture->linesize[0] * height; + picture->data[3] = NULL; + return size; case PIX_FMT_PAL8: size2 = (size + 3) & ~3; picture->data[0] = ptr; picture->data[1] = ptr + size2; /* palette is stored here as 256 32 bit words */ picture->data[2] = NULL; - picture->linesize[0] = width; - picture->linesize[1] = 4; + picture->data[3] = NULL; return size2 + 256 * 4; default: -fail: picture->data[0] = NULL; picture->data[1] = NULL; picture->data[2] = NULL; @@ -523,6 +601,19 @@ fail: } } +int avpicture_fill(AVPicture *picture, uint8_t *ptr, + int pix_fmt, int width, int height) +{ + + if(avcodec_check_dimensions(NULL, width, height)) + return -1; + + if (ff_fill_linesize(picture, pix_fmt, width)) + return -1; + + return ff_fill_pointer(picture, ptr, pix_fmt, height); +} + int avpicture_layout(const AVPicture* src, int pix_fmt, int width, int height, unsigned char *dest, int dest_size) { @@ -750,10 +841,9 @@ void ff_img_copy_plane(uint8_t *dst, int dst_wrap, } } -void av_picture_copy(AVPicture *dst, const AVPicture *src, - int pix_fmt, int width, int height) +int ff_get_plane_bytewidth(enum PixelFormat pix_fmt, int width, int plane) { - int bwidth, bits, i; + int bits; const PixFmtInfo *pf = &pix_fmt_info[pix_fmt]; pf = &pix_fmt_info[pix_fmt]; @@ -775,21 +865,42 @@ void av_picture_copy(AVPicture *dst, const AVPicture *src, bits = pf->depth * pf->nb_channels; break; } - bwidth = (width * bits + 7) >> 3; - ff_img_copy_plane(dst->data[0], dst->linesize[0], - src->data[0], src->linesize[0], - bwidth, height); + return (width * bits + 7) >> 3; + break; + case FF_PIXEL_PLANAR: + if (plane == 1 || plane == 2) + width >>= pf->x_chroma_shift; + + return (width * pf->depth + 7) >> 3; break; + case FF_PIXEL_PALETTE: + if (plane == 0) + return width; + break; + } + + return -1; +} + +void av_picture_copy(AVPicture *dst, const AVPicture *src, + int pix_fmt, int width, int height) +{ + int i; + const PixFmtInfo *pf = &pix_fmt_info[pix_fmt]; + + pf = &pix_fmt_info[pix_fmt]; + switch(pf->pixel_type) { + case FF_PIXEL_PACKED: case FF_PIXEL_PLANAR: for(i = 0; i < pf->nb_channels; i++) { int w, h; + int bwidth = ff_get_plane_bytewidth(pix_fmt, width, i); w = width; h = height; if (i == 1 || i == 2) { w >>= pf->x_chroma_shift; h >>= pf->y_chroma_shift; } - bwidth = (w * pf->depth + 7) >> 3; ff_img_copy_plane(dst->data[i], dst->linesize[i], src->data[i], src->linesize[i], bwidth, h); @@ -1158,247 +1269,32 @@ static void yuv420p_to_uyvy422(AVPicture *dst, const AVPicture *src, } } -#define SCALEBITS 10 -#define ONE_HALF (1 << (SCALEBITS - 1)) -#define FIX(x) ((int) ((x) * (1<> SCALEBITS];\ - g = cm[(y + g_add) >> SCALEBITS];\ - b = cm[(y + b_add) >> SCALEBITS];\ -} - -#define YUV_TO_RGB1(cb1, cr1)\ -{\ - cb = (cb1) - 128;\ - cr = (cr1) - 128;\ - r_add = FIX(1.40200) * cr + ONE_HALF;\ - g_add = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;\ - b_add = FIX(1.77200) * cb + ONE_HALF;\ -} - -#define YUV_TO_RGB2(r, g, b, y1)\ -{\ - y = (y1) << SCALEBITS;\ - r = cm[(y + r_add) >> SCALEBITS];\ - g = cm[(y + g_add) >> SCALEBITS];\ - b = cm[(y + b_add) >> SCALEBITS];\ -} - -#define Y_CCIR_TO_JPEG(y)\ - cm[((y) * FIX(255.0/219.0) + (ONE_HALF - 16 * FIX(255.0/219.0))) >> SCALEBITS] - -#define Y_JPEG_TO_CCIR(y)\ - (((y) * FIX(219.0/255.0) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS) - -#define C_CCIR_TO_JPEG(y)\ - cm[(((y) - 128) * FIX(127.0/112.0) + (ONE_HALF + (128 << SCALEBITS))) >> SCALEBITS] - -/* NOTE: the clamp is really necessary! */ -static inline int C_JPEG_TO_CCIR(int y) { - y = (((y - 128) * FIX(112.0/127.0) + (ONE_HALF + (128 << SCALEBITS))) >> SCALEBITS); - if (y < 16) - y = 16; - return y; -} - - -#define RGB_TO_Y(r, g, b) \ -((FIX(0.29900) * (r) + FIX(0.58700) * (g) + \ - FIX(0.11400) * (b) + ONE_HALF) >> SCALEBITS) - -#define RGB_TO_U(r1, g1, b1, shift)\ -(((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + \ - FIX(0.50000) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) - -#define RGB_TO_V(r1, g1, b1, shift)\ -(((FIX(0.50000) * r1 - FIX(0.41869) * g1 - \ - FIX(0.08131) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) - -#define RGB_TO_Y_CCIR(r, g, b) \ -((FIX(0.29900*219.0/255.0) * (r) + FIX(0.58700*219.0/255.0) * (g) + \ - FIX(0.11400*219.0/255.0) * (b) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS) - -#define RGB_TO_U_CCIR(r1, g1, b1, shift)\ -(((- FIX(0.16874*224.0/255.0) * r1 - FIX(0.33126*224.0/255.0) * g1 + \ - FIX(0.50000*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) - -#define RGB_TO_V_CCIR(r1, g1, b1, shift)\ -(((FIX(0.50000*224.0/255.0) * r1 - FIX(0.41869*224.0/255.0) * g1 - \ - FIX(0.08131*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) - -static uint8_t y_ccir_to_jpeg[256]; -static uint8_t y_jpeg_to_ccir[256]; -static uint8_t c_ccir_to_jpeg[256]; -static uint8_t c_jpeg_to_ccir[256]; - -/* init various conversion tables */ -static void img_convert_init(void) -{ - int i; - uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; - - for(i = 0;i < 256; i++) { - y_ccir_to_jpeg[i] = Y_CCIR_TO_JPEG(i); - y_jpeg_to_ccir[i] = Y_JPEG_TO_CCIR(i); - c_ccir_to_jpeg[i] = C_CCIR_TO_JPEG(i); - c_jpeg_to_ccir[i] = C_JPEG_TO_CCIR(i); - } -} - -/* apply to each pixel the given table */ -static void img_apply_table(uint8_t *dst, int dst_wrap, - const uint8_t *src, int src_wrap, - int width, int height, const uint8_t *table1) +/* 2x2 -> 1x1 */ +void ff_shrink22(uint8_t *dst, int dst_wrap, + const uint8_t *src, int src_wrap, + int width, int height) { - int n; - const uint8_t *s; + int w; + const uint8_t *s1, *s2; uint8_t *d; - const uint8_t *table; - table = table1; for(;height > 0; height--) { - s = src; + s1 = src; + s2 = s1 + src_wrap; d = dst; - n = width; - while (n >= 4) { - d[0] = table[s[0]]; - d[1] = table[s[1]]; - d[2] = table[s[2]]; - d[3] = table[s[3]]; + for(w = width;w >= 4; w-=4) { + d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2; + d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 2; + d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 2; + d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 2; + s1 += 8; + s2 += 8; d += 4; - s += 4; - n -= 4; } - while (n > 0) { - d[0] = table[s[0]]; - d++; - s++; - n--; - } - dst += dst_wrap; - src += src_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 shrink12(uint8_t *dst, int dst_wrap, - const uint8_t *src, int src_wrap, - int width, int height) -{ - int w; - uint8_t *d; - const uint8_t *s1, *s2; - - for(;height > 0; height--) { - s1 = src; - s2 = s1 + src_wrap; - d = dst; - for(w = width;w >= 4; w-=4) { - d[0] = (s1[0] + s2[0]) >> 1; - d[1] = (s1[1] + s2[1]) >> 1; - d[2] = (s1[2] + s2[2]) >> 1; - d[3] = (s1[3] + s2[3]) >> 1; - s1 += 4; - s2 += 4; - d += 4; - } - for(;w > 0; w--) { - d[0] = (s1[0] + s2[0]) >> 1; - s1++; - s2++; - d++; - } - src += 2 * src_wrap; - dst += dst_wrap; - } -} - -/* 2x2 -> 1x1 */ -void ff_shrink22(uint8_t *dst, int dst_wrap, - const uint8_t *src, int src_wrap, - int width, int height) -{ - int w; - const uint8_t *s1, *s2; - uint8_t *d; - - for(;height > 0; height--) { - s1 = src; - s2 = s1 + src_wrap; - d = dst; - for(w = width;w >= 4; w-=4) { - d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2; - d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 2; - d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 2; - d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 2; - s1 += 8; - s2 += 8; - d += 4; - } - for(;w > 0; w--) { - d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2; - s1 += 2; - s2 += 2; + for(;w > 0; w--) { + d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2; + s1 += 2; + s2 += 2; d++; } src += 2 * src_wrap; @@ -1459,131 +1355,6 @@ void ff_shrink88(uint8_t *dst, int 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, - const uint8_t *src, int src_wrap, - int width, int height) -{ - int w, c; - const uint8_t *s1, *s2; - uint8_t *d; - - width>>=1; - - for(;height > 0; height--) { - s1 = src; - s2 = src + src_wrap; - d = dst; - for(w = width;w > 0; w--) { - c = (s1[0] + s2[0]) >> 1; - d[0] = c; - d[1] = c; - s1++; - s2++; - d += 2; - } - src += src_wrap * 2; - dst += dst_wrap; - } -} - /* XXX: add jpeg quantize code */ #define TRANSP_INDEX (6*6*6) @@ -1913,9 +1684,9 @@ static void gray16_to_gray16(AVPicture *dst, const AVPicture *src, { int x, y, src_wrap, dst_wrap; uint16_t *s, *d; - s = src->data[0]; + s = (uint16_t*)src->data[0]; src_wrap = (src->linesize[0] - width * 2)/2; - d = dst->data[0]; + d = (uint16_t*)dst->data[0]; dst_wrap = (dst->linesize[0] - width * 2)/2; for(y=0; y= PIX_FMT_NB || - dst_pix_fmt < 0 || dst_pix_fmt >= PIX_FMT_NB) - return -1; +/* init various conversion tables */ +static void img_convert_init(void) +{ + int i; + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; + + for(i = 0;i < 256; i++) { + y_ccir_to_jpeg[i] = Y_CCIR_TO_JPEG(i); + y_jpeg_to_ccir[i] = Y_JPEG_TO_CCIR(i); + c_ccir_to_jpeg[i] = C_CCIR_TO_JPEG(i); + c_jpeg_to_ccir[i] = C_JPEG_TO_CCIR(i); + } +} + +/* apply to each pixel the given table */ +static void img_apply_table(uint8_t *dst, int dst_wrap, + const uint8_t *src, int src_wrap, + int width, int height, const uint8_t *table1) +{ + int n; + const uint8_t *s; + uint8_t *d; + const uint8_t *table; + + table = table1; + for(;height > 0; height--) { + s = src; + d = dst; + n = width; + while (n >= 4) { + d[0] = table[s[0]]; + d[1] = table[s[1]]; + d[2] = table[s[2]]; + d[3] = table[s[3]]; + d += 4; + s += 4; + n -= 4; + } + while (n > 0) { + d[0] = table[s[0]]; + d++; + s++; + n--; + } + dst += dst_wrap; + src += src_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 shrink12(uint8_t *dst, int dst_wrap, + const uint8_t *src, int src_wrap, + int width, int height) +{ + int w; + uint8_t *d; + const uint8_t *s1, *s2; + + for(;height > 0; height--) { + s1 = src; + s2 = s1 + src_wrap; + d = dst; + for(w = width;w >= 4; w-=4) { + d[0] = (s1[0] + s2[0]) >> 1; + d[1] = (s1[1] + s2[1]) >> 1; + d[2] = (s1[2] + s2[2]) >> 1; + d[3] = (s1[3] + s2[3]) >> 1; + s1 += 4; + s2 += 4; + d += 4; + } + for(;w > 0; w--) { + d[0] = (s1[0] + s2[0]) >> 1; + s1++; + s2++; + d++; + } + src += 2 * 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 -> 1x2 */ +static void grow12(uint8_t *dst, int dst_wrap, + const uint8_t *src, int src_wrap, + int width, int height) +{ + for(;height > 0; height-=2) { + memcpy(dst, src, width); + dst += dst_wrap; + memcpy(dst, src, width); + dst += dst_wrap; + src += src_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, + const uint8_t *src, int src_wrap, + int width, int height) +{ + int w, c; + const uint8_t *s1, *s2; + uint8_t *d; + + width>>=1; + + for(;height > 0; height--) { + s1 = src; + s2 = src + src_wrap; + d = dst; + for(w = width;w > 0; w--) { + c = (s1[0] + s2[0]) >> 1; + d[0] = c; + d[1] = c; + s1++; + s2++; + d += 2; + } + src += src_wrap * 2; + dst += dst_wrap; + } +} + +/* XXX: always use linesize. Return -1 if not supported */ +int img_convert(AVPicture *dst, int dst_pix_fmt, + const AVPicture *src, int src_pix_fmt, + int src_width, int src_height) +{ + static int initialized; + int i, ret, dst_width, dst_height, int_pix_fmt; + const PixFmtInfo *src_pix, *dst_pix; + const ConvertEntry *ce; + AVPicture tmp1, *tmp = &tmp1; + + if (src_pix_fmt < 0 || src_pix_fmt >= PIX_FMT_NB || + dst_pix_fmt < 0 || dst_pix_fmt >= PIX_FMT_NB) + return -1; if (src_width <= 0 || src_height <= 0) return 0; - if (!inited) { - inited = 1; + if (!initialized) { + initialized = 1; img_convert_init(); } @@ -2470,6 +2514,9 @@ int img_convert(AVPicture *dst, int dst_pix_fmt, case 0xf0: resize_func = grow21; break; + case 0x0f: + resize_func = grow12; + break; case 0xe0: resize_func = grow41; break; @@ -2564,6 +2611,8 @@ int img_convert(AVPicture *dst, int dst_pix_fmt, else int_pix_fmt = PIX_FMT_RGB24; } + if (src_pix_fmt == int_pix_fmt) + return -1; if (avpicture_alloc(tmp, int_pix_fmt, dst_width, dst_height) < 0) return -1; ret = -1; @@ -2833,7 +2882,8 @@ int avpicture_deinterlace(AVPicture *dst, const AVPicture *src, if (pix_fmt != PIX_FMT_YUV420P && pix_fmt != PIX_FMT_YUV422P && pix_fmt != PIX_FMT_YUV444P && - pix_fmt != PIX_FMT_YUV411P) + pix_fmt != PIX_FMT_YUV411P && + pix_fmt != PIX_FMT_GRAY8) return -1; if ((width & 3) != 0 || (height & 3) != 0) return -1; @@ -2854,6 +2904,9 @@ int avpicture_deinterlace(AVPicture *dst, const AVPicture *src, default: break; } + if (pix_fmt == PIX_FMT_GRAY8) { + break; + } } if (src == dst) { deinterlace_bottom_field_inplace(dst->data[i], dst->linesize[i], @@ -2864,10 +2917,7 @@ int avpicture_deinterlace(AVPicture *dst, const AVPicture *src, width, height); } } -#ifdef HAVE_MMX - emms(); -#endif + emms_c(); return 0; } -#undef FIX