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

Commit 03c556ae authored by Lajos Molnar's avatar Lajos Molnar
Browse files

stagefright: add flexible YUV support

Bug: 10706245
Change-Id: Icd246f22edfc67ed5240d59f5a5bde3e5f749465
parent 90b16fbd
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ namespace android {

struct ABuffer;
struct MemoryDealer;
struct DescribeColorFormatParams;

struct ACodec : public AHierarchicalStateMachine, public CodecBase {
    ACodec();
@@ -305,6 +306,8 @@ private:
            OMX_ERRORTYPE error = OMX_ErrorUndefined,
            status_t internalError = UNKNOWN_ERROR);

    static void describeDefaultColorFormat(DescribeColorFormatParams &describeParams);

    status_t requestIDRFrame();
    status_t setParameters(const sp<AMessage> &params);

+104 −0
Original line number Diff line number Diff line
@@ -2709,6 +2709,83 @@ void ACodec::processDeferredMessages() {
    }
}

// static
void ACodec::describeDefaultColorFormat(DescribeColorFormatParams &params) {
    MediaImage &image = params.sMediaImage;
    memset(&image, 0, sizeof(image));

    image.mType = MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
    image.mNumPlanes = 0;

    const OMX_COLOR_FORMATTYPE fmt = params.eColorFormat;
    // we need stride and slice-height to be non-zero
    if (params.nStride == 0 || params.nSliceHeight == 0) {
        ALOGW("cannot describe color format 0x%x = %d with stride=%u and sliceHeight=%u",
                fmt, fmt, params.nStride, params.nSliceHeight);
        return;
    }

    image.mWidth = params.nFrameWidth;
    image.mHeight = params.nFrameHeight;

    // only supporting YUV420
    if (fmt != OMX_COLOR_FormatYUV420Planar &&
        fmt != OMX_COLOR_FormatYUV420PackedPlanar &&
        fmt != OMX_COLOR_FormatYUV420SemiPlanar &&
        fmt != OMX_COLOR_FormatYUV420PackedSemiPlanar) {
        ALOGW("do not know color format 0x%x = %d", fmt, fmt);
        return;
    }

    // set-up YUV format
    image.mType = MediaImage::MEDIA_IMAGE_TYPE_YUV;
    image.mNumPlanes = 3;
    image.mBitDepth = 8;
    image.mPlane[image.Y].mOffset = 0;
    image.mPlane[image.Y].mColInc = 1;
    image.mPlane[image.Y].mRowInc = params.nStride;
    image.mPlane[image.Y].mHorizSubsampling = 1;
    image.mPlane[image.Y].mVertSubsampling = 1;

    switch (fmt) {
        case OMX_COLOR_FormatYUV420Planar: // used for YV12
        case OMX_COLOR_FormatYUV420PackedPlanar:
            image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight;
            image.mPlane[image.U].mColInc = 1;
            image.mPlane[image.U].mRowInc = params.nStride / 2;
            image.mPlane[image.U].mHorizSubsampling = 2;
            image.mPlane[image.U].mVertSubsampling = 2;

            image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset
                    + (params.nStride * params.nSliceHeight / 4);
            image.mPlane[image.V].mColInc = 1;
            image.mPlane[image.V].mRowInc = params.nStride / 2;
            image.mPlane[image.V].mHorizSubsampling = 2;
            image.mPlane[image.V].mVertSubsampling = 2;
            break;

        case OMX_COLOR_FormatYUV420SemiPlanar:
            // FIXME: NV21 for sw-encoder, NV12 for decoder and hw-encoder
        case OMX_COLOR_FormatYUV420PackedSemiPlanar:
            // NV12
            image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight;
            image.mPlane[image.U].mColInc = 2;
            image.mPlane[image.U].mRowInc = params.nStride;
            image.mPlane[image.U].mHorizSubsampling = 2;
            image.mPlane[image.U].mVertSubsampling = 2;

            image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset + 1;
            image.mPlane[image.V].mColInc = 2;
            image.mPlane[image.V].mRowInc = params.nStride;
            image.mPlane[image.V].mHorizSubsampling = 2;
            image.mPlane[image.V].mVertSubsampling = 2;
            break;

        default:
            TRESPASS();
    }
}

status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> &notify) {
    // TODO: catch errors an return them instead of using CHECK
    OMX_PARAM_PORTDEFINITIONTYPE def;
@@ -2736,6 +2813,33 @@ status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> &notify) {
                    notify->setInt32("slice-height", videoDef->nSliceHeight);
                    notify->setInt32("color-format", videoDef->eColorFormat);


                    DescribeColorFormatParams describeParams;
                    InitOMXParams(&describeParams);
                    describeParams.eColorFormat = videoDef->eColorFormat;
                    describeParams.nFrameWidth = videoDef->nFrameWidth;
                    describeParams.nFrameHeight = videoDef->nFrameHeight;
                    describeParams.nStride = videoDef->nStride;
                    describeParams.nSliceHeight = videoDef->nSliceHeight;

                    OMX_INDEXTYPE describeColorFormatIndex;
                    if (mOMX->getExtensionIndex(
                            mNode, "OMX.google.android.index.describeColorFormat",
                            &describeColorFormatIndex) ||
                        mOMX->getParameter(
                            mNode, describeColorFormatIndex,
                            &describeParams, sizeof(describeParams))) {
                        describeDefaultColorFormat(describeParams);
                    }

                    if (describeParams.sMediaImage.mType != MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN) {
                        notify->setBuffer(
                                "image-data",
                                ABuffer::CreateAsCopy(
                                        &describeParams.sMediaImage,
                                        sizeof(describeParams.sMediaImage)));
                    }

                    OMX_CONFIG_RECTTYPE rect;
                    InitOMXParams(&rect);
                    rect.nPortIndex = kPortIndexOutput;
+12 −0
Original line number Diff line number Diff line
@@ -1948,6 +1948,18 @@ ssize_t MediaCodec::dequeuePortBuffer(int32_t portIndex) {
        Mutex::Autolock al(mBufferLock);
        info->mFormat = portIndex == kPortIndexInput ? mInputFormat : mOutputFormat;
        info->mOwnedByClient = true;

        // set image-data
        if (info->mFormat != NULL) {
            sp<ABuffer> imageData;
            if (info->mFormat->findBuffer("image-data", &imageData)) {
                info->mData->meta()->setBuffer("image-data", imageData);
            }
            int32_t left, top, right, bottom;
            if (info->mFormat->findRect("crop", &left, &top, &right, &bottom)) {
                info->mData->meta()->setRect("crop-rect", left, top, right, bottom);
            }
        }
    }

    return index;