Merge "Fix the problem where the first h264 frame in the recorded video is not marked as sync frame The root cause was that the socket node was not sending the info for SLICE bitstream mode Changes include: 1. Change I-Sync frames to be IDR frames for h264 2. Inform encoder of framerate changes to ensure correct bitrate output"
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));