stagefright: add flexible YUV support

Bug: 10706245
Change-Id: Icd246f22edfc67ed5240d59f5a5bde3e5f749465
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index 142b7cb..42a03bb 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -32,6 +32,7 @@
 
 struct ABuffer;
 struct MemoryDealer;
+struct DescribeColorFormatParams;
 
 struct ACodec : public AHierarchicalStateMachine, public CodecBase {
     ACodec();
@@ -305,6 +306,8 @@
             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);
 
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index b6cc742..1b1d7a9 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -2709,6 +2709,83 @@
     }
 }
 
+// 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 @@
                     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;
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 15e062e..e944766 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -1948,6 +1948,18 @@
         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;