Add adaptive playback support to VPX decoder.

Bug: 13842676
Change-Id: I9c054ea489fd3a71b3b2394f15a85b84d42edb5a
diff --git a/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.h b/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.h
index 23d5ff1..cfa9ca5 100644
--- a/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.h
+++ b/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.h
@@ -67,10 +67,6 @@
         kNumBuffers = 2,
     };
 
-    enum {
-        kStoreMetaDataExtensionIndex = OMX_IndexVendorStartUnused + 1
-    };
-
     // OMX input buffer's timestamp and flags
     typedef struct {
         int64_t mTimeUs;
diff --git a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.h b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.h
index cc4ea8f..c59a1b9 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.h
+++ b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.h
@@ -56,10 +56,6 @@
         kNumBuffers = 2,
     };
 
-    enum {
-        kStoreMetaDataExtensionIndex = OMX_IndexVendorStartUnused + 1
-    };
-
     // OMX input buffer's timestamp and flags
     typedef struct {
         int64_t mTimeUs;
diff --git a/media/libstagefright/codecs/on2/dec/SoftVPX.cpp b/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
index 423a057..a4258dd 100644
--- a/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
+++ b/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
@@ -143,11 +143,24 @@
                 mWidth = width;
                 mHeight = height;
 
-                updatePortDefinitions();
-
-                notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
-                mOutputPortSettingsChange = AWAITING_DISABLED;
-                return;
+                if (!mIsAdaptive || width > mAdaptiveMaxWidth || height > mAdaptiveMaxHeight) {
+                    if (mIsAdaptive) {
+                        if (width > mAdaptiveMaxWidth) {
+                            mAdaptiveMaxWidth = width;
+                        }
+                        if (height > mAdaptiveMaxHeight) {
+                            mAdaptiveMaxHeight = height;
+                        }
+                    }
+                    updatePortDefinitions();
+                    notify(OMX_EventPortSettingsChanged, kOutputPortIndex, 0, NULL);
+                    mOutputPortSettingsChange = AWAITING_DISABLED;
+                    return;
+                } else {
+                    updatePortDefinitions();
+                    notify(OMX_EventPortSettingsChanged, kOutputPortIndex,
+                           OMX_IndexConfigCommonOutputCrop, NULL);
+                }
             }
 
             outHeader->nOffset = 0;
@@ -155,29 +168,35 @@
             outHeader->nFlags = EOSseen ? OMX_BUFFERFLAG_EOS : 0;
             outHeader->nTimeStamp = inHeader->nTimeStamp;
 
+            uint32_t buffer_stride = mIsAdaptive ? mAdaptiveMaxWidth : mWidth;
+            uint32_t buffer_height = mIsAdaptive ? mAdaptiveMaxHeight : mHeight;
+
             const uint8_t *srcLine = (const uint8_t *)img->planes[PLANE_Y];
             uint8_t *dst = outHeader->pBuffer;
