BasicPlanarYCbCrImage(const gfx::IntSize& aScaleHint, gfxImageFormat aOffscreenFormat, BufferRecycleBin *aRecycleBin) : PlanarYCbCrImage(aRecycleBin) , mScaleHint(aScaleHint) , mDelayedConversion(false) { SetOffscreenFormat(aOffscreenFormat); }
void BasicPlanarYCbCrImage::SetData(const Data& aData) { PlanarYCbCrImage::SetData(aData); // Do some sanity checks to prevent integer overflow if (aData.mYSize.width > PlanarYCbCrImage::MAX_DIMENSION || aData.mYSize.height > PlanarYCbCrImage::MAX_DIMENSION) { NS_ERROR("Illegal image source width or height"); return; } gfxASurface::gfxImageFormat format = GetOffscreenFormat(); gfxIntSize size(mScaleHint); gfxUtils::GetYCbCrToRGBDestFormatAndSize(aData, format, size); if (size.width > PlanarYCbCrImage::MAX_DIMENSION || size.height > PlanarYCbCrImage::MAX_DIMENSION) { NS_ERROR("Illegal image dest width or height"); return; } mStride = gfxASurface::FormatStrideForWidth(format, size.width); mDecodedBuffer = AllocateBuffer(size.height * mStride); if (!mDecodedBuffer) { // out of memory return; } gfxUtils::ConvertYCbCrToRGB(aData, format, size, mDecodedBuffer, mStride); SetOffscreenFormat(format); mSize = size; }
void BasicPlanarYCbCrImage::SetData(const Data& aData) { // Do some sanity checks to prevent integer overflow if (aData.mYSize.width > 16384 || aData.mYSize.height > 16384) { NS_ERROR("Illegal width or height"); return; } gfxASurface::gfxImageFormat format = GetOffscreenFormat(); gfx::YUVType type = gfx::YV12; if (aData.mYSize.width == aData.mCbCrSize.width && aData.mYSize.height == aData.mCbCrSize.height) { type = gfx::YV24; } else if (aData.mYSize.width / 2 == aData.mCbCrSize.width && aData.mYSize.height == aData.mCbCrSize.height) { type = gfx::YV16; } else if (aData.mYSize.width / 2 == aData.mCbCrSize.width && aData.mYSize.height / 2 == aData.mCbCrSize.height ) { type = gfx::YV12; } else { NS_ERROR("YCbCr format not supported"); } // 'prescale' is true if the scaling is to be done as part of the // YCbCr to RGB conversion rather than on the RGB data when rendered. // We don't prescale if the image has an offset. See bug 639415. PRBool prescale = mScaleHint.width > 0 && mScaleHint.height > 0 && aData.mPicX == 0 && aData.mPicY == 0; if (format == gfxASurface::ImageFormatRGB16_565) { #if defined(HAVE_YCBCR_TO_RGB565) if (prescale && gfx::IsConvertYCbCrToRGB565Fast(aData.mPicX, aData.mPicY, aData.mPicSize.width, aData.mPicSize.height, type)) { // yuv2rgb16 with scale function not yet available for NEON prescale = PR_FALSE; } else #endif { // yuv2rgb16 function not yet available for non-NEON, and currently // using it requires a number of extra graphics operations, so it's // probably better to fall back to 24-bit RGB. // See https://bugzilla.mozilla.org/show_bug.cgi?id=641196 format = gfxASurface::ImageFormatRGB24; } } gfxIntSize size(prescale ? mScaleHint.width : aData.mPicSize.width, prescale ? mScaleHint.height : aData.mPicSize.height); mStride = gfxASurface::FormatStrideForWidth(format, size.width); mBuffer = new PRUint8[size.height * mStride]; if (!mBuffer) { // out of memory return; } // Convert from YCbCr to RGB now, scaling the image if needed. if (size != aData.mPicSize) { if (format == gfxASurface::ImageFormatRGB24) { gfx::ScaleYCbCrToRGB32(aData.mYChannel, aData.mCbChannel, aData.mCrChannel, mBuffer, aData.mPicSize.width, aData.mPicSize.height, size.width, size.height, aData.mYStride, aData.mCbCrStride, mStride, type, gfx::ROTATE_0, gfx::FILTER_BILINEAR); } else { NS_ERROR("Fail, ScaleYCbCrToRGB format not supported\n"); } } else { // no prescale #if defined(HAVE_YCBCR_TO_RGB565) if (format == gfxASurface::ImageFormatRGB16_565) { gfx::ConvertYCbCrToRGB565(aData.mYChannel, aData.mCbChannel, aData.mCrChannel, mBuffer, aData.mPicX, aData.mPicY, aData.mPicSize.width, aData.mPicSize.height, aData.mYStride, aData.mCbCrStride, mStride, type); } else // format != gfxASurface::ImageFormatRGB16_565 #endif gfx::ConvertYCbCrToRGB32(aData.mYChannel, aData.mCbChannel, aData.mCrChannel, mBuffer, aData.mPicX, aData.mPicY, aData.mPicSize.width, aData.mPicSize.height, aData.mYStride, aData.mCbCrStride, mStride, type); } SetOffscreenFormat(format); mSize = size; }
void BasicPlanarYCbCrImage::SetData(const Data& aData) { // Do some sanity checks to prevent integer overflow if (aData.mYSize.width > 16384 || aData.mYSize.height > 16384) { NS_ERROR("Illegal width or height"); return; } gfxASurface::gfxImageFormat format = GetOffscreenFormat(); gfx::YUVType type = gfx::YV12; if (aData.mYSize.width == aData.mCbCrSize.width && aData.mYSize.height == aData.mCbCrSize.height) { type = gfx::YV24; } else if (aData.mYSize.width / 2 == aData.mCbCrSize.width && aData.mYSize.height == aData.mCbCrSize.height) { type = gfx::YV16; } else if (aData.mYSize.width / 2 == aData.mCbCrSize.width && aData.mYSize.height / 2 == aData.mCbCrSize.height ) { type = gfx::YV12; } else { NS_ERROR("YCbCr format not supported"); } // 'prescale' is true if the scaling is to be done as part of the // YCbCr to RGB conversion rather than on the RGB data when rendered. PRBool prescale = mScaleHint.width > 0 && mScaleHint.height > 0 && mScaleHint != aData.mPicSize; if (format == gfxASurface::ImageFormatRGB16_565) { #if defined(HAVE_YCBCR_TO_RGB565) if (prescale && !gfx::IsScaleYCbCrToRGB565Fast(aData.mPicX, aData.mPicY, aData.mPicSize.width, aData.mPicSize.height, mScaleHint.width, mScaleHint.height, type, gfx::FILTER_BILINEAR) && gfx::IsConvertYCbCrToRGB565Fast(aData.mPicX, aData.mPicY, aData.mPicSize.width, aData.mPicSize.height, type)) { prescale = PR_FALSE; } #else // yuv2rgb16 function not available format = gfxASurface::ImageFormatRGB24; #endif } else if (format != gfxASurface::ImageFormatRGB24) { // No other formats are currently supported. format = gfxASurface::ImageFormatRGB24; } if (format == gfxASurface::ImageFormatRGB24) { /* ScaleYCbCrToRGB32 does not support a picture offset, nor 4:4:4 data. See bugs 639415 and 640073. */ if (aData.mPicX != 0 || aData.mPicY != 0 || type == gfx::YV24) prescale = PR_FALSE; } gfxIntSize size(prescale ? mScaleHint.width : aData.mPicSize.width, prescale ? mScaleHint.height : aData.mPicSize.height); mStride = gfxASurface::FormatStrideForWidth(format, size.width); mBuffer = new PRUint8[size.height * mStride]; if (!mBuffer) { // out of memory return; } // Convert from YCbCr to RGB now, scaling the image if needed. if (size != aData.mPicSize) { #if defined(HAVE_YCBCR_TO_RGB565) if (format == gfxASurface::ImageFormatRGB16_565) { gfx::ScaleYCbCrToRGB565(aData.mYChannel, aData.mCbChannel, aData.mCrChannel, mBuffer, aData.mPicX, aData.mPicY, aData.mPicSize.width, aData.mPicSize.height, size.width, size.height, aData.mYStride, aData.mCbCrStride, mStride, type, gfx::FILTER_BILINEAR); } else #endif gfx::ScaleYCbCrToRGB32(aData.mYChannel, aData.mCbChannel, aData.mCrChannel, mBuffer, aData.mPicSize.width, aData.mPicSize.height, size.width, size.height, aData.mYStride, aData.mCbCrStride, mStride, type, gfx::ROTATE_0, gfx::FILTER_BILINEAR); } else { // no prescale #if defined(HAVE_YCBCR_TO_RGB565) if (format == gfxASurface::ImageFormatRGB16_565) { gfx::ConvertYCbCrToRGB565(aData.mYChannel, aData.mCbChannel, aData.mCrChannel, mBuffer, aData.mPicX, aData.mPicY, aData.mPicSize.width, aData.mPicSize.height, aData.mYStride, aData.mCbCrStride, mStride, type); } else // format != gfxASurface::ImageFormatRGB16_565 #endif gfx::ConvertYCbCrToRGB32(aData.mYChannel, aData.mCbChannel, aData.mCrChannel, mBuffer, aData.mPicX, aData.mPicY, aData.mPicSize.width, aData.mPicSize.height, aData.mYStride, aData.mCbCrStride, mStride, type); } SetOffscreenFormat(format); mSize = size; }
BasicPlanarYCbCrImage(const gfxIntSize& aScaleHint, gfxImageFormat aOffscreenFormat, BufferRecycleBin *aRecycleBin) : PlanarYCbCrImage(aRecycleBin) , mScaleHint(aScaleHint) { SetOffscreenFormat(aOffscreenFormat); }