Codec2BufferUtils: add support for more color aspects
This patch adds support for RANGE_FULL and BT.709 dataspace
in RGB to PlanarYUV conversion
Test: atest android.mediav2.cts.EncodeDecodeAccuracyTest
Bug: 170747332
Change-Id: Ia3314ad250cc0bafc216b087e78f3a5256b5c4d7
diff --git a/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp b/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp
index 0966988..5f87c66 100644
--- a/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp
+++ b/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp
@@ -507,9 +507,21 @@
};
}
+// Matrix coefficient to convert RGB to Planar YUV data.
+// Each sub-array represents the 3X3 coeff used with R, G and B
+static const int16_t bt601Matrix[2][3][3] = {
+ { { 76, 150, 29 }, { -43, -85, 128 }, { 128, -107, -21 } }, /* RANGE_FULL */
+ { { 66, 129, 25 }, { -38, -74, 112 }, { 112, -94, -18 } }, /* RANGE_LIMITED */
+};
+
+static const int16_t bt709Matrix[2][3][3] = {
+ { { 54, 183, 18 }, { -29, -99, 128 }, { 128, -116, -12 } }, /* RANGE_FULL */
+ { { 47, 157, 16 }, { -26, -86, 112 }, { 112, -102, -10 } }, /* RANGE_LIMITED */
+};
+
status_t ConvertRGBToPlanarYUV(
uint8_t *dstY, size_t dstStride, size_t dstVStride, size_t bufferSize,
- const C2GraphicView &src) {
+ const C2GraphicView &src, C2Color::matrix_t colorMatrix, C2Color::range_t colorRange) {
CHECK(dstY != nullptr);
CHECK((src.width() & 1) == 0);
CHECK((src.height() & 1) == 0);
@@ -527,28 +539,38 @@
const uint8_t *pGreen = src.data()[C2PlanarLayout::PLANE_G];
const uint8_t *pBlue = src.data()[C2PlanarLayout::PLANE_B];
-#define CLIP3(x,y,z) (((z) < (x)) ? (x) : (((z) > (y)) ? (y) : (z)))
+ // set default range as limited
+ if (colorRange != C2Color::RANGE_FULL && colorRange != C2Color::RANGE_LIMITED) {
+ colorRange = C2Color::RANGE_LIMITED;
+ }
+ const int16_t (*weights)[3] =
+ (colorMatrix == C2Color::MATRIX_BT709) ?
+ bt709Matrix[colorRange - 1] : bt601Matrix[colorRange - 1];
+ uint8_t zeroLvl = colorRange == C2Color::RANGE_FULL ? 0 : 16;
+ uint8_t maxLvlLuma = colorRange == C2Color::RANGE_FULL ? 255 : 235;
+ uint8_t maxLvlChroma = colorRange == C2Color::RANGE_FULL ? 255 : 240;
+
+#define CLIP3(min,v,max) (((v) < (min)) ? (min) : (((max) > (v)) ? (v) : (max)))
for (size_t y = 0; y < src.height(); ++y) {
for (size_t x = 0; x < src.width(); ++x) {
- uint8_t red = *pRed;
- uint8_t green = *pGreen;
- uint8_t blue = *pBlue;
+ uint8_t r = *pRed;
+ uint8_t g = *pGreen;
+ uint8_t b = *pBlue;
- // using ITU-R BT.601 conversion matrix
- unsigned luma =
- CLIP3(0, (((red * 66 + green * 129 + blue * 25) >> 8) + 16), 255);
+ unsigned luma = ((r * weights[0][0] + g * weights[0][1] + b * weights[0][2]) >> 8) +
+ zeroLvl;
- dstY[x] = luma;
+ dstY[x] = CLIP3(zeroLvl, luma, maxLvlLuma);
if ((x & 1) == 0 && (y & 1) == 0) {
- unsigned U =
- CLIP3(0, (((-red * 38 - green * 74 + blue * 112) >> 8) + 128), 255);
+ unsigned U = ((r * weights[1][0] + g * weights[1][1] + b * weights[1][2]) >> 8) +
+ 128;
- unsigned V =
- CLIP3(0, (((red * 112 - green * 94 - blue * 18) >> 8) + 128), 255);
+ unsigned V = ((r * weights[2][0] + g * weights[2][1] + b * weights[2][2]) >> 8) +
+ 128;
- dstU[x >> 1] = U;
- dstV[x >> 1] = V;
+ dstU[x >> 1] = CLIP3(zeroLvl, U, maxLvlChroma);
+ dstV[x >> 1] = CLIP3(zeroLvl, V, maxLvlChroma);
}
pRed += layout.planes[C2PlanarLayout::PLANE_R].colInc;
pGreen += layout.planes[C2PlanarLayout::PLANE_G].colInc;