Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d79ee1fd authored by Wonsik Kim's avatar Wonsik Kim
Browse files

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
parent 29e3c4d6
Loading
Loading
Loading
Loading
+82 −13
Original line number Diff line number Diff line
@@ -883,19 +883,84 @@ void CCodec::configure(const sp<AMessage> &msg) {
        /*
         * 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,14 +1112,18 @@ void CCodec::configure(const sp<AMessage> &msg) {

            // Set desired color format from configuration parameter
            int32_t format;
            if (msg->findInt32("android._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);
            }
        }
        }

        // propagate encoder delay and padding to output format
        if ((config->mDomain & Config::IS_DECODER) && (config->mDomain & Config::IS_AUDIO)) {
@@ -2010,7 +2079,7 @@ public:
            }
            if (param->type() == C2PortAllocatorsTuning::input::PARAM_TYPE) {
                mInputAllocators.reset(
                        C2PortAllocatorsTuning::input::From(params[0].get()));
                        C2PortAllocatorsTuning::input::From(param));
            }
        }
        mInitStatus = OK;
+18 −3
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include <mediadrm/ICrypto.h>

#include "CCodecBuffers.h"
#include "Codec2Mapper.h"

namespace android {

@@ -1019,18 +1020,32 @@ void GraphicInputBuffers::flush() {
    // 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 @@ sp<Codec2Buffer> GraphicInputBuffers::createNewBuffer() {
    // 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
+193 −163

File changed.

Preview size limit exceeded, changes collapsed.

+5 −4
Original line number Diff line number Diff line
@@ -958,13 +958,11 @@ bool C2Mapper::mapPixelFormatFrameworkToCodec(
            *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 @@ bool C2Mapper::mapPixelFormatCodecToFramework(
        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: