Merge "Fix the 0-timestamp issue Don't return an output buffer back to the omx client if the input buffer(s) processed are only meant for setting the configuration"
diff --git a/libstagefrighthw/TIHardwareRenderer.cpp b/libstagefrighthw/TIHardwareRenderer.cpp
index c5477da..155fe85 100644
--- a/libstagefrighthw/TIHardwareRenderer.cpp
+++ b/libstagefrighthw/TIHardwareRenderer.cpp
@@ -193,7 +193,13 @@
 
     overlay_buffer_t overlay_buffer;
     if (!mIsFirstFrame) {
-        CHECK_EQ(mOverlay->dequeueBuffer(&overlay_buffer), OK);
+        status_t err = mOverlay->dequeueBuffer(&overlay_buffer);
+
+        if (err == ALL_BUFFERS_FLUSHED) {
+            mIsFirstFrame = true;
+        } else {
+            return;
+        }
     } else {
         mIsFirstFrame = false;
     }
diff --git a/omx/system/src/openmax_il/omx_core/src/OMX_Core.c b/omx/system/src/openmax_il/omx_core/src/OMX_Core.c
index 33fd603..af18744 100755
--- a/omx/system/src/openmax_il/omx_core/src/OMX_Core.c
+++ b/omx/system/src/openmax_il/omx_core/src/OMX_Core.c
@@ -88,7 +88,9 @@
     {"OMX.TI.WMA.decode", "audio_decoder.wma"},
     {"OMX.TI.WBAMR.decode", "audio_decoder.amrwb"},
     {"OMX.TI.AMR.decode", "audio_decoder.amrnb"},
+#if 0
     {"OMX.TI.AMR.encode", "audio_encoder.amrnb"},
+#endif
     {"OMX.TI.WBAMR.encode", "audio_encoder.amrwb"},
 #endif
 /*  {"OMX.TI.PCM.encode", NULL},
diff --git a/omx/video/src/openmax_il/video_encode/inc/OMX_VideoEnc_Utils.h b/omx/video/src/openmax_il/video_encode/inc/OMX_VideoEnc_Utils.h
index 5e5470f..e45bb66 100644
--- a/omx/video/src/openmax_il/video_encode/inc/OMX_VideoEnc_Utils.h
+++ b/omx/video/src/openmax_il/video_encode/inc/OMX_VideoEnc_Utils.h
@@ -105,6 +105,7 @@
     #define OMX_BUFFERFLAG_SYNCFRAME 0x00000040
 #endif
 #define OMX_LFRAMETYPE_H264 1
+#define OMX_LFRAMETYPE_IDR_H264 4
 #define OMX_CFRAMETYPE_MPEG4 1
 /*Select Timeout */
 #define  VIDENC_TIMEOUT_SEC 120;
@@ -595,15 +596,16 @@
     OMX_PTR pMarkData;
     OMX_HANDLETYPE hMarkTargetComponent;
     OMX_U32 nFlags;
-    OMX_U32 nCounter;
     /* these are duplicates */
     unsigned int nIntraFrameInterval;  /* should be OMX_VIDEO_CONFIG_AVCINTRAPERIOD */
     unsigned int nTargetFrameRate;  /* should be OMX_CONFIG_FRAMERATETYPE */
+    unsigned int nPrevTargetFrameRate;
     unsigned int nQPI;              /* same as OMX_VIDEO_PARAM_QUANTIZATIONTYPE */
     unsigned int nAIRRate;          /* same as OMX_VIDEO_PARAM_INTRAREFRESHTYPE */
     unsigned int nTargetBitRate;    /* should be OMX_VIDEO_CONFIG_BITRATETYPE */
     OMX_U32 nMIRRate;
     OMX_U8  ucUnrestrictedMV;
+    OMX_BOOL bSentFirstSpsPps;
 
     OMX_U32 nInBufferSize;
     OMX_U32 nOutBufferSize;
