Fix of issue 4973565 Cannot export movie.
Also fixes 4441452 Native Crash after applying transition

Change-Id: Ic48c44bc2c5d07e57edb8f63393cea424d3275f4
diff --git a/libvideoeditor/osal/inc/M4OSA_Error.h b/libvideoeditor/osal/inc/M4OSA_Error.h
index abcfe4f..4d59529 100755
--- a/libvideoeditor/osal/inc/M4OSA_Error.h
+++ b/libvideoeditor/osal/inc/M4OSA_Error.h
@@ -167,6 +167,8 @@
 /* The server asks for a redirection */
 #define M4WAR_REDIRECT               M4OSA_ERR_CREATE(M4_WAR,M4_COMMON,0x000007)
 #define M4WAR_TOO_MUCH_STREAMS     M4OSA_ERR_CREATE(M4_WAR,M4_COMMON,0x000008)
+/* SF Codec detected INFO_FORMAT_CHANGE during decode */
+#define M4WAR_INFO_FORMAT_CHANGE M4OSA_ERR_CREATE(M4_WAR, M4_COMMON, 0x000009)
 
 #endif /*M4OSA_ERROR_H*/
 
diff --git a/libvideoeditor/vss/common/inc/M4AD_Common.h b/libvideoeditor/vss/common/inc/M4AD_Common.h
index 7efee24..f6e596d 100755
--- a/libvideoeditor/vss/common/inc/M4AD_Common.h
+++ b/libvideoeditor/vss/common/inc/M4AD_Common.h
@@ -67,7 +67,25 @@
     /**
      * Get the number of used bytes in the latest decode
      (used only when decoding AAC from ADIF file) */
-    M4AD_kOptionID_UsedBytes        = M4OSA_OPTION_ID_CREATE(M4_READ , M4DECODER_AUDIO, 0x11)
+    M4AD_kOptionID_UsedBytes        = M4OSA_OPTION_ID_CREATE(M4_READ , M4DECODER_AUDIO, 0x11),
+
+    /* Reader Interface */
+    M4AD_kOptionID_3gpReaderInterface = M4OSA_OPTION_ID_CREATE(M4_READ, M4DECODER_AUDIO, 0x012),
+
+    /* Audio Access Unit */
+    M4AD_kOptionID_AudioAU = M4OSA_OPTION_ID_CREATE(M4_READ, M4DECODER_AUDIO, 0x13),
+
+    /* Reader error code */
+    M4AD_kOptionID_GetAudioAUErrCode = M4OSA_OPTION_ID_CREATE(M4_READ, M4DECODER_AUDIO, 0x14),
+
+    /* Number of channels */
+    M4AD_kOptionID_AudioNbChannels = M4OSA_OPTION_ID_CREATE(M4_READ, M4DECODER_AUDIO, 0x15),
+
+    /* Sampling frequency */
+    M4AD_kOptionID_AudioSampFrequency = M4OSA_OPTION_ID_CREATE(M4_READ, M4DECODER_AUDIO, 0x16),
+
+    /* Audio AU CTS */
+    M4AD_kOptionID_AuCTS = M4OSA_OPTION_ID_CREATE(M4_READ, M4DECODER_AUDIO, 0x17)
 
 } M4AD_OptionID;
 
diff --git a/libvideoeditor/vss/mcs/src/M4MCS_API.c b/libvideoeditor/vss/mcs/src/M4MCS_API.c
index 20a3524..4a4008b 100755
--- a/libvideoeditor/vss/mcs/src/M4MCS_API.c
+++ b/libvideoeditor/vss/mcs/src/M4MCS_API.c
@@ -119,6 +119,8 @@
 static M4OSA_ERR M4MCS_intReallocTemporaryAU(
                                     M4OSA_MemAddr8 *addr,
                                     M4OSA_UInt32 newSize );
+static M4OSA_ERR M4MCS_intCheckAndGetCodecAacProperties(
+                                 M4MCS_InternalContext *pC);
 
 /**
  **********************************************************************
@@ -6083,6 +6085,12 @@
             M4AD_kOptionID_UserParam, (M4OSA_DataOption) &AacDecParam);
     }
 
+    pC->m_pAudioDecoder->m_pFctSetOptionAudioDec(pC->pAudioDecCtxt,
+           M4AD_kOptionID_3gpReaderInterface, (M4OSA_DataOption) pC->m_pReaderDataIt);
+
+    pC->m_pAudioDecoder->m_pFctSetOptionAudioDec(pC->pAudioDecCtxt,
+           M4AD_kOptionID_AudioAU, (M4OSA_DataOption) &pC->ReaderAudioAU);
+
     if( pC->m_pAudioDecoder->m_pFctStartAudioDec != M4OSA_NULL )
     {
         /* Not implemented in all decoders */
@@ -8223,6 +8231,8 @@
     /*FlB 2009.03.04: apply audio effects if an effect is active*/
     M4OSA_Int8 *pActiveEffectNumber = &(pC->pActiveEffectNumber);
 
+    uint32_t errCode = M4NO_ERROR;
+
     if( pC->noaudio )
         return M4NO_ERROR;
 
@@ -8237,49 +8247,9 @@
         goto m4mcs_intaudiotranscoding_feed_resampler;
     }
 
-    /* Check if all audio frame has been decoded */
-    if( pC->ReaderAudioAU.m_size == 0 )
-    {
-        /**
-        * Read the next audio AU in the input file */
-        err = pC->m_pReaderDataIt->m_pFctGetNextAu(pC->pReaderContext,
-            (M4_StreamHandler *)pC->pReaderAudioStream, &pC->ReaderAudioAU);
-
-#ifdef MCS_DUMP_PCM_TO_FILE
-
-        fwrite(pC->ReaderAudioAU.m_dataAddress, pC->ReaderAudioAU.m_size, 1,
-            file_au_reader);
-        fwrite("____", 4, 1, file_au_reader);
-
-#endif
-
-        if( M4WAR_NO_MORE_AU == err ) /**< The audio transcoding is finished */
-        {
-            pC->AudioState = M4MCS_kStreamState_FINISHED;
-            M4OSA_TRACE2_0(
-                "M4MCS_intAudioTranscoding():\
-                 m_pReaderDataIt->m_pFctGetNextAu(audio) returns M4WAR_NO_MORE_AU");
-            return err;
-        }
-        else if( M4NO_ERROR != err )
-        {
-            M4OSA_TRACE1_1(
-                "M4MCS_intAudioTranscoding():\
-                 m_pReaderDataIt->m_pFctGetNextAu(Audio) returns 0x%x",
-                err);
-            return err;
-        }
-    }
-
-    /**
-    * Decode the AU */
-    pC->AudioDecBufferIn.m_dataAddress = pC->ReaderAudioAU.m_dataAddress;
-    pC->AudioDecBufferIn.m_bufferSize = pC->ReaderAudioAU.m_size;
-    pC->AudioDecBufferIn.m_timeStampUs =
-     (int64_t) (pC->ReaderAudioAU.m_CTS * 1000LL);
-
     err = pC->m_pAudioDecoder->m_pFctStepAudioDec(pC->pAudioDecCtxt,
-        &pC->AudioDecBufferIn, &pC->AudioDecBufferOut, M4OSA_FALSE);
+        M4OSA_NULL, &pC->AudioDecBufferOut, M4OSA_FALSE);
+
 
     if( M4NO_ERROR != err )
     {
@@ -8296,10 +8266,16 @@
 
 #endif
 
-    /* update the part of audio that has been decoded into the frame */
+    pC->m_pAudioDecoder->m_pFctGetOptionAudioDec(pC->pAudioDecCtxt,
+           M4AD_kOptionID_GetAudioAUErrCode, (M4OSA_DataOption) &errCode);
 
-    pC->ReaderAudioAU.m_dataAddress += pC->AudioDecBufferIn.m_bufferSize;
-    pC->ReaderAudioAU.m_size -= pC->AudioDecBufferIn.m_bufferSize;
+    if ( M4WAR_NO_MORE_AU == errCode ) {
+        pC->AudioState = M4MCS_kStreamState_FINISHED;
+            M4OSA_TRACE2_0(
+                "M4MCS_intAudioTranscoding():\
+                 m_pReaderDataIt->m_pFctGetNextAu(audio) returns M4WAR_NO_MORE_AU");
+            return errCode;
+   }
 
     /* Set the current position in the decoder out buffer */
     pC->pPosInDecBufferOut = pC->AudioDecBufferOut.m_dataAddress;
@@ -9839,10 +9815,9 @@
             if( M4DA_StreamTypeAudioAac
                 == pC->pReaderAudioStream->m_basicProperties.m_streamType )
             {
-                if( M4OSA_FALSE == pC->bExtOMXAudDecoder )
-                    err = pC->m_pAudioDecoder->m_pFctCreateAudioDec(
-                    &pC->pAudioDecCtxt,
-                    pC->pReaderAudioStream, &(pC->AacProperties));
+                if( M4OSA_FALSE == pC->bExtOMXAudDecoder ) {
+                    err = M4MCS_intCheckAndGetCodecAacProperties(pC);
+                }
                 else
                 {
                     err = pC->m_pAudioDecoder->m_pFctCreateAudioDec(
@@ -10800,3 +10775,97 @@
     return M4NO_ERROR;
 }
 
+M4OSA_ERR M4MCS_intCheckAndGetCodecAacProperties(
+                                 M4MCS_InternalContext *pC) {
+
+    M4OSA_ERR err = M4NO_ERROR;
+    M4AD_Buffer outputBuffer;
+    uint32_t optionValue =0;
+
+    M4OSA_TRACE3_0("M4MCS_intCheckAndGetCodecAacProperties :start");
+
+    // Decode first audio frame from clip to get properties from codec
+
+    err = pC->m_pAudioDecoder->m_pFctCreateAudioDec(
+                    &pC->pAudioDecCtxt,
+                    pC->pReaderAudioStream, &(pC->AacProperties));
+
+    pC->m_pAudioDecoder->m_pFctSetOptionAudioDec(pC->pAudioDecCtxt,
+           M4AD_kOptionID_3gpReaderInterface, (M4OSA_DataOption) pC->m_pReaderDataIt);
+
+    pC->m_pAudioDecoder->m_pFctSetOptionAudioDec(pC->pAudioDecCtxt,
+           M4AD_kOptionID_AudioAU, (M4OSA_DataOption) &pC->ReaderAudioAU);
+
+    if( pC->m_pAudioDecoder->m_pFctStartAudioDec != M4OSA_NULL ) {
+
+        err = pC->m_pAudioDecoder->m_pFctStartAudioDec(pC->pAudioDecCtxt);
+        if( M4NO_ERROR != err ) {
+
+            M4OSA_TRACE1_1(
+                "M4MCS_intCheckAndGetCodecAACProperties: m_pFctStartAudioDec \
+                 returns 0x%x", err);
+            return err;
+        }
+    }
+
+    /**
+    * Allocate output buffer for the audio decoder */
+    outputBuffer.m_bufferSize =
+        pC->pReaderAudioStream->m_byteFrameLength
+        * pC->pReaderAudioStream->m_byteSampleSize
+        * pC->pReaderAudioStream->m_nbChannels;
+
+    if( outputBuffer.m_bufferSize > 0 ) {
+
+        outputBuffer.m_dataAddress =
+            (M4OSA_MemAddr8)M4OSA_32bitAlignedMalloc(outputBuffer.m_bufferSize \
+            *sizeof(short), M4MCS, (M4OSA_Char *)"outputBuffer.m_bufferSize");
+
+        if( M4OSA_NULL == outputBuffer.m_dataAddress ) {
+
+            M4OSA_TRACE1_0(
+                "M4MCS_intCheckAndGetCodecAACProperties():\
+                 unable to allocate outputBuffer.m_dataAddress, returning M4ERR_ALLOC");
+            return M4ERR_ALLOC;
+        }
+    }
+
+    err = pC->m_pAudioDecoder->m_pFctStepAudioDec(pC->pAudioDecCtxt,
+        M4OSA_NULL, &outputBuffer, M4OSA_FALSE);
+
+    if ( err == M4WAR_INFO_FORMAT_CHANGE ) {
+
+        // Get the properties from codec node
+        pC->m_pAudioDecoder->m_pFctGetOptionAudioDec(pC->pAudioDecCtxt,
+           M4AD_kOptionID_AudioNbChannels, (M4OSA_DataOption) &optionValue);
+
+        pC->AacProperties.aNumChan = optionValue;
+        // Reset Reader structure value also
+        pC->pReaderAudioStream->m_nbChannels = optionValue;
+
+        pC->m_pAudioDecoder->m_pFctGetOptionAudioDec(pC->pAudioDecCtxt,
+         M4AD_kOptionID_AudioSampFrequency, (M4OSA_DataOption) &optionValue);
+
+        pC->AacProperties.aSampFreq = optionValue;
+        // Reset Reader structure value also
+        pC->pReaderAudioStream->m_samplingFrequency = optionValue;
+
+    } else if( err != M4NO_ERROR) {
+        M4OSA_TRACE1_1("M4MCS_intCheckAndGetCodecAACProperties:\
+            m_pFctStepAudioDec returns err = 0x%x", err);
+    }
+
+    free(outputBuffer.m_dataAddress);
+
+    // Reset the stream reader
+    err = pC->m_pReader->m_pFctReset(pC->pReaderContext,
+                 (M4_StreamHandler *)pC->pReaderAudioStream);
+
+    if (M4NO_ERROR != err) {
+        M4OSA_TRACE1_1("M4MCS_intCheckAndGetCodecAACProperties\
+            Error in reseting reader: 0x%x", err);
+    }
+
+    return err;
+
+}
diff --git a/libvideoeditor/vss/src/M4VSS3GPP_Clip.c b/libvideoeditor/vss/src/M4VSS3GPP_Clip.c
index 5eaedf7..91ba966 100755
--- a/libvideoeditor/vss/src/M4VSS3GPP_Clip.c
+++ b/libvideoeditor/vss/src/M4VSS3GPP_Clip.c
@@ -61,6 +61,9 @@
 static M4OSA_ERR M4VSS3GPP_intClipPrepareAudioDecoder(
     M4VSS3GPP_ClipContext *pClipCtxt );
 
+static M4OSA_ERR M4VSS3GPP_intCheckAndGetCodecAacProperties(
+        M4VSS3GPP_ClipContext *pClipCtxt);
+
 /**
  ******************************************************************************
  * M4OSA_ERR M4VSS3GPP_intClipOpen()
@@ -1140,16 +1143,16 @@
 
         if( M4OSA_TRUE == pClipCtxt->ShellAPI.bAllowFreeingOMXCodecInterface )
         {
-            /* NXP SW codec interface is used*/
-            if( M4DA_StreamTypeAudioAac == audiotype )
+            if( M4DA_StreamTypeAudioAac == audiotype ) {
+                err = M4VSS3GPP_intCheckAndGetCodecAacProperties(
+                       pClipCtxt);
+            } else if (M4DA_StreamTypeAudioPcm != audiotype) {
                 err = pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctCreateAudioDec(
                 &pClipCtxt->pAudioDecCtxt, pClipCtxt->pAudioStream,
-                &(pClipCtxt->AacProperties));
-            else
-                err = pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctCreateAudioDec(
-                &pClipCtxt->pAudioDecCtxt, pClipCtxt->pAudioStream,
-                M4OSA_NULL /* to be changed with HW interfaces */);
-
+                M4OSA_NULL);
+            } else {
+                err = M4NO_ERROR;
+            }
             if( M4NO_ERROR != err )
             {
                 M4OSA_TRACE1_1(
@@ -1310,6 +1313,16 @@
             M4AD_kOptionID_UserParam, (M4OSA_DataOption) &AacDecParam);
     }
 
+    if( M4OSA_NULL != pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctSetOptionAudioDec ) {
+        pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctSetOptionAudioDec(
+         pClipCtxt->pAudioDecCtxt, M4AD_kOptionID_3gpReaderInterface,
+         (M4OSA_DataOption) pClipCtxt->ShellAPI.m_pReaderDataIt);
+
+        pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctSetOptionAudioDec(
+         pClipCtxt->pAudioDecCtxt, M4AD_kOptionID_AudioAU,
+         (M4OSA_DataOption) &pClipCtxt->AudioAU);
+    }
+
     if( M4OSA_NULL != pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctStartAudioDec )
     {
         /* Not implemented in all decoders */
@@ -1412,16 +1425,26 @@
     {
         /**
         * Decode current AMR frame */
-        pClipCtxt->AudioDecBufferIn.m_dataAddress =
-            (M4OSA_MemAddr8)pClipCtxt->pAudioFramePtr;
-        pClipCtxt->AudioDecBufferIn.m_bufferSize = pClipCtxt->uiAudioFrameSize;
-        pClipCtxt->AudioDecBufferIn.m_timeStampUs =
-            (int64_t) (pClipCtxt->iAudioFrameCts * 1000LL);
+        if ( pClipCtxt->pAudioFramePtr != M4OSA_NULL ) {
+            pClipCtxt->AudioDecBufferIn.m_dataAddress =
+             (M4OSA_MemAddr8)pClipCtxt->pAudioFramePtr;
+            pClipCtxt->AudioDecBufferIn.m_bufferSize =
+             pClipCtxt->uiAudioFrameSize;
+            pClipCtxt->AudioDecBufferIn.m_timeStampUs =
+             (int64_t) (pClipCtxt->iAudioFrameCts * 1000LL);
 
-        err = pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctStepAudioDec(
-            pClipCtxt->pAudioDecCtxt,
-            &pClipCtxt->AudioDecBufferIn, &pClipCtxt->AudioDecBufferOut,
-            M4OSA_FALSE);
+            err = pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctStepAudioDec(
+             pClipCtxt->pAudioDecCtxt,
+             &pClipCtxt->AudioDecBufferIn, &pClipCtxt->AudioDecBufferOut,
+             M4OSA_FALSE);
+        } else {
+            // Pass Null input buffer
+            // Reader invoked from Audio decoder source
+            err = pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctStepAudioDec(
+             pClipCtxt->pAudioDecCtxt,
+             M4OSA_NULL, &pClipCtxt->AudioDecBufferOut,
+             M4OSA_FALSE);
+        }
 
         if( M4NO_ERROR != err )
         {
@@ -1953,3 +1976,102 @@
 
     return (1 + (( frameSize + 7) / 8));
 }
+
+M4OSA_ERR M4VSS3GPP_intCheckAndGetCodecAacProperties(
+                                 M4VSS3GPP_ClipContext *pClipCtxt) {
+
+    M4OSA_ERR err = M4NO_ERROR;
+    M4AD_Buffer outputBuffer;
+    uint32_t optionValue =0;
+
+    // Decode first audio frame from clip to get properties from codec
+
+    err = pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctCreateAudioDec(
+                    &pClipCtxt->pAudioDecCtxt,
+                    pClipCtxt->pAudioStream, &(pClipCtxt->AacProperties));
+
+    pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctSetOptionAudioDec(
+     pClipCtxt->pAudioDecCtxt, M4AD_kOptionID_3gpReaderInterface,
+     (M4OSA_DataOption) pClipCtxt->ShellAPI.m_pReaderDataIt);
+
+    pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctSetOptionAudioDec(
+     pClipCtxt->pAudioDecCtxt, M4AD_kOptionID_AudioAU,
+     (M4OSA_DataOption) &pClipCtxt->AudioAU);
+
+    if( pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctStartAudioDec != M4OSA_NULL ) {
+
+        err = pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctStartAudioDec(
+         pClipCtxt->pAudioDecCtxt);
+        if( M4NO_ERROR != err ) {
+
+            M4OSA_TRACE1_1(
+                "M4VSS3GPP_intCheckAndGetCodecAacProperties: \
+                 m_pFctStartAudioDec returns 0x%x", err);
+            return err;
+        }
+    }
+
+    /**
+    * Allocate output buffer for the audio decoder */
+    outputBuffer.m_bufferSize =
+        pClipCtxt->pAudioStream->m_byteFrameLength
+        * pClipCtxt->pAudioStream->m_byteSampleSize
+        * pClipCtxt->pAudioStream->m_nbChannels;
+
+    if( outputBuffer.m_bufferSize > 0 ) {
+
+        outputBuffer.m_dataAddress =
+            (M4OSA_MemAddr8)M4OSA_32bitAlignedMalloc(outputBuffer.m_bufferSize \
+            *sizeof(short), M4VSS3GPP, (M4OSA_Char *)"outputBuffer.m_bufferSize");
+
+        if( M4OSA_NULL == outputBuffer.m_dataAddress ) {
+
+            M4OSA_TRACE1_0(
+                "M4VSS3GPP_intCheckAndGetCodecAacProperties():\
+                 unable to allocate outputBuffer.m_dataAddress");
+            return M4ERR_ALLOC;
+        }
+    }
+
+    err = pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctStepAudioDec(
+            pClipCtxt->pAudioDecCtxt, M4OSA_NULL, &outputBuffer, M4OSA_FALSE);
+
+    if ( err == M4WAR_INFO_FORMAT_CHANGE ) {
+
+        // Get the properties from codec node
+        pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctGetOptionAudioDec(
+         pClipCtxt->pAudioDecCtxt,
+           M4AD_kOptionID_AudioNbChannels, (M4OSA_DataOption) &optionValue);
+
+        pClipCtxt->AacProperties.aNumChan = optionValue;
+        // Reset Reader structure value also
+        pClipCtxt->pAudioStream->m_nbChannels = optionValue;
+
+        pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctGetOptionAudioDec(
+         pClipCtxt->pAudioDecCtxt,
+          M4AD_kOptionID_AudioSampFrequency, (M4OSA_DataOption) &optionValue);
+
+        pClipCtxt->AacProperties.aSampFreq = optionValue;
+        // Reset Reader structure value also
+        pClipCtxt->pAudioStream->m_samplingFrequency = optionValue;
+
+    } else if( err != M4NO_ERROR) {
+        M4OSA_TRACE1_1("M4VSS3GPP_intCheckAndGetCodecAacProperties:\
+            m_pFctStepAudioDec returns err = 0x%x", err);
+    }
+
+    free(outputBuffer.m_dataAddress);
+
+    // Reset the stream reader
+    err = pClipCtxt->ShellAPI.m_pReader->m_pFctReset(
+     pClipCtxt->pReaderContext,
+     (M4_StreamHandler *)pClipCtxt->pAudioStream);
+
+    if (M4NO_ERROR != err) {
+        M4OSA_TRACE1_1("M4VSS3GPP_intCheckAndGetCodecAacProperties\
+            Error in reseting reader: 0x%x", err);
+    }
+
+    return err;
+
+}
diff --git a/libvideoeditor/vss/src/M4VSS3GPP_EditAudio.c b/libvideoeditor/vss/src/M4VSS3GPP_EditAudio.c
index 85b939d..746883d 100755
--- a/libvideoeditor/vss/src/M4VSS3GPP_EditAudio.c
+++ b/libvideoeditor/vss/src/M4VSS3GPP_EditAudio.c
@@ -229,6 +229,7 @@
 M4OSA_ERR M4VSS3GPP_intEditStepAudio( M4VSS3GPP_InternalEditContext *pC )
 {
     M4OSA_ERR err;
+    int32_t auTimeStamp = -1;
 
     M4ENCODER_AudioBuffer pEncInBuffer;  /**< Encoder input buffer for api */
     M4ENCODER_AudioBuffer pEncOutBuffer; /**< Encoder output buffer for api */
@@ -563,23 +564,21 @@
                             } //if(0 != pEncInBuffer.pTableBufferSize[0])
 
 #endif
+                            pC->pC1->pAudioFramePtr = M4OSA_NULL;
 
-                            err = M4VSS3GPP_intClipReadNextAudioFrame(pC->pC1);
+                            // Get timestamp of last read AU
+                            pC->pC1->ShellAPI.m_pAudioDecoder->m_pFctGetOptionAudioDec(
+                             pC->pC1->pAudioDecCtxt, M4AD_kOptionID_AuCTS,
+                             (M4OSA_DataOption) &auTimeStamp);
 
-                            M4OSA_TRACE2_3(
-                                "F .... read  : cts  = %.0f + %.0f [ 0x%x ]",
-                                pC->pC1->iAudioFrameCts / pC->pC1->scale_audio,
-                                pC->pC1->iAoffset / pC->pC1->scale_audio,
-                                pC->pC1->uiAudioFrameSize);
-
-                            if( M4OSA_ERR_IS_ERROR(err) )
-                            {
-                                M4OSA_TRACE1_1(
-                                    "M4VSS3GPP_intEditStepAudio: DECODE_ENCODE-prefetch:\
-                                    M4VSS3GPP_intClipReadNextAudioFrame(b) returns 0x%x!",
-                                    err);
-                                return err;
+                            if (auTimeStamp == -1) {
+                                M4OSA_TRACE1_0("M4VSS3GPP_intEditStepAudio: \
+                                 invalid audio timestamp returned");
+                                return M4WAR_INVALID_TIME;
                             }
+
+                            pC->pC1->iAudioFrameCts = auTimeStamp;
+
                         }
                     }
 
@@ -601,6 +600,21 @@
                     return err;
                 }
 
+                pC->pC1->pAudioFramePtr = M4OSA_NULL;
+
+                // Get timestamp of last read AU
+                pC->pC1->ShellAPI.m_pAudioDecoder->m_pFctGetOptionAudioDec(
+                 pC->pC1->pAudioDecCtxt, M4AD_kOptionID_AuCTS,
+                 (M4OSA_DataOption) &auTimeStamp);
+
+                if (auTimeStamp == -1) {
+                    M4OSA_TRACE1_0("M4VSS3GPP_intEditStepAudio: invalid audio \
+                     timestamp returned");
+                    return M4WAR_INVALID_TIME;
+                }
+
+                pC->pC1->iAudioFrameCts = auTimeStamp;
+
                 /**
                 * Apply the effect */
                 if( pC->iClip1ActiveEffect >= 0 )
diff --git a/libvideoeditor/vss/stagefrightshells/src/VideoEditorAudioDecoder.cpp b/libvideoeditor/vss/stagefrightshells/src/VideoEditorAudioDecoder.cpp
index 0227e0a..3ffdf21 100755
--- a/libvideoeditor/vss/stagefrightshells/src/VideoEditorAudioDecoder.cpp
+++ b/libvideoeditor/vss/stagefrightshells/src/VideoEditorAudioDecoder.cpp
@@ -52,7 +52,7 @@
 struct VideoEditorAudioDecoderSource : public MediaSource {
     public:
         static sp<VideoEditorAudioDecoderSource> Create(
-                const sp<MetaData>& format);
+                const sp<MetaData>& format, void *decoderShellContext);
         virtual status_t start(MetaData *params = NULL);
         virtual status_t stop();
         virtual sp<MetaData> getFormat();
@@ -73,37 +73,63 @@
             STARTED,
             ERROR
         };
-        VideoEditorAudioDecoderSource(const sp<MetaData>& format);
+        VideoEditorAudioDecoderSource(const sp<MetaData>& format,
+         void *decoderShellContext);
         sp<MetaData> mFormat;
         MediaBufferChain* mFirstBufferLink;
         MediaBufferChain* mLastBufferLink;
         int32_t mNbBuffer;
         bool mIsEOS;
         State mState;
-
+        void* mDecShellContext;
         // Don't call me.
         VideoEditorAudioDecoderSource(const VideoEditorAudioDecoderSource&);
         VideoEditorAudioDecoderSource& operator=(
             const VideoEditorAudioDecoderSource &);
 };
 
+/**
+ ******************************************************************************
+ * structure VideoEditorAudioDecoder_Context
+ * @brief    This structure defines the context of the StageFright audio decoder
+ *           shell
+ ******************************************************************************
+*/
+
+typedef struct {
+    M4AD_Type                          mDecoderType;
+    M4_AudioStreamHandler*             mAudioStreamHandler;
+    sp<VideoEditorAudioDecoderSource>  mDecoderSource;
+    OMXClient                          mClient;
+    sp<MediaSource>                    mDecoder;
+    int32_t                            mNbOutputChannels;
+    uint32_t                           mNbInputFrames;
+    uint32_t                           mNbOutputFrames;
+    M4READER_DataInterface  *m_pReader;
+    M4_AccessUnit* m_pNextAccessUnitToDecode;
+    M4OSA_ERR readerErrCode;
+    int32_t timeStampMs;
+
+} VideoEditorAudioDecoder_Context;
+
 sp<VideoEditorAudioDecoderSource> VideoEditorAudioDecoderSource::Create(
-        const sp<MetaData>& format) {
+        const sp<MetaData>& format, void *decoderShellContext) {
 
     sp<VideoEditorAudioDecoderSource> aSource =
-        new VideoEditorAudioDecoderSource(format);
+        new VideoEditorAudioDecoderSource(format, decoderShellContext);
 
     return aSource;
 }
 
 VideoEditorAudioDecoderSource::VideoEditorAudioDecoderSource(
-        const sp<MetaData>& format):
+        const sp<MetaData>& format, void* decoderShellContext):
         mFormat(format),
         mFirstBufferLink(NULL),
         mLastBufferLink(NULL),
         mNbBuffer(0),
         mIsEOS(false),
