SoftAVCEnc: Added support for Main Profile encoding.

Configured intra frame interval and deblock in setParams.

Change-Id: If501fa0ac42f2c4bf6604ea84715f7f13f707e74
diff --git a/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp b/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
index a00f324..9ee3518 100644
--- a/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
+++ b/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
@@ -49,10 +49,10 @@
     params->nVersion.s.nStep = 0;
 }
 
-typedef struct LevelConversion {
+struct LevelConversion {
     OMX_VIDEO_AVCLEVELTYPE omxLevel;
     WORD32 avcLevel;
-} LevelConcersion;
+};
 
 static LevelConversion ConversionTable[] = {
     { OMX_VIDEO_AVCLevel1,  10 },
@@ -87,8 +87,21 @@
     { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel32 },
     { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel4  },
     { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel41 },
-};
+    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel1  },
+    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel1b },
+    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel11 },
+    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel12 },
+    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel13 },
+    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel2  },
+    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel21 },
+    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel22 },
+    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel3  },
+    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel31 },
+    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel32 },
+    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel4  },
+    { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel41 },
 
+};
 
 static size_t GetCPUCoreCount() {
     long cpuCoreCount = 1;
@@ -99,7 +112,7 @@
     cpuCoreCount = sysconf(_SC_NPROC_ONLN);
 #endif
     CHECK(cpuCoreCount >= 1);
-    ALOGD("Number of CPU cores: %ld", cpuCoreCount);
+    ALOGV("Number of CPU cores: %ld", cpuCoreCount);
     return (size_t)cpuCoreCount;
 }
 
@@ -144,15 +157,15 @@
             kProfileLevels, NELEM(kProfileLevels),
             176 /* width */, 144 /* height */,
             callbacks, appData, component),
+      mBitrateUpdated(false),
+      mKeyFrameRequested(false),
       mIvVideoColorFormat(IV_YUV_420P),
-      mIDRFrameRefreshIntervalInSec(1),
       mAVCEncProfile(IV_PROFILE_BASE),
-      mAVCEncLevel(31),
-      mPrevTimestampUs(-1),
+      mAVCEncLevel(41),
       mStarted(false),
       mSawInputEOS(false),
+      mSawOutputEOS(false),
       mSignalledError(false),
-      mConversionBuffer(NULL),
       mCodecCtx(NULL) {
 
     initPorts(kNumBuffers, kNumBuffers, ((mWidth * mHeight * 3) >> 1),
@@ -162,6 +175,10 @@
     GENERATE_FILE_NAMES();
     CREATE_DUMP_FILE(mInFile);
     CREATE_DUMP_FILE(mOutFile);
+    memset(mConversionBuffers, 0, sizeof(mConversionBuffers));
+    memset(mInputBufferInfo, 0, sizeof(mInputBufferInfo));
+
+    initEncParams();
 
 }
 
@@ -173,7 +190,7 @@
     CHECK(inQueue.empty());
 }
 