@@ -684,6 +686,11 @@
     pthread_mutex_t mutexStateChangeRequest;
     pthread_cond_t StateChangeCondition;
 
+    /* Variable related to variabe frame rate settings */
+    OMX_TICKS nLastUpdateTime;          /* Timstamp of last framerate update */
+    OMX_U32   nFrameRateUpdateInterval; /* Unit is number of frames */
+    OMX_U32   nFrameCount;              /* Number of input frames received since last framerate update */
+    OMX_TICKS nVideoTime;               /* Video duration since last framerate update */
 } VIDENC_COMPONENT_PRIVATE;
 
 typedef OMX_ERRORTYPE (*fpo)(OMX_HANDLETYPE);
diff --git a/omx/video/src/openmax_il/video_encode/src/OMX_VideoEnc_Utils.c b/omx/video/src/openmax_il/video_encode/src/OMX_VideoEnc_Utils.c
index ba0482b..cf7d74d 100644
--- a/omx/video/src/openmax_il/video_encode/src/OMX_VideoEnc_Utils.c
+++ b/omx/video/src/openmax_il/video_encode/src/OMX_VideoEnc_Utils.c
@@ -86,6 +86,10 @@
 // opencore to request the correct level based on resolution/bitrate/etc
 #define VIDEO_ENCODER_MHZ (400 - 45 + 2) 
 
+/* H264 Specific */
+#define SPS_CODE_PREFIX 0x07
+#define PPS_CODE_PREFIX 0x08
+
 #ifdef UNDER_CE
     HINSTANCE g_hLcmlDllHandle = NULL;
 #endif
@@ -2872,9 +2876,23 @@
         }
 
             /* Set lFrameType*/
-            if (((H264VE_GPP_SN_UALGOutputParams*)pBufferPrivate->pUalgParam)->lFrameType == OMX_LFRAMETYPE_H264)
+            if (((H264VE_GPP_SN_UALGOutputParams*)pBufferPrivate->pUalgParam)->lFrameType == OMX_LFRAMETYPE_H264 ||
+                 ((H264VE_GPP_SN_UALGOutputParams*)pBufferPrivate->pUalgParam)->lFrameType == OMX_LFRAMETYPE_IDR_H264)
             {
                 /* IDR Frame */
+                OMX_S32 nalType = pBufHead->pBuffer[0] & 0x1F;
+                if (nalType == SPS_CODE_PREFIX || nalType == PPS_CODE_PREFIX) {
+                    /* Need to drop subsequent SPS or PPS NAL unit since opencore does not
+                     * correctly handle storage */
+                    if (!pComponentPrivate->bSentFirstSpsPps) {
+                        /* we can assume here that PPS always comes second */
+                        if (nalType == PPS_CODE_PREFIX)
+                            pComponentPrivate->bSentFirstSpsPps = OMX_TRUE;
+                    } else {
+                        pBufHead->nFilledLen = 0;
+                    }
+                }
+
                 pBufHead->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
             }
 
@@ -3254,7 +3272,8 @@
 
     /* set run-time frame and bit rates to create-time values */
     pComponentPrivate->nTargetFrameRate       = pCreatePhaseArgs->ulFrameRate;
-
+    pComponentPrivate->nPrevTargetFrameRate   = 0;
+    pComponentPrivate->bSentFirstSpsPps       = OMX_FALSE;
 
     if (pPortDefIn->format.video.eColorFormat == OMX_COLOR_FormatYUV420Planar)
     {
@@ -3383,7 +3402,8 @@
         pCreatePhaseArgs->ucDeblockingEnable  = 0;
         pCreatePhaseArgs->ucLevel = 30;
     }
-
+    /* Ensure frame rate update interval, which forces IDR frames, is same as I-Slice interval */
+    pComponentPrivate->nFrameRateUpdateInterval = pComponentPrivate->nIntraFrameInterval;
     pCreatePhaseArgs->usNalCallback = pComponentPrivate->AVCNALFormat;
     pCreatePhaseArgs->ulEncodingPreset = pComponentPrivate->nEncodingPreset;
     pCreatePhaseArgs->ulRcAlgo = 0;
