CCodec: revamp color format support
- Allow color format pass-through
- Query vendor flexible color format
Bug: 163020028
Test: atest CtsMediaTestCases -- --module-arg CtsMediaTestCases:size:small
Test: atest ccodec_unit_test:RawGraphicOutputBuffersTest
Change-Id: I5a0827eb54f0c6834a247bfaa653489e4633b6c7
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index ab7c9af..b6262b7 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -883,19 +883,84 @@
/*
* Handle desired color format.
*/
+ int32_t defaultColorFormat = COLOR_FormatYUV420Flexible;
if ((config->mDomain & (Config::IS_VIDEO | Config::IS_IMAGE))) {
- int32_t format = -1;
+ int32_t format = 0;
+ // Query vendor format for Flexible YUV
+ std::vector<std::unique_ptr<C2Param>> heapParams;
+ C2StoreFlexiblePixelFormatDescriptorsInfo *pixelFormatInfo = nullptr;
+ if (mClient->query(
+ {},
+ {C2StoreFlexiblePixelFormatDescriptorsInfo::PARAM_TYPE},
+ C2_MAY_BLOCK,
+ &heapParams) == C2_OK
+ && heapParams.size() == 1u) {
+ pixelFormatInfo = C2StoreFlexiblePixelFormatDescriptorsInfo::From(
+ heapParams[0].get());
+ } else {
+ pixelFormatInfo = nullptr;
+ }
+ std::optional<uint32_t> flexPixelFormat{};
+ std::optional<uint32_t> flexPlanarPixelFormat{};
+ std::optional<uint32_t> flexSemiPlanarPixelFormat{};
+ if (pixelFormatInfo && *pixelFormatInfo) {
+ for (size_t i = 0; i < pixelFormatInfo->flexCount(); ++i) {
+ const C2FlexiblePixelFormatDescriptorStruct &desc =
+ pixelFormatInfo->m.values[i];
+ if (desc.bitDepth != 8
+ || desc.subsampling != C2Color::YUV_420
+ // TODO(b/180076105): some device report wrong layout
+ // || desc.layout == C2Color::INTERLEAVED_PACKED
+ // || desc.layout == C2Color::INTERLEAVED_ALIGNED
+ || desc.layout == C2Color::UNKNOWN_LAYOUT) {
+ continue;
+ }
+ if (!flexPixelFormat) {
+ flexPixelFormat = desc.pixelFormat;
+ }
+ if (desc.layout == C2Color::PLANAR_PACKED && !flexPlanarPixelFormat) {
+ flexPlanarPixelFormat = desc.pixelFormat;
+ }
+ if (desc.layout == C2Color::SEMIPLANAR_PACKED && !flexSemiPlanarPixelFormat) {
+ flexSemiPlanarPixelFormat = desc.pixelFormat;
+ }
+ }
+ }
if (!msg->findInt32(KEY_COLOR_FORMAT, &format)) {
- /*
- * Also handle default color format (encoders require color format, so this is only
- * needed for decoders.
- */
+ // Also handle default color format (encoders require color format, so this is only
+ // needed for decoders.
if (!(config->mDomain & Config::IS_ENCODER)) {
- format = (surface == nullptr) ? COLOR_FormatYUV420Planar : COLOR_FormatSurface;
+ if (surface == nullptr) {
+ format = flexPixelFormat.value_or(COLOR_FormatYUV420Flexible);
+ } else {
+ format = COLOR_FormatSurface;
+ }
+ defaultColorFormat = format;
+ }
+ } else {
+ if ((config->mDomain & Config::IS_ENCODER) || !surface) {
+ switch (format) {
+ case COLOR_FormatYUV420Flexible:
+ format = flexPixelFormat.value_or(COLOR_FormatYUV420Planar);
+ break;
+ case COLOR_FormatYUV420Planar:
+ case COLOR_FormatYUV420PackedPlanar:
+ format = flexPlanarPixelFormat.value_or(
+ flexPixelFormat.value_or(format));
+ break;
+ case COLOR_FormatYUV420SemiPlanar:
+ case COLOR_FormatYUV420PackedSemiPlanar:
+ format = flexSemiPlanarPixelFormat.value_or(
+ flexPixelFormat.value_or(format));
+ break;
+ default:
+ // No-op
+ break;
+ }
}
}
- if (format >= 0) {
+ if (format != 0) {
msg->setInt32("android._color-format", format);
}
}
@@ -1047,12 +1112,16 @@
// Set desired color format from configuration parameter
int32_t format;
- if (msg->findInt32("android._color-format", &format)) {
- if (config->mDomain & Config::IS_ENCODER) {
- config->mInputFormat->setInt32(KEY_COLOR_FORMAT, format);
- } else {
- config->mOutputFormat->setInt32(KEY_COLOR_FORMAT, format);
+ if (!msg->findInt32(KEY_COLOR_FORMAT, &format)) {
+ format = defaultColorFormat;
+ }
+ if (config->mDomain & Config::IS_ENCODER) {
+ config->mInputFormat->setInt32(KEY_COLOR_FORMAT, format);
+ if (msg->findInt32("android._color-format", &format)) {
+ config->mInputFormat->setInt32("android._color-format", format);
}
+ } else {
+ config->mOutputFormat->setInt32(KEY_COLOR_FORMAT, format);
}
}
@@ -2010,7 +2079,7 @@
}
if (param->type() == C2PortAllocatorsTuning::input::PARAM_TYPE) {
mInputAllocators.reset(
- C2PortAllocatorsTuning::input::From(params[0].get()));
+ C2PortAllocatorsTuning::input::From(param));
}
}
mInitStatus = OK;
diff --git a/media/codec2/sfplugin/CCodecBuffers.cpp b/media/codec2/sfplugin/CCodecBuffers.cpp
index 566a18f..c2ec665 100644
--- a/media/codec2/sfplugin/CCodecBuffers.cpp
+++ b/media/codec2/sfplugin/CCodecBuffers.cpp
@@ -27,6 +27,7 @@
#include <mediadrm/ICrypto.h>
#include "CCodecBuffers.h"
+#include "Codec2Mapper.h"
namespace android {
@@ -1019,18 +1020,32 @@
// track of the flushed work.
}
+static uint32_t extractPixelFormat(const sp<AMessage> &format) {
+ int32_t frameworkColorFormat = 0;
+ if (!format->findInt32("android._color-format", &frameworkColorFormat)) {
+ return PIXEL_FORMAT_UNKNOWN;
+ }
+ uint32_t pixelFormat = PIXEL_FORMAT_UNKNOWN;
+ if (C2Mapper::mapPixelFormatFrameworkToCodec(frameworkColorFormat, &pixelFormat)) {
+ return pixelFormat;
+ }
+ return PIXEL_FORMAT_UNKNOWN;
+}
+
std::unique_ptr<InputBuffers> GraphicInputBuffers::toArrayMode(size_t size) {
std::unique_ptr<InputBuffersArray> array(
new InputBuffersArray(mComponentName.c_str(), "2D-BB-Input[N]"));
array->setPool(mPool);
array->setFormat(mFormat);
+ uint32_t pixelFormat = extractPixelFormat(mFormat);
array->initialize(
mImpl,
size,
- [pool = mPool, format = mFormat, lbp = mLocalBufferPool]() -> sp<Codec2Buffer> {
+ [pool = mPool, format = mFormat, lbp = mLocalBufferPool, pixelFormat]()
+ -> sp<Codec2Buffer> {
C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
return AllocateGraphicBuffer(
- pool, format, HAL_PIXEL_FORMAT_YV12, usage, lbp);
+ pool, format, pixelFormat, usage, lbp);
});
return std::move(array);
}
@@ -1043,7 +1058,7 @@
// TODO: read usage from intf
C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
return AllocateGraphicBuffer(
- mPool, mFormat, HAL_PIXEL_FORMAT_YV12, usage, mLocalBufferPool);
+ mPool, mFormat, extractPixelFormat(mFormat), usage, mLocalBufferPool);
}
// OutputBuffersArray
diff --git a/media/codec2/sfplugin/Codec2Buffer.cpp b/media/codec2/sfplugin/Codec2Buffer.cpp
index fa0d4ac..fc4ee51 100644
--- a/media/codec2/sfplugin/Codec2Buffer.cpp
+++ b/media/codec2/sfplugin/Codec2Buffer.cpp
@@ -212,21 +212,24 @@
* Creates a C2GraphicView <=> MediaImage converter
*
* \param view C2GraphicView object
- * \param colorFormat desired SDK color format for the MediaImage (if this is a flexible format,
- * an attempt is made to simply represent the graphic view as a flexible SDK format
- * without a memcpy)
+ * \param format buffer format
* \param copy whether the converter is used for copy or not
*/
GraphicView2MediaImageConverter(
- const C2GraphicView &view, int32_t colorFormat, bool copy)
+ const C2GraphicView &view, const sp<AMessage> &format, bool copy)
: mInitCheck(NO_INIT),
mView(view),
mWidth(view.width()),
mHeight(view.height()),
- mColorFormat(colorFormat),
mAllocatedDepth(0),
mBackBufferSize(0),
mMediaImage(new ABuffer(sizeof(MediaImage2))) {
+ if (!format->findInt32(KEY_COLOR_FORMAT, &mClientColorFormat)) {
+ mClientColorFormat = COLOR_FormatYUV420Flexible;
+ }
+ if (!format->findInt32("android._color-format", &mComponentColorFormat)) {
+ mComponentColorFormat = COLOR_FormatYUV420Flexible;
+ }
if (view.error() != C2_OK) {
ALOGD("Converter: view.error() = %d", view.error());
mInitCheck = BAD_VALUE;
@@ -247,70 +250,57 @@
uint32_t stride = align(view.crop().width, 2) * divUp(layout.planes[0].allocatedDepth, 8u);
uint32_t vStride = align(view.crop().height, 2);
+ bool tryWrapping = !copy;
+
switch (layout.type) {
- case C2PlanarLayout::TYPE_YUV:
+ case C2PlanarLayout::TYPE_YUV: {
mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_YUV;
if (layout.numPlanes != 3) {
ALOGD("Converter: %d planes for YUV layout", layout.numPlanes);
mInitCheck = BAD_VALUE;
return;
}
- if (layout.planes[0].channel != C2PlaneInfo::CHANNEL_Y
- || layout.planes[1].channel != C2PlaneInfo::CHANNEL_CB
- || layout.planes[2].channel != C2PlaneInfo::CHANNEL_CR
- || layout.planes[0].colSampling != 1
- || layout.planes[0].rowSampling != 1
- || layout.planes[1].colSampling != 2
- || layout.planes[1].rowSampling != 2
- || layout.planes[2].colSampling != 2
- || layout.planes[2].rowSampling != 2) {
- ALOGD("Converter: not YUV420 for YUV layout");
+ C2PlaneInfo yPlane = layout.planes[C2PlanarLayout::PLANE_Y];
+ C2PlaneInfo uPlane = layout.planes[C2PlanarLayout::PLANE_U];
+ C2PlaneInfo vPlane = layout.planes[C2PlanarLayout::PLANE_V];
+ if (yPlane.channel != C2PlaneInfo::CHANNEL_Y
+ || uPlane.channel != C2PlaneInfo::CHANNEL_CB
+ || vPlane.channel != C2PlaneInfo::CHANNEL_CR) {
+ ALOGD("Converter: not YUV layout");
mInitCheck = BAD_VALUE;
return;
}
- switch (mColorFormat) {
- case COLOR_FormatYUV420Flexible:
- if (!copy) {
- // try to map directly. check if the planes are near one another
- const uint8_t *minPtr = mView.data()[0];
- const uint8_t *maxPtr = mView.data()[0];
- int32_t planeSize = 0;
- for (uint32_t i = 0; i < layout.numPlanes; ++i) {
- const C2PlaneInfo &plane = layout.planes[i];
- int64_t planeStride = std::abs(plane.rowInc / plane.colInc);
- ssize_t minOffset = plane.minOffset(
- mWidth / plane.colSampling, mHeight / plane.rowSampling);
- ssize_t maxOffset = plane.maxOffset(
- mWidth / plane.colSampling, mHeight / plane.rowSampling);
- if (minPtr > mView.data()[i] + minOffset) {
- minPtr = mView.data()[i] + minOffset;
- }
- if (maxPtr < mView.data()[i] + maxOffset) {
- maxPtr = mView.data()[i] + maxOffset;
- }
- planeSize += planeStride * divUp(mAllocatedDepth, 8u)
- * align(mHeight, 64) / plane.rowSampling;
- }
-
- if (minPtr == mView.data()[0] && (maxPtr - minPtr + 1) <= planeSize) {
- // FIXME: this is risky as reading/writing data out of bound results
- // in an undefined behavior, but gralloc does assume a
- // contiguous mapping
- for (uint32_t i = 0; i < layout.numPlanes; ++i) {
- const C2PlaneInfo &plane = layout.planes[i];
- mediaImage->mPlane[i].mOffset = mView.data()[i] - minPtr;
- mediaImage->mPlane[i].mColInc = plane.colInc;
- mediaImage->mPlane[i].mRowInc = plane.rowInc;
- mediaImage->mPlane[i].mHorizSubsampling = plane.colSampling;
- mediaImage->mPlane[i].mVertSubsampling = plane.rowSampling;
- }
- mWrapped = new ABuffer(const_cast<uint8_t *>(minPtr),
- maxPtr - minPtr + 1);
- break;
- }
+ bool yuv420888 = yPlane.rowSampling == 1 && yPlane.colSampling == 1
+ && uPlane.rowSampling == 2 && uPlane.colSampling == 2
+ && vPlane.rowSampling == 2 && vPlane.colSampling == 2;
+ if (yuv420888) {
+ for (uint32_t i = 0; i < 3; ++i) {
+ const C2PlaneInfo &plane = layout.planes[i];
+ if (plane.allocatedDepth != 8 || plane.bitDepth != 8) {
+ yuv420888 = false;
+ break;
}
- [[fallthrough]];
-
+ }
+ yuv420888 = yuv420888 && yPlane.colInc == 1 && uPlane.rowInc == vPlane.rowInc;
+ }
+ int32_t copyFormat = mClientColorFormat;
+ if (yuv420888 && mClientColorFormat == COLOR_FormatYUV420Flexible) {
+ if (uPlane.colInc == 2 && vPlane.colInc == 2
+ && yPlane.rowInc == uPlane.rowInc) {
+ copyFormat = COLOR_FormatYUV420PackedSemiPlanar;
+ } else if (uPlane.colInc == 1 && vPlane.colInc == 1
+ && yPlane.rowInc == uPlane.rowInc * 2) {
+ copyFormat = COLOR_FormatYUV420PackedPlanar;
+ }
+ }
+ ALOGV("client_fmt=0x%x y:{colInc=%d rowInc=%d} u:{colInc=%d rowInc=%d} "
+ "v:{colInc=%d rowInc=%d}",
+ mClientColorFormat,
+ yPlane.colInc, yPlane.rowInc,
+ uPlane.colInc, uPlane.rowInc,
+ vPlane.colInc, vPlane.rowInc);
+ switch (copyFormat) {
+ case COLOR_FormatYUV420Flexible:
case COLOR_FormatYUV420Planar:
case COLOR_FormatYUV420PackedPlanar:
mediaImage->mPlane[mediaImage->Y].mOffset = 0;
@@ -330,6 +320,13 @@
mediaImage->mPlane[mediaImage->V].mRowInc = stride / 2;
mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2;
mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2;
+
+ if (tryWrapping && mClientColorFormat != COLOR_FormatYUV420Flexible) {
+ tryWrapping = yuv420888 && uPlane.colInc == 1 && vPlane.colInc == 1
+ && yPlane.rowInc == uPlane.rowInc * 2
+ && view.data()[0] < view.data()[1]
+ && view.data()[1] < view.data()[2];
+ }
break;
case COLOR_FormatYUV420SemiPlanar:
@@ -351,49 +348,16 @@
mediaImage->mPlane[mediaImage->V].mRowInc = stride;
mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2;
mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2;
+
+ if (tryWrapping && mClientColorFormat != COLOR_FormatYUV420Flexible) {
+ tryWrapping = yuv420888 && uPlane.colInc == 2 && vPlane.colInc == 2
+ && yPlane.rowInc == uPlane.rowInc
+ && view.data()[0] < view.data()[1]
+ && view.data()[1] < view.data()[2];
+ }
break;
case COLOR_FormatYUVP010:
- if (!copy) {
- // try to map directly. check if the planes are near one another
- const uint8_t *minPtr = mView.data()[0];
- const uint8_t *maxPtr = mView.data()[0];
- int32_t planeSize = 0;
- for (uint32_t i = 0; i < layout.numPlanes; ++i) {
- const C2PlaneInfo &plane = layout.planes[i];
- ssize_t minOffset = plane.minOffset(
- mWidth / plane.colSampling, mHeight / plane.rowSampling);
- ssize_t maxOffset = plane.maxOffset(
- mWidth / plane.colSampling, mHeight / plane.rowSampling);
- if (minPtr > mView.data()[i] + minOffset) {
- minPtr = mView.data()[i] + minOffset;
- }
- if (maxPtr < mView.data()[i] + maxOffset) {
- maxPtr = mView.data()[i] + maxOffset;
- }
- planeSize += std::abs(plane.rowInc) * align(mHeight, 64)
- / plane.rowSampling / plane.colSampling
- * divUp(mAllocatedDepth, 8u);
- }
-
- if ((maxPtr - minPtr + 1) <= planeSize) {
- // FIXME: this is risky as reading/writing data out of bound results
- // in an undefined behavior, but gralloc does assume a
- // contiguous mapping
- for (uint32_t i = 0; i < layout.numPlanes; ++i) {
- const C2PlaneInfo &plane = layout.planes[i];
- mediaImage->mPlane[i].mOffset = mView.data()[i] - minPtr;
- mediaImage->mPlane[i].mColInc = plane.colInc;
- mediaImage->mPlane[i].mRowInc = plane.rowInc;
- mediaImage->mPlane[i].mHorizSubsampling = plane.colSampling;
- mediaImage->mPlane[i].mVertSubsampling = plane.rowSampling;
- }
- mWrapped = new ABuffer(
- const_cast<uint8_t *>(minPtr),
- maxPtr - minPtr + divUp(mAllocatedDepth, 8u));
- break;
- }
- }
mediaImage->mPlane[mediaImage->Y].mOffset = 0;
mediaImage->mPlane[mediaImage->Y].mColInc = 2;
mediaImage->mPlane[mediaImage->Y].mRowInc = stride * 2;
@@ -411,64 +375,138 @@
mediaImage->mPlane[mediaImage->V].mRowInc = stride * 2;
mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2;
mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2;
+ if (tryWrapping) {
+ tryWrapping = yPlane.allocatedDepth == 16
+ && uPlane.allocatedDepth == 16
+ && vPlane.allocatedDepth == 16
+ && yPlane.bitDepth == 10
+ && uPlane.bitDepth == 10
+ && vPlane.bitDepth == 10
+ && yPlane.rightShift == 6
+ && uPlane.rightShift == 6
+ && vPlane.rightShift == 6
+ && yPlane.rowSampling == 1 && yPlane.colSampling == 1
+ && uPlane.rowSampling == 2 && uPlane.colSampling == 2
+ && vPlane.rowSampling == 2 && vPlane.colSampling == 2
+ && yPlane.colInc == 2
+ && uPlane.colInc == 4
+ && vPlane.colInc == 4
+ && yPlane.rowInc == uPlane.rowInc
+ && yPlane.rowInc == vPlane.rowInc;
+ }
break;
- default:
- ALOGD("Converter: incompactible color format (%d) for YUV layout", mColorFormat);
- mInitCheck = BAD_VALUE;
- return;
+ default: {
+ // default to fully planar format --- this will be overridden if wrapping
+ // TODO: keep interleaved format
+ int32_t colInc = divUp(mAllocatedDepth, 8u);
+ int32_t rowInc = stride * colInc / yPlane.colSampling;
+ mediaImage->mPlane[mediaImage->Y].mOffset = 0;
+ mediaImage->mPlane[mediaImage->Y].mColInc = colInc;
+ mediaImage->mPlane[mediaImage->Y].mRowInc = rowInc;
+ mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = yPlane.colSampling;
+ mediaImage->mPlane[mediaImage->Y].mVertSubsampling = yPlane.rowSampling;
+ int32_t offset = rowInc * vStride / yPlane.rowSampling;
+
+ rowInc = stride * colInc / uPlane.colSampling;
+ mediaImage->mPlane[mediaImage->U].mOffset = offset;
+ mediaImage->mPlane[mediaImage->U].mColInc = colInc;
+ mediaImage->mPlane[mediaImage->U].mRowInc = rowInc;
+ mediaImage->mPlane[mediaImage->U].mHorizSubsampling = uPlane.colSampling;
+ mediaImage->mPlane[mediaImage->U].mVertSubsampling = uPlane.rowSampling;
+ offset += rowInc * vStride / uPlane.rowSampling;
+
+ rowInc = stride * colInc / vPlane.colSampling;
+ mediaImage->mPlane[mediaImage->V].mOffset = offset;
+ mediaImage->mPlane[mediaImage->V].mColInc = colInc;
+ mediaImage->mPlane[mediaImage->V].mRowInc = rowInc;
+ mediaImage->mPlane[mediaImage->V].mHorizSubsampling = vPlane.colSampling;
+ mediaImage->mPlane[mediaImage->V].mVertSubsampling = vPlane.rowSampling;
+ break;
+ }
}
break;
+ }
+
case C2PlanarLayout::TYPE_YUVA:
- mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_YUVA;
- // We don't have an SDK YUVA format
- ALOGD("Converter: incompactible color format (%d) for YUVA layout", mColorFormat);
- mInitCheck = BAD_VALUE;
+ ALOGD("Converter: unrecognized color format "
+ "(client %d component %d) for YUVA layout",
+ mClientColorFormat, mComponentColorFormat);
+ mInitCheck = NO_INIT;
return;
case C2PlanarLayout::TYPE_RGB:
- mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_RGB;
- switch (mColorFormat) {
- // TODO media image
- case COLOR_FormatRGBFlexible:
- case COLOR_Format24bitBGR888:
- case COLOR_Format24bitRGB888:
- break;
- default:
- ALOGD("Converter: incompactible color format (%d) for RGB layout", mColorFormat);
- mInitCheck = BAD_VALUE;
- return;
- }
- if (layout.numPlanes != 3) {
- ALOGD("Converter: %d planes for RGB layout", layout.numPlanes);
- mInitCheck = BAD_VALUE;
- return;
- }
- break;
+ ALOGD("Converter: unrecognized color format "
+ "(client %d component %d) for RGB layout",
+ mClientColorFormat, mComponentColorFormat);
+ mInitCheck = NO_INIT;
+ // TODO: support MediaImage layout
+ return;
case C2PlanarLayout::TYPE_RGBA:
- mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_RGBA;
- switch (mColorFormat) {
- // TODO media image
- case COLOR_FormatRGBAFlexible:
- case COLOR_Format32bitABGR8888:
- case COLOR_Format32bitARGB8888:
- case COLOR_Format32bitBGRA8888:
- break;
- default:
- ALOGD("Incompactible color format (%d) for RGBA layout", mColorFormat);
- mInitCheck = BAD_VALUE;
- return;
- }
- if (layout.numPlanes != 4) {
- ALOGD("Converter: %d planes for RGBA layout", layout.numPlanes);
- mInitCheck = BAD_VALUE;
- return;
- }
- break;
+ ALOGD("Converter: unrecognized color format "
+ "(client %d component %d) for RGBA layout",
+ mClientColorFormat, mComponentColorFormat);
+ mInitCheck = NO_INIT;
+ // TODO: support MediaImage layout
+ return;
default:
mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN;
- ALOGD("Unknown layout");
- mInitCheck = BAD_VALUE;
- return;
+ if (layout.numPlanes == 1) {
+ const C2PlaneInfo &plane = layout.planes[0];
+ if (plane.colInc < 0 || plane.rowInc < 0) {
+ // Copy-only if we have negative colInc/rowInc
+ tryWrapping = false;
+ }
+ mediaImage->mPlane[0].mOffset = 0;
+ mediaImage->mPlane[0].mColInc = std::abs(plane.colInc);
+ mediaImage->mPlane[0].mRowInc = std::abs(plane.rowInc);
+ mediaImage->mPlane[0].mHorizSubsampling = plane.colSampling;
+ mediaImage->mPlane[0].mVertSubsampling = plane.rowSampling;
+ } else {
+ ALOGD("Converter: unrecognized layout: color format (client %d component %d)",
+ mClientColorFormat, mComponentColorFormat);
+ mInitCheck = NO_INIT;
+ return;
+ }
+ break;
+ }
+ if (tryWrapping) {
+ // try to map directly. check if the planes are near one another
+ const uint8_t *minPtr = mView.data()[0];
+ const uint8_t *maxPtr = mView.data()[0];
+ int32_t planeSize = 0;
+ for (uint32_t i = 0; i < layout.numPlanes; ++i) {
+ const C2PlaneInfo &plane = layout.planes[i];
+ int64_t planeStride = std::abs(plane.rowInc / plane.colInc);
+ ssize_t minOffset = plane.minOffset(
+ mWidth / plane.colSampling, mHeight / plane.rowSampling);
+ ssize_t maxOffset = plane.maxOffset(
+ mWidth / plane.colSampling, mHeight / plane.rowSampling);
+ if (minPtr > mView.data()[i] + minOffset) {
+ minPtr = mView.data()[i] + minOffset;
+ }
+ if (maxPtr < mView.data()[i] + maxOffset) {
+ maxPtr = mView.data()[i] + maxOffset;
+ }
+ planeSize += planeStride * divUp(mAllocatedDepth, 8u)
+ * align(mHeight, 64) / plane.rowSampling;
+ }
+
+ if ((maxPtr - minPtr + 1) <= planeSize) {
+ // FIXME: this is risky as reading/writing data out of bound results
+ // in an undefined behavior, but gralloc does assume a
+ // contiguous mapping
+ for (uint32_t i = 0; i < layout.numPlanes; ++i) {
+ const C2PlaneInfo &plane = layout.planes[i];
+ mediaImage->mPlane[i].mOffset = mView.data()[i] - minPtr;
+ mediaImage->mPlane[i].mColInc = plane.colInc;
+ mediaImage->mPlane[i].mRowInc = plane.rowInc;
+ mediaImage->mPlane[i].mHorizSubsampling = plane.colSampling;
+ mediaImage->mPlane[i].mVertSubsampling = plane.rowSampling;
+ }
+ mWrapped = new ABuffer(const_cast<uint8_t *>(minPtr),
+ maxPtr - minPtr + 1);
+ ALOGV("Converter: wrapped (capacity=%zu)", mWrapped->capacity());
+ }
}
mediaImage->mNumPlanes = layout.numPlanes;
mediaImage->mWidth = view.crop().width;
@@ -491,12 +529,12 @@
return;
}
if (plane.allocatedDepth != mAllocatedDepth || plane.bitDepth != bitDepth) {
- ALOGV("different allocatedDepth/bitDepth per plane unsupported");
+ ALOGD("different allocatedDepth/bitDepth per plane unsupported");
mInitCheck = BAD_VALUE;
return;
}
bufferSize += stride * vStride
- / plane.rowSampling / plane.colSampling;
+ / plane.rowSampling / plane.colSampling * divUp(mAllocatedDepth, 8u);
}
mBackBufferSize = bufferSize;
@@ -551,7 +589,8 @@
const C2GraphicView mView;
uint32_t mWidth;
uint32_t mHeight;
- int32_t mColorFormat; ///< SDK color format for MediaImage
+ int32_t mClientColorFormat; ///< SDK color format for MediaImage
+ int32_t mComponentColorFormat; ///< SDK color format from component
sp<ABuffer> mWrapped; ///< wrapped buffer (if we can map C2Buffer to an ABuffer)
uint32_t mAllocatedDepth;
uint32_t mBackBufferSize;
@@ -580,10 +619,7 @@
return nullptr;
}
- int32_t colorFormat = COLOR_FormatYUV420Flexible;
- (void)format->findInt32("color-format", &colorFormat);
-
- GraphicView2MediaImageConverter converter(view, colorFormat, false /* copy */);
+ GraphicView2MediaImageConverter converter(view, format, false /* copy */);
if (converter.initCheck() != OK) {
ALOGD("Converter init failed: %d", converter.initCheck());
return nullptr;
@@ -709,10 +745,7 @@
buffer->data().graphicBlocks()[0].map().get()));
std::unique_ptr<const C2GraphicView> holder;
- int32_t colorFormat = COLOR_FormatYUV420Flexible;
- (void)format->findInt32("color-format", &colorFormat);
-
- GraphicView2MediaImageConverter converter(*view, colorFormat, false /* copy */);
+ GraphicView2MediaImageConverter converter(*view, format, false /* copy */);
if (converter.initCheck() != OK) {
ALOGD("Converter init failed: %d", converter.initCheck());
return nullptr;
@@ -804,12 +837,11 @@
return false;
}
- int32_t colorFormat = COLOR_FormatYUV420Flexible;
- // FIXME: format() is not const, but we cannot change it, so do a const cast here
- const_cast<ConstGraphicBlockBuffer *>(this)->format()->findInt32("color-format", &colorFormat);
-
GraphicView2MediaImageConverter converter(
- buffer->data().graphicBlocks()[0].map().get(), colorFormat, true /* copy */);
+ buffer->data().graphicBlocks()[0].map().get(),
+ // FIXME: format() is not const, but we cannot change it, so do a const cast here
+ const_cast<ConstGraphicBlockBuffer *>(this)->format(),
+ true /* copy */);
if (converter.initCheck() != OK) {
ALOGD("ConstGraphicBlockBuffer::canCopy: converter init failed: %d", converter.initCheck());
return false;
@@ -827,11 +859,9 @@
setRange(0, 0);
return true;
}
- int32_t colorFormat = COLOR_FormatYUV420Flexible;
- format()->findInt32("color-format", &colorFormat);
GraphicView2MediaImageConverter converter(
- buffer->data().graphicBlocks()[0].map().get(), colorFormat, true /* copy */);
+ buffer->data().graphicBlocks()[0].map().get(), format(), true /* copy */);
if (converter.initCheck() != OK) {
ALOGD("ConstGraphicBlockBuffer::copy: converter init failed: %d", converter.initCheck());
return false;
diff --git a/media/codec2/sfplugin/utils/Codec2Mapper.cpp b/media/codec2/sfplugin/utils/Codec2Mapper.cpp
index dcded8f..1390642 100644
--- a/media/codec2/sfplugin/utils/Codec2Mapper.cpp
+++ b/media/codec2/sfplugin/utils/Codec2Mapper.cpp
@@ -958,13 +958,11 @@
*c2Value = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
return true;
case COLOR_FormatYUV420Flexible:
- *c2Value = HAL_PIXEL_FORMAT_YCBCR_420_888;
- return true;
case COLOR_FormatYUV420Planar:
case COLOR_FormatYUV420SemiPlanar:
case COLOR_FormatYUV420PackedPlanar:
case COLOR_FormatYUV420PackedSemiPlanar:
- *c2Value = HAL_PIXEL_FORMAT_YV12;
+ *c2Value = HAL_PIXEL_FORMAT_YCBCR_420_888;
return true;
default:
// Passthrough
@@ -980,8 +978,11 @@
case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
*frameworkValue = COLOR_FormatSurface;
return true;
- case HAL_PIXEL_FORMAT_YV12:
+ case HAL_PIXEL_FORMAT_YCBCR_422_SP:
+ case HAL_PIXEL_FORMAT_YCRCB_420_SP:
+ case HAL_PIXEL_FORMAT_YCBCR_422_I:
case HAL_PIXEL_FORMAT_YCBCR_420_888:
+ case HAL_PIXEL_FORMAT_YV12:
*frameworkValue = COLOR_FormatYUV420Flexible;
return true;
default: