resolved conflicts for merge of 6571ed31 to lmp-mr1-dev-plus-aosp

Change-Id: Ibaea3a0766f75a61964615482a9ef28651a42b37
diff --git a/include/media/stagefright/foundation/AUtils.h b/include/media/stagefright/foundation/AUtils.h
index 3a73a39..d7ecf50 100644
--- a/include/media/stagefright/foundation/AUtils.h
+++ b/include/media/stagefright/foundation/AUtils.h
@@ -40,6 +40,12 @@
     }
 }
 
+/* == ceil(nom / den) * den. T must be integer type, alignment must be positive power of 2 */
+template<class T, class U>
+inline static const T align(const T &nom, const U &den) {
+    return (nom + (T)(den - 1)) & (T)~(den - 1);
+}
+
 template<class T>
 inline static T abs(const T &a) {
     return a < 0 ? -a : a;
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index ef21c9a..653d16c 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -4237,7 +4237,8 @@
 
         case RESUBMIT_BUFFERS:
         {
-            if (rangeLength == 0 && !(flags & OMX_BUFFERFLAG_EOS)) {
+            if (rangeLength == 0 && (!(flags & OMX_BUFFERFLAG_EOS)
+                    || mCodec->mPortEOS[kPortIndexOutput])) {
                 ALOGV("[%s] calling fillBuffer %u",
                      mCodec->mComponentName.c_str(), info->mBufferID);
 
diff --git a/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp b/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp
index cfc37b7..928a74f 100644
--- a/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp
+++ b/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp
@@ -17,6 +17,7 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "SoftAVCEncoder"
 #include <utils/Log.h>
+#include <utils/misc.h>
 
 #include "avcenc_api.h"
 #include "avcenc_int.h"
@@ -25,6 +26,7 @@
 #include <HardwareAPI.h>
 #include <MetadataBufferType.h>
 #include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AUtils.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MetaData.h>
@@ -51,31 +53,36 @@
     params->nVersion.s.nStep = 0;
 }
 
+static const CodecProfileLevel kProfileLevels[] = {
+    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel2  },
+};
+
 typedef struct LevelConversion {
     OMX_U32 omxLevel;
     AVCLevel avcLevel;
+    uint32_t maxMacroBlocks;
 } LevelConcersion;
 
 static LevelConversion ConversionTable[] = {
-    { OMX_VIDEO_AVCLevel1,  AVC_LEVEL1_B },
-    { OMX_VIDEO_AVCLevel1b, AVC_LEVEL1   },
-    { OMX_VIDEO_AVCLevel11, AVC_LEVEL1_1 },
-    { OMX_VIDEO_AVCLevel12, AVC_LEVEL1_2 },
-    { OMX_VIDEO_AVCLevel13, AVC_LEVEL1_3 },
-    { OMX_VIDEO_AVCLevel2,  AVC_LEVEL2 },
+    { OMX_VIDEO_AVCLevel1,  AVC_LEVEL1_B, 99 },
+    { OMX_VIDEO_AVCLevel1b, AVC_LEVEL1,   99 },
+    { OMX_VIDEO_AVCLevel11, AVC_LEVEL1_1, 396 },
+    { OMX_VIDEO_AVCLevel12, AVC_LEVEL1_2, 396 },
+    { OMX_VIDEO_AVCLevel13, AVC_LEVEL1_3, 396 },
+    { OMX_VIDEO_AVCLevel2,  AVC_LEVEL2,   396 },
 #if 0
-    // encoding speed is very poor if video
-    // resolution is higher than CIF
-    { OMX_VIDEO_AVCLevel21, AVC_LEVEL2_1 },
-    { OMX_VIDEO_AVCLevel22, AVC_LEVEL2_2 },
-    { OMX_VIDEO_AVCLevel3,  AVC_LEVEL3   },
-    { OMX_VIDEO_AVCLevel31, AVC_LEVEL3_1 },
-    { OMX_VIDEO_AVCLevel32, AVC_LEVEL3_2 },
-    { OMX_VIDEO_AVCLevel4,  AVC_LEVEL4   },
-    { OMX_VIDEO_AVCLevel41, AVC_LEVEL4_1 },
-    { OMX_VIDEO_AVCLevel42, AVC_LEVEL4_2 },
-    { OMX_VIDEO_AVCLevel5,  AVC_LEVEL5   },
-    { OMX_VIDEO_AVCLevel51, AVC_LEVEL5_1 },
+    // encoding speed is very poor if video resolution
+    // is higher than CIF or if level is higher than 2
+    { OMX_VIDEO_AVCLevel21, AVC_LEVEL2_1, 792 },
+    { OMX_VIDEO_AVCLevel22, AVC_LEVEL2_2, 1620 },
+    { OMX_VIDEO_AVCLevel3,  AVC_LEVEL3,   1620 },
+    { OMX_VIDEO_AVCLevel31, AVC_LEVEL3_1, 3600 },
+    { OMX_VIDEO_AVCLevel32, AVC_LEVEL3_2, 5120 },
+    { OMX_VIDEO_AVCLevel4,  AVC_LEVEL4,   8192 },
+    { OMX_VIDEO_AVCLevel41, AVC_LEVEL4_1, 8192 },
+    { OMX_VIDEO_AVCLevel42, AVC_LEVEL4_2, 8704 },
+    { OMX_VIDEO_AVCLevel5,  AVC_LEVEL5,   22080 },
+    { OMX_VIDEO_AVCLevel51, AVC_LEVEL5_1, 36864 },
 #endif
 };
 
@@ -148,13 +155,11 @@
             const OMX_CALLBACKTYPE *callbacks,
             OMX_PTR appData,
             OMX_COMPONENTTYPE **component)
-    : SoftVideoEncoderOMXComponent(name, callbacks, appData, component),
-      mVideoWidth(176),
-      mVideoHeight(144),
-      mVideoFrameRate(30),
-      mVideoBitRate(192000),
-      mVideoColorFormat(OMX_COLOR_FormatYUV420Planar),
-      mStoreMetaDataInBuffers(false),
+    : SoftVideoEncoderOMXComponent(
+            name, "video_encoder.avc", OMX_VIDEO_CodingAVC,
+            kProfileLevels, NELEM(kProfileLevels),
+            176 /* width */, 144 /* height */,
+            callbacks, appData, component),
       mIDRFrameRefreshIntervalInSec(1),
       mAVCEncProfile(AVC_BASELINE),
       mAVCEncLevel(AVC_LEVEL2),
@@ -168,7 +173,13 @@
       mInputFrameData(NULL),
       mSliceGroup(NULL) {
 
-    initPorts();
+    const size_t kOutputBufferSize =
+        320 * ConversionTable[NELEM(ConversionTable) - 1].maxMacroBlocks;
+
+    initPorts(
+            kNumBuffers, kNumBuffers, kOutputBufferSize,
+            MEDIA_MIMETYPE_VIDEO_AVC, 2 /* minCompressionRatio */);
+
     ALOGI("Construct SoftAVCEncoder");
 }
 
@@ -230,30 +241,28 @@
 
     mEncParams->use_overrun_buffer = AVC_OFF;
 
-    if (mVideoColorFormat != OMX_COLOR_FormatYUV420Planar
-            || mStoreMetaDataInBuffers) {
+    if (mColorFormat != OMX_COLOR_FormatYUV420Planar || mInputDataIsMeta) {
         // Color conversion is needed.
         free(mInputFrameData);
         mInputFrameData =
-            (uint8_t *) malloc((mVideoWidth * mVideoHeight * 3 ) >> 1);
+            (uint8_t *) malloc((mWidth * mHeight * 3 ) >> 1);
         CHECK(mInputFrameData != NULL);
     }
 
     // PV's AVC encoder requires the video dimension of multiple
-    if (mVideoWidth % 16 != 0 || mVideoHeight % 16 != 0) {
+    if (mWidth % 16 != 0 || mHeight % 16 != 0) {
         ALOGE("Video frame size %dx%d must be a multiple of 16",
-            mVideoWidth, mVideoHeight);
+            mWidth, mHeight);
         return OMX_ErrorBadParameter;
     }
 
-    mEncParams->width = mVideoWidth;
-    mEncParams->height = mVideoHeight;
-    mEncParams->bitrate = mVideoBitRate;
-    mEncParams->frame_rate = 1000 * mVideoFrameRate;  // In frames/ms!
-    mEncParams->CPB_size = (uint32_t) (mVideoBitRate >> 1);
+    mEncParams->width = mWidth;
+    mEncParams->height = mHeight;
+    mEncParams->bitrate = mBitrate;
+    mEncParams->frame_rate = (1000 * mFramerate) >> 16;  // In frames/ms!, mFramerate is in Q16
+    mEncParams->CPB_size = (uint32_t) (mBitrate >> 1);
 
-    int32_t nMacroBlocks = ((((mVideoWidth + 15) >> 4) << 4) *
-            (((mVideoHeight + 15) >> 4) << 4)) >> 8;
+    int32_t nMacroBlocks = divUp(mWidth, 16) * divUp(mHeight, 16);
     CHECK(mSliceGroup == NULL);
     mSliceGroup = (uint32_t *) malloc(sizeof(uint32_t) * nMacroBlocks);
     CHECK(mSliceGroup != NULL);
@@ -272,7 +281,7 @@
         mEncParams->idr_period = 1;  // All I frames
     } else {
         mEncParams->idr_period =
-            (mIDRFrameRefreshIntervalInSec * mVideoFrameRate);
+            (mIDRFrameRefreshIntervalInSec * mFramerate) >> 16; // mFramerate is in Q16
     }
 
     // Set profile and level
@@ -345,71 +354,9 @@
     mOutputBuffers.clear();
 }
 
-void SoftAVCEncoder::initPorts() {
-    OMX_PARAM_PORTDEFINITIONTYPE def;
-    InitOMXParams(&def);
-
-    const size_t kInputBufferSize = (mVideoWidth * mVideoHeight * 3) >> 1;
-
-    // 31584 is PV's magic number.  Not sure why.
-    const size_t kOutputBufferSize =
-            (kInputBufferSize > 31584) ? kInputBufferSize: 31584;
-
-    def.nPortIndex = 0;
-    def.eDir = OMX_DirInput;
-    def.nBufferCountMin = kNumBuffers;
-    def.nBufferCountActual = def.nBufferCountMin;
-    def.nBufferSize = kInputBufferSize;
-    def.bEnabled = OMX_TRUE;
-    def.bPopulated = OMX_FALSE;
-    def.eDomain = OMX_PortDomainVideo;
-    def.bBuffersContiguous = OMX_FALSE;
-    def.nBufferAlignment = 1;
-
-    def.format.video.cMIMEType = const_cast<char *>("video/raw");
-    def.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
-    def.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar;
-    def.format.video.xFramerate = (mVideoFrameRate << 16);  // Q16 format
-    def.format.video.nBitrate = mVideoBitRate;
-    def.format.video.nFrameWidth = mVideoWidth;
-    def.format.video.nFrameHeight = mVideoHeight;
-    def.format.video.nStride = mVideoWidth;
-    def.format.video.nSliceHeight = mVideoHeight;
-
-    addPort(def);
-
-    def.nPortIndex = 1;
-    def.eDir = OMX_DirOutput;
-    def.nBufferCountMin = kNumBuffers;
-    def.nBufferCountActual = def.nBufferCountMin;
-    def.nBufferSize = kOutputBufferSize;
-    def.bEnabled = OMX_TRUE;
-    def.bPopulated = OMX_FALSE;
-    def.eDomain = OMX_PortDomainVideo;
-    def.bBuffersContiguous = OMX_FALSE;
-    def.nBufferAlignment = 2;
-
-    def.format.video.cMIMEType = const_cast<char *>("video/avc");
-    def.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC;
-    def.format.video.eColorFormat = OMX_COLOR_FormatUnused;
-    def.format.video.xFramerate = (0 << 16);  // Q16 format
-    def.format.video.nBitrate = mVideoBitRate;
-    def.format.video.nFrameWidth = mVideoWidth;
-    def.format.video.nFrameHeight = mVideoHeight;
-    def.format.video.nStride = mVideoWidth;
-    def.format.video.nSliceHeight = mVideoHeight;
-
-    addPort(def);
-}
-
 OMX_ERRORTYPE SoftAVCEncoder::internalGetParameter(
         OMX_INDEXTYPE index, OMX_PTR params) {
     switch (index) {
-        case OMX_IndexParamVideoErrorCorrection:
-        {
-            return OMX_ErrorNotImplemented;
-        }
-
         case OMX_IndexParamVideoBitrate:
         {
             OMX_VIDEO_PARAM_BITRATETYPE *bitRate =
@@ -420,37 +367,7 @@
             }
 
             bitRate->eControlRate = OMX_Video_ControlRateVariable;
-            bitRate->nTargetBitrate = mVideoBitRate;
-            return OMX_ErrorNone;
-        }
-
-        case OMX_IndexParamVideoPortFormat:
-        {
-            OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
-                (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
-
-            if (formatParams->nPortIndex > 1) {
-                return OMX_ErrorUndefined;
-            }
-
-            if (formatParams->nIndex > 2) {
-                return OMX_ErrorNoMore;
-            }
-
-            if (formatParams->nPortIndex == 0) {
-                formatParams->eCompressionFormat = OMX_VIDEO_CodingUnused;
-                if (formatParams->nIndex == 0) {
-                    formatParams->eColorFormat = OMX_COLOR_FormatYUV420Planar;
-                } else if (formatParams->nIndex == 1) {
-                    formatParams->eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
-                } else {
-                    formatParams->eColorFormat = OMX_COLOR_FormatAndroidOpaque;
-                }
-            } else {
-                formatParams->eCompressionFormat = OMX_VIDEO_CodingAVC;
-                formatParams->eColorFormat = OMX_COLOR_FormatUnused;
-            }
-
+            bitRate->nTargetBitrate = mBitrate;
             return OMX_ErrorNone;
         }
 
@@ -487,30 +404,8 @@
             return OMX_ErrorNone;
         }
 
-        case OMX_IndexParamVideoProfileLevelQuerySupported:
-        {
-            OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevel =
-                (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)params;
-
-            if (profileLevel->nPortIndex != 1) {
-                return OMX_ErrorUndefined;
-            }
-
-            const size_t size =
-                    sizeof(ConversionTable) / sizeof(ConversionTable[0]);
-
-            if (profileLevel->nProfileIndex >= size) {
-                return OMX_ErrorNoMore;
-            }
-
-            profileLevel->eProfile = OMX_VIDEO_AVCProfileBaseline;
-            profileLevel->eLevel = ConversionTable[profileLevel->nProfileIndex].omxLevel;
-
-            return OMX_ErrorNone;
-        }
-
         default:
-            return SimpleSoftOMXComponent::internalGetParameter(index, params);
+            return SoftVideoEncoderOMXComponent::internalGetParameter(index, params);
     }
 }
 
@@ -519,11 +414,6 @@
     int32_t indexFull = index;
 
     switch (indexFull) {
-        case OMX_IndexParamVideoErrorCorrection:
-        {
-            return OMX_ErrorNotImplemented;
-        }
-
         case OMX_IndexParamVideoBitrate:
         {
             OMX_VIDEO_PARAM_BITRATETYPE *bitRate =
@@ -534,109 +424,7 @@
                 return OMX_ErrorUndefined;
             }
 
-            mVideoBitRate = bitRate->nTargetBitrate;
-            return OMX_ErrorNone;
-        }
-
-        case OMX_IndexParamPortDefinition:
-        {
-            OMX_PARAM_PORTDEFINITIONTYPE *def =
-                (OMX_PARAM_PORTDEFINITIONTYPE *)params;
-            if (def->nPortIndex > 1) {
-                return OMX_ErrorUndefined;
-            }
-
-            if (def->nPortIndex == 0) {
-                if (def->format.video.eCompressionFormat != OMX_VIDEO_CodingUnused ||
-                    (def->format.video.eColorFormat != OMX_COLOR_FormatYUV420Planar &&
-                     def->format.video.eColorFormat != OMX_COLOR_FormatYUV420SemiPlanar &&
-                     def->format.video.eColorFormat != OMX_COLOR_FormatAndroidOpaque)) {
-                    return OMX_ErrorUndefined;
-                }
-            } else {
-                if (def->format.video.eCompressionFormat != OMX_VIDEO_CodingAVC ||
-                    (def->format.video.eColorFormat != OMX_COLOR_FormatUnused)) {
-                    return OMX_ErrorUndefined;
-                }
-            }
-
-            OMX_ERRORTYPE err = SimpleSoftOMXComponent::internalSetParameter(index, params);
-            if (OMX_ErrorNone != err) {
-                return err;
-            }
-
-            if (def->nPortIndex == 0) {
-                mVideoWidth = def->format.video.nFrameWidth;
-                mVideoHeight = def->format.video.nFrameHeight;
-                mVideoFrameRate = def->format.video.xFramerate >> 16;
-                mVideoColorFormat = def->format.video.eColorFormat;
-
-                OMX_PARAM_PORTDEFINITIONTYPE *portDef =
-                    &editPortInfo(0)->mDef;
-                portDef->format.video.nFrameWidth = mVideoWidth;
-                portDef->format.video.nFrameHeight = mVideoHeight;
-                portDef->format.video.nStride = portDef->format.video.nFrameWidth;
-                portDef->format.video.nSliceHeight = portDef->format.video.nFrameHeight;
-                portDef->format.video.xFramerate = def->format.video.xFramerate;
-                portDef->format.video.eColorFormat =
-                    (OMX_COLOR_FORMATTYPE) mVideoColorFormat;
-                portDef->nBufferSize =
-                    (portDef->format.video.nStride * portDef->format.video.nSliceHeight * 3) / 2;
-                portDef = &editPortInfo(1)->mDef;
-                portDef->format.video.nFrameWidth = mVideoWidth;
-                portDef->format.video.nFrameHeight = mVideoHeight;
-            } else {
-                mVideoBitRate = def->format.video.nBitrate;
-            }
-
-            return OMX_ErrorNone;
-        }
-
-        case OMX_IndexParamStandardComponentRole:
-        {
-            const OMX_PARAM_COMPONENTROLETYPE *roleParams =
-                (const OMX_PARAM_COMPONENTROLETYPE *)params;
-
-            if (strncmp((const char *)roleParams->cRole,
-                        "video_encoder.avc",
-                        OMX_MAX_STRINGNAME_SIZE - 1)) {
-                return OMX_ErrorUndefined;
-            }
-
-            return OMX_ErrorNone;
-        }
-
-        case OMX_IndexParamVideoPortFormat:
-        {
-            const OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
-                (const OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
-
-            if (formatParams->nPortIndex > 1) {
-                return OMX_ErrorUndefined;
-            }
-
-            if (formatParams->nIndex > 2) {
-                return OMX_ErrorNoMore;
-            }
-
-            if (formatParams->nPortIndex == 0) {
-                if (formatParams->eCompressionFormat != OMX_VIDEO_CodingUnused ||
-                    ((formatParams->nIndex == 0 &&
-                      formatParams->eColorFormat != OMX_COLOR_FormatYUV420Planar) ||
-                    (formatParams->nIndex == 1 &&
-                     formatParams->eColorFormat != OMX_COLOR_FormatYUV420SemiPlanar) ||
-                    (formatParams->nIndex == 2 &&
-                     formatParams->eColorFormat != OMX_COLOR_FormatAndroidOpaque) )) {
-                    return OMX_ErrorUndefined;
-                }
-                mVideoColorFormat = formatParams->eColorFormat;
-            } else {
-                if (formatParams->eCompressionFormat != OMX_VIDEO_CodingAVC ||
-                    formatParams->eColorFormat != OMX_COLOR_FormatUnused) {
-                    return OMX_ErrorUndefined;
-                }
-            }
-
+            mBitrate = bitRate->nTargetBitrate;
             return OMX_ErrorNone;
         }
 
@@ -673,29 +461,8 @@
             return OMX_ErrorNone;
         }
 
-        case kStoreMetaDataExtensionIndex:
-        {
-            StoreMetaDataInBuffersParams *storeParams =
-                    (StoreMetaDataInBuffersParams*)params;
-            if (storeParams->nPortIndex != 0) {
-                ALOGE("%s: StoreMetadataInBuffersParams.nPortIndex not zero!",
-                        __FUNCTION__);
-                return OMX_ErrorUndefined;
-            }
-
-            mStoreMetaDataInBuffers = storeParams->bStoreMetaData;
-            ALOGV("StoreMetaDataInBuffers set to: %s",
-                    mStoreMetaDataInBuffers ? " true" : "false");
-
-            if (mStoreMetaDataInBuffers) {
-                mVideoColorFormat = OMX_COLOR_FormatAndroidOpaque;
-            }
-
-            return OMX_ErrorNone;
-        }
-
         default:
-            return SimpleSoftOMXComponent::internalSetParameter(index, params);
+            return SoftVideoEncoderOMXComponent::internalSetParameter(index, params);
     }
 }
 
@@ -789,16 +556,16 @@
             if (inHeader->nFilledLen > 0) {
                 AVCFrameIO videoInput;
                 memset(&videoInput, 0, sizeof(videoInput));
-                videoInput.height = ((mVideoHeight  + 15) >> 4) << 4;
-                videoInput.pitch = ((mVideoWidth + 15) >> 4) << 4;
+                videoInput.height = align(mHeight, 16);
+                videoInput.pitch = align(mWidth, 16);
                 videoInput.coding_timestamp = (inHeader->nTimeStamp + 500) / 1000;  // in ms
                 const uint8_t *inputData = NULL;
-                if (mStoreMetaDataInBuffers) {
+                if (mInputDataIsMeta) {
                     inputData =
                         extractGraphicBuffer(
-                                mInputFrameData, (mVideoWidth * mVideoHeight * 3) >> 1,
+                                mInputFrameData, (mWidth * mHeight * 3) >> 1,
                                 inHeader->pBuffer + inHeader->nOffset, inHeader->nFilledLen,
-                                mVideoWidth, mVideoHeight);
+                                mWidth, mHeight);
                     if (inputData == NULL) {
                         ALOGE("Unable to extract gralloc buffer in metadata mode");
                         mSignalledError = true;
@@ -808,9 +575,9 @@
                     // TODO: Verify/convert pixel format enum
                 } else {
                     inputData = (const uint8_t *)inHeader->pBuffer + inHeader->nOffset;
-                    if (mVideoColorFormat != OMX_COLOR_FormatYUV420Planar) {
+                    if (mColorFormat != OMX_COLOR_FormatYUV420Planar) {
                         ConvertYUV420SemiPlanarToYUV420Planar(
-                            inputData, mInputFrameData, mVideoWidth, mVideoHeight);
+                            inputData, mInputFrameData, mWidth, mHeight);
                         inputData = mInputFrameData;
                     }
                 }
diff --git a/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.h b/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.h
index 3e6cd0a..81de109 100644
--- a/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.h
+++ b/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.h
@@ -66,12 +66,6 @@
         int32_t mFlags;
     } InputBufferInfo;
 
-    int32_t  mVideoWidth;
-    int32_t  mVideoHeight;
-    int32_t  mVideoFrameRate;
-    int32_t  mVideoBitRate;
-    int32_t  mVideoColorFormat;
-    bool     mStoreMetaDataInBuffers;
     int32_t  mIDRFrameRefreshIntervalInSec;
     AVCProfile mAVCEncProfile;
     AVCLevel   mAVCEncLevel;
@@ -92,7 +86,6 @@
     Vector<MediaBuffer *> mOutputBuffers;
     Vector<InputBufferInfo> mInputBufferInfoVec;
 
-    void initPorts();
     OMX_ERRORTYPE initEncParams();
     OMX_ERRORTYPE initEncoder();
     OMX_ERRORTYPE releaseEncoder();
diff --git a/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp b/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp
index f4cba54..cddd176 100644
--- a/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp
+++ b/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp
@@ -26,6 +26,7 @@
 #include "SoftHEVC.h"
 
 #include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AUtils.h>
 #include <media/stagefright/MediaDefs.h>
 #include <OMX_VideoExt.h>
 
@@ -75,8 +76,12 @@
       mNewWidth(mWidth),
       mNewHeight(mHeight),
       mChangingResolution(false) {
-    initPorts(kNumBuffers, INPUT_BUF_SIZE, kNumBuffers,
-            CODEC_MIME_TYPE);
+    const size_t kMinCompressionRatio = 4 /* compressionRatio (for Level 4+) */;
+    const size_t kMaxOutputBufferSize = 2048 * 2048 * 3 / 2;
+    // INPUT_BUF_SIZE is given by HEVC codec as minimum input size
+    initPorts(
+            kNumBuffers, max(kMaxOutputBufferSize / kMinCompressionRatio, (size_t)INPUT_BUF_SIZE),
+            kNumBuffers, CODEC_MIME_TYPE, kMinCompressionRatio);
     CHECK_EQ(initDecoder(), (status_t)OK);
 }
 
@@ -644,7 +649,7 @@
             // The decoder should be fixed so that |u4_error_code| instead of |status| returns
             // IHEVCD_UNSUPPORTED_DIMENSIONS.
             bool unsupportedDimensions =
-                ((IHEVCD_UNSUPPORTED_DIMENSIONS == status)
+                ((IHEVCD_UNSUPPORTED_DIMENSIONS == (IHEVCD_CXA_ERROR_CODES_T)status)
                     || (IHEVCD_UNSUPPORTED_DIMENSIONS == s_dec_op.u4_error_code));
             bool resChanged = (IVD_RES_CHANGED == (s_dec_op.u4_error_code & 0xFF));
 
diff --git a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
index 246069b..ede645c 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
@@ -21,6 +21,7 @@
 #include "SoftMPEG4.h"
 
 #include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AUtils.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/IOMX.h>
@@ -70,7 +71,7 @@
       mPvTime(0) {
     initPorts(
             kNumInputBuffers,
-            8192 /* inputBufferSize */,
+            352 * 288 * 3 / 2 /* minInputBufferSize */,
             kNumOutputBuffers,
             (mMode == MODE_MPEG4)
             ? MEDIA_MIMETYPE_VIDEO_MPEG4 : MEDIA_MIMETYPE_VIDEO_H263);
@@ -353,14 +354,14 @@
     }
 }
 
-void SoftMPEG4::updatePortDefinitions(bool updateCrop) {
-    SoftVideoDecoderOMXComponent::updatePortDefinitions(updateCrop);
+void SoftMPEG4::updatePortDefinitions(bool updateCrop, bool updateInputSize) {
+    SoftVideoDecoderOMXComponent::updatePortDefinitions(updateCrop, updateInputSize);
 
     /* We have to align our width and height - this should affect stride! */
     OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kOutputPortIndex)->mDef;
-    def->nBufferSize =
-        (((def->format.video.nFrameWidth + 15) & -16)
-            * ((def->format.video.nFrameHeight + 15) & -16) * 3) / 2;
+    def->format.video.nStride = align(def->format.video.nStride, 16);
+    def->format.video.nSliceHeight = align(def->format.video.nSliceHeight, 16);
+    def->nBufferSize = (def->format.video.nStride * def->format.video.nSliceHeight * 3) / 2;
 }
 
 }  // namespace android
diff --git a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.h b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.h
index 31577e2..4114e7d 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.h
+++ b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.h
@@ -66,7 +66,7 @@
 
     status_t initDecoder();
 
-    virtual void updatePortDefinitions(bool updateCrop = true);
+    virtual void updatePortDefinitions(bool updateCrop = true, bool updateInputSize = false);
     bool handlePortSettingsChange();
 
     DISALLOW_EVIL_CONSTRUCTORS(SoftMPEG4);
diff --git a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
index 1d0a2f0..8240f83 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
+++ b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
@@ -17,6 +17,7 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "SoftMPEG4Encoder"
 #include <utils/Log.h>
+#include <utils/misc.h>
 
 #include "mp4enc_api.h"
 #include "OMX_Video.h"
@@ -24,6 +25,7 @@
 #include <HardwareAPI.h>
 #include <MetadataBufferType.h>
 #include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AUtils.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MetaData.h>
@@ -46,19 +48,30 @@
     params->nVersion.s.nStep = 0;
 }
 
+static const CodecProfileLevel kMPEG4ProfileLevels[] = {
+    { OMX_VIDEO_MPEG4ProfileCore, OMX_VIDEO_MPEG4Level2 },
+};
+
+static const CodecProfileLevel kH263ProfileLevels[] = {
+    { OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level45 },
+};
+
 SoftMPEG4Encoder::SoftMPEG4Encoder(
             const char *name,
+            const char *componentRole,
+            OMX_VIDEO_CODINGTYPE codingType,
+            const char *mime,
+            const CodecProfileLevel *profileLevels,
+            size_t numProfileLevels,
             const OMX_CALLBACKTYPE *callbacks,
             OMX_PTR appData,
             OMX_COMPONENTTYPE **component)
-    : SoftVideoEncoderOMXComponent(name, callbacks, appData, component),
+    : SoftVideoEncoderOMXComponent(
+            name, componentRole, codingType,
+            profileLevels, numProfileLevels,
+            176 /* width */, 144 /* height */,
+            callbacks, appData, component),
       mEncodeMode(COMBINE_MODE_WITH_ERR_RES),
-      mVideoWidth(176),
-      mVideoHeight(144),
-      mVideoFrameRate(30),
-      mVideoBitRate(192000),
-      mVideoColorFormat(OMX_COLOR_FormatYUV420Planar),
-      mStoreMetaDataInBuffers(false),
       mIDRFrameRefreshIntervalInSec(1),
       mNumInputFrames(-1),
       mStarted(false),
@@ -68,13 +81,15 @@
       mEncParams(new tagvideoEncOptions),
       mInputFrameData(NULL) {
 
-   if (!strcmp(name, "OMX.google.h263.encoder")) {
+    if (codingType == OMX_VIDEO_CodingH263) {
         mEncodeMode = H263_MODE;
-    } else {
-        CHECK(!strcmp(name, "OMX.google.mpeg4.encoder"));
     }
 
-    initPorts();
+    // 256 * 1024 is a magic number for PV's encoder, not sure why
+    const size_t kOutputBufferSize = 256 * 1024;
+
+    initPorts(kNumBuffers, kNumBuffers, kOutputBufferSize, mime);
+
     ALOGI("Construct SoftMPEG4Encoder");
 }
 
@@ -98,9 +113,9 @@
         return OMX_ErrorUndefined;
     }
     mEncParams->encMode = mEncodeMode;
-    mEncParams->encWidth[0] = mVideoWidth;
-    mEncParams->encHeight[0] = mVideoHeight;
-    mEncParams->encFrameRate[0] = mVideoFrameRate;
+    mEncParams->encWidth[0] = mWidth;
+    mEncParams->encHeight[0] = mHeight;
+    mEncParams->encFrameRate[0] = mFramerate >> 16; // mFramerate is in Q16 format
     mEncParams->rcType = VBR_1;
     mEncParams->vbvDelay = 5.0f;
 
@@ -111,27 +126,26 @@
     mEncParams->rvlcEnable = PV_OFF;
     mEncParams->numLayers = 1;
     mEncParams->timeIncRes = 1000;
-    mEncParams->tickPerSrc = mEncParams->timeIncRes / mVideoFrameRate;
+    mEncParams->tickPerSrc = ((int64_t)mEncParams->timeIncRes << 16) / mFramerate;
 
-    mEncParams->bitRate[0] = mVideoBitRate;
+    mEncParams->bitRate[0] = mBitrate;
     mEncParams->iQuant[0] = 15;
     mEncParams->pQuant[0] = 12;
     mEncParams->quantType[0] = 0;
     mEncParams->noFrameSkipped = PV_OFF;
 
-    if (mVideoColorFormat != OMX_COLOR_FormatYUV420Planar
-            || mStoreMetaDataInBuffers) {
+    if (mColorFormat != OMX_COLOR_FormatYUV420Planar || mInputDataIsMeta) {
         // Color conversion is needed.
         free(mInputFrameData);
         mInputFrameData =
-            (uint8_t *) malloc((mVideoWidth * mVideoHeight * 3 ) >> 1);
+            (uint8_t *) malloc((mWidth * mHeight * 3 ) >> 1);
         CHECK(mInputFrameData != NULL);
     }
 
     // PV's MPEG4 encoder requires the video dimension of multiple
-    if (mVideoWidth % 16 != 0 || mVideoHeight % 16 != 0) {
+    if (mWidth % 16 != 0 || mHeight % 16 != 0) {
         ALOGE("Video frame size %dx%d must be a multiple of 16",
-            mVideoWidth, mVideoHeight);
+            mWidth, mHeight);
         return OMX_ErrorBadParameter;
     }
 
@@ -142,7 +156,7 @@
         mEncParams->intraPeriod = 1;  // All I frames
     } else {
         mEncParams->intraPeriod =
-            (mIDRFrameRefreshIntervalInSec * mVideoFrameRate);
+            (mIDRFrameRefreshIntervalInSec * mFramerate) >> 16;
     }
 
     mEncParams->numIntraMB = 0;
@@ -201,81 +215,9 @@
     return OMX_ErrorNone;
 }
 
-void SoftMPEG4Encoder::initPorts() {
-    OMX_PARAM_PORTDEFINITIONTYPE def;
-    InitOMXParams(&def);
-
-    const size_t kInputBufferSize = (mVideoWidth * mVideoHeight * 3) >> 1;
-
-    // 256 * 1024 is a magic number for PV's encoder, not sure why
-    const size_t kOutputBufferSize =
-        (kInputBufferSize > 256 * 1024)
-            ? kInputBufferSize: 256 * 1024;
-
-    def.nPortIndex = 0;
-    def.eDir = OMX_DirInput;
-    def.nBufferCountMin = kNumBuffers;
-    def.nBufferCountActual = def.nBufferCountMin;
-    def.nBufferSize = kInputBufferSize;
-    def.bEnabled = OMX_TRUE;
-    def.bPopulated = OMX_FALSE;
-    def.eDomain = OMX_PortDomainVideo;
-    def.bBuffersContiguous = OMX_FALSE;
-    def.nBufferAlignment = 1;
-
-    def.format.video.cMIMEType = const_cast<char *>("video/raw");
-
-    def.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
-    def.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar;
-    def.format.video.xFramerate = (mVideoFrameRate << 16);  // Q16 format
-    def.format.video.nBitrate = mVideoBitRate;
-    def.format.video.nFrameWidth = mVideoWidth;
-    def.format.video.nFrameHeight = mVideoHeight;
-    def.format.video.nStride = mVideoWidth;
-    def.format.video.nSliceHeight = mVideoHeight;
-
-    addPort(def);
-
-    def.nPortIndex = 1;
-    def.eDir = OMX_DirOutput;
-    def.nBufferCountMin = kNumBuffers;
-    def.nBufferCountActual = def.nBufferCountMin;
-    def.nBufferSize = kOutputBufferSize;
-    def.bEnabled = OMX_TRUE;
-    def.bPopulated = OMX_FALSE;
-    def.eDomain = OMX_PortDomainVideo;
-    def.bBuffersContiguous = OMX_FALSE;
-    def.nBufferAlignment = 2;
-
-    def.format.video.cMIMEType =
-        (mEncodeMode == COMBINE_MODE_WITH_ERR_RES)
-            ? const_cast<char *>(MEDIA_MIMETYPE_VIDEO_MPEG4)
-            : const_cast<char *>(MEDIA_MIMETYPE_VIDEO_H263);
-
-    def.format.video.eCompressionFormat =
-        (mEncodeMode == COMBINE_MODE_WITH_ERR_RES)
-            ? OMX_VIDEO_CodingMPEG4
-            : OMX_VIDEO_CodingH263;
-
-    def.format.video.eColorFormat = OMX_COLOR_FormatUnused;
-    def.format.video.xFramerate = (0 << 16);  // Q16 format
-    def.format.video.nBitrate = mVideoBitRate;
-    def.format.video.nFrameWidth = mVideoWidth;
-    def.format.video.nFrameHeight = mVideoHeight;
-    def.format.video.nStride = mVideoWidth;
-    def.format.video.nSliceHeight = mVideoHeight;
-
-    addPort(def);
-}
-
 OMX_ERRORTYPE SoftMPEG4Encoder::internalGetParameter(
         OMX_INDEXTYPE index, OMX_PTR params) {
     switch (index) {
-        case OMX_IndexParamVideoErrorCorrection:
-        {
-            return OMX_ErrorNotImplemented;
-        }
-
         case OMX_IndexParamVideoBitrate:
         {
             OMX_VIDEO_PARAM_BITRATETYPE *bitRate =
@@ -286,41 +228,7 @@
             }
 
             bitRate->eControlRate = OMX_Video_ControlRateVariable;
-            bitRate->nTargetBitrate = mVideoBitRate;
-            return OMX_ErrorNone;
-        }
-
-        case OMX_IndexParamVideoPortFormat:
-        {
-            OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
-                (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
-
-            if (formatParams->nPortIndex > 1) {
-                return OMX_ErrorUndefined;
-            }
-
-            if (formatParams->nIndex > 2) {
-                return OMX_ErrorNoMore;
-            }
-
-            if (formatParams->nPortIndex == 0) {
-                formatParams->eCompressionFormat = OMX_VIDEO_CodingUnused;
-                if (formatParams->nIndex == 0) {
-                    formatParams->eColorFormat = OMX_COLOR_FormatYUV420Planar;
-                } else if (formatParams->nIndex == 1) {
-                    formatParams->eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
-                } else {
-                    formatParams->eColorFormat = OMX_COLOR_FormatAndroidOpaque;
-                }
-            } else {
-                formatParams->eCompressionFormat =
-                    (mEncodeMode == COMBINE_MODE_WITH_ERR_RES)
-                        ? OMX_VIDEO_CodingMPEG4
-                        : OMX_VIDEO_CodingH263;
-
-                formatParams->eColorFormat = OMX_COLOR_FormatUnused;
-            }
-
+            bitRate->nTargetBitrate = mBitrate;
             return OMX_ErrorNone;
         }
 
@@ -369,32 +277,8 @@
             return OMX_ErrorNone;
         }
 
-        case OMX_IndexParamVideoProfileLevelQuerySupported:
-        {
-            OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevel =
-                (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)params;
-
-            if (profileLevel->nPortIndex != 1) {
-                return OMX_ErrorUndefined;
-            }
-
-            if (profileLevel->nProfileIndex > 0) {
-                return OMX_ErrorNoMore;
-            }
-
-            if (mEncodeMode == H263_MODE) {
-                profileLevel->eProfile = OMX_VIDEO_H263ProfileBaseline;
-                profileLevel->eLevel = OMX_VIDEO_H263Level45;
-            } else {
-                profileLevel->eProfile = OMX_VIDEO_MPEG4ProfileCore;
-                profileLevel->eLevel = OMX_VIDEO_MPEG4Level2;
-            }
-
-            return OMX_ErrorNone;
-        }
-
         default:
-            return SimpleSoftOMXComponent::internalGetParameter(index, params);
+            return SoftVideoEncoderOMXComponent::internalGetParameter(index, params);
     }
 }
 
