diff --git a/src/add-ons/media/plugins/avcodec/gfx_conv_c.cpp b/src/add-ons/media/plugins/avcodec/gfx_conv_c.cpp index a7a8689613..e9be69d423 100644 --- a/src/add-ons/media/plugins/avcodec/gfx_conv_c.cpp +++ b/src/add-ons/media/plugins/avcodec/gfx_conv_c.cpp @@ -268,3 +268,64 @@ void gfx_conv_YCbCr420p_RGB32_c(AVFrame *in, AVFrame *out, int width, int height } #endif + +#define CLIP(a) if (0xffffff00 & (uint32)a) { if (a < 0) a = 0; else a = 255; } + +// http://en.wikipedia.org/wiki/YUV +uint32 YUV444TORGBA8888(uint8 y, uint8 u, uint8 v) +{ + uint32 pixel = 0; + int32 c, d, e; + int32 r,g,b; + + c = y - 16; + d = u - 128; + e = v - 128; + + r = (298 * c + 409 * e + 128) >> 8; + g = (298 * c - 100 * d - 208 * e + 128) >> 8; + b = (298 * c + 516 * d + 128) >> 8; + + CLIP(r); + CLIP(g); + CLIP(b); + + pixel = (r << 16) | (g << 8) | b; + + return pixel; +} + +void gfx_conv_YCbCr422_RGB32_c(AVFrame *in, AVFrame *out, int width, int height) +{ + uint8 *ybase = (uint8 *)in->data[0]; + uint8 *ubase = (uint8 *)in->data[1]; + uint8 *vbase = (uint8 *)in->data[2]; + + uint32 *rgbbase = (uint32 *)out->data[0]; + + int uv_index; + + for (uint32 i = 0; i < height; i++) { + + uv_index = 0; + + for (uint32 j=0; j < width; j+=2) { + rgbbase[j] = YUV444TORGBA8888(ybase[j] ,ubase[uv_index],vbase[uv_index]); + rgbbase[j+1] = YUV444TORGBA8888(ybase[j+1],ubase[uv_index],vbase[uv_index]); + + uv_index++; + } + + ybase += in->linesize[0]; + ubase += in->linesize[1]; + vbase += in->linesize[2]; + + rgbbase += out->linesize[0] / 4; + } + + if (height & 1) { + // XXX special case for last line if height not multiple of 2 goes here + memset((height - 1) * out->linesize[0] + (uint8 *)out->data[0], 0, width * 4); + } + +} diff --git a/src/add-ons/media/plugins/avcodec/gfx_conv_c.h b/src/add-ons/media/plugins/avcodec/gfx_conv_c.h index dfb43242d9..9f9f1eee95 100644 --- a/src/add-ons/media/plugins/avcodec/gfx_conv_c.h +++ b/src/add-ons/media/plugins/avcodec/gfx_conv_c.h @@ -14,5 +14,6 @@ void gfx_conv_yuv420p_ycbcr422_c(AVFrame *in, AVFrame *out, int width, int heigh void gfx_conv_yuv410p_rgb32_c(AVFrame *in, AVFrame *out, int width, int height); void gfx_conv_yuv411p_rgb32_c(AVFrame *in, AVFrame *out, int width, int height); void gfx_conv_YCbCr420p_RGB32_c(AVFrame *in, AVFrame *out, int width, int height); +void gfx_conv_YCbCr422_RGB32_c(AVFrame *in, AVFrame *out, int width, int height); #endif diff --git a/src/add-ons/media/plugins/avcodec/gfx_util.cpp b/src/add-ons/media/plugins/avcodec/gfx_util.cpp index afcc3fa138..e6b0fe3cea 100644 --- a/src/add-ons/media/plugins/avcodec/gfx_util.cpp +++ b/src/add-ons/media/plugins/avcodec/gfx_util.cpp @@ -68,6 +68,10 @@ gfx_convert_func resolve_colorspace(color_space colorSpace, PixelFormat pixelFor } } + if (pixelFormat == PIX_FMT_YUV422P || pixelFormat == PIX_FMT_YUVJ422P) { + return gfx_conv_YCbCr422_RGB32_c; + } + TRACE("resolve_colorspace: %s => B_RGB32: NULL\n", pixfmt_to_string(pixelFormat)); return NULL; @@ -120,7 +124,7 @@ gfx_convert_func resolve_colorspace(color_space colorSpace, PixelFormat pixelFor } } - if (pixelFormat == PIX_FMT_YUV422) { + if (pixelFormat == PIX_FMT_YUV422 || PIX_FMT_YUVJ422P) { #if INCLUDE_MMX if (mmx) { TRACE("resolve_colorspace: PIX_FMT_YUV422 => B_YCbCr422: gfx_conv_null_mmx\n"); @@ -134,7 +138,7 @@ gfx_convert_func resolve_colorspace(color_space colorSpace, PixelFormat pixelFor } TRACE("resolve_colorspace: %s => B_YCbCr422: NULL\n", pixfmt_to_string(pixelFormat)); - return NULL; + return gfx_conv_null_c; default: TRACE("resolve_colorspace: default: NULL !!!\n"); @@ -159,6 +163,8 @@ const char *pixfmt_to_string(int p) return "PIX_FMT_BGR24"; case PIX_FMT_YUV422P: return "PIX_FMT_YUV422P"; + case PIX_FMT_YUVJ422P: + return "PIX_FMT_YUVJ422P - YUV422P (Jpeg)"; case PIX_FMT_YUV444P: return "PIX_FMT_YUV444P"; case PIX_FMT_RGBA32: