Merge "Support 10-bit YUV in color converter for thumbnails" into pi-dev
am: 3994704062
Change-Id: I002b09c63e90e1ed4b7580acbb0a1a5eb3fe9591
diff --git a/media/libstagefright/colorconversion/ColorConverter.cpp b/media/libstagefright/colorconversion/ColorConverter.cpp
index 1b38852..05f4104 100644
--- a/media/libstagefright/colorconversion/ColorConverter.cpp
+++ b/media/libstagefright/colorconversion/ColorConverter.cpp
@@ -25,7 +25,7 @@
#include "libyuv/convert_from.h"
#include "libyuv/video_common.h"
-
+#include <functional>
#include <sys/time.h>
#define USE_LIBYUV
@@ -58,14 +58,16 @@
bool ColorConverter::isValid() const {
switch (mSrcFormat) {
+ case OMX_COLOR_FormatYUV420Planar16:
+ if (mDstFormat == OMX_COLOR_FormatYUV444Y410) {
+ return true;
+ }
+ // fall-thru
case OMX_COLOR_FormatYUV420Planar:
return mDstFormat == OMX_COLOR_Format16bitRGB565
|| mDstFormat == OMX_COLOR_Format32BitRGBA8888
|| mDstFormat == OMX_COLOR_Format32bitBGRA8888;
- case OMX_COLOR_FormatYUV420Planar16:
- return mDstFormat == OMX_COLOR_FormatYUV444Y410;
-
case OMX_COLOR_FormatCbYCrY:
case OMX_QCOM_COLOR_FormatYVU420SemiPlanar:
case OMX_COLOR_FormatYUV420SemiPlanar:
@@ -311,84 +313,120 @@
return OK;
}
-void ColorConverter::writeToDst(
- void *dst_ptr, uint8_t *kAdjustedClip, bool uncropped,
- signed r1, signed g1, signed b1,
- signed r2, signed g2, signed b2) {
- switch (mDstFormat) {
+std::function<void (void *, void *, void *, size_t,
+ signed *, signed *, signed *, signed *)>
+getReadFromSrc(OMX_COLOR_FORMATTYPE srcFormat) {
+ switch(srcFormat) {
+ case OMX_COLOR_FormatYUV420Planar:
+ return [](void *src_y, void *src_u, void *src_v, size_t x,
+ signed *y1, signed *y2, signed *u, signed *v) {
+ *y1 = ((uint8_t*)src_y)[x] - 16;
+ *y2 = ((uint8_t*)src_y)[x + 1] - 16;
+ *u = ((uint8_t*)src_u)[x / 2] - 128;
+ *v = ((uint8_t*)src_v)[x / 2] - 128;
+ };
+ case OMX_COLOR_FormatYUV420Planar16:
+ return [](void *src_y, void *src_u, void *src_v, size_t x,
+ signed *y1, signed *y2, signed *u, signed *v) {
+ *y1 = (signed)(((uint16_t*)src_y)[x] >> 2) - 16;
+ *y2 = (signed)(((uint16_t*)src_y)[x + 1] >> 2) - 16;
+ *u = (signed)(((uint16_t*)src_u)[x / 2] >> 2) - 128;
+ *v = (signed)(((uint16_t*)src_v)[x / 2] >> 2) - 128;
+ };
+ default:
+ TRESPASS();
+ }
+ return nullptr;
+}
+
+std::function<void (void *, bool, signed, signed, signed, signed, signed, signed)>
+getWriteToDst(OMX_COLOR_FORMATTYPE dstFormat, uint8_t *kAdjustedClip) {
+ switch (dstFormat) {
case OMX_COLOR_Format16bitRGB565:
{
- uint32_t rgb1 =
- ((kAdjustedClip[r1] >> 3) << 11)
- | ((kAdjustedClip[g1] >> 2) << 5)
- | (kAdjustedClip[b1] >> 3);
+ return [kAdjustedClip](void *dst_ptr, bool uncropped,
+ signed r1, signed g1, signed b1,
+ signed r2, signed g2, signed b2) {
+ uint32_t rgb1 =
+ ((kAdjustedClip[r1] >> 3) << 11)
+ | ((kAdjustedClip[g1] >> 2) << 5)
+ | (kAdjustedClip[b1] >> 3);
- if (uncropped) {
- uint32_t rgb2 =
- ((kAdjustedClip[r2] >> 3) << 11)
- | ((kAdjustedClip[g2] >> 2) << 5)
- | (kAdjustedClip[b2] >> 3);
+ if (uncropped) {
+ uint32_t rgb2 =
+ ((kAdjustedClip[r2] >> 3) << 11)
+ | ((kAdjustedClip[g2] >> 2) << 5)
+ | (kAdjustedClip[b2] >> 3);
- *(uint32_t *)dst_ptr = (rgb2 << 16) | rgb1;
- } else {
- *(uint16_t *)dst_ptr = rgb1;
- }
- break;
+ *(uint32_t *)dst_ptr = (rgb2 << 16) | rgb1;
+ } else {
+ *(uint16_t *)dst_ptr = rgb1;
+ }
+ };
}
case OMX_COLOR_Format32BitRGBA8888:
{
- ((uint32_t *)dst_ptr)[0] =
- (kAdjustedClip[r1])
- | (kAdjustedClip[g1] << 8)
- | (kAdjustedClip[b1] << 16)
- | (0xFF << 24);
-
- if (uncropped) {
- ((uint32_t *)dst_ptr)[1] =
- (kAdjustedClip[r2])
- | (kAdjustedClip[g2] << 8)
- | (kAdjustedClip[b2] << 16)
+ return [kAdjustedClip](void *dst_ptr, bool uncropped,
+ signed r1, signed g1, signed b1,
+ signed r2, signed g2, signed b2) {
+ ((uint32_t *)dst_ptr)[0] =
+ (kAdjustedClip[r1])
+ | (kAdjustedClip[g1] << 8)
+ | (kAdjustedClip[b1] << 16)
| (0xFF << 24);
- }
- break;
+
+ if (uncropped) {
+ ((uint32_t *)dst_ptr)[1] =
+ (kAdjustedClip[r2])
+ | (kAdjustedClip[g2] << 8)
+ | (kAdjustedClip[b2] << 16)
+ | (0xFF << 24);
+ }
+ };
}
case OMX_COLOR_Format32bitBGRA8888:
{
- ((uint32_t *)dst_ptr)[0] =
- (kAdjustedClip[b1])
- | (kAdjustedClip[g1] << 8)
- | (kAdjustedClip[r1] << 16)
- | (0xFF << 24);
-
- if (uncropped) {
- ((uint32_t *)dst_ptr)[1] =
- (kAdjustedClip[b2])
- | (kAdjustedClip[g2] << 8)
- | (kAdjustedClip[r2] << 16)
+ return [kAdjustedClip](void *dst_ptr, bool uncropped,
+ signed r1, signed g1, signed b1,
+ signed r2, signed g2, signed b2) {
+ ((uint32_t *)dst_ptr)[0] =
+ (kAdjustedClip[b1])
+ | (kAdjustedClip[g1] << 8)
+ | (kAdjustedClip[r1] << 16)
| (0xFF << 24);
- }
- break;
+
+ if (uncropped) {
+ ((uint32_t *)dst_ptr)[1] =
+ (kAdjustedClip[b2])
+ | (kAdjustedClip[g2] << 8)
+ | (kAdjustedClip[r2] << 16)
+ | (0xFF << 24);
+ }
+ };
}
default:
- break;
+ TRESPASS();
}
+ return nullptr;
}
+
status_t ColorConverter::convertYUV420Planar(
const BitmapParams &src, const BitmapParams &dst) {
uint8_t *kAdjustedClip = initClip();
+ auto readFromSrc = getReadFromSrc(mSrcFormat);
+ auto writeToDst = getWriteToDst(mDstFormat, kAdjustedClip);
+
uint8_t *dst_ptr = (uint8_t *)dst.mBits
- + dst.mCropTop * dst.mStride + dst.mCropLeft * dst.mBpp;
+ + dst.mCropTop * dst.mStride + dst.mCropLeft * dst.mBpp;
- const uint8_t *src_y =
- (const uint8_t *)src.mBits + src.mCropTop * src.mStride + src.mCropLeft;
+ uint8_t *src_y = (uint8_t *)src.mBits
+ + src.mCropTop * src.mStride + src.mCropLeft * src.mBpp;
- const uint8_t *src_u =
- (const uint8_t *)src.mBits + src.mStride * src.mHeight
- + (src.mCropTop / 2) * (src.mStride / 2) + src.mCropLeft / 2;
+ uint8_t *src_u = (uint8_t *)src.mBits + src.mStride * src.mHeight
+ + (src.mCropTop / 2) * (src.mStride / 2) + src.mCropLeft / 2 * src.mBpp;
- const uint8_t *src_v =
- src_u + (src.mStride / 2) * (src.mHeight / 2);
+ uint8_t *src_v = src_u + (src.mStride / 2) * (src.mHeight / 2);
for (size_t y = 0; y < src.cropHeight(); ++y) {
for (size_t x = 0; x < src.cropWidth(); x += 2) {
@@ -410,11 +448,8 @@
// clip range -278 .. 535
- signed y1 = (signed)src_y[x] - 16;
- signed y2 = (signed)src_y[x + 1] - 16;
-
- signed u = (signed)src_u[x / 2] - 128;
- signed v = (signed)src_v[x / 2] - 128;
+ signed y1, y2, u, v;
+ readFromSrc(src_y, src_u, src_v, x, &y1, &y2, &u, &v);
signed u_b = u * 517;
signed u_g = -u * 100;
@@ -432,8 +467,7 @@
signed r2 = (tmp2 + v_r) / 256;
bool uncropped = x + 1 < src.cropWidth();
- (void)writeToDst(dst_ptr + x * dst.mBpp,
- kAdjustedClip, uncropped, r1, g1, b1, r2, g2, b2);
+ writeToDst(dst_ptr + x * dst.mBpp, uncropped, r1, g1, b1, r2, g2, b2);
}
src_y += src.mStride;
@@ -449,6 +483,15 @@
return OK;
}
+status_t ColorConverter::convertYUV420Planar16(
+ const BitmapParams &src, const BitmapParams &dst) {
+ if (mDstFormat == OMX_COLOR_FormatYUV444Y410) {
+ return convertYUV420Planar16ToY410(src, dst);
+ }
+
+ return convertYUV420Planar(src, dst);
+}
+
/*
* Pack 10-bit YUV into RGBA_1010102.
*
@@ -480,7 +523,7 @@
#if !USE_NEON_Y410
-status_t ColorConverter::convertYUV420Planar16(
+status_t ColorConverter::convertYUV420Planar16ToY410(
const BitmapParams &src, const BitmapParams &dst) {
uint8_t *dst_ptr = (uint8_t *)dst.mBits
+ dst.mCropTop * dst.mStride + dst.mCropLeft * dst.mBpp;
@@ -554,7 +597,7 @@
#else
-status_t ColorConverter::convertYUV420Planar16(
+status_t ColorConverter::convertYUV420Planar16ToY410(
const BitmapParams &src, const BitmapParams &dst) {
uint8_t *out = (uint8_t *)dst.mBits
+ dst.mCropTop * dst.mStride + dst.mCropLeft * dst.mBpp;
diff --git a/media/libstagefright/colorconversion/SoftwareRenderer.cpp b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
index 838bc5f..657a05b 100644
--- a/media/libstagefright/colorconversion/SoftwareRenderer.cpp
+++ b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
@@ -79,13 +79,26 @@
cropBottomNew = heightNew - 1;
}
+ // The native window buffer format for high-bitdepth content could
+ // depend on the dataspace also.
+ android_dataspace dataSpace;
+ bool dataSpaceChangedForPlanar16 = false;
+ if (colorFormatNew == OMX_COLOR_FormatYUV420Planar16
+ && format->findInt32("android._dataspace", (int32_t *)&dataSpace)
+ && dataSpace != mDataSpace) {
+ // Do not modify mDataSpace here, it's only modified at last
+ // when we do native_window_set_buffers_data_space().
+ dataSpaceChangedForPlanar16 = true;
+ }
+
if (static_cast<int32_t>(mColorFormat) == colorFormatNew &&
mWidth == widthNew &&
mHeight == heightNew &&
mCropLeft == cropLeftNew &&
mCropTop == cropTopNew &&
mCropRight == cropRightNew &&
- mCropBottom == cropBottomNew) {
+ mCropBottom == cropBottomNew &&
+ !dataSpaceChangedForPlanar16) {
// Nothing changed, no need to reset renderer.
return;
}
@@ -135,11 +148,16 @@
}
case OMX_COLOR_FormatYUV420Planar16:
{
- // Here we would convert OMX_COLOR_FormatYUV420Planar16 into
- // OMX_COLOR_FormatYUV444Y410, and put it inside a buffer with
- // format HAL_PIXEL_FORMAT_RGBA_1010102. Surfaceflinger will
- // use render engine to convert it to RGB if needed.
- halFormat = HAL_PIXEL_FORMAT_RGBA_1010102;
+ if (((dataSpace & HAL_DATASPACE_STANDARD_MASK) == HAL_DATASPACE_STANDARD_BT2020)
+ && ((dataSpace & HAL_DATASPACE_TRANSFER_MASK) == HAL_DATASPACE_TRANSFER_ST2084)) {
+ // Here we would convert OMX_COLOR_FormatYUV420Planar16 into
+ // OMX_COLOR_FormatYUV444Y410, and put it inside a buffer with
+ // format HAL_PIXEL_FORMAT_RGBA_1010102. Surfaceflinger will
+ // use render engine to convert it to RGB if needed.
+ halFormat = HAL_PIXEL_FORMAT_RGBA_1010102;
+ } else {
+ halFormat = HAL_PIXEL_FORMAT_YV12;
+ }
bufWidth = (mCropWidth + 1) & ~1;
bufHeight = (mCropHeight + 1) & ~1;
break;
@@ -155,7 +173,7 @@
mConverter = new ColorConverter(
mColorFormat, OMX_COLOR_Format16bitRGB565);
CHECK(mConverter->isValid());
- } else if (mColorFormat == OMX_COLOR_FormatYUV420Planar16) {
+ } else if (halFormat == HAL_PIXEL_FORMAT_RGBA_1010102) {
mConverter = new ColorConverter(
mColorFormat, OMX_COLOR_FormatYUV444Y410);
CHECK(mConverter->isValid());
@@ -300,6 +318,46 @@
dst_u += dst_c_stride;
dst_v += dst_c_stride;
}
+ } else if (mColorFormat == OMX_COLOR_FormatYUV420Planar16) {
+ const uint16_t *src_y = (const uint16_t *)data;
+ const uint16_t *src_u = (const uint16_t *)data + mWidth * mHeight;
+ const uint16_t *src_v = src_u + (mWidth / 2 * mHeight / 2);
+
+ src_y += mCropLeft + mCropTop * mWidth;
+ src_u += (mCropLeft + mCropTop * mWidth / 2) / 2;
+ src_v += (mCropLeft + mCropTop * mWidth / 2) / 2;
+
+ uint8_t *dst_y = (uint8_t *)dst;
+ size_t dst_y_size = buf->stride * buf->height;
+ size_t dst_c_stride = ALIGN(buf->stride / 2, 16);
+ size_t dst_c_size = dst_c_stride * buf->height / 2;
+ uint8_t *dst_v = dst_y + dst_y_size;
+ uint8_t *dst_u = dst_v + dst_c_size;
+
+ dst_y += mCropTop * buf->stride + mCropLeft;
+ dst_v += (mCropTop / 2) * dst_c_stride + mCropLeft / 2;
+ dst_u += (mCropTop / 2) * dst_c_stride + mCropLeft / 2;
+
+ for (int y = 0; y < mCropHeight; ++y) {
+ for (int x = 0; x < mCropWidth; ++x) {
+ dst_y[x] = (uint8_t)(src_y[x] >> 2);
+ }
+
+ src_y += mWidth;
+ dst_y += buf->stride;
+ }
+
+ for (int y = 0; y < (mCropHeight + 1) / 2; ++y) {
+ for (int x = 0; x < (mCropWidth + 1) / 2; ++x) {
+ dst_u[x] = (uint8_t)(src_u[x] >> 2);
+ dst_v[x] = (uint8_t)(src_v[x] >> 2);
+ }
+
+ src_u += mWidth / 2;
+ src_v += mWidth / 2;
+ dst_u += dst_c_stride;
+ dst_v += dst_c_stride;
+ }
} else if (mColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar
|| mColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
const uint8_t *src_y = (const uint8_t *)data;
diff --git a/media/libstagefright/include/media/stagefright/ColorConverter.h b/media/libstagefright/include/media/stagefright/ColorConverter.h
index a6c8981..5b3543d 100644
--- a/media/libstagefright/include/media/stagefright/ColorConverter.h
+++ b/media/libstagefright/include/media/stagefright/ColorConverter.h
@@ -75,10 +75,16 @@
status_t convertYUV420Planar(
const BitmapParams &src, const BitmapParams &dst);
+ status_t convertYUV420PlanarUseLibYUV(
+ const BitmapParams &src, const BitmapParams &dst);
+
status_t convertYUV420Planar16(
const BitmapParams &src, const BitmapParams &dst);
- status_t convertYUV420PlanarUseLibYUV(
+ status_t convertYUV420Planar16ToY410(
+ const BitmapParams &src, const BitmapParams &dst);
+
+ status_t convertYUV420Planar16ToRGB(
const BitmapParams &src, const BitmapParams &dst);
status_t convertQCOMYUV420SemiPlanar(
@@ -90,10 +96,6 @@
status_t convertTIYUV420PackedSemiPlanar(
const BitmapParams &src, const BitmapParams &dst);
- void writeToDst(void *dst_ptr, uint8_t *kAdjustedClip, bool uncropped,
- signed r1, signed g1, signed b1,
- signed r2, signed g2, signed b2);
-
ColorConverter(const ColorConverter &);
ColorConverter &operator=(const ColorConverter &);
};