@@ -403,11 +287,6 @@
     int32_t indexFull = index;
 
     switch (indexFull) {
-        case OMX_IndexParamVideoErrorCorrection:
-        {
-            return OMX_ErrorNotImplemented;
-        }
-
         case OMX_IndexParamVideoBitrate:
         {
             OMX_VIDEO_PARAM_BITRATETYPE *bitRate =
@@ -418,116 +297,7 @@
                 return OMX_ErrorUndefined;
             }
 
-            mVideoBitRate = bitRate->nTargetBitrate;
-            return OMX_ErrorNone;
-        }
-
-        case OMX_IndexParamPortDefinition:
-        {
-            OMX_PARAM_PORTDEFINITIONTYPE *def =
-                (OMX_PARAM_PORTDEFINITIONTYPE *)params;
-            if (def->nPortIndex > 1) {
-                return OMX_ErrorUndefined;
-            }
-
-            if (def->nPortIndex == 0) {
-                if (def->format.video.eCompressionFormat != OMX_VIDEO_CodingUnused ||
-                    (def->format.video.eColorFormat != OMX_COLOR_FormatYUV420Planar &&
-                     def->format.video.eColorFormat != OMX_COLOR_FormatYUV420SemiPlanar &&
-                     def->format.video.eColorFormat != OMX_COLOR_FormatAndroidOpaque)) {
-                    return OMX_ErrorUndefined;
-                }
-            } else {
-                if ((mEncodeMode == COMBINE_MODE_WITH_ERR_RES &&
-                        def->format.video.eCompressionFormat != OMX_VIDEO_CodingMPEG4) ||
-                    (mEncodeMode == H263_MODE &&
-                        def->format.video.eCompressionFormat != OMX_VIDEO_CodingH263) ||
-                    (def->format.video.eColorFormat != OMX_COLOR_FormatUnused)) {
-                    return OMX_ErrorUndefined;
-                }
-            }
-
-            OMX_ERRORTYPE err = SimpleSoftOMXComponent::internalSetParameter(index, params);
-            if (OMX_ErrorNone != err) {
-                return err;
-            }
-
-            if (def->nPortIndex == 0) {
-                mVideoWidth = def->format.video.nFrameWidth;
-                mVideoHeight = def->format.video.nFrameHeight;
-                mVideoFrameRate = def->format.video.xFramerate >> 16;
-                mVideoColorFormat = def->format.video.eColorFormat;
-
-                OMX_PARAM_PORTDEFINITIONTYPE *portDef =
-                    &editPortInfo(0)->mDef;
-                portDef->format.video.nFrameWidth = mVideoWidth;
-                portDef->format.video.nFrameHeight = mVideoHeight;
-                portDef->format.video.nStride = portDef->format.video.nFrameWidth;
-                portDef->format.video.nSliceHeight = portDef->format.video.nFrameHeight;
-                portDef->format.video.xFramerate = def->format.video.xFramerate;
-                portDef->format.video.eColorFormat =
-                    (OMX_COLOR_FORMATTYPE) mVideoColorFormat;
-                portDef->nBufferSize =
-                    (portDef->format.video.nStride * portDef->format.video.nSliceHeight * 3) / 2;
-                portDef = &editPortInfo(1)->mDef;
-                portDef->format.video.nFrameWidth = mVideoWidth;
-                portDef->format.video.nFrameHeight = mVideoHeight;
-            } else {
-                mVideoBitRate = def->format.video.nBitrate;
-            }
-
-            return OMX_ErrorNone;
-        }
-
-        case OMX_IndexParamStandardComponentRole:
-        {
-            const OMX_PARAM_COMPONENTROLETYPE *roleParams =
-                (const OMX_PARAM_COMPONENTROLETYPE *)params;
-
-            if (strncmp((const char *)roleParams->cRole,
-                        (mEncodeMode == H263_MODE)
-                            ? "video_encoder.h263": "video_encoder.mpeg4",
-                        OMX_MAX_STRINGNAME_SIZE - 1)) {
-                return OMX_ErrorUndefined;
-            }
-
-            return OMX_ErrorNone;
-        }
-
-        case OMX_IndexParamVideoPortFormat:
-        {
-            const OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
-                (const OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
-
-            if (formatParams->nPortIndex > 1) {
-                return OMX_ErrorUndefined;
-            }
-
-            if (formatParams->nIndex > 2) {
-                return OMX_ErrorNoMore;
-            }
-
-            if (formatParams->nPortIndex == 0) {
-                if (formatParams->eCompressionFormat != OMX_VIDEO_CodingUnused ||
-                    ((formatParams->nIndex == 0 &&
-                      formatParams->eColorFormat != OMX_COLOR_FormatYUV420Planar) ||
-                    (formatParams->nIndex == 1 &&
-                     formatParams->eColorFormat != OMX_COLOR_FormatYUV420SemiPlanar) ||
-                    (formatParams->nIndex == 2 &&
-                     formatParams->eColorFormat != OMX_COLOR_FormatAndroidOpaque) )) {
-                    return OMX_ErrorUndefined;
-                }
-                mVideoColorFormat = formatParams->eColorFormat;
-            } else {
-                if ((mEncodeMode == H263_MODE &&
-                        formatParams->eCompressionFormat != OMX_VIDEO_CodingH263) ||
-                    (mEncodeMode == COMBINE_MODE_WITH_ERR_RES &&
-                        formatParams->eCompressionFormat != OMX_VIDEO_CodingMPEG4) ||
-                    formatParams->eColorFormat != OMX_COLOR_FormatUnused) {
-                    return OMX_ErrorUndefined;
-                }
-            }
-
+            mBitrate = bitRate->nTargetBitrate;
             return OMX_ErrorNone;
         }
 
@@ -578,29 +348,8 @@
             return OMX_ErrorNone;
         }
 
-        case kStoreMetaDataExtensionIndex:
-        {
-            StoreMetaDataInBuffersParams *storeParams =
-                    (StoreMetaDataInBuffersParams*)params;
-            if (storeParams->nPortIndex != 0) {
-                ALOGE("%s: StoreMetadataInBuffersParams.nPortIndex not zero!",
-                        __FUNCTION__);
-                return OMX_ErrorUndefined;
-            }
-
-            mStoreMetaDataInBuffers = storeParams->bStoreMetaData;
-            ALOGV("StoreMetaDataInBuffers set to: %s",
-                    mStoreMetaDataInBuffers ? " true" : "false");
-
-            if (mStoreMetaDataInBuffers) {
-                mVideoColorFormat = OMX_COLOR_FormatAndroidOpaque;
-            }
-
-            return OMX_ErrorNone;
-        }
-
         default:
-            return SimpleSoftOMXComponent::internalSetParameter(index, params);
+            return SoftVideoEncoderOMXComponent::internalSetParameter(index, params);
     }
 }
 
