2013-12-13 17:31:57 +00:00
|
|
|
/* -*- 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;
|
|
|
|
|
2015-10-23 06:01:31 +00:00
|
|
|
if (aSuggestedFormat == SurfaceFormat::R5G6B5_UINT16) {
|
2013-12-13 17:31:57 +00:00
|
|
|
#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
|
2014-01-10 19:06:16 +00:00
|
|
|
aSuggestedFormat = SurfaceFormat::B8G8R8X8;
|
2013-12-13 17:31:57 +00:00
|
|
|
#endif
|
|
|
|
}
|
2014-01-10 19:06:16 +00:00
|
|
|
else if (aSuggestedFormat != SurfaceFormat::B8G8R8X8) {
|
2013-12-13 17:31:57 +00:00
|
|
|
// No other formats are currently supported.
|
2014-01-10 19:06:16 +00:00
|
|
|
aSuggestedFormat = SurfaceFormat::B8G8R8X8;
|
2013-12-13 17:31:57 +00:00
|
|
|
}
|
2014-01-10 19:06:16 +00:00
|
|
|
if (aSuggestedFormat == SurfaceFormat::B8G8R8X8) {
|
2013-12-13 17:31:57 +00:00
|
|
|
/* 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.
|
2013-12-20 16:46:29 +00:00
|
|
|
if (aDestSize != aData.mPicSize) {
|
2013-12-13 17:31:57 +00:00
|
|
|
#if defined(HAVE_YCBCR_TO_RGB565)
|
2015-10-23 06:01:31 +00:00
|
|
|
if (aDestFormat == SurfaceFormat::R5G6B5_UINT16) {
|
2013-12-13 17:31:57 +00:00
|
|
|
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,
|
|
|
|
ROTATE_0,
|
|
|
|
FILTER_BILINEAR);
|
|
|
|
} else { // no prescale
|
|
|
|
#if defined(HAVE_YCBCR_TO_RGB565)
|
2015-10-23 06:01:31 +00:00
|
|
|
if (aDestFormat == SurfaceFormat::R5G6B5_UINT16) {
|
2013-12-13 17:31:57 +00:00
|
|
|
ConvertYCbCrToRGB565(aData.mYChannel,
|
|
|
|
aData.mCbChannel,
|
|
|
|
aData.mCrChannel,
|
|
|
|
aDestBuffer,
|
|
|
|
aData.mPicX,
|
|
|
|
aData.mPicY,
|
|
|
|
aData.mPicSize.width,
|
|
|
|
aData.mPicSize.height,
|
|
|
|
aData.mYStride,
|
|
|
|
aData.mCbCrStride,
|
|
|
|
aStride,
|
|
|
|
yuvtype);
|
2014-01-23 18:26:40 +00:00
|
|
|
} else // aDestFormat != gfxImageFormat::RGB16_565
|
2013-12-13 17:31:57 +00:00
|
|
|
#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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-13 15:25:42 +00:00
|
|
|
} // namespace gfx
|
|
|
|
} // namespace mozilla
|