summaryrefslogtreecommitdiffstats
path: root/gfx/ycbcr/YCbCrUtils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/ycbcr/YCbCrUtils.cpp')
-rw-r--r--gfx/ycbcr/YCbCrUtils.cpp157
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