@@ -663,12 +412,12 @@
 
         if (inHeader->nFilledLen > 0) {
             const uint8_t *inputData = NULL;
-            if (mStoreMetaDataInBuffers) {
+            if (mInputDataIsMeta) {
                 inputData =
                     extractGraphicBuffer(
-                            mInputFrameData, (mVideoWidth * mVideoHeight * 3) >> 1,
+                            mInputFrameData, (mWidth * mHeight * 3) >> 1,
                             inHeader->pBuffer + inHeader->nOffset, inHeader->nFilledLen,
-                            mVideoWidth, mVideoHeight);
+                            mWidth, mHeight);
                 if (inputData == NULL) {
                     ALOGE("Unable to extract gralloc buffer in metadata mode");
                     mSignalledError = true;
@@ -677,9 +426,9 @@
                 }
             } else {
                 inputData = (const uint8_t *)inHeader->pBuffer + inHeader->nOffset;
-                if (mVideoColorFormat != OMX_COLOR_FormatYUV420Planar) {
+                if (mColorFormat != OMX_COLOR_FormatYUV420Planar) {
                     ConvertYUV420SemiPlanarToYUV420Planar(
-                        inputData, mInputFrameData, mVideoWidth, mVideoHeight);
+                        inputData, mInputFrameData, mWidth, mHeight);
                     inputData = mInputFrameData;
                 }
             }
@@ -689,8 +438,8 @@
             VideoEncFrameIO vin, vout;
             memset(&vin, 0, sizeof(vin));
             memset(&vout, 0, sizeof(vout));
-            vin.height = ((mVideoHeight  + 15) >> 4) << 4;
-            vin.pitch = ((mVideoWidth + 15) >> 4) << 4;
+            vin.height = align(mHeight, 16);
+            vin.pitch = align(mWidth, 16);
             vin.timestamp = (inHeader->nTimeStamp + 500) / 1000;  // in ms
             vin.yChan = (uint8_t *)inputData;
             vin.uChan = vin.yChan + vin.height * vin.pitch;
@@ -738,5 +487,19 @@
 android::SoftOMXComponent *createSoftOMXComponent(
         const char *name, const OMX_CALLBACKTYPE *callbacks,
         OMX_PTR appData, OMX_COMPONENTTYPE **component) {
-    return new android::SoftMPEG4Encoder(name, callbacks, appData, component);
+    using namespace android;
+    if (!strcmp(name, "OMX.google.h263.encoder")) {
+        return new android::SoftMPEG4Encoder(
+                name, "video_encoder.h263", OMX_VIDEO_CodingH263, MEDIA_MIMETYPE_VIDEO_H263,
+                kH263ProfileLevels, NELEM(kH263ProfileLevels),
+                callbacks, appData, component);
+    } else if (!strcmp(name, "OMX.google.mpeg4.encoder")) {
+        return new android::SoftMPEG4Encoder(
+                name, "video_encoder.mpeg4", OMX_VIDEO_CodingMPEG4, MEDIA_MIMETYPE_VIDEO_MPEG4,
+                kMPEG4ProfileLevels, NELEM(kMPEG4ProfileLevels),
+                callbacks, appData, component);
+    } else {
+        CHECK(!"Unknown component");
+    }
+    return NULL;
 }
diff --git a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.h b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.h
index d706bb4..3389c37 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.h
+++ b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.h
@@ -25,9 +25,16 @@
 
 namespace android {
 
+struct CodecProfileLevel;
+
 struct SoftMPEG4Encoder : public SoftVideoEncoderOMXComponent {
     SoftMPEG4Encoder(
             const char *name,
+            const char *componentRole,
+            OMX_VIDEO_CODINGTYPE codingType,
+            const char *mime,
+            const CodecProfileLevel *profileLevels,
+            size_t numProfileLevels,
             const OMX_CALLBACKTYPE *callbacks,
             OMX_PTR appData,
             OMX_COMPONENTTYPE **component);
@@ -56,12 +63,6 @@
     } InputBufferInfo;
 
     MP4EncodingMode mEncodeMode;
-    int32_t  mVideoWidth;
-    int32_t  mVideoHeight;
-    int32_t  mVideoFrameRate;
-    int32_t  mVideoBitRate;
-    int32_t  mVideoColorFormat;
-    bool     mStoreMetaDataInBuffers;
     int32_t  mIDRFrameRefreshIntervalInSec;
 
     int64_t  mNumInputFrames;
@@ -74,7 +75,6 @@
     uint8_t               *mInputFrameData;
     Vector<InputBufferInfo> mInputBufferInfoVec;
 
-    void initPorts();
     OMX_ERRORTYPE initEncParams();
     OMX_ERRORTYPE initEncoder();
     OMX_ERRORTYPE releaseEncoder();
diff --git a/media/libstagefright/codecs/on2/dec/SoftVPX.cpp b/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
index 87d6961..8a95643 100644
--- a/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
+++ b/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
@@ -40,10 +40,13 @@
       mMode(codingType == OMX_VIDEO_CodingVP8 ? MODE_VP8 : MODE_VP9),
       mCtx(NULL),
       mImg(NULL) {
-    initPorts(kNumBuffers, 768 * 1024 /* inputBufferSize */,
-            kNumBuffers,
-            codingType == OMX_VIDEO_CodingVP8 ? MEDIA_MIMETYPE_VIDEO_VP8 : MEDIA_MIMETYPE_VIDEO_VP9);
-
+    // arbitrary from avc/hevc as vpx does not specify a min compression ratio
+    const size_t kMinCompressionRatio = mMode == MODE_VP8 ? 2 : 4;
+    const char *mime = mMode == MODE_VP8 ? MEDIA_MIMETYPE_VIDEO_VP8 : MEDIA_MIMETYPE_VIDEO_VP9;
+    const size_t kMaxOutputBufferSize = 2048 * 2048 * 3 / 2;
+    initPorts(
+            kNumBuffers, kMaxOutputBufferSize / kMinCompressionRatio /* inputBufferSize */,
+            kNumBuffers, mime, kMinCompressionRatio);
     CHECK_EQ(initDecoder(), (status_t)OK);
 }
 
diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
index 0285feb..970acf3 100644
--- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
+++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
@@ -19,6 +19,7 @@
 #include "SoftVPXEncoder.h"
 
 #include <utils/Log.h>
+#include <utils/misc.h>
 
 #include <media/hardware/HardwareAPI.h>
 #include <media/hardware/MetadataBufferType.h>
@@ -50,23 +51,29 @@
     return cpuCoreCount;
 }
 
+static const CodecProfileLevel kProfileLevels[] = {
+    { OMX_VIDEO_VP8ProfileMain, OMX_VIDEO_VP8Level_Version0 },
+    { OMX_VIDEO_VP8ProfileMain, OMX_VIDEO_VP8Level_Version1 },
+    { OMX_VIDEO_VP8ProfileMain, OMX_VIDEO_VP8Level_Version2 },
+    { OMX_VIDEO_VP8ProfileMain, OMX_VIDEO_VP8Level_Version3 },
+};
+
 SoftVPXEncoder::SoftVPXEncoder(const char *name,
                                const OMX_CALLBACKTYPE *callbacks,
                                OMX_PTR appData,
                                OMX_COMPONENTTYPE **component)
-    : SoftVideoEncoderOMXComponent(name, callbacks, appData, component),
+    : SoftVideoEncoderOMXComponent(
+            name, "video_encoder.vp8", OMX_VIDEO_CodingVP8,
+            kProfileLevels, NELEM(kProfileLevels),
+            176 /* width */, 144 /* height */,
+            callbacks, appData, component),
       mCodecContext(NULL),
       mCodecConfiguration(NULL),
       mCodecInterface(NULL),
-      mWidth(176),
-      mHeight(144),
-      mBitrate(192000),  // in bps
-      mFramerate(30 << 16), // in Q16 format
       mBitrateUpdated(false),
       mBitrateControlMode(VPX_VBR),  // variable bitrate
       mDCTPartitions(0),
       mErrorResilience(OMX_FALSE),
-      mColorFormat(OMX_COLOR_FormatYUV420Planar),
       mLevel(OMX_VIDEO_VP8Level_Version0),
       mKeyFrameInterval(0),
       mMinQuantizer(0),
@@ -77,11 +84,15 @@
       mTemporalPatternIdx(0),
       mLastTimestamp(0x7FFFFFFFFFFFFFFFLL),
       mConversionBuffer(NULL),
-      mInputDataIsMeta(false),
       mKeyFrameRequested(false) {
     memset(mTemporalLayerBitrateRatio, 0, sizeof(mTemporalLayerBitrateRatio));
     mTemporalLayerBitrateRatio[0] = 100;
-    initPorts();
+
+    const size_t kMinOutputBufferSize = 1024 * 1024; // arbitrary
+
+    initPorts(
+            kNumBuffers, kNumBuffers, kMinOutputBufferSize,
+            MEDIA_MIMETYPE_VIDEO_VP8, 2 /* minCompressionRatio */);
 }
 
 
@@ -89,71 +100,6 @@
     releaseEncoder();
 }
 
-
-void SoftVPXEncoder::initPorts() {
-    OMX_PARAM_PORTDEFINITIONTYPE inputPort;
-    OMX_PARAM_PORTDEFINITIONTYPE outputPort;
-
-    InitOMXParams(&inputPort);
-    InitOMXParams(&outputPort);
-
-    inputPort.nBufferCountMin = kNumBuffers;
-    inputPort.nBufferCountActual = inputPort.nBufferCountMin;
-    inputPort.bEnabled = OMX_TRUE;
-    inputPort.bPopulated = OMX_FALSE;
-    inputPort.eDomain = OMX_PortDomainVideo;
-    inputPort.bBuffersContiguous = OMX_FALSE;
-    inputPort.format.video.pNativeRender = NULL;
-    inputPort.format.video.nFrameWidth = mWidth;
-    inputPort.format.video.nFrameHeight = mHeight;
-    inputPort.format.video.nStride = inputPort.format.video.nFrameWidth;
-    inputPort.format.video.nSliceHeight = inputPort.format.video.nFrameHeight;
-    inputPort.format.video.nBitrate = 0;
-    // frameRate is in Q16 format.
-    inputPort.format.video.xFramerate = mFramerate;
-    inputPort.format.video.bFlagErrorConcealment = OMX_FALSE;
-    inputPort.nPortIndex = kInputPortIndex;
-    inputPort.eDir = OMX_DirInput;
-    inputPort.nBufferAlignment = kInputBufferAlignment;
-    inputPort.format.video.cMIMEType =
-        const_cast<char *>(MEDIA_MIMETYPE_VIDEO_RAW);
-    inputPort.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
-    inputPort.format.video.eColorFormat = mColorFormat;
-    inputPort.format.video.pNativeWindow = NULL;
-    inputPort.nBufferSize =
-        (inputPort.format.video.nStride *
-        inputPort.format.video.nSliceHeight * 3) / 2;
-
-    addPort(inputPort);
-
-    outputPort.nBufferCountMin = kNumBuffers;
-    outputPort.nBufferCountActual = outputPort.nBufferCountMin;
-    outputPort.bEnabled = OMX_TRUE;
-    outputPort.bPopulated = OMX_FALSE;
-    outputPort.eDomain = OMX_PortDomainVideo;
-    outputPort.bBuffersContiguous = OMX_FALSE;
-    outputPort.format.video.pNativeRender = NULL;
-    outputPort.format.video.nFrameWidth = mWidth;
-    outputPort.format.video.nFrameHeight = mHeight;
-    outputPort.format.video.nStride = outputPort.format.video.nFrameWidth;
-    outputPort.format.video.nSliceHeight = outputPort.format.video.nFrameHeight;
-    outputPort.format.video.nBitrate = mBitrate;
-    outputPort.format.video.xFramerate = 0;
-    outputPort.format.video.bFlagErrorConcealment = OMX_FALSE;
-    outputPort.nPortIndex = kOutputPortIndex;
-    outputPort.eDir = OMX_DirOutput;
-    outputPort.nBufferAlignment = kOutputBufferAlignment;
-    outputPort.format.video.cMIMEType =
-        const_cast<char *>(MEDIA_MIMETYPE_VIDEO_VP8);
-    outputPort.format.video.eCompressionFormat = OMX_VIDEO_CodingVP8;
-    outputPort.format.video.eColorFormat = OMX_COLOR_FormatUnused;
-    outputPort.format.video.pNativeWindow = NULL;
-    outputPort.nBufferSize = 1024 * 1024; // arbitrary
-
-    addPort(outputPort);
-}
-
-
 status_t SoftVPXEncoder::initEncoder() {
     vpx_codec_err_t codec_return;
 
@@ -409,38 +355,6 @@
     const int32_t indexFull = index;
 
     switch (indexFull) {
-        case OMX_IndexParamVideoPortFormat: {
-            OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
-                (OMX_VIDEO_PARAM_PORTFORMATTYPE *)param;
-
-            if (formatParams->nPortIndex == kInputPortIndex) {
-                if (formatParams->nIndex >= kNumberOfSupportedColorFormats) {
-                    return OMX_ErrorNoMore;
-                }
-
-                // Color formats, in order of preference
-                if (formatParams->nIndex == 0) {
-                    formatParams->eColorFormat = OMX_COLOR_FormatYUV420Planar;
-                } else if (formatParams->nIndex == 1) {
-                    formatParams->eColorFormat =
-                        OMX_COLOR_FormatYUV420SemiPlanar;
-                } else {
-                    formatParams->eColorFormat = OMX_COLOR_FormatAndroidOpaque;
-                }
-
-                formatParams->eCompressionFormat = OMX_VIDEO_CodingUnused;
-                formatParams->xFramerate = mFramerate;
-                return OMX_ErrorNone;
-            } else if (formatParams->nPortIndex == kOutputPortIndex) {
-                formatParams->eCompressionFormat = OMX_VIDEO_CodingVP8;
-                formatParams->eColorFormat = OMX_COLOR_FormatUnused;
-                formatParams->xFramerate = 0;
-                return OMX_ErrorNone;
-            } else {
-                return OMX_ErrorBadPortIndex;
-            }
-        }
-
         case OMX_IndexParamVideoBitrate: {
             OMX_VIDEO_PARAM_BITRATETYPE *bitrate =
                 (OMX_VIDEO_PARAM_BITRATETYPE *)param;
@@ -495,54 +409,8 @@
                 return OMX_ErrorNone;
         }
 
-        case OMX_IndexParamVideoProfileLevelQuerySupported: {
-            OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileAndLevel =
-                (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)param;
-
-            if (profileAndLevel->nPortIndex != kOutputPortIndex) {
-                return OMX_ErrorUnsupportedIndex;
-            }
-
-            switch (profileAndLevel->nProfileIndex) {
-                case 0:
-                    profileAndLevel->eLevel = OMX_VIDEO_VP8Level_Version0;
-                    break;
-
-                case 1:
-                    profileAndLevel->eLevel = OMX_VIDEO_VP8Level_Version1;
-                    break;
-
-                case 2:
-                    profileAndLevel->eLevel = OMX_VIDEO_VP8Level_Version2;
-                    break;
-
-                case 3:
-                    profileAndLevel->eLevel = OMX_VIDEO_VP8Level_Version3;
-                    break;
-
-                default:
-                    return OMX_ErrorNoMore;
-            }
-
-            profileAndLevel->eProfile = OMX_VIDEO_VP8ProfileMain;
-            return OMX_ErrorNone;
-        }
-
-        case OMX_IndexParamVideoProfileLevelCurrent: {
-            OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileAndLevel =
-                (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)param;
-
-            if (profileAndLevel->nPortIndex != kOutputPortIndex) {
-                return OMX_ErrorUnsupportedIndex;
-            }
-
-            profileAndLevel->eLevel = mLevel;
-            profileAndLevel->eProfile = OMX_VIDEO_VP8ProfileMain;
-            return OMX_ErrorNone;
-        }
-
         default:
-            return SimpleSoftOMXComponent::internalGetParameter(index, param);
+            return SoftVideoEncoderOMXComponent::internalGetParameter(index, param);
     }
 }
 