-            for (size_t i = 0; i < img->d_h; ++i) {
-                memcpy(dst, srcLine, img->d_w);
-
-                srcLine += img->stride[PLANE_Y];
-                dst += img->d_w;
+            for (size_t i = 0; i < buffer_height; ++i) {
+                if (i < img->d_h) {
+                    memcpy(dst, srcLine, img->d_w);
+                    srcLine += img->stride[PLANE_Y];
+                }
+                dst += buffer_stride;
             }
 
             srcLine = (const uint8_t *)img->planes[PLANE_U];
-            for (size_t i = 0; i < img->d_h / 2; ++i) {
-                memcpy(dst, srcLine, img->d_w / 2);
-
-                srcLine += img->stride[PLANE_U];
-                dst += img->d_w / 2;
+            for (size_t i = 0; i < buffer_height / 2; ++i) {
+                if (i < img->d_h / 2) {
+                    memcpy(dst, srcLine, img->d_w / 2);
+                    srcLine += img->stride[PLANE_U];
+                }
+                dst += buffer_stride / 2;
             }
 
             srcLine = (const uint8_t *)img->planes[PLANE_V];
-            for (size_t i = 0; i < img->d_h / 2; ++i) {
-                memcpy(dst, srcLine, img->d_w / 2);
-
-                srcLine += img->stride[PLANE_V];
-                dst += img->d_w / 2;
+            for (size_t i = 0; i < buffer_height / 2; ++i) {
+                if (i < img->d_h / 2) {
+                    memcpy(dst, srcLine, img->d_w / 2);
+                    srcLine += img->stride[PLANE_V];
+                }
+                dst += buffer_stride / 2;
             }
 
             outInfo->mOwnedByUs = false;
diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h
index c5a83d1..5b4c954 100644
--- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h
+++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h
@@ -91,10 +91,6 @@
             const char *name, OMX_INDEXTYPE *index);
 
 private:
-    enum {
-        kStoreMetaDataExtensionIndex = OMX_IndexVendorStartUnused + 1,
-    };
-
     enum TemporalReferences {
         // For 1 layer case: reference all (last, golden, and alt ref), but only
         // update last.
diff --git a/media/libstagefright/include/SimpleSoftOMXComponent.h b/media/libstagefright/include/SimpleSoftOMXComponent.h
index f8c61eb..591b38e 100644
--- a/media/libstagefright/include/SimpleSoftOMXComponent.h
+++ b/media/libstagefright/include/SimpleSoftOMXComponent.h
@@ -58,6 +58,11 @@
         } mTransition;
     };
 
+    enum {
+        kStoreMetaDataExtensionIndex = OMX_IndexVendorStartUnused + 1,
+        kPrepareForAdaptivePlaybackIndex,
+    };
+
     void addPort(const OMX_PARAM_PORTDEFINITIONTYPE &def);
 
     virtual OMX_ERRORTYPE internalGetParameter(
diff --git a/media/libstagefright/include/SoftVideoDecoderOMXComponent.h b/media/libstagefright/include/SoftVideoDecoderOMXComponent.h
index 7f200dd..ee553d9 100644
--- a/media/libstagefright/include/SoftVideoDecoderOMXComponent.h
+++ b/media/libstagefright/include/SoftVideoDecoderOMXComponent.h
@@ -55,6 +55,9 @@
     virtual OMX_ERRORTYPE getConfig(
             OMX_INDEXTYPE index, OMX_PTR params);
 
+    virtual OMX_ERRORTYPE getExtensionIndex(
+            const char *name, OMX_INDEXTYPE *index);
+
     void initPorts(OMX_U32 numInputBuffers,
             OMX_U32 inputBufferSize,
             OMX_U32 numOutputBuffers,
@@ -68,6 +71,8 @@
         kMaxPortIndex = 1,
     };
 
+    bool mIsAdaptive;
+    uint32_t mAdaptiveMaxWidth, mAdaptiveMaxHeight;
     uint32_t mWidth, mHeight;
     uint32_t mCropLeft, mCropTop, mCropWidth, mCropHeight;
 
diff --git a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
index 1c383f7..69b572e 100644
--- a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
+++ b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
@@ -22,6 +22,7 @@
 
 #include "include/SoftVideoDecoderOMXComponent.h"
 
+#include <media/hardware/HardwareAPI.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALooper.h>
 #include <media/stagefright/foundation/AMessage.h>
@@ -50,6 +51,9 @@
         OMX_PTR appData,
         OMX_COMPONENTTYPE **component)
         : SimpleSoftOMXComponent(name, callbacks, appData, component),
+        mIsAdaptive(false),
+        mAdaptiveMaxWidth(0),
+        mAdaptiveMaxHeight(0),
         mWidth(width),
         mHeight(height),
         mCropLeft(0),
@@ -127,8 +131,8 @@
     def->format.video.nSliceHeight = def->format.video.nFrameHeight;
 
     def = &editPortInfo(kOutputPortIndex)->mDef;
-    def->format.video.nFrameWidth = mWidth;
-    def->format.video.nFrameHeight = mHeight;
+    def->format.video.nFrameWidth = mIsAdaptive ? mAdaptiveMaxWidth : mWidth;
+    def->format.video.nFrameHeight = mIsAdaptive ? mAdaptiveMaxHeight : mHeight;
     def->format.video.nStride = def->format.video.nFrameWidth;
     def->format.video.nSliceHeight = def->format.video.nFrameHeight;
 
@@ -199,7 +203,10 @@
 
 OMX_ERRORTYPE SoftVideoDecoderOMXComponent::internalSetParameter(
         OMX_INDEXTYPE index, const OMX_PTR params) {
-    switch (index) {
+    // Include extension index OMX_INDEXEXTTYPE.
+    const int32_t indexFull = index;
+
+    switch (indexFull) {
         case OMX_IndexParamStandardComponentRole:
         {
             const OMX_PARAM_COMPONENTROLETYPE *roleParams =
@@ -230,6 +237,24 @@
             return OMX_ErrorNone;
         }
 
+        case kPrepareForAdaptivePlaybackIndex:
+        {
+            const PrepareForAdaptivePlaybackParams* adaptivePlaybackParams =
+                    (const PrepareForAdaptivePlaybackParams *)params;
+            mIsAdaptive = adaptivePlaybackParams->bEnable;
+            if (mIsAdaptive) {
+                mAdaptiveMaxWidth = adaptivePlaybackParams->nMaxFrameWidth;
+                mAdaptiveMaxHeight = adaptivePlaybackParams->nMaxFrameHeight;
+                mWidth = mAdaptiveMaxWidth;
+                mHeight = mAdaptiveMaxHeight;
+            } else {
+                mAdaptiveMaxWidth = 0;
+                mAdaptiveMaxHeight = 0;
+            }
+            updatePortDefinitions();
+            return OMX_ErrorNone;
+        }
+
         default:
             return SimpleSoftOMXComponent::internalSetParameter(index, params);
     }
@@ -259,6 +284,16 @@
     }
 }
 
+OMX_ERRORTYPE SoftVideoDecoderOMXComponent::getExtensionIndex(
+        const char *name, OMX_INDEXTYPE *index) {
+    if (!strcmp(name, "OMX.google.android.index.prepareForAdaptivePlayback")) {
+        *(int32_t*)index = kPrepareForAdaptivePlaybackIndex;
+        return OMX_ErrorNone;
+    }
+
+    return SimpleSoftOMXComponent::getExtensionIndex(name, index);
+}
+
 void SoftVideoDecoderOMXComponent::onReset() {
     mOutputPortSettingsChange = NONE;
 }