-        mState(CREATED) {
+        mState(CREATED),
+        mDecShellContext(decoderShellContext) {
 }
 
 VideoEditorAudioDecoderSource::~VideoEditorAudioDecoderSource() {
@@ -168,6 +194,10 @@
     MediaSource::ReadOptions readOptions;
     status_t err = OK;
     MediaBufferChain* tmpLink = NULL;
+    M4OSA_ERR lerr = M4NO_ERROR;
+
+    VideoEditorAudioDecoder_Context* pDecContext =
+     (VideoEditorAudioDecoder_Context *)mDecShellContext;
 
     LOGV("VideoEditorAudioDecoderSource::read begin");
 
@@ -178,14 +208,40 @@
 
     // Get a buffer from the chain
     if( NULL == mFirstBufferLink ) {
-        *buffer = NULL;
-        if( mIsEOS ) {
+        M4_AccessUnit* pAccessUnit = pDecContext->m_pNextAccessUnitToDecode;
+
+        // Get next AU from reader.
+        lerr = pDecContext->m_pReader->m_pFctGetNextAu(
+                   pDecContext->m_pReader->m_readerContext,
+                   (M4_StreamHandler*)pDecContext->mAudioStreamHandler,
+                   pAccessUnit);
+
+        if (lerr == M4WAR_NO_MORE_AU) {
+            LOGV("VideoEditorAudioDecoderSource::getNextAU() returning err = "
+                "ERROR_END_OF_STREAM;");
+            *buffer = NULL;
             LOGV("VideoEditorAudioDecoderSource::read : EOS");
+            pDecContext->readerErrCode = M4WAR_NO_MORE_AU;
             return ERROR_END_OF_STREAM;
-        } else {
-            LOGV("VideoEditorAudioDecoderSource::read : no buffer available");
-            return UNKNOWN_ERROR;
         }
+
+        MediaBufferChain* newLink = new MediaBufferChain;
+        MediaBuffer* newBuffer = new MediaBuffer((size_t)pAccessUnit->m_size);
+        memcpy((void *)((M4OSA_Int8*)newBuffer->data() + newBuffer->range_offset()),
+            (void *)pAccessUnit->m_dataAddress, pAccessUnit->m_size);
+        newBuffer->meta_data()->setInt64(kKeyTime, (pAccessUnit->m_CTS * 1000LL));
+
+        pDecContext->timeStampMs = pAccessUnit->m_CTS;
+        newLink->buffer = newBuffer;
+        newLink->nextLink = NULL;
+        if( NULL != mLastBufferLink ) {
+            mLastBufferLink->nextLink = newLink;
+        } else {
+            mFirstBufferLink = newLink;
+        }
+        mLastBufferLink = newLink;
+        mNbBuffer++;
+
     }
     *buffer = mFirstBufferLink->buffer;
 
@@ -203,24 +259,51 @@
 
 int32_t VideoEditorAudioDecoderSource::storeBuffer(MediaBuffer *buffer) {
     status_t err = OK;
+    M4OSA_ERR lerr = M4NO_ERROR;
+    MediaBufferChain* newLink = new MediaBufferChain;
+
+    VideoEditorAudioDecoder_Context* pDecContext =
+     (VideoEditorAudioDecoder_Context *)mDecShellContext;
 
     LOGV("VideoEditorAudioDecoderSource::storeBuffer begin");
 
-    // A NULL input buffer means that the end of stream was reached
     if( NULL == buffer ) {
-        mIsEOS = true;
-    } else {
-        MediaBufferChain* newLink = new MediaBufferChain;
-        newLink->buffer = buffer;
-        newLink->nextLink = NULL;
-        if( NULL != mLastBufferLink ) {
-            mLastBufferLink->nextLink = newLink;
-        } else {
-            mFirstBufferLink = newLink;
+        M4_AccessUnit* pAccessUnit = pDecContext->m_pNextAccessUnitToDecode;
+        // Get next AU from reader.
+        lerr = pDecContext->m_pReader->m_pFctGetNextAu(
+                   pDecContext->m_pReader->m_readerContext,
+                   (M4_StreamHandler*)pDecContext->mAudioStreamHandler,
+                   pAccessUnit);
+
+        if (lerr == M4WAR_NO_MORE_AU) {
+            LOGV("VideoEditorAudioDecoderSource::getNextAU() returning err = "
+                "ERROR_END_OF_STREAM;");
+            pDecContext->readerErrCode = M4WAR_NO_MORE_AU;
+            delete newLink;
+            return mNbBuffer;
         }
-        mLastBufferLink = newLink;
-        mNbBuffer++;
+
+        MediaBuffer* newBuffer = new MediaBuffer((size_t)pAccessUnit->m_size);
+        memcpy((void *)((M4OSA_Int8*)newBuffer->data() + newBuffer->range_offset()),
+            (void *)pAccessUnit->m_dataAddress, pAccessUnit->m_size);
+        newBuffer->meta_data()->setInt64(kKeyTime, (pAccessUnit->m_CTS * 1000LL));
+
+        pDecContext->timeStampMs = pAccessUnit->m_CTS;
+        newLink->buffer = newBuffer;
+
+    } else {
+        LOGV("VideoEditorAudioDecoderSource::storeBuffer else case");
+        newLink->buffer = buffer;
     }
+    newLink->nextLink = NULL;
+    if( NULL != mLastBufferLink ) {
+        mLastBufferLink->nextLink = newLink;
+    } else {
+        mFirstBufferLink = newLink;
+    }
+    mLastBufferLink = newLink;
+    mNbBuffer++;
+
     LOGV("VideoEditorAudioDecoderSource::storeBuffer END");
     return mNbBuffer;
 }
@@ -353,24 +436,6 @@
  * ENGINE INTERFACE *
  ********************/
 
-/**
- ******************************************************************************
- * structure VideoEditorAudioDecoder_Context
- * @brief    This structure defines the context of the StageFright audio decoder
- *           shell
- ******************************************************************************
-*/
-typedef struct {
-    M4AD_Type                          mDecoderType;
-    M4_AudioStreamHandler*             mAudioStreamHandler;
-    sp<VideoEditorAudioDecoderSource>  mDecoderSource;
-    OMXClient                          mClient;
-    sp<MediaSource>                    mDecoder;
-    int32_t                            mNbOutputChannels;
-    uint32_t                           mNbInputFrames;
-    uint32_t                           mNbOutputFrames;
-} VideoEditorAudioDecoder_Context;
-
 M4OSA_ERR VideoEditorAudioDecoder_destroy(M4AD_Context pContext) {
     M4OSA_ERR err = M4NO_ERROR;
     VideoEditorAudioDecoder_Context* pDecoderContext = M4OSA_NULL;
@@ -430,6 +495,8 @@
 
     pDecoderContext->mNbInputFrames  = 0;
     pDecoderContext->mNbOutputFrames = 0;
+    pDecoderContext->readerErrCode = M4NO_ERROR;
+    pDecoderContext->timeStampMs = -1;
 
     LOGV("VideoEditorAudioDecoder_create : maxAUSize %d",
         pDecoderContext->mAudioStreamHandler->m_basicProperties.m_maxAUSize);
@@ -518,7 +585,7 @@
 
     // Create the decoder source
     pDecoderContext->mDecoderSource = VideoEditorAudioDecoderSource::Create(
-        decoderMetaData);
+        decoderMetaData, (void *)pDecoderContext);
     VIDEOEDITOR_CHECK(NULL != pDecoderContext->mDecoderSource.get(),
         M4ERR_STATE);
 
@@ -709,11 +776,32 @@
 
     // Read
     result = pDecoderContext->mDecoder->read(&outputBuffer, NULL);
-    if(OK != result) {
-        LOGE("VideoEditorAudioDecoder_step  result = %d",result);
+    if (INFO_FORMAT_CHANGED == result) {
+        LOGV("VideoEditorAudioDecoder_step: Audio decoder \
+         returned INFO_FORMAT_CHANGED");
+        CHECK(outputBuffer == NULL);
+        sp<MetaData> meta = pDecoderContext->mDecoder->getFormat();
+        int32_t sampleRate, channelCount;
 
+        CHECK(meta->findInt32(kKeySampleRate, &sampleRate));
+        CHECK(meta->findInt32(kKeyChannelCount, &channelCount));
+        LOGV("VideoEditorAudioDecoder_step: samplingFreq = %d", sampleRate);
+        LOGV("VideoEditorAudioDecoder_step: channelCnt = %d", channelCount);
+        pDecoderContext->mAudioStreamHandler->m_samplingFrequency =
+         (uint32_t)sampleRate;
+        pDecoderContext->mAudioStreamHandler->m_nbChannels =
+         (uint32_t)channelCount;
+        pDecoderContext->mNbOutputChannels = channelCount;
+
+        return M4WAR_INFO_FORMAT_CHANGE;
+    } else if (ERROR_END_OF_STREAM == result) {
+        LOGV("VideoEditorAudioDecoder_step: Audio decoder \
+         returned ERROR_END_OF_STREAM");
+        pDecoderContext->readerErrCode = M4WAR_NO_MORE_AU;
+        return M4WAR_NO_MORE_AU;
+    } else if (OK != result) {
+        return M4ERR_STATE;
     }
-    VIDEOEDITOR_CHECK(OK == result, M4ERR_STATE);
 
     // Convert the PCM buffer
     err = VideoEditorAudioDecoder_processOutputBuffer(pDecoderContext,
@@ -769,6 +857,19 @@
             LOGV("VideoEditorAudioDecodersetOption UserParam is not supported");
             err = M4ERR_NOT_IMPLEMENTED;
             break;
+
+        case M4AD_kOptionID_3gpReaderInterface:
+            LOGV("VideoEditorAudioDecodersetOption 3gpReaderInterface");
+            pDecoderContext->m_pReader =
+             (M4READER_DataInterface *)optionValue;
+            break;
+
+        case M4AD_kOptionID_AudioAU:
+            LOGV("VideoEditorAudioDecodersetOption AudioAU");
+            pDecoderContext->m_pNextAccessUnitToDecode =
+             (M4_AccessUnit *)optionValue;
+            break;
+
         default:
             LOGV("VideoEditorAudioDecoder_setOption  unsupported optionId 0x%X",
                 optionID);
@@ -799,6 +900,25 @@
     pDecoderContext = (VideoEditorAudioDecoder_Context*)pContext;
 
     switch( optionID ) {
+
+        case M4AD_kOptionID_GetAudioAUErrCode:
+            *(uint32_t *)optionValue = pDecoderContext->readerErrCode;
+            break;
+
+        case M4AD_kOptionID_AudioNbChannels:
+            *(uint32_t *)optionValue =
+             pDecoderContext->mAudioStreamHandler->m_nbChannels;
+            break;
+
+        case M4AD_kOptionID_AudioSampFrequency:
+            *(uint32_t *)optionValue =
+             pDecoderContext->mAudioStreamHandler->m_samplingFrequency;
+            break;
+
+        case M4AD_kOptionID_AuCTS:
+            *(uint32_t *)optionValue = pDecoderContext->timeStampMs;
+            break;
+
         default:
             LOGV("VideoEditorAudioDecoder_getOption unsupported optionId 0x%X",
                 optionID);