@@ -553,30 +421,10 @@
     const int32_t indexFull = index;
 
     switch (indexFull) {
-        case OMX_IndexParamStandardComponentRole:
-            return internalSetRoleParams(
-                (const OMX_PARAM_COMPONENTROLETYPE *)param);
-
         case OMX_IndexParamVideoBitrate:
             return internalSetBitrateParams(
                 (const OMX_VIDEO_PARAM_BITRATETYPE *)param);
 
-        case OMX_IndexParamPortDefinition:
-        {
-            OMX_ERRORTYPE err = internalSetPortParams(
-                (const OMX_PARAM_PORTDEFINITIONTYPE *)param);
-
-            if (err != OMX_ErrorNone) {
-                return err;
-            }
-
-            return SimpleSoftOMXComponent::internalSetParameter(index, param);
-        }
-
-        case OMX_IndexParamVideoPortFormat:
-            return internalSetFormatParams(
-                (const OMX_VIDEO_PARAM_PORTFORMATTYPE *)param);
-
         case OMX_IndexParamVideoVp8:
             return internalSetVp8Params(
                 (const OMX_VIDEO_PARAM_VP8TYPE *)param);
@@ -585,27 +433,8 @@
             return internalSetAndroidVp8Params(
                 (const OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *)param);
 
-        case OMX_IndexParamVideoProfileLevelCurrent:
-            return internalSetProfileLevel(
-                (const OMX_VIDEO_PARAM_PROFILELEVELTYPE *)param);
-
-        case kStoreMetaDataExtensionIndex:
-        {
-            // storeMetaDataInBuffers
-            const StoreMetaDataInBuffersParams *storeParam =
-                (const StoreMetaDataInBuffersParams *)param;
-
-            if (storeParam->nPortIndex != kInputPortIndex) {
-                return OMX_ErrorBadPortIndex;
-            }
-
-            mInputDataIsMeta = (storeParam->bStoreMetaData == OMX_TRUE);
-
-            return OMX_ErrorNone;
-        }
-
         default:
-            return SimpleSoftOMXComponent::internalSetParameter(index, param);
+            return SoftVideoEncoderOMXComponent::internalSetParameter(index, param);
     }
 }
 
@@ -646,29 +475,6 @@
     }
 }
 
-OMX_ERRORTYPE SoftVPXEncoder::internalSetProfileLevel(
-        const OMX_VIDEO_PARAM_PROFILELEVELTYPE* profileAndLevel) {
-    if (profileAndLevel->nPortIndex != kOutputPortIndex) {
-        return OMX_ErrorUnsupportedIndex;
-    }
-
-    if (profileAndLevel->eProfile != OMX_VIDEO_VP8ProfileMain) {
-        return OMX_ErrorBadParameter;
-    }
-
-    if (profileAndLevel->eLevel == OMX_VIDEO_VP8Level_Version0 ||
-        profileAndLevel->eLevel == OMX_VIDEO_VP8Level_Version1 ||
-        profileAndLevel->eLevel == OMX_VIDEO_VP8Level_Version2 ||
-        profileAndLevel->eLevel == OMX_VIDEO_VP8Level_Version3) {
-        mLevel = (OMX_VIDEO_VP8LEVELTYPE)profileAndLevel->eLevel;
-    } else {
-        return OMX_ErrorBadParameter;
-    }
-
-    return OMX_ErrorNone;
-}
-
-
 OMX_ERRORTYPE SoftVPXEncoder::internalSetVp8Params(
         const OMX_VIDEO_PARAM_VP8TYPE* vp8Params) {
     if (vp8Params->nPortIndex != kOutputPortIndex) {
@@ -743,95 +549,6 @@
     return OMX_ErrorNone;
 }
 
-OMX_ERRORTYPE SoftVPXEncoder::internalSetFormatParams(
-        const OMX_VIDEO_PARAM_PORTFORMATTYPE* format) {
-    if (format->nPortIndex == kInputPortIndex) {
-        if (format->eColorFormat == OMX_COLOR_FormatYUV420Planar ||
-            format->eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar ||
-            format->eColorFormat == OMX_COLOR_FormatAndroidOpaque) {
-            mColorFormat = format->eColorFormat;
-
-            OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kInputPortIndex)->mDef;
-            def->format.video.eColorFormat = mColorFormat;
-
-            return OMX_ErrorNone;
-        } else {
-            ALOGE("Unsupported color format %i", format->eColorFormat);
-            return OMX_ErrorUnsupportedSetting;
-        }
-    } else if (format->nPortIndex == kOutputPortIndex) {
-        if (format->eCompressionFormat == OMX_VIDEO_CodingVP8) {
-            return OMX_ErrorNone;
-        } else {
-            return OMX_ErrorUnsupportedSetting;
-        }
-    } else {
-        return OMX_ErrorBadPortIndex;
-    }
-}
-
-
-OMX_ERRORTYPE SoftVPXEncoder::internalSetRoleParams(
-        const OMX_PARAM_COMPONENTROLETYPE* role) {
-    const char* roleText = (const char*)role->cRole;
-    const size_t roleTextMaxSize = OMX_MAX_STRINGNAME_SIZE - 1;
-
-    if (strncmp(roleText, "video_encoder.vp8", roleTextMaxSize)) {
-        ALOGE("Unsupported component role");
-        return OMX_ErrorBadParameter;
-    }
-
-    return OMX_ErrorNone;
-}
-
-
-OMX_ERRORTYPE SoftVPXEncoder::internalSetPortParams(
-        const OMX_PARAM_PORTDEFINITIONTYPE* port) {
-    if (port->nPortIndex == kInputPortIndex) {
-        mWidth = port->format.video.nFrameWidth;
-        mHeight = port->format.video.nFrameHeight;
-
-        // xFramerate comes in Q16 format, in frames per second unit
-        mFramerate = port->format.video.xFramerate;
-
-        if (port->format.video.eColorFormat == OMX_COLOR_FormatYUV420Planar ||
-            port->format.video.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar ||
-            port->format.video.eColorFormat == OMX_COLOR_FormatAndroidOpaque) {
-            mColorFormat = port->format.video.eColorFormat;
-        } else {
-            return OMX_ErrorUnsupportedSetting;
-        }
-
-        OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kInputPortIndex)->mDef;
-        def->format.video.nFrameWidth = mWidth;
-        def->format.video.nFrameHeight = mHeight;
-        def->format.video.nStride = def->format.video.nFrameWidth;
-        def->format.video.nSliceHeight = def->format.video.nFrameHeight;
-        def->format.video.xFramerate = mFramerate;
-        def->format.video.eColorFormat = mColorFormat;
-        def->nBufferSize =
-            (def->format.video.nStride * def->format.video.nSliceHeight * 3) / 2;
-        def = &editPortInfo(kOutputPortIndex)->mDef;
-        def->format.video.nFrameWidth = mWidth;
-        def->format.video.nFrameHeight = mHeight;
-
-        return OMX_ErrorNone;
-    } else if (port->nPortIndex == kOutputPortIndex) {
-        mBitrate = port->format.video.nBitrate;
-        mWidth = port->format.video.nFrameWidth;
-        mHeight = port->format.video.nFrameHeight;
-
-        OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kOutputPortIndex)->mDef;
-        def->format.video.nFrameWidth = mWidth;
-        def->format.video.nFrameHeight = mHeight;
-        def->format.video.nBitrate = mBitrate;
-        return OMX_ErrorNone;
-    } else {
-        return OMX_ErrorBadPortIndex;
-    }
-}
-
-
 OMX_ERRORTYPE SoftVPXEncoder::internalSetBitrateParams(
         const OMX_VIDEO_PARAM_BITRATETYPE* bitrate) {
     if (bitrate->nPortIndex != kOutputPortIndex) {
@@ -920,7 +637,7 @@
     return flags;
 }
 
-void SoftVPXEncoder::onQueueFilled(OMX_U32 portIndex) {
+void SoftVPXEncoder::onQueueFilled(OMX_U32 /* portIndex */) {
     // Initialize encoder if not already
     if (mCodecContext == NULL) {
         if (OK != initEncoder()) {
diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h
index f4c1564..cd0a0cf 100644
--- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h
+++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h
@@ -155,18 +155,6 @@
     // that specifies algorithm interface (e.g. vp8)
     vpx_codec_iface_t* mCodecInterface;
 
-    // Width of the input frames
-    int32_t mWidth;
-
-    // Height of the input frames
-    int32_t mHeight;
-
-    // Target bitrate set for the encoder, in bits per second.
-    uint32_t mBitrate;
-
-    // Target framerate set for the encoder.
-    uint32_t mFramerate;
-
     // If a request for a change it bitrate has been received.
     bool mBitrateUpdated;
 
@@ -182,9 +170,6 @@
     // is enabled in encoder
     OMX_BOOL mErrorResilience;
 
-    // Color format for the input port
-    OMX_COLOR_FORMATTYPE mColorFormat;
-
     // Encoder profile corresponding to OMX level parameter
     //
     // The inconsistency in the naming is caused by
@@ -229,14 +214,8 @@
     // indeed YUV420SemiPlanar.
     uint8_t* mConversionBuffer;
 
-    bool mInputDataIsMeta;
-
     bool mKeyFrameRequested;
 
-    // Initializes input and output OMX ports with sensible
-    // default values.
-    void initPorts();
-
     // Initializes vpx encoder with available settings.
     status_t initEncoder();
 
@@ -250,23 +229,10 @@
     // Get current encode flags
     vpx_enc_frame_flags_t getEncodeFlags();
 
-    // Handles port changes with respect to color formats
-    OMX_ERRORTYPE internalSetFormatParams(
-        const OMX_VIDEO_PARAM_PORTFORMATTYPE* format);
-
-    // Verifies the component role tried to be set to this OMX component is
-    // strictly video_encoder.vp8
-    OMX_ERRORTYPE internalSetRoleParams(
-        const OMX_PARAM_COMPONENTROLETYPE* role);
-
     // Updates bitrate to reflect port settings.
     OMX_ERRORTYPE internalSetBitrateParams(
         const OMX_VIDEO_PARAM_BITRATETYPE* bitrate);
 
-    // Handles port definition changes.
-    OMX_ERRORTYPE internalSetPortParams(
-        const OMX_PARAM_PORTDEFINITIONTYPE* port);
-
     // Handles vp8 specific parameters.
     OMX_ERRORTYPE internalSetVp8Params(
         const OMX_VIDEO_PARAM_VP8TYPE* vp8Params);
@@ -275,10 +241,6 @@
     OMX_ERRORTYPE internalSetAndroidVp8Params(
         const OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE* vp8AndroidParams);
 
-    // Updates encoder profile
-    OMX_ERRORTYPE internalSetProfileLevel(
-        const OMX_VIDEO_PARAM_PROFILELEVELTYPE* profileAndLevel);
-
     DISALLOW_EVIL_CONSTRUCTORS(SoftVPXEncoder);
 };
 
diff --git a/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp b/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp
index 168208f..6b8b395 100644
--- a/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp
+++ b/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp
@@ -64,9 +64,11 @@
       mHeadersDecoded(false),
       mEOSStatus(INPUT_DATA_AVAILABLE),
       mSignalledError(false) {
+    const size_t kMinCompressionRatio = 2;
+    const size_t kMaxOutputBufferSize = 2048 * 2048 * 3 / 2;
     initPorts(
-            kNumInputBuffers, 8192 /* inputBufferSize */,
-            kNumOutputBuffers, MEDIA_MIMETYPE_VIDEO_AVC);
+            kNumInputBuffers, kMaxOutputBufferSize / kMinCompressionRatio /* minInputBufferSize */,
+            kNumOutputBuffers, MEDIA_MIMETYPE_VIDEO_AVC, kMinCompressionRatio);
 
     CHECK_EQ(initDecoder(), (status_t)OK);
 }
diff --git a/media/libstagefright/data/media_codecs_google_video.xml b/media/libstagefright/data/media_codecs_google_video.xml
index 1cbef39..7e9fa18 100644
--- a/media/libstagefright/data/media_codecs_google_video.xml
+++ b/media/libstagefright/data/media_codecs_google_video.xml
@@ -73,7 +73,7 @@
     <Encoders>
         <MediaCodec name="OMX.google.h263.encoder" type="video/3gpp">
             <!-- profiles and levels:  ProfileBaseline : Level45 -->
-            <Limit name="size" min="16x16" max="176x144" />
+            <Limit name="size" min="176x144" max="176x144" />
             <Limit name="alignment" value="16x16" />
             <Limit name="bitrate" range="1-128000" />
         </MediaCodec>
diff --git a/media/libstagefright/include/SoftVideoDecoderOMXComponent.h b/media/libstagefright/include/SoftVideoDecoderOMXComponent.h
index 9e97ebd..4529007 100644
--- a/media/libstagefright/include/SoftVideoDecoderOMXComponent.h
+++ b/media/libstagefright/include/SoftVideoDecoderOMXComponent.h
@@ -61,9 +61,10 @@
     void initPorts(OMX_U32 numInputBuffers,
             OMX_U32 inputBufferSize,
             OMX_U32 numOutputBuffers,
-            const char *mimeType);
+            const char *mimeType,
+            OMX_U32 minCompressionRatio = 1u);
 
-    virtual void updatePortDefinitions(bool updateCrop = true);
+    virtual void updatePortDefinitions(bool updateCrop = true, bool updateInputSize = false);
 
     uint32_t outputBufferWidth();
     uint32_t outputBufferHeight();
@@ -99,6 +100,9 @@
     } mOutputPortSettingsChange;
 
 private:
+    uint32_t mMinInputBufferSize;
+    uint32_t mMinCompressionRatio;
+
     const char *mComponentRole;
     OMX_VIDEO_CODINGTYPE mCodingType;
     const CodecProfileLevel *mProfileLevels;
diff --git a/media/libstagefright/include/SoftVideoEncoderOMXComponent.h b/media/libstagefright/include/SoftVideoEncoderOMXComponent.h
index b3b810d..b43635d 100644
--- a/media/libstagefright/include/SoftVideoEncoderOMXComponent.h
+++ b/media/libstagefright/include/SoftVideoEncoderOMXComponent.h
@@ -18,6 +18,8 @@
 
 #define SOFT_VIDEO_ENCODER_OMX_COMPONENT_H_
 
+#include <media/IOMX.h>
+
 #include "SimpleSoftOMXComponent.h"
 #include <system/window.h>
 
@@ -28,11 +30,26 @@
 struct SoftVideoEncoderOMXComponent : public SimpleSoftOMXComponent {
     SoftVideoEncoderOMXComponent(
             const char *name,
+            const char *componentRole,
+            OMX_VIDEO_CODINGTYPE codingType,
+            const CodecProfileLevel *profileLevels,
+            size_t numProfileLevels,
+            int32_t width,
+            int32_t height,
             const OMX_CALLBACKTYPE *callbacks,
             OMX_PTR appData,
             OMX_COMPONENTTYPE **component);
 
+    virtual OMX_ERRORTYPE internalSetParameter(OMX_INDEXTYPE index, const OMX_PTR param);
+    virtual OMX_ERRORTYPE internalGetParameter(OMX_INDEXTYPE index, OMX_PTR params);
+
 protected:
+    void initPorts(
+            OMX_U32 numInputBuffers, OMX_U32 numOutputBuffers, OMX_U32 outputBufferSize,
+            const char *mime, OMX_U32 minCompressionRatio = 1);
+
+    static void setRawVideoSize(OMX_PARAM_PORTDEFINITIONTYPE *def);
+
     static void ConvertFlexYUVToPlanar(
             uint8_t *dst, size_t dstStride, size_t dstVStride,
             struct android_ycbcr *ycbcr, int32_t width, int32_t height);
@@ -56,9 +73,30 @@
         kOutputPortIndex = 1,
     };
 
+    bool mInputDataIsMeta;
+    int32_t mWidth;      // width of the input frames
+    int32_t mHeight;     // height of the input frames
+    uint32_t mBitrate;   // target bitrate set for the encoder, in bits per second
+    uint32_t mFramerate; // target framerate set for the encoder, in Q16 format
+    OMX_COLOR_FORMATTYPE mColorFormat;  // Color format for the input port
+
 private:
+    void updatePortParams();
+    OMX_ERRORTYPE internalSetPortParams(const OMX_PARAM_PORTDEFINITIONTYPE* port);
+
+    static const uint32_t kInputBufferAlignment = 1;
+    static const uint32_t kOutputBufferAlignment = 2;
+
     mutable const hw_module_t *mGrallocModule;
 
+    uint32_t mMinOutputBufferSize;
+    uint32_t mMinCompressionRatio;
+
+    const char *mComponentRole;
+    OMX_VIDEO_CODINGTYPE mCodingType;
+    const CodecProfileLevel *mProfileLevels;
+    size_t mNumProfileLevels;
+
     DISALLOW_EVIL_CONSTRUCTORS(SoftVideoEncoderOMXComponent);
 };
 