@@ -3616,6 +3636,7 @@
 
    /* set run-time frame and bit rates to create-time values */
     pComponentPrivate->nTargetFrameRate       = pCreatePhaseArgs->ucFrameRate;
+    pComponentPrivate->nPrevTargetFrameRate   = 0;
     pComponentPrivate->nTargetBitRate         = pCreatePhaseArgs->ulTargetBitRate; 
 
      if (pVidParamBitrate->eControlRate == OMX_Video_ControlRateConstant)
diff --git a/omx/video/src/openmax_il/video_encode/src/OMX_VideoEncoder.c b/omx/video/src/openmax_il/video_encode/src/OMX_VideoEncoder.c
index 20056f1..3cd8c79 100644
--- a/omx/video/src/openmax_il/video_encode/src/OMX_VideoEncoder.c
+++ b/omx/video/src/openmax_il/video_encode/src/OMX_VideoEncoder.c
@@ -941,6 +941,10 @@
     pComponentPrivate->pCapabilityFlags->iOMXComponentSupportsPartialFrames=OMX_FALSE;
     pComponentPrivate->pCapabilityFlags->iOMXComponentUsesFullAVCFrames=OMX_FALSE;
     pComponentPrivate->pCapabilityFlags->iOMXComponentUsesNALStartCode=OMX_FALSE;
+    pComponentPrivate->nLastUpdateTime = 0;
+    pComponentPrivate->nFrameRateUpdateInterval = 60;
+    pComponentPrivate->nFrameCount = 0;
+    pComponentPrivate->nVideoTime = 0;
 
 #ifndef UNDER_CE
     /* Initialize Mutex for Buffer Tracking */
@@ -2831,6 +2835,37 @@
 
     pBufferPrivate->eBufferOwner = VIDENC_BUFFER_WITH_COMPONENT;
     pBufferPrivate->bReadFromPipe = OMX_FALSE;
+    /* Check if frame rate needs to be updated */
+    pComponentPrivate->nFrameCount++;
+    pComponentPrivate->nVideoTime = pBufHead->nTimeStamp - pComponentPrivate->nLastUpdateTime;
+
+    if (pComponentPrivate->nFrameCount == pComponentPrivate->nFrameRateUpdateInterval) {
+
+         if(pComponentPrivate->nVideoTime <= 0) {
+            /* Incorrect time stamps */
+            return OMX_ErrorBadParameter;
+         }
+
+        /* Timestamps are in micro seconds  */
+        pComponentPrivate->nTargetFrameRate = pComponentPrivate->nFrameCount * 1000000 / pComponentPrivate->nVideoTime;
+
+        if(pComponentPrivate->pCompPort[VIDENC_OUTPUT_PORT]->pPortDef->format.video.eCompressionFormat == OMX_VIDEO_CodingAVC) {
+             /* H.264 Socket Node expects frame rate to be multiplied by 1000 */
+             pComponentPrivate->nTargetFrameRate *= 1000;
+
+             if((pComponentPrivate->nPrevTargetFrameRate) &&
+                (pComponentPrivate->nTargetFrameRate ==  pComponentPrivate->nPrevTargetFrameRate)) {
+                  pComponentPrivate->bForceIFrame = OMX_TRUE;
+             }
+             else {
+                  pComponentPrivate->nPrevTargetFrameRate = pComponentPrivate->nTargetFrameRate;
+                  pComponentPrivate->bForceIFrame = OMX_FALSE;
+             }
+        }
+        pComponentPrivate->nLastUpdateTime = pBufHead->nTimeStamp;
+        pComponentPrivate->nFrameCount = 0;
+    }
+
     nRet = write(pComponentPrivate->nFilled_iPipe[1],
                  &(pBufHead),
                  sizeof(pBufHead));