-OMX_ERRORTYPE SoftAVC::initEncParams() {
+void  SoftAVC::initEncParams() {
     mCodecCtx = NULL;
     mMemRecords = NULL;
     mNumMemRecords = DEFAULT_MEM_REC_CNT;
@@ -186,7 +203,6 @@
     mIInterval = DEFAULT_I_INTERVAL;
     mIDRInterval = DEFAULT_IDR_INTERVAL;
     mDisableDeblkLevel = DEFAULT_DISABLE_DEBLK_LEVEL;
-    mFrameRate = DEFAULT_SRC_FRAME_RATE;
     mEnableFastSad = DEFAULT_ENABLE_FAST_SAD;
     mEnableAltRef = DEFAULT_ENABLE_ALT_REF;
     mEncSpeed = DEFAULT_ENC_SPEED;
@@ -195,11 +211,12 @@
     mAIRRefreshPeriod = DEFAULT_AIR_REFRESH_PERIOD;
     mPSNREnable = DEFAULT_PSNR_ENABLE;
     mReconEnable = DEFAULT_RECON_ENABLE;
+    mEntropyMode = DEFAULT_ENTROPY_MODE;
+    mBframes = DEFAULT_B_FRAMES;
 
     gettimeofday(&mTimeStart, NULL);
     gettimeofday(&mTimeEnd, NULL);
 
-    return OMX_ErrorNone;
 }
 
 
@@ -260,8 +277,8 @@
     s_frame_rate_ip.e_cmd = IVE_CMD_VIDEO_CTL;
     s_frame_rate_ip.e_sub_cmd = IVE_CMD_CTL_SET_FRAMERATE;
 
-    s_frame_rate_ip.u4_src_frame_rate = mFrameRate;
-    s_frame_rate_ip.u4_tgt_frame_rate = mFrameRate;
+    s_frame_rate_ip.u4_src_frame_rate = mFramerate >> 16;
+    s_frame_rate_ip.u4_tgt_frame_rate = mFramerate >> 16;
 
     s_frame_rate_ip.u4_timestamp_high = -1;
     s_frame_rate_ip.u4_timestamp_low = -1;
@@ -332,7 +349,6 @@
     ive_ctl_set_frame_type_ip_t s_frame_type_ip;
     ive_ctl_set_frame_type_op_t s_frame_type_op;
     IV_STATUS_T status;
-
     s_frame_type_ip.e_cmd = IVE_CMD_VIDEO_CTL;
     s_frame_type_ip.e_sub_cmd = IVE_CMD_CTL_SET_FRAMETYPE;
 
@@ -503,7 +519,6 @@
 
     s_gop_params_ip.u4_i_frm_interval = mIInterval;
     s_gop_params_ip.u4_idr_frm_interval = mIDRInterval;
-    s_gop_params_ip.u4_num_b_frames = DEFAULT_B_FRAMES;
 
     s_gop_params_ip.u4_timestamp_high = -1;
     s_gop_params_ip.u4_timestamp_low = -1;
@@ -529,7 +544,7 @@
     s_profile_params_ip.e_sub_cmd = IVE_CMD_CTL_SET_PROFILE_PARAMS;
 
     s_profile_params_ip.e_profile = DEFAULT_EPROFILE;
-
+    s_profile_params_ip.u4_entropy_coding_mode = mEntropyMode;
     s_profile_params_ip.u4_timestamp_high = -1;
     s_profile_params_ip.u4_timestamp_low = -1;
 
@@ -595,7 +610,6 @@
 
 OMX_ERRORTYPE SoftAVC::initEncoder() {
     IV_STATUS_T status;
-    size_t i;
     WORD32 level;
     uint32_t displaySizeY;
     CHECK(!mStarted);
@@ -618,31 +632,26 @@
     }
     mAVCEncLevel = MAX(level, mAVCEncLevel);
 
-    if (OMX_ErrorNone != (errType = initEncParams())) {
-        ALOGE("Failed to initialize encoder params");
-        mSignalledError = true;
-        notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
-        return errType;
-    }
-
     mStride = mWidth;
 
     if (mInputDataIsMeta) {
-        if (mConversionBuffer) {
-            free(mConversionBuffer);
-            mConversionBuffer = NULL;
-        }
+        for (size_t i = 0; i < MAX_CONVERSION_BUFFERS; i++) {
+            if (mConversionBuffers[i] != NULL) {
+                free(mConversionBuffers[i]);
+            }
 
-        if (mConversionBuffer == NULL) {
             if (((uint64_t)mStride * mHeight) > (((uint64_t)INT32_MAX / 3) * 2)) {
                 ALOGE("Buffer size is too big.");
                 return OMX_ErrorUndefined;
             }
-            mConversionBuffer = (uint8_t *)malloc(mStride * mHeight * 3 / 2);
-            if (mConversionBuffer == NULL) {
+            mConversionBuffers[i] = (uint8_t *)malloc(mStride * mHeight * 3 / 2);
+
+            if (mConversionBuffers[i] == NULL) {
                 ALOGE("Allocating conversion buffer failed.");
                 return OMX_ErrorUndefined;
             }
+
+            mConversionBuffersFree[i] = 1;
         }
     }
 
@@ -658,7 +667,7 @@
             break;
     }
 
-    ALOGV("Params width %d height %d level %d colorFormat %d", mWidth,
+    ALOGD("Params width %d height %d level %d colorFormat %d", mWidth,
             mHeight, mAVCEncLevel, mIvVideoColorFormat);
 
     /* Getting Number of MemRecords */
@@ -699,7 +708,7 @@
     {
         iv_mem_rec_t *ps_mem_rec;
         ps_mem_rec = mMemRecords;
-        for (i = 0; i < mNumMemRecords; i++) {
+        for (size_t i = 0; i < mNumMemRecords; i++) {
             ps_mem_rec->u4_size = sizeof(iv_mem_rec_t);
             ps_mem_rec->pv_base = NULL;
             ps_mem_rec->u4_mem_size = 0;
@@ -746,9 +755,9 @@
         WORD32 total_size;
         iv_mem_rec_t *ps_mem_rec;
         total_size = 0;
-
         ps_mem_rec = mMemRecords;
-        for (i = 0; i < mNumMemRecords; i++) {
+
+        for (size_t i = 0; i < mNumMemRecords; i++) {
             ps_mem_rec->pv_base = ive_aligned_malloc(
                     ps_mem_rec->u4_mem_alignment, ps_mem_rec->u4_mem_size);
             if (ps_mem_rec->pv_base == NULL) {
@@ -763,7 +772,6 @@
 
             ps_mem_rec++;
         }
-        printf("\nTotal memory for codec %d\n", total_size);
     }
 
     /* Codec Instance Creation */
@@ -797,7 +805,7 @@
         s_init_ip.e_rc_mode = DEFAULT_RC_MODE;
         s_init_ip.u4_max_framerate = DEFAULT_MAX_FRAMERATE;
         s_init_ip.u4_max_bitrate = DEFAULT_MAX_BITRATE;
-        s_init_ip.u4_max_num_bframes = DEFAULT_B_FRAMES;
+        s_init_ip.u4_num_bframes = mBframes;
         s_init_ip.e_content_type = IV_PROGRESSIVE;
         s_init_ip.u4_max_srch_rng_x = DEFAULT_MAX_SRCH_RANGE_X;
         s_init_ip.u4_max_srch_rng_y = DEFAULT_MAX_SRCH_RANGE_Y;
@@ -872,7 +880,6 @@
     iv_retrieve_mem_rec_ip_t s_retrieve_mem_ip;
     iv_retrieve_mem_rec_op_t s_retrieve_mem_op;
     iv_mem_rec_t *ps_mem_rec;
-    UWORD32 i;
 
     if (!mStarted) {
         return OMX_ErrorNone;
@@ -893,16 +900,18 @@
 
     /* Free memory records */
     ps_mem_rec = mMemRecords;
-    for (i = 0; i < s_retrieve_mem_op.u4_num_mem_rec_filled; i++) {
+    for (size_t i = 0; i < s_retrieve_mem_op.u4_num_mem_rec_filled; i++) {
         ive_aligned_free(ps_mem_rec->pv_base);
         ps_mem_rec++;
     }
 
     free(mMemRecords);
 
-    if (mConversionBuffer != NULL) {
-        free(mConversionBuffer);
-        mConversionBuffer = NULL;
+    for (size_t i = 0; i < MAX_CONVERSION_BUFFERS; i++) {
+        if (mConversionBuffers[i]) {
+            free(mConversionBuffers[i]);
+            mConversionBuffers[i] = NULL;
+        }
     }
 
     mStarted = false;
@@ -934,23 +943,21 @@
                 return OMX_ErrorUndefined;
             }
 
-            avcParams->eProfile = OMX_VIDEO_AVCProfileBaseline;
-            OMX_VIDEO_AVCLEVELTYPE omxLevel = OMX_VIDEO_AVCLevel31;
+            OMX_VIDEO_AVCLEVELTYPE omxLevel = OMX_VIDEO_AVCLevel41;
             if (OMX_ErrorNone
                     != ConvertAvcSpecLevelToOmxAvcLevel(mAVCEncLevel, &omxLevel)) {
                 return OMX_ErrorUndefined;
             }
 
+            avcParams->eProfile = OMX_VIDEO_AVCProfileBaseline;
             avcParams->eLevel = omxLevel;
             avcParams->nRefFrames = 1;
-            avcParams->nBFrames = 0;
             avcParams->bUseHadamard = OMX_TRUE;
             avcParams->nAllowedPictureTypes = (OMX_VIDEO_PictureTypeI
-                    | OMX_VIDEO_PictureTypeP);
+                    | OMX_VIDEO_PictureTypeP | OMX_VIDEO_PictureTypeB);
             avcParams->nRefIdx10ActiveMinus1 = 0;
             avcParams->nRefIdx11ActiveMinus1 = 0;
             avcParams->bWeightedPPrediction = OMX_FALSE;
-            avcParams->bEntropyCodingCABAC = OMX_FALSE;
             avcParams->bconstIpred = OMX_FALSE;
             avcParams->bDirect8x8Inference = OMX_FALSE;
             avcParams->bDirectSpatialTemporal = OMX_FALSE;
@@ -981,14 +988,26 @@
                 return OMX_ErrorUndefined;
             }
 
-            if (avcType->eProfile != OMX_VIDEO_AVCProfileBaseline
-                    || avcType->nRefFrames != 1 || avcType->nBFrames != 0
+            mEntropyMode = 0;
+
+            if (OMX_TRUE == avcType->bEntropyCodingCABAC)
+                mEntropyMode = 1;
+
+            if ((avcType->nAllowedPictureTypes & OMX_VIDEO_PictureTypeB) &&
+                    avcType->nPFrames) {
+                mBframes = avcType->nBFrames / avcType->nPFrames;
+            }
+
+            mIInterval = avcType->nPFrames + avcType->nBFrames;
+
+            if (OMX_VIDEO_AVCLoopFilterDisable == avcType->eLoopFilterMode)
+                mDisableDeblkLevel = 4;
+
+            if (avcType->nRefFrames != 1
                     || avcType->bUseHadamard != OMX_TRUE
-                    || (avcType->nAllowedPictureTypes & OMX_VIDEO_PictureTypeB) != 0
                     || avcType->nRefIdx10ActiveMinus1 != 0
                     || avcType->nRefIdx11ActiveMinus1 != 0
                     || avcType->bWeightedPPrediction != OMX_FALSE
-                    || avcType->bEntropyCodingCABAC != OMX_FALSE
                     || avcType->bconstIpred != OMX_FALSE
                     || avcType->bDirect8x8Inference != OMX_FALSE
                     || avcType->bDirectSpatialTemporal != OMX_FALSE
@@ -1083,14 +1102,27 @@
 
     /* Initialize color formats */
     ps_inp_raw_buf->e_color_fmt = mIvVideoColorFormat;
-
     source = NULL;
-    if (inputBufferHeader) {
+    if ((inputBufferHeader != NULL) && inputBufferHeader->nFilledLen) {
         source = inputBufferHeader->pBuffer + inputBufferHeader->nOffset;
 
         if (mInputDataIsMeta) {
+            uint8_t *conversionBuffer = NULL;
+            for (size_t i = 0; i < MAX_CONVERSION_BUFFERS; i++) {
+                if (mConversionBuffersFree[i]) {
+                    mConversionBuffersFree[i] = 0;
+                    conversionBuffer = mConversionBuffers[i];
+                    break;
+                }
+            }
+
+            if (NULL == conversionBuffer) {
+                ALOGE("No free buffers to hold conversion data");
+                return OMX_ErrorUndefined;
+            }
+
             source = extractGraphicBuffer(
-                    mConversionBuffer, (mWidth * mHeight * 3 / 2), source,
+                    conversionBuffer, (mWidth * mHeight * 3 / 2), source,
                     inputBufferHeader->nFilledLen, mWidth, mHeight);
 
             if (source == NULL) {
@@ -1099,6 +1131,18 @@
                 return OMX_ErrorUndefined;
             }
         }
+        ps_encode_ip->u4_is_last = 0;
+        ps_encode_ip->u4_timestamp_high = (inputBufferHeader->nTimeStamp) >> 32;
+        ps_encode_ip->u4_timestamp_low = (inputBufferHeader->nTimeStamp) & 0xFFFFFFFF;
+    }
+    else {
+        if (mSawInputEOS){
+            ps_encode_ip->u4_is_last = 1;
+        }
+        memset(ps_inp_raw_buf, 0, sizeof(iv_raw_buf_t));
+        ps_inp_raw_buf->e_color_fmt = mIvVideoColorFormat;
+        ps_inp_raw_buf->u4_size = sizeof(iv_raw_buf_t);
+        return OMX_ErrorNone;
     }
 
     pu1_buf = (UWORD8 *)source;
@@ -1153,14 +1197,6 @@
             break;
         }
     }
-
-    ps_encode_ip->u4_is_last = 0;
-
-    if (inputBufferHeader) {
-        ps_encode_ip->u4_timestamp_high = (inputBufferHeader->nTimeStamp) >> 32;
-        ps_encode_ip->u4_timestamp_low = (inputBufferHeader->nTimeStamp) & 0xFFFFFFFF;
-    }
-
     return OMX_ErrorNone;
 }
 
@@ -1178,38 +1214,31 @@
             return;
         }
     }
-    if (mSignalledError || mSawInputEOS) {
+    if (mSignalledError) {
         return;
     }
 
     List<BufferInfo *> &inQueue = getPortQueue(0);
     List<BufferInfo *> &outQueue = getPortQueue(1);
 
-    while (!mSawInputEOS && !inQueue.empty() && !outQueue.empty()) {
+    while (!mSawOutputEOS && !outQueue.empty()) {
+
         OMX_ERRORTYPE error;
         ive_video_encode_ip_t s_encode_ip;
         ive_video_encode_op_t s_encode_op;
-
-        BufferInfo *inputBufferInfo = *inQueue.begin();
-        OMX_BUFFERHEADERTYPE *inputBufferHeader = inputBufferInfo->mHeader;
-
         BufferInfo *outputBufferInfo = *outQueue.begin();
         OMX_BUFFERHEADERTYPE *outputBufferHeader = outputBufferInfo->mHeader;
 
-        if (inputBufferHeader->nFlags & OMX_BUFFERFLAG_EOS &&
-                inputBufferHeader->nFilledLen == 0) {
-            mSawInputEOS = true;
+        BufferInfo *inputBufferInfo;
+        OMX_BUFFERHEADERTYPE *inputBufferHeader;
 
-            inQueue.erase(inQueue.begin());
-            inputBufferInfo->mOwnedByUs = false;
-            notifyEmptyBufferDone(inputBufferHeader);
-
-            outputBufferHeader->nFilledLen = 0;
-            outputBufferHeader->nFlags = OMX_BUFFERFLAG_EOS;
-
-            outQueue.erase(outQueue.begin());
-            outputBufferInfo->mOwnedByUs = false;
-            notifyFillBufferDone(outputBufferHeader);
+        if (mSawInputEOS) {
+            inputBufferHeader = NULL;
+            inputBufferInfo = NULL;
+        } else if (!inQueue.empty()) {
+            inputBufferInfo = *inQueue.begin();
+            inputBufferHeader = inputBufferInfo->mHeader;
+        } else {
             return;
         }
 
@@ -1219,6 +1248,10 @@
         outputBufferHeader->nFilledLen = 0;
         outputBufferHeader->nOffset = 0;
 
+        if (inputBufferHeader != NULL) {
+            outputBufferHeader->nFlags = inputBufferHeader->nFlags;
+        }
+
         uint8_t *outPtr = (uint8_t *)outputBufferHeader->pBuffer;
 
         if (!mSpsPpsHeaderReceived) {
@@ -1242,10 +1275,13 @@
 
             outputBufferHeader->nFlags = OMX_BUFFERFLAG_CODECCONFIG;
             outputBufferHeader->nFilledLen = s_encode_op.s_out_buf.u4_bytes;
-            outputBufferHeader->nTimeStamp = inputBufferHeader->nTimeStamp;
+            if (inputBufferHeader != NULL) {
+                outputBufferHeader->nTimeStamp = inputBufferHeader->nTimeStamp;
+            }
 
             outQueue.erase(outQueue.begin());
             outputBufferInfo->mOwnedByUs = false;
+
             DUMP_TO_FILE(
                     mOutFile, outputBufferHeader->pBuffer,
                     outputBufferHeader->nFilledLen);
@@ -1263,14 +1299,24 @@
             setFrameType(IV_IDR_FRAME);
         }
 
-        mPrevTimestampUs = inputBufferHeader->nTimeStamp;
-
-        if (inputBufferHeader->nFlags & OMX_BUFFERFLAG_EOS) {
+        if ((inputBufferHeader != NULL)
+                && (inputBufferHeader->nFlags & OMX_BUFFERFLAG_EOS)) {
             mSawInputEOS = true;
         }
 
+        /* In normal mode, store inputBufferInfo and this will be returned
+           when encoder consumes this input */
+        if (!mInputDataIsMeta && (inputBufferInfo != NULL)) {
+            for (size_t i = 0; i < MAX_INPUT_BUFFER_HEADERS; i++) {
+                if (NULL == mInputBufferInfo[i]) {
+                    mInputBufferInfo[i] = inputBufferInfo;
+                    break;
+                }
+            }
+        }
         error = setEncodeArgs(
                 &s_encode_ip, &s_encode_op, inputBufferHeader, outputBufferHeader);
+
         if (error != OMX_ErrorNone) {
             mSignalledError = true;
             notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
@@ -1280,14 +1326,11 @@
         DUMP_TO_FILE(
                 mInFile, s_encode_ip.s_inp_buf.apv_bufs[0],
                 (mHeight * mStride * 3 / 2));
-        //DUMP_TO_FILE(mInFile, inputBufferHeader->pBuffer + inputBufferHeader->nOffset,
-        //    inputBufferHeader->nFilledLen);
 
         GETTIME(&mTimeStart, NULL);
         /* Compute time elapsed between end of previous decode()
          * to start of current decode() */
         TIME_DIFF(mTimeEnd, mTimeStart, timeDelay);
-
         status = ive_api_function(mCodecCtx, &s_encode_ip, &s_encode_op);
 
         if (IV_SUCCESS != status) {
@@ -1305,38 +1348,77 @@
         ALOGV("timeTaken=%6d delay=%6d numBytes=%6d", timeTaken, timeDelay,
                 s_encode_op.s_out_buf.u4_bytes);
 
+        /* In encoder frees up an input buffer, mark it as free */
+        if (s_encode_op.s_inp_buf.apv_bufs[0] != NULL) {
+            if (mInputDataIsMeta) {
+                for (size_t i = 0; i < MAX_CONVERSION_BUFFERS; i++) {
+                    if (mConversionBuffers[i] == s_encode_op.s_inp_buf.apv_bufs[0]) {
+                        mConversionBuffersFree[i] = 1;
+                        break;
+                    }
+                }
+            } else {
+                /* In normal mode, call EBD on inBuffeHeader that is freed by the codec */
+                for (size_t i = 0; i < MAX_INPUT_BUFFER_HEADERS; i++) {
+                    uint8_t *buf = NULL;
+                    OMX_BUFFERHEADERTYPE *bufHdr = NULL;
+                    if (mInputBufferInfo[i] != NULL) {
+                        bufHdr = mInputBufferInfo[i]->mHeader;
+                        buf = bufHdr->pBuffer + bufHdr->nOffset;
+                    }
+                    if (s_encode_op.s_inp_buf.apv_bufs[0] == buf) {
+                        mInputBufferInfo[i]->mOwnedByUs = false;
+                        notifyEmptyBufferDone(bufHdr);
+                        mInputBufferInfo[i] = NULL;
+                        break;
+                    }
+                }
+            }
+        }
 
-        outputBufferHeader->nFlags = inputBufferHeader->nFlags;
         outputBufferHeader->nFilledLen = s_encode_op.s_out_buf.u4_bytes;
-        outputBufferHeader->nTimeStamp = inputBufferHeader->nTimeStamp;
 
-        if (IV_IDR_FRAME
-                == s_encode_op.u4_encoded_frame_type) {
+        if (IV_IDR_FRAME == s_encode_op.u4_encoded_frame_type) {
             outputBufferHeader->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
         }
 
-        inQueue.erase(inQueue.begin());
-        inputBufferInfo->mOwnedByUs = false;
+        if (inputBufferHeader != NULL) {
+            inQueue.erase(inQueue.begin());
 
-        notifyEmptyBufferDone(inputBufferHeader);
-
-        if (mSawInputEOS) {
-            outputBufferHeader->nFlags |= OMX_BUFFERFLAG_EOS;
+            /* If in meta data, call EBD on input */
+            /* In case of normal mode, EBD will be done once encoder
+            releases the input buffer */
+            if (mInputDataIsMeta) {
+                inputBufferInfo->mOwnedByUs = false;
+                notifyEmptyBufferDone(inputBufferHeader);
+            }
         }
 
-        outputBufferInfo->mOwnedByUs = false;
-        outQueue.erase(outQueue.begin());
+        if (s_encode_op.u4_is_last) {
+            outputBufferHeader->nFlags |= OMX_BUFFERFLAG_EOS;
+            mSawOutputEOS = true;
+        } else {
+            outputBufferHeader->nFlags &= ~OMX_BUFFERFLAG_EOS;
+        }
 
-        DUMP_TO_FILE(
-                mOutFile, outputBufferHeader->pBuffer,
-                outputBufferHeader->nFilledLen);
-        notifyFillBufferDone(outputBufferHeader);
+        if (outputBufferHeader->nFilledLen || s_encode_op.u4_is_last) {
+            outputBufferHeader->nTimeStamp = s_encode_op.u4_timestamp_high;
+            outputBufferHeader->nTimeStamp <<= 32;
+            outputBufferHeader->nTimeStamp |= s_encode_op.u4_timestamp_low;
+            outputBufferInfo->mOwnedByUs = false;
+            outQueue.erase(outQueue.begin());
+            DUMP_TO_FILE(mOutFile, outputBufferHeader->pBuffer,
+                    outputBufferHeader->nFilledLen);
+            notifyFillBufferDone(outputBufferHeader);
+        }
 
+        if (s_encode_op.u4_is_last == 1) {
+            return;
+        }
     }
     return;
 }
 
-
 }  // namespace android
 
 android::SoftOMXComponent *createSoftOMXComponent(
diff --git a/media/libstagefright/codecs/avcenc/SoftAVCEnc.h b/media/libstagefright/codecs/avcenc/SoftAVCEnc.h
index 2b35d45..4418a7f 100644
--- a/media/libstagefright/codecs/avcenc/SoftAVCEnc.h
+++ b/media/libstagefright/codecs/avcenc/SoftAVCEnc.h
@@ -17,7 +17,7 @@
 #ifndef __SOFT_AVC_ENC_H__
 #define __SOFT_AVC_ENC_H__
 
-#include <media/stagefright/MediaBuffer.h>
+
 #include <media/stagefright/foundation/ABase.h>
 #include <utils/Vector.h>
 
@@ -25,14 +25,14 @@
 
 namespace android {
 
-class MediaBuffer;
-
+#define MAX_INPUT_BUFFER_HEADERS 4
+#define MAX_CONVERSION_BUFFERS   4
 #define CODEC_MAX_CORES          4
 #define LEN_STATUS_BUFFER        (10  * 1024)
 #define MAX_VBV_BUFF_SIZE        (120 * 16384)
 #define MAX_NUM_IO_BUFS           3
 
-#define DEFAULT_MAX_REF_FRM         1
+#define DEFAULT_MAX_REF_FRM         2
 #define DEFAULT_MAX_REORDER_FRM     0
 #define DEFAULT_QP_MIN              10
 #define DEFAULT_QP_MAX              40
@@ -57,7 +57,7 @@
 #define DEFAULT_TGT_FRAME_RATE      30
 #define DEFAULT_MAX_WD              1920
 #define DEFAULT_MAX_HT              1920
-#define DEFAULT_MAX_LEVEL           40
+#define DEFAULT_MAX_LEVEL           41
 #define DEFAULT_STRIDE              0
 #define DEFAULT_WD                  1280
 #define DEFAULT_HT                  720
@@ -88,6 +88,7 @@
 #define DEFAULT_QPEL                1
 #define DEFAULT_I4                  1
 #define DEFAULT_EPROFILE            IV_PROFILE_BASE
+#define DEFAULT_ENTROPY_MODE        0
 #define DEFAULT_SLICE_MODE          IVE_SLICE_MODE_NONE
 #define DEFAULT_SLICE_PARAM         256
 #define DEFAULT_ARCH                ARCH_ARM_A9Q
@@ -149,8 +150,6 @@
 
     int32_t  mStride;
 
-    uint32_t mFrameRate;
-
     struct timeval mTimeStart;   // Time at the start of decode()
     struct timeval mTimeEnd;     // Time at the end of decode()
 
@@ -167,32 +166,32 @@
 
     IV_COLOR_FORMAT_T mIvVideoColorFormat;
 
-    int32_t  mIDRFrameRefreshIntervalInSec;
     IV_PROFILE_T mAVCEncProfile;
     WORD32   mAVCEncLevel;
-    int64_t  mNumInputFrames;
-    int64_t  mPrevTimestampUs;
     bool     mStarted;
     bool     mSpsPpsHeaderReceived;
 
     bool     mSawInputEOS;
+    bool     mSawOutputEOS;
     bool     mSignalledError;
     bool     mIntra4x4;
     bool     mEnableFastSad;
     bool     mEnableAltRef;
-    bool    mReconEnable;
-    bool    mPSNREnable;
+    bool     mReconEnable;
+    bool     mPSNREnable;
+    bool     mEntropyMode;
     IVE_SPEED_CONFIG     mEncSpeed;
 
-    uint8_t *mConversionBuffer;
-
+    uint8_t *mConversionBuffers[MAX_CONVERSION_BUFFERS];
+    bool     mConversionBuffersFree[MAX_CONVERSION_BUFFERS];
+    BufferInfo *mInputBufferInfo[MAX_INPUT_BUFFER_HEADERS];
     iv_obj_t *mCodecCtx;         // Codec context
     iv_mem_rec_t *mMemRecords;   // Memory records requested by the codec
     size_t mNumMemRecords;       // Number of memory records requested by codec
     size_t mNumCores;            // Number of cores used by the codec
 
     UWORD32 mHeaderGenerated;
-
+    UWORD32 mBframes;
     IV_ARCH_T mArch;
     IVE_SLICE_MODE_T mSliceMode;
     UWORD32 mSliceParam;
@@ -203,7 +202,7 @@
     IVE_AIR_MODE_T mAIRMode;
     UWORD32 mAIRRefreshPeriod;
 
-    OMX_ERRORTYPE initEncParams();
+    void initEncParams();
     OMX_ERRORTYPE initEncoder();
     OMX_ERRORTYPE releaseEncoder();
 
@@ -292,6 +291,8 @@
         fclose(fp);                                     \
     } else {                                            \
         ALOGD("Could not write to file %s", m_filename);\
+        if (fp != NULL)                                 \
+            fclose(fp);                                 \
     }                                                   \
 }
 #else /* FILE_DUMP_ENABLE */