diff --git a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
index 2f83610..532cf2f 100644
--- a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
+++ b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
@@ -26,6 +26,7 @@
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALooper.h>
 #include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/AUtils.h>
 #include <media/stagefright/MediaDefs.h>
 
 namespace android {
@@ -61,6 +62,8 @@
         mCropWidth(width),
         mCropHeight(height),
         mOutputPortSettingsChange(NONE),
+        mMinInputBufferSize(384), // arbitrary, using one uncompressed macroblock
+        mMinCompressionRatio(1),  // max input size is normally the output size
         mComponentRole(componentRole),
         mCodingType(codingType),
         mProfileLevels(profileLevels),
@@ -71,7 +74,11 @@
         OMX_U32 numInputBuffers,
         OMX_U32 inputBufferSize,
         OMX_U32 numOutputBuffers,
-        const char *mimeType) {
+        const char *mimeType,
+        OMX_U32 minCompressionRatio) {
+    mMinInputBufferSize = inputBufferSize;
+    mMinCompressionRatio = minCompressionRatio;
+
     OMX_PARAM_PORTDEFINITIONTYPE def;
     InitOMXParams(&def);
 
@@ -120,27 +127,30 @@
 
     addPort(def);
 
-    updatePortDefinitions();
+    updatePortDefinitions(true /* updateCrop */, true /* updateInputSize */);
 }
 
-void SoftVideoDecoderOMXComponent::updatePortDefinitions(bool updateCrop) {
-    OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kInputPortIndex)->mDef;
-    def->format.video.nFrameWidth = mWidth;
-    def->format.video.nFrameHeight = mHeight;
-    def->format.video.nStride = def->format.video.nFrameWidth;
-    def->format.video.nSliceHeight = def->format.video.nFrameHeight;
+void SoftVideoDecoderOMXComponent::updatePortDefinitions(bool updateCrop, bool updateInputSize) {
+    OMX_PARAM_PORTDEFINITIONTYPE *outDef = &editPortInfo(kOutputPortIndex)->mDef;
+    outDef->format.video.nFrameWidth = outputBufferWidth();
+    outDef->format.video.nFrameHeight = outputBufferHeight();
+    outDef->format.video.nStride = outDef->format.video.nFrameWidth;
+    outDef->format.video.nSliceHeight = outDef->format.video.nFrameHeight;
 
-    def->nBufferSize = def->format.video.nFrameWidth * def->format.video.nFrameHeight * 3 / 2;
+    outDef->nBufferSize =
+        (outDef->format.video.nStride * outDef->format.video.nSliceHeight * 3) / 2;
 
-    def = &editPortInfo(kOutputPortIndex)->mDef;
-    def->format.video.nFrameWidth = outputBufferWidth();
-    def->format.video.nFrameHeight = outputBufferHeight();
-    def->format.video.nStride = def->format.video.nFrameWidth;
-    def->format.video.nSliceHeight = def->format.video.nFrameHeight;
+    OMX_PARAM_PORTDEFINITIONTYPE *inDef = &editPortInfo(kInputPortIndex)->mDef;
+    inDef->format.video.nFrameWidth = mWidth;
+    inDef->format.video.nFrameHeight = mHeight;
+    // input port is compressed, hence it has no stride
+    inDef->format.video.nStride = 0;
+    inDef->format.video.nSliceHeight = 0;
 
-    def->nBufferSize =
-            (def->format.video.nFrameWidth *
-             def->format.video.nFrameHeight * 3) / 2;
+    // when output format changes, input buffer size does not actually change
+    if (updateInputSize) {
+        inDef->nBufferSize = max(outDef->nBufferSize / mMinCompressionRatio, mMinInputBufferSize);
+    }
 
     if (updateCrop) {
         mCropLeft = 0;
@@ -169,7 +179,8 @@
     bool strideChanged = false;
     if (fakeStride) {
         OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kOutputPortIndex)->mDef;
-        if (def->format.video.nStride != width || def->format.video.nSliceHeight != height) {
+        if (def->format.video.nStride != (OMX_S32)width
+                || def->format.video.nSliceHeight != (OMX_U32)height) {
             strideChanged = true;
         }
     }
@@ -252,7 +263,7 @@
                 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
 
             if (formatParams->nPortIndex > kMaxPortIndex) {
-                return OMX_ErrorUndefined;
+                return OMX_ErrorBadPortIndex;
             }
 
             if (formatParams->nIndex != 0) {
@@ -324,13 +335,25 @@
                 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
 
             if (formatParams->nPortIndex > kMaxPortIndex) {
-                return OMX_ErrorUndefined;
+                return OMX_ErrorBadPortIndex;
             }
 
             if (formatParams->nIndex != 0) {
                 return OMX_ErrorNoMore;
             }
 
+            if (formatParams->nPortIndex == kInputPortIndex) {
+                if (formatParams->eCompressionFormat != mCodingType
+                        || formatParams->eColorFormat != OMX_COLOR_FormatUnused) {
+                    return OMX_ErrorUnsupportedSetting;
+                }
+            } else {
+                if (formatParams->eCompressionFormat != OMX_VIDEO_CodingUnused
+                        || formatParams->eColorFormat != OMX_COLOR_FormatYUV420Planar) {
+                    return OMX_ErrorUnsupportedSetting;
+                }
+            }
+
             return OMX_ErrorNone;
         }
 
@@ -348,7 +371,7 @@
                 mAdaptiveMaxWidth = 0;
                 mAdaptiveMaxHeight = 0;
             }
-            updatePortDefinitions();
+            updatePortDefinitions(true /* updateCrop */, true /* updateInputSize */);
             return OMX_ErrorNone;
         }
 
@@ -369,11 +392,18 @@
                     (mIsAdaptive && outputPort) ? mAdaptiveMaxWidth : newWidth;
                 def->format.video.nFrameHeight =
                     (mIsAdaptive && outputPort) ? mAdaptiveMaxHeight : newHeight;
