diff --git a/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp b/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp index 278ac32be5..a4e6fece19 100644 --- a/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp +++ b/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp @@ -490,7 +490,8 @@ AVCodecDecoder::_NegotiateVideoOutputFormat(media_format* inOutFormat) } #else fFormatConversionFunc = resolve_colorspace( - fOutputVideoFormat.display.format, fContext->pix_fmt); + fOutputVideoFormat.display.format, fContext->pix_fmt, + fContext->width, fContext->height); } if (fFormatConversionFunc != NULL) break; @@ -749,7 +750,8 @@ AVCodecDecoder::_DecodeVideo(void* outBuffer, int64* outFrameCount, #else if (fFormatConversionFunc == NULL) { fFormatConversionFunc = resolve_colorspace( - fOutputVideoFormat.display.format, fContext->pix_fmt); + fOutputVideoFormat.display.format, fContext->pix_fmt, + fContext->width, fContext->height); } #endif diff --git a/src/add-ons/media/plugins/ffmpeg/gfx_conv_mmx.cpp b/src/add-ons/media/plugins/ffmpeg/gfx_conv_mmx.cpp index 2c215725ab..ff6bb07a26 100644 --- a/src/add-ons/media/plugins/ffmpeg/gfx_conv_mmx.cpp +++ b/src/add-ons/media/plugins/ffmpeg/gfx_conv_mmx.cpp @@ -41,27 +41,29 @@ void gfx_conv_yuv420p_rgb32_mmx(AVFrame *in, AVFrame *out, int width, int height // Planar YUV420 void gfx_conv_yuv420p_rgba32_sse2(AVFrame *in, AVFrame *out, int width, int height) { - // width must be divisible by 8 and height divisible by 2 - // also in and out must be aligned to 32 bytes - if (width % 8 == 0 && height % 2 == 0 - && (off_t)out->data[0] % 32 == 0 && (off_t)in->data[0] % 32 == 0 - && (off_t)in->data[1] % 32 == 0 && (off_t)in->data[2] % 32 == 0) { + // in and out buffers must be aligned to 32 bytes, in should be as ffmpeg allocates it + if ((off_t)out->data[0] % 32 == 0) { uint8 *ybase = (uint8 *)in->data[0]; uint8 *ubase = (uint8 *)in->data[1]; uint8 *vbase = (uint8 *)in->data[2]; uint8 *rgbbase = (uint8 *)out->data[0]; - + + int yBaseInc = in->linesize[0]; + int uBaseInc = in->linesize[1]; + int vBaseInc = in->linesize[2]; + int rgbBaseInc = out->linesize[0]; + for (int i=0;ilinesize[0]; - rgbbase += out->linesize[0]; + ybase += yBaseInc; + rgbbase += rgbBaseInc; _Convert_YUV420P_RGBA32_SSE2(ybase, ubase, vbase, rgbbase, width); // Second Y row but same u and v row - ybase += in->linesize[0]; - ubase += in->linesize[1]; - vbase += in->linesize[2]; - rgbbase += out->linesize[0]; + ybase += yBaseInc; + ubase += uBaseInc; + vbase += vBaseInc; + rgbbase += rgbBaseInc; } } else { gfx_conv_YCbCr420p_RGB32_c(in, out, width, height); @@ -71,10 +73,8 @@ void gfx_conv_yuv420p_rgba32_sse2(AVFrame *in, AVFrame *out, int width, int heig // Packed YUV422 void gfx_conv_yuv422p_rgba32_sse2(AVFrame *in, AVFrame *out, int width, int height) { - // width must be divisibile by 8 - // also in and out must be aligned to 32 bytes - if (width % 8 == 0 - && (off_t)out->data[0] % 32 == 0 && (off_t)in->data[0] % 32 == 0) { + // in and out buffers must be aligned to 32 bytes, in should be as ffmpeg allocates it + if ((off_t)out->data[0] % 32 == 0) { uint8 *ybase = (uint8 *)in->data[0]; uint8 *rgbbase = (uint8 *)out->data[0]; diff --git a/src/add-ons/media/plugins/ffmpeg/gfx_util.cpp b/src/add-ons/media/plugins/ffmpeg/gfx_util.cpp index 4d2743ee8c..306f3da6fe 100644 --- a/src/add-ons/media/plugins/ffmpeg/gfx_util.cpp +++ b/src/add-ons/media/plugins/ffmpeg/gfx_util.cpp @@ -18,7 +18,7 @@ // this function will try to find the best colorspaces for both the ff-codec and // the Media Kit sides. -gfx_convert_func resolve_colorspace(color_space colorSpace, PixelFormat pixelFormat) +gfx_convert_func resolve_colorspace(color_space colorSpace, PixelFormat pixelFormat, int width, int height) { CPUCapabilities cpu; @@ -46,7 +46,7 @@ CPUCapabilities cpu; } if (pixelFormat == PIX_FMT_YUV420P || pixelFormat == PIX_FMT_YUVJ420P) { - if (cpu.HasSSE2()) { + if (cpu.HasSSE2() && width % 8 == 0 && height % 2 == 0 ) { TRACE("resolve_colorspace: gfx_conv_yuv420p_rgba32_sse2\n"); return gfx_conv_yuv420p_rgba32_sse2; } else { @@ -56,7 +56,7 @@ CPUCapabilities cpu; } if (pixelFormat == PIX_FMT_YUV422P || pixelFormat == PIX_FMT_YUVJ422P) { - if (cpu.HasSSE2()) { + if (cpu.HasSSE2() && width % 8 == 0) { return gfx_conv_yuv422p_rgba32_sse2; } else { return gfx_conv_YCbCr422_RGB32_c; diff --git a/src/add-ons/media/plugins/ffmpeg/gfx_util.h b/src/add-ons/media/plugins/ffmpeg/gfx_util.h index 105009fad0..609cec51d2 100644 --- a/src/add-ons/media/plugins/ffmpeg/gfx_util.h +++ b/src/add-ons/media/plugins/ffmpeg/gfx_util.h @@ -32,7 +32,7 @@ typedef void (*gfx_convert_func) (AVFrame *in, AVFrame *out, int width, int heig // this function will try to find the best colorspaces for both the ff-codec and // the Media Kit sides. -gfx_convert_func resolve_colorspace(color_space cs, PixelFormat pixelFormat); +gfx_convert_func resolve_colorspace(color_space cs, PixelFormat pixelFormat, int width, int height); const char *pixfmt_to_string(int format);