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 5383e21076..ecc7e51ea2 100644 --- a/src/add-ons/media/plugins/avcodec/gfx_conv_c.cpp +++ b/src/add-ons/media/plugins/avcodec/gfx_conv_c.cpp @@ -176,41 +176,51 @@ void gfx_conv_yuv411p_rgb32_c(AVFrame *in, AVFrame *out, int width, int height) void gfx_conv_yuv420p_rgb32_c(AVFrame *in, AVFrame *out, int width, int height) { + uint32 poutInc = 2 * out->linesize[0]; + uint32 *poutEven = (uint32 *)out->data[0]; + uint32 *poutOdd = (uint32 *)(out->linesize[0] + (uint8 *)poutEven); + + uint32 pi1Inc = in->linesize[0]; + uint32 pi1Inc2 = 2 * pi1Inc; + uint32 pi2Inc = in->linesize[1]; + uint32 pi3Inc = in->linesize[2]; + + uint8 *pi1Base = (uint8 *)in->data[0]; + uint8 *pi2Base = (uint8 *)in->data[1]; + uint8 *pi3Base = (uint8 *)in->data[2]; - for (int i = 0; i < height; i++) { + uint32 runs = height / 2; + for (uint32 i = 0; i < runs; i++) { - uint32 *pout = (uint32 *)(i * out->linesize[0] + (uint8 *)out->data[0]); - uint8 *pi1 = i * in->linesize[0] + (uint8 *)in->data[0]; - uint8 *pi2 = (i/2) * in->linesize[1] + (uint8 *)in->data[1]; - uint8 *pi3 = (i/2) * in->linesize[2] + (uint8 *)in->data[2]; + uint8 *pi1Even = i * pi1Inc2 + pi1Base; + uint8 *pi1Odd = pi1Inc + pi1Even; + uint8 *pi2 = i * pi2Inc + pi2Base; + uint8 *pi3 = i *pi3Inc + pi3Base; - for (int j = 0; j < width; j+= 2) { + for (uint32 j = 0; j < (uint32)width; j+= 2) { - int32 Cb, Cr, Y0, Y1, Cr_R, Cr_G, Cb_G, Cb_B, R, G, B; - - uint32 Y = *(uint16 *)pi1; - pi1 += 2; + int32 Cr_R, Cr_G, Cb_G, Cb_B; + register int32 Y0, Y1, R, G, B; + + B = - 128 + *(pi2++); + R = - 128 + *(pi3++); + Cr_R = R * 52298; + Cr_G = R * -26640; + Cb_G = B * -12845; + Cb_B = B * 66493; + + G = *(uint16 *)pi1Even; + pi1Even += 2; + Y0 = ((G & 0x000000ff) - 16) * 38142; + Y1 = (((G & 0x0000ff00) >> 8) - 16) * 38142; - Y1 = (((Y & 0x0000ff00) >> 8) - 16) * 38142; - Y0 = ((Y & 0x000000ff) - 16) * 38142; - - Cb = - 128 + *pi2; - Cr = - 128 + *pi3; - pi2 ++; - pi3 ++; - - Cr_R = Cr * 52298; - Cr_G = Cr * -26640; - Cb_G = Cb * -12845; - Cb_B = Cb * 66493; - R = (Y0 + Cr_R) >> 15; if (R < 0) R = 0; else if (R > 255) R = 255; G = (Y0 + Cr_G + Cb_G) >> 15; if (G < 0) G = 0; else if (G > 255) G = 255; B = (Y0 + Cb_B) >> 15; if (B < 0) B = 0; else if (B > 255) B = 255; - pout[j] = (R << 16) | (G << 8) | B; + poutEven[j] = (R << 16) | (G << 8) | B; R = (Y1 + Cr_R) >> 15; if (R < 0) R = 0; else if (R > 255) R = 255; @@ -218,9 +228,34 @@ void gfx_conv_yuv420p_rgb32_c(AVFrame *in, AVFrame *out, int width, int height) if (G < 0) G = 0; else if (G > 255) G = 255; B = (Y1 + Cb_B) >> 15; if (B < 0) B = 0; else if (B > 255) B = 255; - pout[j + 1] = (R << 16) | (G << 8) | B; + poutEven[j + 1] = (R << 16) | (G << 8) | B; + G = *(uint16 *)pi1Odd; + pi1Odd += 2; + Y0 = ((G & 0x000000ff) - 16) * 38142; + Y1 = (((G & 0x0000ff00) >> 8) - 16) * 38142; + + R = (Y0 + Cr_R) >> 15; + if (R < 0) R = 0; else if (R > 255) R = 255; + G = (Y0 + Cr_G + Cb_G) >> 15; + if (G < 0) G = 0; else if (G > 255) G = 255; + B = (Y0 + Cb_B) >> 15; + if (B < 0) B = 0; else if (B > 255) B = 255; + poutOdd[j] = (R << 16) | (G << 8) | B; + + R = (Y1 + Cr_R) >> 15; + if (R < 0) R = 0; else if (R > 255) R = 255; + G = (Y1 + Cr_G + Cb_G) >> 15; + if (G < 0) G = 0; else if (G > 255) G = 255; + B = (Y1 + Cb_B) >> 15; + if (B < 0) B = 0; else if (B > 255) B = 255; + poutOdd[j + 1] = (R << 16) | (G << 8) | B; } + poutEven = (uint32 *)(poutInc + (uint8 *)poutEven); + poutOdd = (uint32 *)(poutInc + (uint8 *)poutOdd); + } + 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); } } -