-                def->format.video.nStride = def->format.video.nFrameWidth;
-                def->format.video.nSliceHeight = def->format.video.nFrameHeight;
-                def->nBufferSize =
-                    def->format.video.nFrameWidth * def->format.video.nFrameHeight * 3 / 2;
                 if (outputPort) {
+                    def->format.video.nStride = def->format.video.nFrameWidth;
+                    def->format.video.nSliceHeight = def->format.video.nFrameHeight;
+                    def->nBufferSize =
+                        def->format.video.nStride * def->format.video.nSliceHeight * 3 / 2;
+
+
+                    OMX_PARAM_PORTDEFINITIONTYPE *inDef = &editPortInfo(kInputPortIndex)->mDef;
+                    // increase input buffer size if required
+                    inDef->nBufferSize =
+                        max(def->nBufferSize / mMinCompressionRatio, inDef->nBufferSize);
+
                     mWidth = newWidth;
                     mHeight = newHeight;
                     mCropLeft = 0;
diff --git a/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp b/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
index 70ec6e4..d4d6217 100644
--- a/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
+++ b/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
@@ -19,6 +19,7 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "SoftVideoEncoderOMXComponent"
 #include <utils/Log.h>
+#include <utils/misc.h>
 
 #include "include/SoftVideoEncoderOMXComponent.h"
 
@@ -27,6 +28,7 @@
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALooper.h>
 #include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/AUtils.h>
 #include <media/stagefright/MediaDefs.h>
 
 #include <ui/GraphicBuffer.h>
@@ -34,13 +36,316 @@
 
 namespace android {
 
+const static OMX_COLOR_FORMATTYPE kSupportedColorFormats[] = {
+    OMX_COLOR_FormatYUV420Planar,
+    OMX_COLOR_FormatYUV420SemiPlanar,
+    OMX_COLOR_FormatAndroidOpaque
+};
+
+template<class T>
+static void InitOMXParams(T *params) {
+    params->nSize = sizeof(T);
+    params->nVersion.s.nVersionMajor = 1;
+    params->nVersion.s.nVersionMinor = 0;
+    params->nVersion.s.nRevision = 0;
+    params->nVersion.s.nStep = 0;
+}
+
 SoftVideoEncoderOMXComponent::SoftVideoEncoderOMXComponent(
         const char *name,
+        const char *componentRole,
+        OMX_VIDEO_CODINGTYPE codingType,
+        const CodecProfileLevel *profileLevels,
+        size_t numProfileLevels,
+        int32_t width,
+        int32_t height,
         const OMX_CALLBACKTYPE *callbacks,
         OMX_PTR appData,
         OMX_COMPONENTTYPE **component)
     : SimpleSoftOMXComponent(name, callbacks, appData, component),
-      mGrallocModule(NULL) {
+      mInputDataIsMeta(false),
+      mWidth(width),
+      mHeight(height),
+      mBitrate(192000),
+      mFramerate(30 << 16), // Q16 format
+      mColorFormat(OMX_COLOR_FormatYUV420Planar),
+      mGrallocModule(NULL),
+      mMinOutputBufferSize(384), // arbitrary, using one uncompressed macroblock
+      mMinCompressionRatio(1),   // max output size is normally the input size
+      mComponentRole(componentRole),
+      mCodingType(codingType),
+      mProfileLevels(profileLevels),
+      mNumProfileLevels(numProfileLevels) {
+}
+
+void SoftVideoEncoderOMXComponent::initPorts(
+        OMX_U32 numInputBuffers, OMX_U32 numOutputBuffers, OMX_U32 outputBufferSize,
+        const char *mime, OMX_U32 minCompressionRatio) {
+    OMX_PARAM_PORTDEFINITIONTYPE def;
+
+    mMinOutputBufferSize = outputBufferSize;
+    mMinCompressionRatio = minCompressionRatio;
+
+    InitOMXParams(&def);
+
+    def.nPortIndex = kInputPortIndex;
+    def.eDir = OMX_DirInput;
+    def.nBufferCountMin = numInputBuffers;
+    def.nBufferCountActual = def.nBufferCountMin;
+    def.bEnabled = OMX_TRUE;
+    def.bPopulated = OMX_FALSE;
+    def.eDomain = OMX_PortDomainVideo;
+    def.bBuffersContiguous = OMX_FALSE;
+    def.format.video.pNativeRender = NULL;
+    def.format.video.nFrameWidth = mWidth;
+    def.format.video.nFrameHeight = mHeight;
+    def.format.video.nStride = def.format.video.nFrameWidth;
+    def.format.video.nSliceHeight = def.format.video.nFrameHeight;
+    def.format.video.nBitrate = 0;
+    // frameRate is in Q16 format.
+    def.format.video.xFramerate = mFramerate;
+    def.format.video.bFlagErrorConcealment = OMX_FALSE;
+    def.nBufferAlignment = kInputBufferAlignment;
+    def.format.video.cMIMEType = const_cast<char *>("video/raw");
+    def.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
+    def.format.video.eColorFormat = mColorFormat;
+    def.format.video.pNativeWindow = NULL;
+    // buffersize set in updatePortParams
+
+    addPort(def);
+
+    InitOMXParams(&def);
+
+    def.nPortIndex = kOutputPortIndex;
+    def.eDir = OMX_DirOutput;
+    def.nBufferCountMin = numOutputBuffers;
+    def.nBufferCountActual = def.nBufferCountMin;
+    def.bEnabled = OMX_TRUE;
+    def.bPopulated = OMX_FALSE;
+    def.eDomain = OMX_PortDomainVideo;
+    def.bBuffersContiguous = OMX_FALSE;
+    def.format.video.pNativeRender = NULL;
+    def.format.video.nFrameWidth = mWidth;
+    def.format.video.nFrameHeight = mHeight;
+    def.format.video.nStride = 0;
+    def.format.video.nSliceHeight = 0;
+    def.format.video.nBitrate = mBitrate;
+    def.format.video.xFramerate = 0 << 16;
+    def.format.video.bFlagErrorConcealment = OMX_FALSE;
+    def.nBufferAlignment = kOutputBufferAlignment;
+    def.format.video.cMIMEType = const_cast<char *>(mime);
+    def.format.video.eCompressionFormat = mCodingType;
+    def.format.video.eColorFormat = OMX_COLOR_FormatUnused;
+    def.format.video.pNativeWindow = NULL;
+    // buffersize set in updatePortParams
+
+    addPort(def);
+
+    updatePortParams();
+}
+
+void SoftVideoEncoderOMXComponent::updatePortParams() {
+    OMX_PARAM_PORTDEFINITIONTYPE *inDef = &editPortInfo(kInputPortIndex)->mDef;
+    inDef->format.video.nFrameWidth = mWidth;
+    inDef->format.video.nFrameHeight = mHeight;
+    inDef->format.video.nStride = inDef->format.video.nFrameWidth;
+    inDef->format.video.nSliceHeight = inDef->format.video.nFrameHeight;
+    inDef->format.video.xFramerate = mFramerate;
+    inDef->format.video.eColorFormat = mColorFormat;
+    uint32_t rawBufferSize =
+        inDef->format.video.nStride * inDef->format.video.nSliceHeight * 3 / 2;
+    if (inDef->format.video.eColorFormat == OMX_COLOR_FormatAndroidOpaque) {
+        inDef->nBufferSize = 4 + max(sizeof(buffer_handle_t), sizeof(GraphicBuffer *));
+    } else {
+        inDef->nBufferSize = rawBufferSize;
+    }
+
+    OMX_PARAM_PORTDEFINITIONTYPE *outDef = &editPortInfo(kOutputPortIndex)->mDef;
+    outDef->format.video.nFrameWidth = mWidth;
+    outDef->format.video.nFrameHeight = mHeight;
+    outDef->format.video.nBitrate = mBitrate;
+
+    outDef->nBufferSize = max(mMinOutputBufferSize, rawBufferSize / mMinCompressionRatio);
+}
+
+OMX_ERRORTYPE SoftVideoEncoderOMXComponent::internalSetPortParams(
+        const OMX_PARAM_PORTDEFINITIONTYPE *port) {
+    if (port->nPortIndex == kInputPortIndex) {
+        mWidth = port->format.video.nFrameWidth;
+        mHeight = port->format.video.nFrameHeight;
+
+        // xFramerate comes in Q16 format, in frames per second unit
+        mFramerate = port->format.video.xFramerate;
+
+        if (port->format.video.eCompressionFormat != OMX_VIDEO_CodingUnused
+                || (port->format.video.eColorFormat != OMX_COLOR_FormatYUV420Planar
+                        && port->format.video.eColorFormat != OMX_COLOR_FormatYUV420SemiPlanar
+                        && port->format.video.eColorFormat != OMX_COLOR_FormatAndroidOpaque)) {
+            return OMX_ErrorUnsupportedSetting;
+        }
+
+        mColorFormat = port->format.video.eColorFormat;
+    } else if (port->nPortIndex == kOutputPortIndex) {
+        if (port->format.video.eCompressionFormat != mCodingType
+                || port->format.video.eColorFormat != OMX_COLOR_FormatUnused) {
+            return OMX_ErrorUnsupportedSetting;
+        }
+
+        mBitrate = port->format.video.nBitrate;
+    } else {
+        return OMX_ErrorBadPortIndex;
+    }
+
+    updatePortParams();
+    return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE SoftVideoEncoderOMXComponent::internalSetParameter(
+        OMX_INDEXTYPE index, const OMX_PTR param) {
+    // can include extension index OMX_INDEXEXTTYPE
+    const int32_t indexFull = index;
+
+    switch (indexFull) {
+        case OMX_IndexParamVideoErrorCorrection:
+        {
+            return OMX_ErrorNotImplemented;
+        }
+
+        case OMX_IndexParamStandardComponentRole:
+        {
+            const OMX_PARAM_COMPONENTROLETYPE *roleParams =
+                (const OMX_PARAM_COMPONENTROLETYPE *)param;
+
+            if (strncmp((const char *)roleParams->cRole,
+                        mComponentRole,
+                        OMX_MAX_STRINGNAME_SIZE - 1)) {
+                return OMX_ErrorUnsupportedSetting;
+            }
+
+            return OMX_ErrorNone;
+        }
+
+        case OMX_IndexParamPortDefinition:
+        {
+            OMX_ERRORTYPE err = internalSetPortParams((const OMX_PARAM_PORTDEFINITIONTYPE *)param);
+
+            if (err != OMX_ErrorNone) {
+                return err;
+            }
+
+            return SimpleSoftOMXComponent::internalSetParameter(index, param);
+        }
+
+        case OMX_IndexParamVideoPortFormat:
+        {
+            const OMX_VIDEO_PARAM_PORTFORMATTYPE* format =
+                (const OMX_VIDEO_PARAM_PORTFORMATTYPE *)param;
+
+            if (format->nPortIndex == kInputPortIndex) {
+                if (format->eColorFormat == OMX_COLOR_FormatYUV420Planar ||
+                    format->eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar ||
+                    format->eColorFormat == OMX_COLOR_FormatAndroidOpaque) {
+                    mColorFormat = format->eColorFormat;
+
+                    updatePortParams();
+                    return OMX_ErrorNone;
+                } else {
+                    ALOGE("Unsupported color format %i", format->eColorFormat);
+                    return OMX_ErrorUnsupportedSetting;
+                }
+            } else if (format->nPortIndex == kOutputPortIndex) {
+                if (format->eCompressionFormat == mCodingType) {
+                    return OMX_ErrorNone;
+                } else {
+                    return OMX_ErrorUnsupportedSetting;
+                }
+            } else {
+                return OMX_ErrorBadPortIndex;
+            }
+        }
+
+        case kStoreMetaDataExtensionIndex:
+        {
+            // storeMetaDataInBuffers
+            const StoreMetaDataInBuffersParams *storeParam =
+                (const StoreMetaDataInBuffersParams *)param;
+
+            if (storeParam->nPortIndex == kOutputPortIndex) {
+                return storeParam->bStoreMetaData ? OMX_ErrorUnsupportedSetting : OMX_ErrorNone;
+            } else if (storeParam->nPortIndex != kInputPortIndex) {
+                return OMX_ErrorBadPortIndex;
+            }
+
+            mInputDataIsMeta = (storeParam->bStoreMetaData == OMX_TRUE);
+            if (mInputDataIsMeta) {
+                mColorFormat = OMX_COLOR_FormatAndroidOpaque;
+            } else if (mColorFormat == OMX_COLOR_FormatAndroidOpaque) {
+                mColorFormat = OMX_COLOR_FormatYUV420Planar;
+            }
+            updatePortParams();
+            return OMX_ErrorNone;
+        }
+
+        default:
+            return SimpleSoftOMXComponent::internalSetParameter(index, param);
+    }
+}
+
+OMX_ERRORTYPE SoftVideoEncoderOMXComponent::internalGetParameter(
+        OMX_INDEXTYPE index, OMX_PTR param) {
+    switch (index) {
+        case OMX_IndexParamVideoErrorCorrection:
+        {
+            return OMX_ErrorNotImplemented;
+        }
+
+        case OMX_IndexParamVideoPortFormat:
+        {
+            OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
+                (OMX_VIDEO_PARAM_PORTFORMATTYPE *)param;
+
+            if (formatParams->nPortIndex == kInputPortIndex) {
+                if (formatParams->nIndex >= NELEM(kSupportedColorFormats)) {
+                    return OMX_ErrorNoMore;
+                }
+
+                // Color formats, in order of preference
+                formatParams->eColorFormat = kSupportedColorFormats[formatParams->nIndex];
+                formatParams->eCompressionFormat = OMX_VIDEO_CodingUnused;
+                formatParams->xFramerate = mFramerate;
+                return OMX_ErrorNone;
+            } else if (formatParams->nPortIndex == kOutputPortIndex) {
+                formatParams->eCompressionFormat = mCodingType;
+                formatParams->eColorFormat = OMX_COLOR_FormatUnused;
+                formatParams->xFramerate = 0;
+                return OMX_ErrorNone;
+            } else {
+                return OMX_ErrorBadPortIndex;
+            }
+        }
+
+        case OMX_IndexParamVideoProfileLevelQuerySupported:
+        {
+            OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevel =
+                  (OMX_VIDEO_PARAM_PROFILELEVELTYPE *) param;
+
+            if (profileLevel->nPortIndex != kOutputPortIndex) {
+                ALOGE("Invalid port index: %u", profileLevel->nPortIndex);
+                return OMX_ErrorUnsupportedIndex;
+            }
+
+            if (profileLevel->nProfileIndex >= mNumProfileLevels) {
+                return OMX_ErrorNoMore;
+            }
+
+            profileLevel->eProfile = mProfileLevels[profileLevel->nProfileIndex].mProfile;
+            profileLevel->eLevel   = mProfileLevels[profileLevel->nProfileIndex].mLevel;
+            return OMX_ErrorNone;
+        }
+
+        default:
+            return SimpleSoftOMXComponent::internalGetParameter(index, param);
+    }
 }
 
 // static
diff --git a/media/libstagefright/tests/Utils_test.cpp b/media/libstagefright/tests/Utils_test.cpp
index 43e0269..5c323c1 100644
--- a/media/libstagefright/tests/Utils_test.cpp
+++ b/media/libstagefright/tests/Utils_test.cpp
@@ -172,6 +172,13 @@
     ASSERT_EQ(divUp(12, 4), 3);
     ASSERT_EQ(divUp(13, 4), 4);
 
+    ASSERT_EQ(align(11, 4), 12);
+    ASSERT_EQ(align(12, 4), 12);
+    ASSERT_EQ(align(13, 4), 16);
+    ASSERT_EQ(align(11, 8), 16);
+    ASSERT_EQ(align(11, 2), 12);
+    ASSERT_EQ(align(11, 1), 11);
+
     ASSERT_EQ(abs(5L), 5L);
     ASSERT_EQ(abs(-25), 25);