Merge "Support VP8 encoder key frame interval and number of temporal layers configuration."
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 4aecb80..f11791c 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -36,6 +36,7 @@
 #include <media/hardware/HardwareAPI.h>
 
 #include <OMX_AudioExt.h>
+#include <OMX_VideoExt.h>
 #include <OMX_Component.h>
 #include <OMX_IndexExt.h>
 
@@ -2370,12 +2371,81 @@
 
 status_t ACodec::setupVPXEncoderParameters(const sp<AMessage> &msg) {
     int32_t bitrate;
+    int32_t iFrameInterval = 0;
+    size_t tsLayers = 0;
+    OMX_VIDEO_ANDROID_VPXTEMPORALLAYERPATTERNTYPE pattern =
+        OMX_VIDEO_VPXTemporalLayerPatternNone;
+    static const uint32_t kVp8LayerRateAlloction
+        [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS]
+        [OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS] = {
+        {100, 100, 100},  // 1 layer
+        { 60, 100, 100},  // 2 layers {60%, 40%}
+        { 40,  60, 100},  // 3 layers {40%, 20%, 40%}
+    };
     if (!msg->findInt32("bitrate", &bitrate)) {
         return INVALID_OPERATION;
     }
+    msg->findInt32("i-frame-interval", &iFrameInterval);
 
     OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
 
+    float frameRate;
+    if (!msg->findFloat("frame-rate", &frameRate)) {
+        int32_t tmp;
+        if (!msg->findInt32("frame-rate", &tmp)) {
+            return INVALID_OPERATION;
+        }
+        frameRate = (float)tmp;
+    }
+
+    AString tsSchema;
+    if (msg->findString("ts-schema", &tsSchema)) {
+        if (tsSchema == "webrtc.vp8.1-layer") {
+            pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
+            tsLayers = 1;
+        } else if (tsSchema == "webrtc.vp8.2-layer") {
+            pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
+            tsLayers = 2;
+        } else if (tsSchema == "webrtc.vp8.3-layer") {
+            pattern = OMX_VIDEO_VPXTemporalLayerPatternWebRTC;
+            tsLayers = 3;
+        } else {
+            ALOGW("Unsupported ts-schema [%s]", tsSchema.c_str());
+        }
+    }
+
+    OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE vp8type;
+    InitOMXParams(&vp8type);
+    vp8type.nPortIndex = kPortIndexOutput;
+    status_t err = mOMX->getParameter(
+            mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
+            &vp8type, sizeof(vp8type));
+
+    if (err == OK) {
+        if (iFrameInterval > 0) {
+            vp8type.nKeyFrameInterval = setPFramesSpacing(iFrameInterval, frameRate);
+        }
+        vp8type.eTemporalPattern = pattern;
+        vp8type.nTemporalLayerCount = tsLayers;
+        if (tsLayers > 0) {
+            for (size_t i = 0; i < OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS; i++) {
+                vp8type.nTemporalLayerBitrateRatio[i] =
+                    kVp8LayerRateAlloction[tsLayers - 1][i];
+            }
+        }
+        if (bitrateMode == OMX_Video_ControlRateConstant) {
+            vp8type.nMinQuantizer = 2;
+            vp8type.nMaxQuantizer = 63;
+        }
+
+        err = mOMX->setParameter(
+                mNode, (OMX_INDEXTYPE)OMX_IndexParamVideoAndroidVp8Encoder,
+                &vp8type, sizeof(vp8type));
+        if (err != OK) {
+            ALOGW("Extended VP8 parameters set failed: %d", err);
+        }
+    }
+
     return configureBitrate(bitrate, bitrateMode);
 }
 
diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
index b3a6bcc..dc38ea8 100644
--- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
+++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
@@ -27,7 +27,6 @@
 
 namespace android {
 
-
 template<class T>
 static void InitOMXParams(T *params) {
     params->nSize = sizeof(T);
@@ -148,10 +147,20 @@
       mErrorResilience(OMX_FALSE),
       mColorFormat(OMX_COLOR_FormatYUV420Planar),
       mLevel(OMX_VIDEO_VP8Level_Version0),
+      mKeyFrameInterval(0),
+      mMinQuantizer(0),
+      mMaxQuantizer(0),
+      mTemporalLayers(0),
+      mTemporalPatternType(OMX_VIDEO_VPXTemporalLayerPatternNone),
+      mTemporalPatternLength(0),
+      mTemporalPatternIdx(0),
+      mLastTimestamp(0x7FFFFFFFFFFFFFFFLL),
       mConversionBuffer(NULL),
       mInputDataIsMeta(false),
       mGrallocModule(NULL),
       mKeyFrameRequested(false) {
+    memset(mTemporalLayerBitrateRatio, 0, sizeof(mTemporalLayerBitrateRatio));
+    mTemporalLayerBitrateRatio[0] = 100;
     initPorts();
 }
 
@@ -235,7 +244,9 @@
     if (mCodecInterface == NULL) {
         return UNKNOWN_ERROR;
     }
-
+    ALOGD("VP8: initEncoder. BRMode: %u. TSLayers: %zu. KF: %u. QP: %u - %u",
+          (uint32_t)mBitrateControlMode, mTemporalLayers, mKeyFrameInterval,
+          mMinQuantizer, mMaxQuantizer);
     codec_return = vpx_codec_enc_config_default(mCodecInterface,
                                                 mCodecConfiguration,
                                                 0);  // Codec specific flags
@@ -276,7 +287,7 @@
     mCodecConfiguration->g_timebase.num = 1;
     mCodecConfiguration->g_timebase.den = 1000000;
     // rc_target_bitrate is in kbps, mBitrate in bps
-    mCodecConfiguration->rc_target_bitrate = mBitrate / 1000;
+    mCodecConfiguration->rc_target_bitrate = (mBitrate + 500) / 1000;
     mCodecConfiguration->rc_end_usage = mBitrateControlMode;
     // Disable frame drop - not allowed in MediaCodec now.
     mCodecConfiguration->rc_dropframe_thresh = 0;
@@ -285,10 +296,6 @@
         mCodecConfiguration->rc_resize_allowed = 0;
         // Single-pass mode.
         mCodecConfiguration->g_pass = VPX_RC_ONE_PASS;
-        // Minimum quantization level.
-        mCodecConfiguration->rc_min_quantizer = 2;
-        // Maximum quantization level.
-        mCodecConfiguration->rc_max_quantizer = 63;
         // Maximum amount of bits that can be subtracted from the target
         // bitrate - expressed as percentage of the target bitrate.
         mCodecConfiguration->rc_undershoot_pct = 100;
@@ -306,10 +313,95 @@
         mCodecConfiguration->g_error_resilient = 1;
         // Disable lagged encoding.
         mCodecConfiguration->g_lag_in_frames = 0;
+        // Maximum key frame interval - for CBR boost to 3000
+        mCodecConfiguration->kf_max_dist = 3000;
         // Encoder determines optimal key frame placement automatically.
         mCodecConfiguration->kf_mode = VPX_KF_AUTO;
     }
 
+    // Frames temporal pattern - for now WebRTC like pattern is only supported.
+    switch (mTemporalLayers) {
+        case 0:
+        {
+            mTemporalPatternLength = 0;
+            break;
+        }
+        case 1:
+        {
+            mCodecConfiguration->ts_number_layers = 1;
+            mCodecConfiguration->ts_rate_decimator[0] = 1;
+            mCodecConfiguration->ts_periodicity = 1;
+            mCodecConfiguration->ts_layer_id[0] = 0;
+            mTemporalPattern[0] = kTemporalUpdateLastRefAll;
+            mTemporalPatternLength = 1;
+            break;
+        }
+        case 2:
+        {
+            mCodecConfiguration->ts_number_layers = 2;
+            mCodecConfiguration->ts_rate_decimator[0] = 2;
+            mCodecConfiguration->ts_rate_decimator[1] = 1;
+            mCodecConfiguration->ts_periodicity = 2;
+            mCodecConfiguration->ts_layer_id[0] = 0;
+            mCodecConfiguration->ts_layer_id[1] = 1;
+            mTemporalPattern[0] = kTemporalUpdateLastAndGoldenRefAltRef;
+            mTemporalPattern[1] = kTemporalUpdateGoldenWithoutDependencyRefAltRef;
+            mTemporalPattern[2] = kTemporalUpdateLastRefAltRef;
+            mTemporalPattern[3] = kTemporalUpdateGoldenRefAltRef;
+            mTemporalPattern[4] = kTemporalUpdateLastRefAltRef;
+            mTemporalPattern[5] = kTemporalUpdateGoldenRefAltRef;
+            mTemporalPattern[6] = kTemporalUpdateLastRefAltRef;
+            mTemporalPattern[7] = kTemporalUpdateNone;
+            mTemporalPatternLength = 8;
+            break;
+        }
+        case 3:
+        {
+            mCodecConfiguration->ts_number_layers = 3;
+            mCodecConfiguration->ts_rate_decimator[0] = 4;
+            mCodecConfiguration->ts_rate_decimator[1] = 2;
+            mCodecConfiguration->ts_rate_decimator[2] = 1;
+            mCodecConfiguration->ts_periodicity = 4;
+            mCodecConfiguration->ts_layer_id[0] = 0;
+            mCodecConfiguration->ts_layer_id[1] = 2;
+            mCodecConfiguration->ts_layer_id[2] = 1;
+            mCodecConfiguration->ts_layer_id[3] = 2;
+            mTemporalPattern[0] = kTemporalUpdateLastAndGoldenRefAltRef;
+            mTemporalPattern[1] = kTemporalUpdateNoneNoRefGoldenRefAltRef;
+            mTemporalPattern[2] = kTemporalUpdateGoldenWithoutDependencyRefAltRef;
+            mTemporalPattern[3] = kTemporalUpdateNone;
+            mTemporalPattern[4] = kTemporalUpdateLastRefAltRef;
+            mTemporalPattern[5] = kTemporalUpdateNone;
+            mTemporalPattern[6] = kTemporalUpdateGoldenRefAltRef;
+            mTemporalPattern[7] = kTemporalUpdateNone;
+            mTemporalPatternLength = 8;
+            break;
+        }
+        default:
+        {
+            ALOGE("Wrong number of temporal layers %u", mTemporalLayers);
+            return UNKNOWN_ERROR;
+        }
+    }
+
+    // Set bitrate values for each layer
+    for (size_t i = 0; i < mCodecConfiguration->ts_number_layers; i++) {
+        mCodecConfiguration->ts_target_bitrate[i] =
+            mCodecConfiguration->rc_target_bitrate *
+            mTemporalLayerBitrateRatio[i] / 100;
+    }
+    if (mKeyFrameInterval > 0) {
+        mCodecConfiguration->kf_max_dist = mKeyFrameInterval;
+        mCodecConfiguration->kf_min_dist = mKeyFrameInterval;
+        mCodecConfiguration->kf_mode = VPX_KF_AUTO;
+    }
+    if (mMinQuantizer > 0) {
+        mCodecConfiguration->rc_min_quantizer = mMinQuantizer;
+    }
+    if (mMaxQuantizer > 0) {
+        mCodecConfiguration->rc_max_quantizer = mMaxQuantizer;
+    }
+
     codec_return = vpx_codec_enc_init(mCodecContext,
                                       mCodecInterface,
                                       mCodecConfiguration,
@@ -466,6 +558,24 @@
                 return OMX_ErrorNone;
         }
 
+        case OMX_IndexParamVideoAndroidVp8Encoder: {
+            OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *vp8AndroidParams =
+                (OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *)param;
+
+                if (vp8AndroidParams->nPortIndex != kOutputPortIndex) {
+                    return OMX_ErrorUnsupportedIndex;
+                }
+
+                vp8AndroidParams->nKeyFrameInterval = mKeyFrameInterval;
+                vp8AndroidParams->eTemporalPattern = mTemporalPatternType;
+                vp8AndroidParams->nTemporalLayerCount = mTemporalLayers;
+                vp8AndroidParams->nMinQuantizer = mMinQuantizer;
+                vp8AndroidParams->nMaxQuantizer = mMaxQuantizer;
+                memcpy(vp8AndroidParams->nTemporalLayerBitrateRatio,
+                       mTemporalLayerBitrateRatio, sizeof(mTemporalLayerBitrateRatio));
+                return OMX_ErrorNone;
+        }
+
         case OMX_IndexParamVideoProfileLevelQuerySupported: {
             OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileAndLevel =
                 (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)param;
@@ -552,11 +662,15 @@
             return internalSetVp8Params(
                 (const OMX_VIDEO_PARAM_VP8TYPE *)param);
 
+        case OMX_IndexParamVideoAndroidVp8Encoder:
+            return internalSetAndroidVp8Params(
+                (const OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *)param);
+
         case OMX_IndexParamVideoProfileLevelCurrent:
             return internalSetProfileLevel(
                 (const OMX_VIDEO_PARAM_PROFILELEVELTYPE *)param);
 
-        case OMX_IndexVendorStartUnused:
+        case kStoreMetaDataExtensionIndex:
         {
             // storeMetaDataInBuffers
             const StoreMetaDataInBuffersParams *storeParam =
@@ -665,6 +779,50 @@
     return OMX_ErrorNone;
 }
 
+OMX_ERRORTYPE SoftVPXEncoder::internalSetAndroidVp8Params(
+        const OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE* vp8AndroidParams) {
+    if (vp8AndroidParams->nPortIndex != kOutputPortIndex) {
+        return OMX_ErrorUnsupportedIndex;
+    }
+    if (vp8AndroidParams->eTemporalPattern != OMX_VIDEO_VPXTemporalLayerPatternNone &&
+        vp8AndroidParams->eTemporalPattern != OMX_VIDEO_VPXTemporalLayerPatternWebRTC) {
+        return OMX_ErrorBadParameter;
+    }
+    if (vp8AndroidParams->nTemporalLayerCount > OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS) {
+        return OMX_ErrorBadParameter;
+    }
+    if (vp8AndroidParams->nMinQuantizer > vp8AndroidParams->nMaxQuantizer) {
+        return OMX_ErrorBadParameter;
+    }
+
+    mTemporalPatternType = vp8AndroidParams->eTemporalPattern;
+    if (vp8AndroidParams->eTemporalPattern == OMX_VIDEO_VPXTemporalLayerPatternWebRTC) {
+        mTemporalLayers = vp8AndroidParams->nTemporalLayerCount;
+    } else if (vp8AndroidParams->eTemporalPattern == OMX_VIDEO_VPXTemporalLayerPatternNone) {
+        mTemporalLayers = 0;
+    }
+    // Check the bitrate distribution between layers is in increasing order
+    if (mTemporalLayers > 1) {
+        for (size_t i = 0; i < mTemporalLayers - 1; i++) {
+            if (vp8AndroidParams->nTemporalLayerBitrateRatio[i + 1] <=
+                    vp8AndroidParams->nTemporalLayerBitrateRatio[i]) {
+                ALOGE("Wrong bitrate ratio - should be in increasing order.");
+                return OMX_ErrorBadParameter;
+            }
+        }
+    }
+    mKeyFrameInterval = vp8AndroidParams->nKeyFrameInterval;
+    mMinQuantizer = vp8AndroidParams->nMinQuantizer;
+    mMaxQuantizer = vp8AndroidParams->nMaxQuantizer;
+    memcpy(mTemporalLayerBitrateRatio, vp8AndroidParams->nTemporalLayerBitrateRatio,
+            sizeof(mTemporalLayerBitrateRatio));
+    ALOGD("VP8: internalSetAndroidVp8Params. BRMode: %u. TS: %zu. KF: %u."
+          " QP: %u - %u BR0: %u. BR1: %u. BR2: %u",
+          (uint32_t)mBitrateControlMode, mTemporalLayers, mKeyFrameInterval,
+          mMinQuantizer, mMaxQuantizer, mTemporalLayerBitrateRatio[0],
+          mTemporalLayerBitrateRatio[1], mTemporalLayerBitrateRatio[2]);
+    return OMX_ErrorNone;
+}
 
 OMX_ERRORTYPE SoftVPXEncoder::internalSetFormatParams(
         const OMX_VIDEO_PARAM_PORTFORMATTYPE* format) {
@@ -728,7 +886,7 @@
         OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kInputPortIndex)->mDef;
         def->format.video.nFrameWidth = mWidth;
         def->format.video.nFrameHeight = mHeight;
-        def->format.video.xFramerate = port->format.video.xFramerate;
+        def->format.video.xFramerate = mFramerate;
         def->format.video.eColorFormat = mColorFormat;
         def = &editPortInfo(kOutputPortIndex)->mDef;
         def->format.video.nFrameWidth = mWidth;
@@ -770,6 +928,74 @@
     return OMX_ErrorNone;
 }
 
+vpx_enc_frame_flags_t SoftVPXEncoder::getEncodeFlags() {
+    vpx_enc_frame_flags_t flags = 0;
+    int patternIdx = mTemporalPatternIdx % mTemporalPatternLength;
+    mTemporalPatternIdx++;
+    switch (mTemporalPattern[patternIdx]) {
+        case kTemporalUpdateLast:
+            flags |= VP8_EFLAG_NO_UPD_GF;
+            flags |= VP8_EFLAG_NO_UPD_ARF;
+            flags |= VP8_EFLAG_NO_REF_GF;
+            flags |= VP8_EFLAG_NO_REF_ARF;
+            break;
+        case kTemporalUpdateGoldenWithoutDependency:
+            flags |= VP8_EFLAG_NO_REF_GF;
+            // Deliberately no break here.
+        case kTemporalUpdateGolden:
+            flags |= VP8_EFLAG_NO_REF_ARF;
+            flags |= VP8_EFLAG_NO_UPD_ARF;
+            flags |= VP8_EFLAG_NO_UPD_LAST;
+            break;
+        case kTemporalUpdateAltrefWithoutDependency:
+            flags |= VP8_EFLAG_NO_REF_ARF;
+            flags |= VP8_EFLAG_NO_REF_GF;
+            // Deliberately no break here.
+        case kTemporalUpdateAltref:
+            flags |= VP8_EFLAG_NO_UPD_GF;
+            flags |= VP8_EFLAG_NO_UPD_LAST;
+            break;
+        case kTemporalUpdateNoneNoRefAltref:
+            flags |= VP8_EFLAG_NO_REF_ARF;
+            // Deliberately no break here.
+        case kTemporalUpdateNone:
+            flags |= VP8_EFLAG_NO_UPD_GF;
+            flags |= VP8_EFLAG_NO_UPD_ARF;
+            flags |= VP8_EFLAG_NO_UPD_LAST;
+            flags |= VP8_EFLAG_NO_UPD_ENTROPY;
+            break;
+        case kTemporalUpdateNoneNoRefGoldenRefAltRef:
+            flags |= VP8_EFLAG_NO_REF_GF;
+            flags |= VP8_EFLAG_NO_UPD_GF;
+            flags |= VP8_EFLAG_NO_UPD_ARF;
+            flags |= VP8_EFLAG_NO_UPD_LAST;
+            flags |= VP8_EFLAG_NO_UPD_ENTROPY;
+            break;
+        case kTemporalUpdateGoldenWithoutDependencyRefAltRef:
+            flags |= VP8_EFLAG_NO_REF_GF;
+            flags |= VP8_EFLAG_NO_UPD_ARF;
+            flags |= VP8_EFLAG_NO_UPD_LAST;
+            break;
+        case kTemporalUpdateLastRefAltRef:
+            flags |= VP8_EFLAG_NO_UPD_GF;
+            flags |= VP8_EFLAG_NO_UPD_ARF;
+            flags |= VP8_EFLAG_NO_REF_GF;
+            break;
+        case kTemporalUpdateGoldenRefAltRef:
+            flags |= VP8_EFLAG_NO_UPD_ARF;
+            flags |= VP8_EFLAG_NO_UPD_LAST;
+            break;
+        case kTemporalUpdateLastAndGoldenRefAltRef:
+            flags |= VP8_EFLAG_NO_UPD_ARF;
+            flags |= VP8_EFLAG_NO_REF_GF;
+            break;
+        case kTemporalUpdateLastRefAll:
+            flags |= VP8_EFLAG_NO_UPD_ARF;
+            flags |= VP8_EFLAG_NO_UPD_GF;
+            break;
+    }
+    return flags;
+}
 
 void SoftVPXEncoder::onQueueFilled(OMX_U32 portIndex) {
     // Initialize encoder if not already
@@ -854,6 +1080,9 @@
                      kInputBufferAlignment, source);
 
         vpx_enc_frame_flags_t flags = 0;
+        if (mTemporalPatternLength > 0) {
+            flags = getEncodeFlags();
+        }
         if (mKeyFrameRequested) {
             flags |= VPX_EFLAG_FORCE_KF;
             mKeyFrameRequested = false;
@@ -874,7 +1103,13 @@
             mBitrateUpdated = false;
         }
 
-        uint32_t frameDuration = (uint32_t)(((uint64_t)1000000 << 16) / mFramerate);
+        uint32_t frameDuration;
+        if (inputBufferHeader->nTimeStamp > mLastTimestamp) {
+            frameDuration = (uint32_t)(inputBufferHeader->nTimeStamp - mLastTimestamp);
+        } else {
+            frameDuration = (uint32_t)(((uint64_t)1000000 << 16) / mFramerate);
+        }
+        mLastTimestamp = inputBufferHeader->nTimeStamp;
         codec_return = vpx_codec_encode(
                 mCodecContext,
                 &raw_frame,
@@ -921,10 +1156,9 @@
 OMX_ERRORTYPE SoftVPXEncoder::getExtensionIndex(
         const char *name, OMX_INDEXTYPE *index) {
     if (!strcmp(name, "OMX.google.android.index.storeMetaDataInBuffers")) {
-        *index = OMX_IndexVendorStartUnused;
+        *(int32_t*)index = kStoreMetaDataExtensionIndex;
         return OMX_ErrorNone;
     }
-
     return SimpleSoftOMXComponent::getExtensionIndex(name, index);
 }
 
diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h
index 1c983ab..c5a83d1 100644
--- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h
+++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h
@@ -91,6 +91,47 @@
             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.
+        kTemporalUpdateLastRefAll = 12,
+        // First base layer frame for 3 temporal layers, which updates last and
+        // golden with alt ref dependency.
+        kTemporalUpdateLastAndGoldenRefAltRef = 11,
+        // First enhancement layer with alt ref dependency.
+        kTemporalUpdateGoldenRefAltRef = 10,
+        // First enhancement layer with alt ref dependency.
+        kTemporalUpdateGoldenWithoutDependencyRefAltRef = 9,
+        // Base layer with alt ref dependency.
+        kTemporalUpdateLastRefAltRef = 8,
+        // Highest enhacement layer without dependency on golden with alt ref
+        // dependency.
+        kTemporalUpdateNoneNoRefGoldenRefAltRef = 7,
+        // Second layer and last frame in cycle, for 2 layers.
+        kTemporalUpdateNoneNoRefAltref = 6,
+        // Highest enhancement layer.
+        kTemporalUpdateNone = 5,
+        // Second enhancement layer.
+        kTemporalUpdateAltref = 4,
+        // Second enhancement layer without dependency on previous frames in
+        // the second enhancement layer.
+        kTemporalUpdateAltrefWithoutDependency = 3,
+        // First enhancement layer.
+        kTemporalUpdateGolden = 2,
+        // First enhancement layer without dependency on previous frames in
+        // the first enhancement layer.
+        kTemporalUpdateGoldenWithoutDependency = 1,
+        // Base layer.
+        kTemporalUpdateLast = 0,
+    };
+    enum {
+        kMaxTemporalPattern = 8
+    };
+
     // number of buffers allocated per port
     static const uint32_t kNumBuffers = 4;
 
@@ -159,6 +200,36 @@
     // something else.
     OMX_VIDEO_VP8LEVELTYPE mLevel;
 
+    // Key frame interval in frames
+    uint32_t mKeyFrameInterval;
+
+    // Minimum (best quality) quantizer
+    uint32_t mMinQuantizer;
+
+    // Maximum (worst quality) quantizer
+    uint32_t mMaxQuantizer;
+
+    // Number of coding temporal layers to be used.
+    size_t mTemporalLayers;
+
+    // Temporal layer bitrare ratio in percentage
+    uint32_t mTemporalLayerBitrateRatio[OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS];
+
+    // Temporal pattern type
+    OMX_VIDEO_ANDROID_VPXTEMPORALLAYERPATTERNTYPE mTemporalPatternType;
+
+    // Temporal pattern length
+    size_t mTemporalPatternLength;
+
+    // Temporal pattern current index
+    size_t mTemporalPatternIdx;
+
+    // Frame type temporal pattern
+    TemporalReferences mTemporalPattern[kMaxTemporalPattern];
+
+    // Last input buffer timestamp
+    OMX_TICKS mLastTimestamp;
+
     // Conversion buffer is needed to convert semi
     // planar yuv420 to planar format
     // It is only allocated if input format is
@@ -184,6 +255,9 @@
     // dtor.
     status_t releaseEncoder();
 
+    // 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);
@@ -205,6 +279,10 @@
     OMX_ERRORTYPE internalSetVp8Params(
         const OMX_VIDEO_PARAM_VP8TYPE* vp8Params);
 
+    // Handles Android vp8 specific parameters.
+    OMX_ERRORTYPE internalSetAndroidVp8Params(
+        const OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE* vp8AndroidParams);
+
     // Updates encoder profile
     OMX_ERRORTYPE internalSetProfileLevel(
         const OMX_VIDEO_PARAM_PROFILELEVELTYPE* profileAndLevel);