Line data Source code
1 : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #include "gfx2DGlue.h"
7 :
8 : #include "YCbCrUtils.h"
9 : #include "yuv_convert.h"
10 : #include "ycbcr_to_rgb565.h"
11 :
12 : namespace mozilla {
13 : namespace gfx {
14 :
15 : void
16 0 : GetYCbCrToRGBDestFormatAndSize(const layers::PlanarYCbCrData& aData,
17 : SurfaceFormat& aSuggestedFormat,
18 : IntSize& aSuggestedSize)
19 : {
20 : YUVType yuvtype =
21 0 : TypeFromSize(aData.mYSize.width,
22 0 : aData.mYSize.height,
23 0 : aData.mCbCrSize.width,
24 0 : aData.mCbCrSize.height);
25 :
26 : // 'prescale' is true if the scaling is to be done as part of the
27 : // YCbCr to RGB conversion rather than on the RGB data when rendered.
28 0 : bool prescale = aSuggestedSize.width > 0 && aSuggestedSize.height > 0 &&
29 0 : aSuggestedSize != aData.mPicSize;
30 :
31 0 : if (aSuggestedFormat == SurfaceFormat::R5G6B5_UINT16) {
32 : #if defined(HAVE_YCBCR_TO_RGB565)
33 : if (prescale &&
34 : !IsScaleYCbCrToRGB565Fast(aData.mPicX,
35 : aData.mPicY,
36 : aData.mPicSize.width,
37 : aData.mPicSize.height,
38 : aSuggestedSize.width,
39 : aSuggestedSize.height,
40 : yuvtype,
41 : FILTER_BILINEAR) &&
42 : IsConvertYCbCrToRGB565Fast(aData.mPicX,
43 : aData.mPicY,
44 : aData.mPicSize.width,
45 : aData.mPicSize.height,
46 : yuvtype)) {
47 : prescale = false;
48 : }
49 : #else
50 : // yuv2rgb16 function not available
51 0 : aSuggestedFormat = SurfaceFormat::B8G8R8X8;
52 : #endif
53 : }
54 0 : else if (aSuggestedFormat != SurfaceFormat::B8G8R8X8) {
55 : // No other formats are currently supported.
56 0 : aSuggestedFormat = SurfaceFormat::B8G8R8X8;
57 : }
58 0 : if (aSuggestedFormat == SurfaceFormat::B8G8R8X8) {
59 : /* ScaleYCbCrToRGB32 does not support a picture offset, nor 4:4:4 data.
60 : See bugs 639415 and 640073. */
61 0 : if (aData.mPicX != 0 || aData.mPicY != 0 || yuvtype == YV24)
62 0 : prescale = false;
63 : }
64 0 : if (!prescale) {
65 0 : aSuggestedSize = aData.mPicSize;
66 : }
67 0 : }
68 :
69 : void
70 0 : ConvertYCbCrToRGB(const layers::PlanarYCbCrData& aData,
71 : const SurfaceFormat& aDestFormat,
72 : const IntSize& aDestSize,
73 : unsigned char* aDestBuffer,
74 : int32_t aStride)
75 : {
76 : // ConvertYCbCrToRGB et al. assume the chroma planes are rounded up if the
77 : // luma plane is odd sized.
78 0 : MOZ_ASSERT((aData.mCbCrSize.width == aData.mYSize.width ||
79 : aData.mCbCrSize.width == (aData.mYSize.width + 1) >> 1) &&
80 : (aData.mCbCrSize.height == aData.mYSize.height ||
81 : aData.mCbCrSize.height == (aData.mYSize.height + 1) >> 1));
82 : YUVType yuvtype =
83 0 : TypeFromSize(aData.mYSize.width,
84 0 : aData.mYSize.height,
85 0 : aData.mCbCrSize.width,
86 0 : aData.mCbCrSize.height);
87 :
88 : // Convert from YCbCr to RGB now, scaling the image if needed.
89 0 : if (aDestSize != aData.mPicSize) {
90 : #if defined(HAVE_YCBCR_TO_RGB565)
91 : if (aDestFormat == SurfaceFormat::R5G6B5_UINT16) {
92 : ScaleYCbCrToRGB565(aData.mYChannel,
93 : aData.mCbChannel,
94 : aData.mCrChannel,
95 : aDestBuffer,
96 : aData.mPicX,
97 : aData.mPicY,
98 : aData.mPicSize.width,
99 : aData.mPicSize.height,
100 : aDestSize.width,
101 : aDestSize.height,
102 : aData.mYStride,
103 : aData.mCbCrStride,
104 : aStride,
105 : yuvtype,
106 : FILTER_BILINEAR);
107 : } else
108 : #endif
109 0 : ScaleYCbCrToRGB32(aData.mYChannel, //
110 0 : aData.mCbChannel,
111 0 : aData.mCrChannel,
112 : aDestBuffer,
113 0 : aData.mPicSize.width,
114 0 : aData.mPicSize.height,
115 0 : aDestSize.width,
116 0 : aDestSize.height,
117 0 : aData.mYStride,
118 0 : aData.mCbCrStride,
119 : aStride,
120 : yuvtype,
121 0 : aData.mYUVColorSpace,
122 0 : FILTER_BILINEAR);
123 : } else { // no prescale
124 : #if defined(HAVE_YCBCR_TO_RGB565)
125 : if (aDestFormat == SurfaceFormat::R5G6B5_UINT16) {
126 : ConvertYCbCrToRGB565(aData.mYChannel,
127 : aData.mCbChannel,
128 : aData.mCrChannel,
129 : aDestBuffer,
130 : aData.mPicX,
131 : aData.mPicY,
132 : aData.mPicSize.width,
133 : aData.mPicSize.height,
134 : aData.mYStride,
135 : aData.mCbCrStride,
136 : aStride,
137 : yuvtype);
138 : } else // aDestFormat != SurfaceFormat::R5G6B5_UINT16
139 : #endif
140 0 : ConvertYCbCrToRGB32(aData.mYChannel, //
141 0 : aData.mCbChannel,
142 0 : aData.mCrChannel,
143 : aDestBuffer,
144 0 : aData.mPicX,
145 0 : aData.mPicY,
146 0 : aData.mPicSize.width,
147 0 : aData.mPicSize.height,
148 0 : aData.mYStride,
149 0 : aData.mCbCrStride,
150 : aStride,
151 : yuvtype,
152 0 : aData.mYUVColorSpace);
153 : }
154 0 : }
155 :
156 : void
157 0 : ConvertYCbCrAToARGB(const uint8_t* aSrcY,
158 : const uint8_t* aSrcU,
159 : const uint8_t* aSrcV,
160 : const uint8_t* aSrcA,
161 : int aSrcStrideYA, int aSrcStrideUV,
162 : uint8_t* aDstARGB, int aDstStrideARGB,
163 : int aWidth, int aHeight) {
164 :
165 : ConvertYCbCrAToARGB32(aSrcY,
166 : aSrcU,
167 : aSrcV,
168 : aSrcA,
169 : aDstARGB,
170 : aWidth,
171 : aHeight,
172 : aSrcStrideYA,
173 : aSrcStrideUV,
174 0 : aDstStrideARGB);
175 0 : }
176 :
177 : } // namespace gfx
178 : } // namespace mozilla
|