diff options
Diffstat (limited to 'gfx/ycbcr/YCbCrUtils.cpp')
-rw-r--r-- | gfx/ycbcr/YCbCrUtils.cpp | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/gfx/ycbcr/YCbCrUtils.cpp b/gfx/ycbcr/YCbCrUtils.cpp new file mode 100644 index 000000000..882197857 --- /dev/null +++ b/gfx/ycbcr/YCbCrUtils.cpp @@ -0,0 +1,157 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "gfx2DGlue.h" + +#include "YCbCrUtils.h" +#include "yuv_convert.h" +#include "ycbcr_to_rgb565.h" + +namespace mozilla { +namespace gfx { + +void +GetYCbCrToRGBDestFormatAndSize(const layers::PlanarYCbCrData& aData, + SurfaceFormat& aSuggestedFormat, + IntSize& aSuggestedSize) +{ + YUVType yuvtype = + TypeFromSize(aData.mYSize.width, + aData.mYSize.height, + aData.mCbCrSize.width, + aData.mCbCrSize.height); + + // '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. + bool prescale = aSuggestedSize.width > 0 && aSuggestedSize.height > 0 && + aSuggestedSize != aData.mPicSize; + + if (aSuggestedFormat == SurfaceFormat::R5G6B5_UINT16) { +#if defined(HAVE_YCBCR_TO_RGB565) + if (prescale && + !IsScaleYCbCrToRGB565Fast(aData.mPicX, + aData.mPicY, + aData.mPicSize.width, + aData.mPicSize.height, + aSuggestedSize.width, + aSuggestedSize.height, + yuvtype, + FILTER_BILINEAR) && + IsConvertYCbCrToRGB565Fast(aData.mPicX, + aData.mPicY, + aData.mPicSize.width, + aData.mPicSize.height, + yuvtype)) { + prescale = false; + } +#else + // yuv2rgb16 function not available + aSuggestedFormat = SurfaceFormat::B8G8R8X8; +#endif + } + else if (aSuggestedFormat != SurfaceFormat::B8G8R8X8) { + // No other formats are currently supported. + aSuggestedFormat = SurfaceFormat::B8G8R8X8; + } + if (aSuggestedFormat == SurfaceFormat::B8G8R8X8) { + /* ScaleYCbCrToRGB32 does not support a picture offset, nor 4:4:4 data. + See bugs 639415 and 640073. */ + if (aData.mPicX != 0 || aData.mPicY != 0 || yuvtype == YV24) + prescale = false; + } + if (!prescale) { + aSuggestedSize = aData.mPicSize; + } +} + +void +ConvertYCbCrToRGB(const layers::PlanarYCbCrData& aData, + const SurfaceFormat& aDestFormat, + const IntSize& aDestSize, + unsigned char* aDestBuffer, + int32_t aStride) +{ + // ConvertYCbCrToRGB et al. assume the chroma planes are rounded up if the + // luma plane is odd sized. + MOZ_ASSERT((aData.mCbCrSize.width == aData.mYSize.width || + aData.mCbCrSize.width == (aData.mYSize.width + 1) >> 1) && + (aData.mCbCrSize.height == aData.mYSize.height || + aData.mCbCrSize.height == (aData.mYSize.height + 1) >> 1)); + YUVType yuvtype = + TypeFromSize(aData.mYSize.width, + aData.mYSize.height, + aData.mCbCrSize.width, + aData.mCbCrSize.height); + + // Convert from YCbCr to RGB now, scaling the image if needed. + if (aDestSize != aData.mPicSize) { +#if defined(HAVE_YCBCR_TO_RGB565) + if (aDestFormat == SurfaceFormat::R5G6B5_UINT16) { + ScaleYCbCrToRGB565(aData.mYChannel, + aData.mCbChannel, + aData.mCrChannel, + aDestBuffer, + aData.mPicX, + aData.mPicY, + aData.mPicSize.width, + aData.mPicSize.height, + aDestSize.width, + aDestSize.height, + aData.mYStride, + aData.mCbCrStride, + aStride, + yuvtype, + FILTER_BILINEAR); + } else +#endif + ScaleYCbCrToRGB32(aData.mYChannel, // + aData.mCbChannel, + aData.mCrChannel, + aDestBuffer, + aData.mPicSize.width, + aData.mPicSize.height, + aDestSize.width, + aDestSize.height, + aData.mYStride, + aData.mCbCrStride, + aStride, + yuvtype, + aData.mYUVColorSpace, + FILTER_BILINEAR); + } else { // no prescale +#if defined(HAVE_YCBCR_TO_RGB565) + if (aDestFormat == SurfaceFormat::R5G6B5_UINT16) { + ConvertYCbCrToRGB565(aData.mYChannel, + aData.mCbChannel, + aData.mCrChannel, + aDestBuffer, + aData.mPicX, + aData.mPicY, + aData.mPicSize.width, + aData.mPicSize.height, + aData.mYStride, + aData.mCbCrStride, + aStride, + yuvtype); + } else // aDestFormat != SurfaceFormat::R5G6B5_UINT16 +#endif + ConvertYCbCrToRGB32(aData.mYChannel, // + aData.mCbChannel, + aData.mCrChannel, + aDestBuffer, + aData.mPicX, + aData.mPicY, + aData.mPicSize.width, + aData.mPicSize.height, + aData.mYStride, + aData.mCbCrStride, + aStride, + yuvtype, + aData.mYUVColorSpace); + } +} + +} // namespace gfx +} // namespace mozilla |