Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 /**
     17  ******************************************************************************
     18  * @file    M4VSS3GPP_AudioMixing.c
     19  * @brief    Video Studio Service 3GPP audio mixing implementation.
     20  * @note
     21  ******************************************************************************
     22  */
     23 
     24 /****************/
     25 /*** Includes ***/
     26 /****************/
     27 
     28 #include "NXPSW_CompilerSwitches.h"
     29 /**
     30  * Our headers */
     31 #include "M4VSS3GPP_API.h"
     32 #include "M4VSS3GPP_InternalTypes.h"
     33 #include "M4VSS3GPP_InternalFunctions.h"
     34 #include "M4VSS3GPP_ErrorCodes.h"
     35 
     36 /* Put the definition of silence frames here */
     37 #define M4VSS3GPP_SILENCE_FRAMES
     38 #include "M4VSS3GPP_InternalConfig.h"
     39 
     40 /**
     41  * OSAL headers */
     42 #include "M4OSA_Memory.h" /**< OSAL memory management */
     43 #include "M4OSA_Debug.h"  /**< OSAL debug management */
     44 
     45 
     46 #include "VideoEditorResampler.h"
     47 /**
     48  ******************************************************************************
     49  * @brief    Static functions
     50  ******************************************************************************
     51  */
     52 static M4OSA_ERR
     53 M4VSS3GPP_intAudioMixingOpen( M4VSS3GPP_InternalAudioMixingContext *pC,
     54                              M4VSS3GPP_AudioMixingSettings *pSettings );
     55 static M4OSA_ERR M4VSS3GPP_intAudioMixingStepVideo(
     56     M4VSS3GPP_InternalAudioMixingContext *pC );
     57 static M4OSA_ERR M4VSS3GPP_intAudioMixingStepAudioMix(
     58     M4VSS3GPP_InternalAudioMixingContext *pC );
     59 static M4OSA_ERR M4VSS3GPP_intAudioMixingStepAudioReplace(
     60     M4VSS3GPP_InternalAudioMixingContext *pC );
     61 static M4OSA_ERR M4VSS3GPP_intAudioMixingCopyOrig(
     62     M4VSS3GPP_InternalAudioMixingContext *pC );
     63 static M4OSA_ERR M4VSS3GPP_intAudioMixingCopyAdded(
     64     M4VSS3GPP_InternalAudioMixingContext *pC );
     65 static M4OSA_ERR M4VSS3GPP_intAudioMixingConvert(
     66     M4VSS3GPP_InternalAudioMixingContext *pC );
     67 static M4OSA_ERR M4VSS3GPP_intAudioMixingDoMixing(
     68     M4VSS3GPP_InternalAudioMixingContext *pC );
     69 static M4OSA_ERR M4VSS3GPP_intAudioMixingWriteSilence(
     70     M4VSS3GPP_InternalAudioMixingContext *pC );
     71 static M4OSA_ERR M4VSS3GPP_intAudioMixingTransition(
     72     M4VSS3GPP_InternalAudioMixingContext *pC );
     73 static M4OSA_ERR M4VSS3GPP_intAudioMixingCreateVideoEncoder(
     74     M4VSS3GPP_InternalAudioMixingContext *pC );
     75 static M4OSA_ERR M4VSS3GPP_intAudioMixingDestroyVideoEncoder(
     76     M4VSS3GPP_InternalAudioMixingContext *pC );
     77 static M4OSA_Bool M4VSS3GPP_isThresholdBreached( M4OSA_Int32 *averageValue,
     78                                                 M4OSA_Int32 storeCount,
     79                                                 M4OSA_Int32 thresholdValue );
     80 /**
     81  *    Internal warning */
     82 #define M4VSS3GPP_WAR_END_OF_ADDED_AUDIO    M4OSA_ERR_CREATE( M4_WAR, M4VSS3GPP, 0x0030)
     83 
     84 /* A define used with SSRC 1.04 and above to avoid taking
     85 blocks smaller that the minimal block size */
     86 #define M4VSS_SSRC_MINBLOCKSIZE        600
     87 
     88 /**
     89  ******************************************************************************
     90  * M4OSA_ERR M4VSS3GPP_audioMixingInit(M4VSS3GPP_AudioMixingContext* pContext,
     91  *                                     M4VSS3GPP_AudioMixingSettings* pSettings)
     92  * @brief    Initializes the VSS audio mixing operation (allocates an execution context).
     93  * @note
     94  * @param    pContext        (OUT) Pointer on the VSS audio mixing context to allocate
     95  * @param    pSettings        (IN) Pointer to valid audio mixing settings
     96  * @param    pFileReadPtrFct        (IN) Pointer to OSAL file reader functions
     97  * @param   pFileWritePtrFct    (IN) Pointer to OSAL file writer functions
     98  * @return    M4NO_ERROR:            No error
     99  * @return    M4ERR_PARAMETER:    At least one parameter is M4OSA_NULL (debug only)
    100  * @return    M4ERR_ALLOC:        There is no more available memory
    101  ******************************************************************************
    102  */
    103 
    104 M4OSA_ERR M4VSS3GPP_audioMixingInit( M4VSS3GPP_AudioMixingContext *pContext,
    105                                     M4VSS3GPP_AudioMixingSettings *pSettings,
    106                                     M4OSA_FileReadPointer *pFileReadPtrFct,
    107                                     M4OSA_FileWriterPointer *pFileWritePtrFct )
    108 {
    109     M4VSS3GPP_InternalAudioMixingContext *pC;
    110     M4OSA_ERR err;
    111 
    112     M4OSA_TRACE3_2(
    113         "M4VSS3GPP_audioMixingInit called with pContext=0x%x, pSettings=0x%x",
    114         pContext, pSettings);
    115 
    116     /**
    117     * Check input parameters */
    118     M4OSA_DEBUG_IF2((M4OSA_NULL == pContext), M4ERR_PARAMETER,
    119         "M4VSS3GPP_audioMixingInit: pContext is M4OSA_NULL");
    120     M4OSA_DEBUG_IF2((M4OSA_NULL == pSettings), M4ERR_PARAMETER,
    121         "M4VSS3GPP_audioMixingInit: pSettings is M4OSA_NULL");
    122     M4OSA_DEBUG_IF2((M4OSA_NULL == pFileReadPtrFct), M4ERR_PARAMETER,
    123         "M4VSS3GPP_audioMixingInit: pFileReadPtrFct is M4OSA_NULL");
    124     M4OSA_DEBUG_IF2((M4OSA_NULL == pFileWritePtrFct), M4ERR_PARAMETER,
    125         "M4VSS3GPP_audioMixingInit: pFileWritePtrFct is M4OSA_NULL");
    126 
    127     if( pSettings->uiBeginLoop > pSettings->uiEndLoop )
    128     {
    129         M4OSA_TRACE1_0(
    130             "M4VSS3GPP_audioMixingInit: Begin loop time is higher than end loop time!");
    131         return M4VSS3GPP_ERR_BEGINLOOP_HIGHER_ENDLOOP;
    132     }
    133 
    134     /**
    135     * Allocate the VSS audio mixing context and return it to the user */
    136     pC = (M4VSS3GPP_InternalAudioMixingContext
    137         *)M4OSA_32bitAlignedMalloc(sizeof(M4VSS3GPP_InternalAudioMixingContext),
    138         M4VSS3GPP,(M4OSA_Char *)"M4VSS3GPP_InternalAudioMixingContext");
    139     *pContext = pC;
    140 
    141     if( M4OSA_NULL == pC )
    142     {
    143         M4OSA_TRACE1_0(
    144             "M4VSS3GPP_audioMixingInit(): unable to allocate \
    145             M4VSS3GPP_InternalAudioMixingContext,returning M4ERR_ALLOC");
    146         return M4ERR_ALLOC;
    147     }
    148 
    149     /* Initialization of context Variables */
    150     memset((void *)pC ,0,
    151                  sizeof(M4VSS3GPP_InternalAudioMixingContext));
    152     /**
    153     * Copy this setting in context */
    154     pC->iAddCts = pSettings->uiAddCts;
    155     pC->bRemoveOriginal = pSettings->bRemoveOriginal;
    156     pC->b_DuckingNeedeed = pSettings->b_DuckingNeedeed;
    157     pC->InDucking_threshold = pSettings->InDucking_threshold;
    158     pC->fBTVolLevel = pSettings->fBTVolLevel;
    159     pC->fPTVolLevel = pSettings->fPTVolLevel;
    160     pC->InDucking_lowVolume = pSettings->InDucking_lowVolume;
    161     pC->bDoDucking = M4OSA_FALSE;
    162     pC->bLoop = pSettings->bLoop;
    163     pC->bNoLooping = M4OSA_FALSE;
    164     pC->bjumpflag = M4OSA_TRUE;
    165     /**
    166     * Init some context variables */
    167 
    168     pC->pInputClipCtxt = M4OSA_NULL;
    169     pC->pAddedClipCtxt = M4OSA_NULL;
    170     pC->fOrigFactor = 1.0F;
    171     pC->fAddedFactor = 0.0F;
    172     pC->bSupportSilence = M4OSA_FALSE;
    173     pC->bHasAudio = M4OSA_FALSE;
    174     pC->bAudioMixingIsNeeded = M4OSA_FALSE;
    175 
    176     /* Init PC->ewc members */
    177     // Decorrelate input and output encoding timestamp to handle encoder prefetch
    178     pC->ewc.VideoStreamType = M4SYS_kVideoUnknown;
    179     pC->ewc.bVideoDataPartitioning = M4OSA_FALSE;
    180     pC->ewc.pVideoOutputDsi = M4OSA_NULL;
    181     pC->ewc.AudioStreamType = M4SYS_kAudioUnknown;
    182     pC->ewc.uiNbChannels = 1;
    183     pC->ewc.pAudioOutputDsi = M4OSA_NULL;
    184     pC->ewc.pAudioEncCtxt = M4OSA_NULL;
    185     pC->ewc.pAudioEncDSI.pInfo = M4OSA_NULL;
    186     pC->ewc.pSilenceFrameData = M4OSA_NULL;
    187     pC->ewc.pEncContext = M4OSA_NULL;
    188     pC->ewc.pDummyAuBuffer = M4OSA_NULL;
    189     pC->ewc.p3gpWriterContext = M4OSA_NULL;
    190     pC->pLVAudioResampler = M4OSA_NULL;
    191     /**
    192     * Set the OSAL filesystem function set */
    193     pC->pOsaFileReadPtr = pFileReadPtrFct;
    194     pC->pOsaFileWritPtr = pFileWritePtrFct;
    195 
    196     /**
    197     * Ssrc stuff */
    198     pC->b_SSRCneeded = M4OSA_FALSE;
    199     pC->pSsrcBufferIn = M4OSA_NULL;
    200     pC->pSsrcBufferOut = M4OSA_NULL;
    201     pC->pTempBuffer = M4OSA_NULL;
    202     pC->pPosInTempBuffer = M4OSA_NULL;
    203     pC->pPosInSsrcBufferIn = M4OSA_NULL;
    204     pC->pPosInSsrcBufferOut = M4OSA_NULL;
    205     pC->SsrcScratch = M4OSA_NULL;
    206     pC->uiBeginLoop = pSettings->uiBeginLoop;
    207     pC->uiEndLoop = pSettings->uiEndLoop;
    208 
    209     /*
    210     * Reset pointers for media and codecs interfaces */
    211     err = M4VSS3GPP_clearInterfaceTables(&pC->ShellAPI);
    212     M4ERR_CHECK_RETURN(err);
    213 
    214     /*  Call the media and codecs subscription module */
    215     err = M4VSS3GPP_subscribeMediaAndCodec(&pC->ShellAPI);
    216     M4ERR_CHECK_RETURN(err);
    217 
    218     /**
    219     * Open input clip, added clip and output clip and proceed with the settings */
    220     err = M4VSS3GPP_intAudioMixingOpen(pC, pSettings);
    221     M4ERR_CHECK_RETURN(err);
    222 
    223     /**
    224     * Update main state automaton */
    225     if( M4OSA_NULL != pC->pInputClipCtxt->pVideoStream )
    226         pC->State = M4VSS3GPP_kAudioMixingState_VIDEO;
    227     else
    228         pC->State = M4VSS3GPP_kAudioMixingState_AUDIO_FIRST_SEGMENT;
    229 
    230     pC->ewc.iOutputDuration = (M4OSA_Int32)pC->pInputClipCtxt->pSettings->
    231         ClipProperties.uiClipDuration;
    232     /*gInputParams.lvBTChannelCount*/
    233     pC->pLVAudioResampler = LVAudioResamplerCreate(16,
    234         pC->pAddedClipCtxt->pSettings->ClipProperties.uiNbChannels,
    235         /* gInputParams.lvOutSampleRate*/(M4OSA_Int32)pSettings->outputASF, 1);
    236      if( M4OSA_NULL == pC->pLVAudioResampler )
    237      {
    238          return M4ERR_ALLOC;
    239      }
    240         LVAudiosetSampleRate(pC->pLVAudioResampler,
    241         /*gInputParams.lvInSampleRate*/
    242         pC->pAddedClipCtxt->pSettings->ClipProperties.uiSamplingFrequency);
    243 
    244     LVAudiosetVolume(pC->pLVAudioResampler,
    245                     (M4OSA_Int16)(0x1000 ),
    246                     (M4OSA_Int16)(0x1000 ));
    247 
    248     /**
    249     * Return with no error */
    250     M4OSA_TRACE3_0("M4VSS3GPP_audioMixingInit(): returning M4NO_ERROR");
    251     return M4NO_ERROR;
    252 }
    253 
    254 /**
    255  ******************************************************************************
    256  * M4OSA_ERR M4VSS3GPP_audioMixingStep(M4VSS3GPP_AudioMixingContext pContext)
    257  * @brief    Perform one step of audio mixing.
    258  * @note
    259  * @param     pContext          (IN) VSS audio mixing context
    260  * @return    M4NO_ERROR:       No error
    261  * @return    M4ERR_PARAMETER:  pContext is M4OSA_NULL (debug only)
    262  * @param     pProgress         (OUT) Progress percentage (0 to 100) of the finalization operation
    263  * @return    M4ERR_STATE:      VSS is not in an appropriate state for this function to be called
    264  * @return    M4VSS3GPP_WAR_END_OF_AUDIO_MIXING: Audio mixing is over, user should now call
    265  *                                               M4VSS3GPP_audioMixingCleanUp()
    266  ******************************************************************************
    267  */
    268 M4OSA_ERR M4VSS3GPP_audioMixingStep( M4VSS3GPP_AudioMixingContext pContext,
    269                                     M4OSA_UInt8 *pProgress )
    270 {
    271     M4OSA_ERR err;
    272     M4VSS3GPP_InternalAudioMixingContext *pC =
    273         (M4VSS3GPP_InternalAudioMixingContext *)pContext;
    274 
    275     M4OSA_TRACE3_1("M4VSS3GPP_audioMixingStep called with pContext=0x%x",
    276         pContext);
    277 
    278     /**
    279     * Check input parameters */
    280     M4OSA_DEBUG_IF2((M4OSA_NULL == pContext), M4ERR_PARAMETER,
    281         "M4VSS3GPP_audioMixingStep: pContext is M4OSA_NULL");
    282 
    283     /**
    284     * State automaton */
    285     switch( pC->State )
    286     {
    287         case M4VSS3GPP_kAudioMixingState_VIDEO:
    288             err = M4VSS3GPP_intAudioMixingStepVideo(pC);
    289 
    290             /**
    291             * Compute the progress percentage
    292             * Note: audio and video CTS are not initialized before
    293             * the call of M4VSS3GPP_intAudioMixingStepVideo */
    294 
    295             /* P4ME00003276: First 0-50% segment is dedicated to state :
    296                M4VSS3GPP_kAudioMixingState_VIDEO */
    297             *pProgress = (M4OSA_UInt8)(50 * (pC->ewc.WriterVideoAU.CTS)
    298                 / pC->pInputClipCtxt->pVideoStream->
    299                 m_basicProperties.m_duration);
    300 
    301             /**
    302             * There may be no audio track (Remove audio track feature).
    303             * In that case we double the current percentage */
    304             if( M4SYS_kAudioUnknown == pC->ewc.WriterAudioStream.streamType )
    305             {
    306                 ( *pProgress) <<= 1; /**< x2 */
    307             }
    308             else if( *pProgress >= 50 )
    309             {
    310                 *pProgress =
    311                     49; /**< Video processing is not greater than 50% */
    312             }
    313 
    314             if( M4WAR_NO_MORE_AU == err )
    315             {
    316                 if( pC->bHasAudio )
    317                 {
    318                     /**
    319                     * Video is over, state transition to audio and return OK */
    320                     if( pC->iAddCts > 0 )
    321                         pC->State =
    322                         M4VSS3GPP_kAudioMixingState_AUDIO_FIRST_SEGMENT;
    323                     else
    324                         pC->State =
    325                         M4VSS3GPP_kAudioMixingState_AUDIO_SECOND_SEGMENT;
    326                 }
    327                 else
    328                 {
    329                     /**
    330                     * No audio, state transition to FINISHED */
    331                     pC->State = M4VSS3GPP_kAudioMixingState_FINISHED;
    332                 }
    333 
    334                 return M4NO_ERROR;
    335             }
    336             else if( M4NO_ERROR != err )
    337             {
    338                 M4OSA_TRACE1_1(
    339                     "M4VSS3GPP_audioMixingStep: M4VSS3GPP_intAudioMixingStepVideo returns 0x%x!",
    340                     err);
    341                 return err;
    342             }
    343             else
    344             {
    345                 return M4NO_ERROR;
    346             }
    347             break;
    348 
    349         case M4VSS3GPP_kAudioMixingState_AUDIO_FIRST_SEGMENT:
    350         case M4VSS3GPP_kAudioMixingState_AUDIO_SECOND_SEGMENT:
    351         case M4VSS3GPP_kAudioMixingState_AUDIO_THIRD_SEGMENT:
    352             if( pC->pAddedClipCtxt->iAudioFrameCts
    353                 != -pC->pAddedClipCtxt->iSilenceFrameDuration
    354                 && (pC->pAddedClipCtxt->iAudioFrameCts - 0.5)
    355                 / pC->pAddedClipCtxt->scale_audio > pC->uiEndLoop
    356                 && pC->uiEndLoop > 0 )
    357             {
    358             if(pC->bLoop == M4OSA_FALSE)
    359             {
    360                 pC->bNoLooping = M4OSA_TRUE;
    361             }
    362             else
    363             {
    364                 M4OSA_Int32 jumpCTS = (M4OSA_Int32)(pC->uiBeginLoop);
    365 
    366                 err = pC->pAddedClipCtxt->ShellAPI.m_pReader->m_pFctJump(
    367                     pC->pAddedClipCtxt->pReaderContext,
    368                     (M4_StreamHandler *)pC->pAddedClipCtxt->
    369                     pAudioStream, &jumpCTS);
    370 
    371                 if( err != M4NO_ERROR )
    372                 {
    373                     M4OSA_TRACE1_1(
    374                         "M4VSS3GPP_audioMixingStep: error when jumping in added audio clip: 0x%x",
    375                         err);
    376                     return err;
    377                 }
    378                 /**
    379                 * Use offset to give a correct CTS ... */
    380                 pC->pAddedClipCtxt->iAoffset =
    381                     (M4OSA_Int32)(pC->ewc.dATo * pC->ewc.scale_audio + 0.5);
    382             }
    383 
    384             }
    385 
    386             if( M4OSA_FALSE == pC->bRemoveOriginal )
    387             {
    388                 err = M4VSS3GPP_intAudioMixingStepAudioMix(pC);
    389             }
    390             else
    391             {
    392                 err = M4VSS3GPP_intAudioMixingStepAudioReplace(pC);
    393             }
    394 
    395             /**
    396             * Compute the progress percentage
    397             * Note: audio and video CTS are not initialized before
    398             * the call of M4VSS3GPP_intAudioMixingStepAudio */
    399             if( 0 != pC->ewc.iOutputDuration )
    400             {
    401                 /* P4ME00003276: Second 50-100% segment is dedicated to states :
    402                 M4VSS3GPP_kAudioMixingState_AUDIO... */
    403                 /* For Audio the progress computation is based on dAto and offset,
    404                    it is more accurate */
    405                 *pProgress = (M4OSA_UInt8)(50
    406                     + (50 * pC->ewc.dATo - pC->pInputClipCtxt->iVoffset)
    407                     / (pC->ewc.iOutputDuration)); /**< 50 for 100/2 **/
    408 
    409                 if( *pProgress >= 100 )
    410                 {
    411                     *pProgress =
    412                         99; /**< It's not really finished, I prefer to return less than 100% */
    413                 }
    414             }
    415             else
    416             {
    417                 *pProgress = 99;
    418             }
    419 
    420             if( M4WAR_NO_MORE_AU == err )
    421             {
    422                 /**
    423                 * Audio is over, state transition to FINISHED */
    424                 pC->State = M4VSS3GPP_kAudioMixingState_FINISHED;
    425                 return M4NO_ERROR;
    426             }
    427             else if( M4NO_ERROR != err )
    428             {
    429                 M4OSA_TRACE1_1(
    430                     "M4VSS3GPP_audioMixingStep: M4VSS3GPP_intAudioMixingStepAudio returns 0x%x!",
    431                     err);
    432                 return err;
    433             }
    434             else
    435             {
    436                 return M4NO_ERROR;
    437             }
    438             break;
    439 
    440         case M4VSS3GPP_kAudioMixingState_FINISHED:
    441 
    442             /**
    443             * Progress percentage: finalize finished -> 100% */
    444             *pProgress = 100;
    445 
    446             /**
    447             * Audio mixing is finished, return correct warning */
    448             return M4VSS3GPP_WAR_END_OF_AUDIO_MIXING;
    449 
    450         default:
    451             M4OSA_TRACE1_1(
    452                 "M4VSS3GPP_audioMixingStep: State error (0x%x)! Returning M4ERR_STATE",
    453                 pC->State);
    454             return M4ERR_STATE;
    455     }
    456 }
    457 
    458 /**
    459  ******************************************************************************
    460  * M4OSA_ERR M4VSS3GPP_audioMixingCleanUp(M4VSS3GPP_AudioMixingContext pContext)
    461  * @brief    Free all resources used by the VSS audio mixing operation.
    462  * @note    The context is no more valid after this call
    463  * @param    pContext            (IN) VSS audio mixing context
    464  * @return    M4NO_ERROR:            No error
    465  * @return    M4ERR_PARAMETER:    pContext is M4OSA_NULL (debug only)
    466  ******************************************************************************
    467  */
    468 M4OSA_ERR M4VSS3GPP_audioMixingCleanUp( M4VSS3GPP_AudioMixingContext pContext )
    469 {
    470     M4VSS3GPP_InternalAudioMixingContext *pC =
    471         (M4VSS3GPP_InternalAudioMixingContext *)pContext;
    472     M4OSA_ERR err;
    473     M4OSA_UInt32 lastCTS;
    474 
    475     M4OSA_TRACE3_1("M4VSS3GPP_audioMixingCleanUp called with pContext=0x%x",
    476         pContext);
    477 
    478     /**
    479     * Check input parameters */
    480     M4OSA_DEBUG_IF2((M4OSA_NULL == pContext), M4ERR_PARAMETER,
    481         "M4VSS3GPP_audioMixingCleanUp: pContext is M4OSA_NULL");
    482 
    483     /**
    484     * Check input parameter */
    485     if( M4OSA_NULL == pContext )
    486     {
    487         M4OSA_TRACE1_0(
    488             "M4VSS3GPP_audioMixingCleanUp(): M4VSS3GPP_audioMixingCleanUp: pContext is\
    489              M4OSA_NULL, returning M4ERR_PARAMETER");
    490         return M4ERR_PARAMETER;
    491     }
    492 
    493     /**
    494     * Close Input 3GPP file */
    495     if( M4OSA_NULL != pC->pInputClipCtxt )
    496     {
    497         M4VSS3GPP_intClipCleanUp(pC->pInputClipCtxt);
    498         pC->pInputClipCtxt = M4OSA_NULL;
    499     }
    500 
    501     /**
    502     * Close Added 3GPP file */
    503     if( M4OSA_NULL != pC->pAddedClipCtxt )
    504     {
    505         M4VSS3GPP_intClipCleanUp(pC->pAddedClipCtxt);
    506         pC->pAddedClipCtxt = M4OSA_NULL;
    507     }
    508 
    509     /**
    510     * Close the 3GP writer. In normal use case it has already been closed,
    511       but not in abort use case */
    512     if( M4OSA_NULL != pC->ewc.p3gpWriterContext )
    513     {
    514         /* Update last Video CTS */
    515         lastCTS = pC->ewc.iOutputDuration;
    516 
    517         err = pC->ShellAPI.pWriterGlobalFcts->pFctSetOption(
    518             pC->ewc.p3gpWriterContext,
    519             (M4OSA_UInt32)M4WRITER_kMaxFileDuration, &lastCTS);
    520 
    521         if( M4NO_ERROR != err )
    522         {
    523             M4OSA_TRACE1_1(
    524                 "M4VSS3GPP_audioMixingCleanUp: SetOption(M4WRITER_kMaxFileDuration) returns 0x%x",
    525                 err);
    526         }
    527 
    528         err = pC->ShellAPI.pWriterGlobalFcts->pFctCloseWrite(
    529             pC->ewc.p3gpWriterContext);
    530 
    531         if( M4NO_ERROR != err )
    532         {
    533             M4OSA_TRACE1_1(
    534                 "M4VSS3GPP_audioMixingCleanUp: pWriterGlobalFcts->pFctCloseWrite returns 0x%x!",
    535                 err);
    536             /**< don't return the error because we have other things to free! */
    537         }
    538         pC->ewc.p3gpWriterContext = M4OSA_NULL;
    539     }
    540 
    541     /**
    542     * Free the Audio encoder context */
    543     if( M4OSA_NULL != pC->ewc.pAudioEncCtxt )
    544     {
    545         err = pC->ShellAPI.pAudioEncoderGlobalFcts->pFctClose(
    546             pC->ewc.pAudioEncCtxt);
    547 
    548         if( M4NO_ERROR != err )
    549         {
    550             M4OSA_TRACE1_1(
    551                 "M4VSS3GPP_audioMixingCleanUp: pAudioEncoderGlobalFcts->pFctClose returns 0x%x",
    552                 err);
    553             /**< don't return, we still have stuff to free */
    554         }
    555 
    556         err = pC->ShellAPI.pAudioEncoderGlobalFcts->pFctCleanUp(
    557             pC->ewc.pAudioEncCtxt);
    558 
    559         if( M4NO_ERROR != err )
    560         {
    561             M4OSA_TRACE1_1(
    562                 "M4VSS3GPP_audioMixingCleanUp: pAudioEncoderGlobalFcts->pFctCleanUp returns 0x%x",
    563                 err);
    564             /**< don't return, we still have stuff to free */
    565         }
    566 
    567         pC->ewc.pAudioEncCtxt = M4OSA_NULL;
    568     }
    569 
    570     /**
    571     * Free the ssrc stuff */
    572 
    573     if( M4OSA_NULL != pC->SsrcScratch )
    574     {
    575         free(pC->SsrcScratch);
    576         pC->SsrcScratch = M4OSA_NULL;
    577     }
    578 
    579     if( M4OSA_NULL != pC->pSsrcBufferIn )
    580     {
    581         free(pC->pSsrcBufferIn);
    582         pC->pSsrcBufferIn = M4OSA_NULL;
    583     }
    584 
    585     if( M4OSA_NULL != pC->pSsrcBufferOut
    586         && (M4OSA_TRUE == pC->b_SSRCneeded || pC->ChannelConversion > 0) )
    587     {
    588         free(pC->pSsrcBufferOut);
    589         pC->pSsrcBufferOut = M4OSA_NULL;
    590     }
    591 
    592     if( M4OSA_NULL != pC->pTempBuffer )
    593     {
    594         free(pC->pTempBuffer);
    595         pC->pTempBuffer = M4OSA_NULL;
    596     }
    597 
    598     if (pC->pLVAudioResampler != M4OSA_NULL)
    599     {
    600         LVDestroy(pC->pLVAudioResampler);
    601         pC->pLVAudioResampler = M4OSA_NULL;
    602     }
    603 
    604     /**
    605     * Free the shells interfaces */
    606     M4VSS3GPP_unRegisterAllWriters(&pC->ShellAPI);
    607     M4VSS3GPP_unRegisterAllEncoders(&pC->ShellAPI);
    608     M4VSS3GPP_unRegisterAllReaders(&pC->ShellAPI);
    609     M4VSS3GPP_unRegisterAllDecoders(&pC->ShellAPI);
    610 
    611     /**
    612     * Free the context */
    613     free(pContext);
    614     pContext = M4OSA_NULL;
    615 
    616     /**
    617     * Return with no error */
    618     M4OSA_TRACE3_0("M4VSS3GPP_audioMixingCleanUp(): returning M4NO_ERROR");
    619     return M4NO_ERROR;
    620 }
    621 
    622 /******************************************************************************/
    623 /******************************************************************************/
    624 /*********                  STATIC FUNCTIONS                         **********/
    625 /******************************************************************************/
    626 /******************************************************************************/
    627 
    628 /**
    629  ******************************************************************************
    630  * M4OSA_ERR M4VSS3GPP_intAudioMixingOpen()
    631  * @brief    Initializes the VSS audio mixing operation (allocates an execution context).
    632  * @note
    633  * @param    pContext        (OUT) Pointer on the VSS audio mixing context to allocate
    634  * @param    pSettings        (IN) Pointer to valid audio mixing settings
    635  * @return    M4NO_ERROR:            No error
    636  * @return    M4ERR_PARAMETER:    At least one parameter is M4OSA_NULL (debug only)
    637  * @return    M4ERR_ALLOC:        There is no more available memory
    638  ******************************************************************************
    639  */
    640 static M4OSA_ERR
    641 M4VSS3GPP_intAudioMixingOpen( M4VSS3GPP_InternalAudioMixingContext *pC,
    642                              M4VSS3GPP_AudioMixingSettings *pSettings )
    643 {
    644     M4OSA_ERR err;
    645     M4OSA_UInt32 outputASF = 0;
    646     M4ENCODER_Header *encHeader;
    647 
    648     M4OSA_TRACE3_2(
    649         "M4VSS3GPP_intAudioMixingOpen called with pContext=0x%x, pSettings=0x%x",
    650         pC, pSettings);
    651 
    652     /**
    653     * The Add Volume must be (strictly) superior than zero */
    654     if( pSettings->uiAddVolume == 0 )
    655     {
    656         M4OSA_TRACE1_0(
    657             "M4VSS3GPP_intAudioMixingOpen(): AddVolume is zero,\
    658             returning M4VSS3GPP_ERR_ADDVOLUME_EQUALS_ZERO");
    659         return M4VSS3GPP_ERR_ADDVOLUME_EQUALS_ZERO;
    660     }
    661     /*
    662     else if(pSettings->uiAddVolume >= 100) // If volume is set to 100, no more original audio ...
    663     {
    664     pC->bRemoveOriginal = M4OSA_TRUE;
    665     }
    666     */
    667     /**
    668     * Build the input clip settings */
    669     pC->InputClipSettings.pFile =
    670         pSettings->pOriginalClipFile; /**< Input 3GPP file descriptor */
    671     pC->InputClipSettings.FileType = M4VIDEOEDITING_kFileType_3GPP;
    672     pC->InputClipSettings.uiBeginCutTime =
    673         0; /**< No notion of cut for the audio mixing feature */
    674     pC->InputClipSettings.uiEndCutTime =
    675         0; /**< No notion of cut for the audio mixing feature */
    676 
    677     /**
    678     * Open the original Audio/Video 3GPP clip */
    679     err = M4VSS3GPP_intClipInit(&pC->pInputClipCtxt, pC->pOsaFileReadPtr);
    680 
    681     if( M4NO_ERROR != err )
    682     {
    683         M4OSA_TRACE1_1(
    684             "M4VSS3GPP_intAudioMixingOpen(): M4VSS3GPP_intClipInit(orig) returns 0x%x",
    685             err);
    686         return err;
    687     }
    688 
    689     err = M4VSS3GPP_intClipOpen(pC->pInputClipCtxt, &pC->InputClipSettings,
    690         M4OSA_FALSE, M4OSA_FALSE, M4OSA_TRUE);
    691 
    692     if( M4NO_ERROR != err )
    693     {
    694         M4OSA_TRACE1_1(
    695             "M4VSS3GPP_intAudioMixingOpen(): M4VSS3GPP_intClipOpen(orig) returns 0x%x",
    696             err);
    697         return err;
    698     }
    699 
    700     if( M4OSA_NULL == pC->pInputClipCtxt->pAudioStream )
    701         {
    702         pC->bRemoveOriginal = M4OSA_TRUE;
    703         }
    704     /**
    705     * If there is no video, it's an error */
    706     if( M4OSA_NULL == pC->pInputClipCtxt->pVideoStream )
    707     {
    708         M4OSA_TRACE1_0(
    709             "M4VSS3GPP_intAudioMixingOpen(): no video stream in clip,\
    710             returning M4VSS3GPP_ERR_NO_SUPPORTED_STREAM_IN_FILE");
    711         return M4VSS3GPP_ERR_NO_SUPPORTED_STREAM_IN_FILE;
    712     }
    713 
    714     /**
    715     * Compute clip properties */
    716     err = M4VSS3GPP_intBuildAnalysis(pC->pInputClipCtxt,
    717         &pC->pInputClipCtxt->pSettings->ClipProperties);
    718 
    719     if( M4NO_ERROR != err )
    720     {
    721         M4OSA_TRACE1_1(
    722             "M4VSS3GPP_intAudioMixingOpen(): M4VSS3GPP_intBuildAnalysis(orig) returns 0x%x",
    723             err);
    724         return err;
    725     }
    726 
    727     /**
    728     * Build the added clip settings */
    729     pC->AddedClipSettings.pFile =
    730         pSettings->pAddedAudioTrackFile; /**< Added file descriptor */
    731     pC->AddedClipSettings.FileType = pSettings->AddedAudioFileType;
    732     pC->AddedClipSettings.uiBeginCutTime =
    733         0; /**< No notion of cut for the audio mixing feature */
    734     pC->AddedClipSettings.uiEndCutTime   = 0;/**< No notion of cut for the audio mixing feature */
    735     pC->AddedClipSettings.ClipProperties.uiNbChannels=
    736         pSettings->uiNumChannels;
    737     pC->AddedClipSettings.ClipProperties.uiSamplingFrequency=    pSettings->uiSamplingFrequency;
    738 
    739     if( M4OSA_NULL != pC->AddedClipSettings.pFile )
    740     {
    741         /**
    742         * Open the added Audio clip */
    743         err = M4VSS3GPP_intClipInit(&pC->pAddedClipCtxt, pC->pOsaFileReadPtr);
    744 
    745         if( M4NO_ERROR != err )
    746         {
    747             M4OSA_TRACE1_1(
    748                 "M4VSS3GPP_intAudioMixingOpen(): M4VSS3GPP_intClipInit(added) returns 0x%x",
    749                 err);
    750             return err;
    751         }
    752 
    753         err = M4VSS3GPP_intClipOpen(pC->pAddedClipCtxt, &pC->AddedClipSettings,
    754             M4OSA_FALSE, M4OSA_FALSE, M4OSA_TRUE);
    755 
    756         if( M4NO_ERROR != err )
    757         {
    758             M4OSA_TRACE1_1(
    759                 "M4VSS3GPP_intAudioMixingOpen(): M4VSS3GPP_intClipOpen(added) returns 0x%x",
    760                 err);
    761             return err;
    762         }
    763 
    764         /**
    765         * If there is no audio, it's an error */
    766         if( M4OSA_NULL == pC->pAddedClipCtxt->pAudioStream )
    767         {
    768             M4OSA_TRACE1_0(
    769                 "M4VSS3GPP_intAudioMixingOpen(): no audio nor video stream in clip,\
    770                 returning M4VSS3GPP_ERR_NO_SUPPORTED_STREAM_IN_FILE");
    771             return M4VSS3GPP_ERR_NO_SUPPORTED_STREAM_IN_FILE;
    772         }
    773 
    774         /**
    775         * Compute clip properties */
    776         err = M4VSS3GPP_intBuildAnalysis(pC->pAddedClipCtxt,
    777             &pC->pAddedClipCtxt->pSettings->ClipProperties);
    778 
    779         if( M4NO_ERROR != err )
    780         {
    781             M4OSA_TRACE1_1(
    782                 "M4VSS3GPP_intAudioMixingOpen(): M4VSS3GPP_intBuildAnalysis(added) returns 0x%x",
    783                 err);
    784             return err;
    785         }
    786 
    787         switch( pSettings->outputASF )
    788         {
    789             case M4VIDEOEDITING_k8000_ASF:
    790                 outputASF = 8000;
    791                 break;
    792 
    793             case M4VIDEOEDITING_k16000_ASF:
    794                 outputASF = 16000;
    795                 break;
    796 
    797             case M4VIDEOEDITING_k22050_ASF:
    798                 outputASF = 22050;
    799                 break;
    800 
    801             case M4VIDEOEDITING_k24000_ASF:
    802                 outputASF = 24000;
    803                 break;
    804 
    805             case M4VIDEOEDITING_k32000_ASF:
    806                 outputASF = 32000;
    807                 break;
    808 
    809             case M4VIDEOEDITING_k44100_ASF:
    810                 outputASF = 44100;
    811                 break;
    812 
    813             case M4VIDEOEDITING_k48000_ASF:
    814                 outputASF = 48000;
    815                 break;
    816 
    817             default:
    818                 M4OSA_TRACE1_0("Bad parameter in output ASF ");
    819                 return M4ERR_PARAMETER;
    820                 break;
    821         }
    822 
    823         if( pC->bRemoveOriginal == M4OSA_TRUE
    824             && (pC->pAddedClipCtxt->pSettings->ClipProperties.AudioStreamType
    825             == M4VIDEOEDITING_kMP3 || pC->pAddedClipCtxt->pSettings->
    826             ClipProperties.AudioStreamType == M4VIDEOEDITING_kPCM
    827             || pC->pAddedClipCtxt->pSettings->
    828             ClipProperties.AudioStreamType
    829             != pSettings->outputAudioFormat
    830             || pC->pAddedClipCtxt->pSettings->
    831             ClipProperties.uiSamplingFrequency != outputASF
    832             || pC->pAddedClipCtxt->pSettings->
    833             ClipProperties.uiNbChannels
    834             != pSettings->outputNBChannels) )
    835         {
    836 
    837             if( pSettings->outputAudioFormat == M4VIDEOEDITING_kAMR_NB )
    838             {
    839                 pSettings->outputASF = M4VIDEOEDITING_k8000_ASF;
    840                 pSettings->outputNBChannels = 1;
    841                 pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize = 320;
    842             }
    843             else if( pSettings->outputAudioFormat == M4VIDEOEDITING_kAAC )
    844             {
    845                 pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize =
    846                     2048 * pSettings->outputNBChannels;
    847             }
    848 
    849             pC->pInputClipCtxt->pSettings->ClipProperties.uiSamplingFrequency =
    850                 outputASF;
    851 
    852             if( outputASF != pC->pAddedClipCtxt->pSettings->
    853                 ClipProperties.uiSamplingFrequency )
    854             {
    855                 /* We need to call SSRC in order to align ASF and/or nb of channels */
    856                 /* Moreover, audio encoder may be needed in case of audio replacing... */
    857                 pC->b_SSRCneeded = M4OSA_TRUE;
    858             }
    859 
    860             if( pSettings->outputNBChannels
    861                 < pC->pAddedClipCtxt->pSettings->ClipProperties.uiNbChannels )
    862             {
    863                 /* Stereo to Mono */
    864                 pC->ChannelConversion = 1;
    865             }
    866             else if( pSettings->outputNBChannels
    867                 > pC->pAddedClipCtxt->pSettings->ClipProperties.uiNbChannels )
    868             {
    869                 /* Mono to Stereo */
    870                 pC->ChannelConversion = 2;
    871             }
    872 
    873             pC->pInputClipCtxt->pSettings->ClipProperties.uiNbChannels =
    874                 pSettings->outputNBChannels;
    875         }
    876 
    877         /**
    878         * Check compatibility chart */
    879         err = M4VSS3GPP_intAudioMixingCompatibility(pC,
    880             &pC->pInputClipCtxt->pSettings->ClipProperties,
    881             &pC->pAddedClipCtxt->pSettings->ClipProperties);
    882 
    883         if( M4NO_ERROR != err )
    884         {
    885             M4OSA_TRACE1_1(
    886                 "M4VSS3GPP_intAudioMixingOpen():\
    887                 M4VSS3GPP_intAudioMixingCompatibility returns 0x%x",
    888                 err);
    889             return err;
    890         }
    891 
    892         /**
    893         * Check loop parameters */
    894         if( pC->uiBeginLoop > pC->pAddedClipCtxt->pSettings->
    895             ClipProperties.uiClipAudioDuration )
    896         {
    897             M4OSA_TRACE1_0(
    898                 "M4VSS3GPP_intAudioMixingOpen():\
    899                 begin loop time is higher than added clip audio duration");
    900             return M4VSS3GPP_ERR_BEGINLOOP_HIGHER_ENDLOOP;
    901         }
    902 
    903         /**
    904         * Ok, let's go with this audio track */
    905         pC->bHasAudio = M4OSA_TRUE;
    906     }
    907     else
    908     {
    909         /* No added file, force remove original */
    910         pC->AddedClipSettings.FileType = M4VIDEOEDITING_kFileType_Unsupported;
    911         pC->bRemoveOriginal = M4OSA_TRUE;
    912         pC->bHasAudio = M4OSA_FALSE;
    913     }
    914 
    915     /**
    916     * Copy the video properties of the input clip to the output properties */
    917     pC->ewc.uiVideoBitrate =
    918         pC->pInputClipCtxt->pSettings->ClipProperties.uiVideoBitrate;
    919     pC->ewc.uiVideoWidth =
    920         pC->pInputClipCtxt->pSettings->ClipProperties.uiVideoWidth;
    921     pC->ewc.uiVideoHeight =
    922         pC->pInputClipCtxt->pSettings->ClipProperties.uiVideoHeight;
    923     pC->ewc.uiVideoTimeScale =
    924         pC->pInputClipCtxt->pSettings->ClipProperties.uiVideoTimeScale;
    925     pC->ewc.bVideoDataPartitioning =
    926         pC->pInputClipCtxt->pSettings->ClipProperties.bMPEG4dataPartition;
    927     pC->ewc.outputVideoProfile =
    928         pC->pInputClipCtxt->pSettings->ClipProperties.uiVideoProfile;
    929     pC->ewc.outputVideoLevel =
    930         pC->pInputClipCtxt->pSettings->ClipProperties.uiVideoLevel;
    931     switch( pC->pInputClipCtxt->pSettings->ClipProperties.VideoStreamType )
    932     {
    933         case M4VIDEOEDITING_kH263:
    934             pC->ewc.VideoStreamType = M4SYS_kH263;
    935             break;
    936 
    937         case M4VIDEOEDITING_kMPEG4:
    938             pC->ewc.VideoStreamType = M4SYS_kMPEG_4;
    939             break;
    940 
    941         case M4VIDEOEDITING_kH264:
    942             pC->ewc.VideoStreamType = M4SYS_kH264;
    943             break;
    944 
    945         default:
    946             pC->ewc.VideoStreamType = M4SYS_kVideoUnknown;
    947             break;
    948     }
    949 
    950     /* Add a link to video dsi */
    951     if( M4SYS_kH264 == pC->ewc.VideoStreamType )
    952     {
    953 
    954         /* For H.264 encoder case
    955         * Fetch the DSI from the shell video encoder, and feed it to the writer */
    956 
    957         M4OSA_TRACE3_0("M4VSS3GPP_intAudioMixingOpen: get DSI for H264 stream");
    958 
    959         if( M4OSA_NULL == pC->ewc.pEncContext )
    960         {
    961             M4OSA_TRACE1_0(
    962                 "M4VSS3GPP_intAudioMixingOpen: pC->ewc.pEncContext is NULL");
    963             err = M4VSS3GPP_intAudioMixingCreateVideoEncoder(pC);
    964 
    965             if( M4NO_ERROR != err )
    966             {
    967                 M4OSA_TRACE1_1(
    968                     "M4VSS3GPP_intAudioMixingOpen:\
    969                     M4VSS3GPP_intAudioMixingCreateVideoEncoder returned error 0x%x",
    970                     err);
    971             }
    972         }
    973 
    974         if( M4OSA_NULL != pC->ewc.pEncContext )
    975         {
    976             err = pC->ShellAPI.pVideoEncoderGlobalFcts->pFctGetOption(
    977                 pC->ewc.pEncContext, M4ENCODER_kOptionID_EncoderHeader,
    978                 (M4OSA_DataOption) &encHeader);
    979 
    980             if( ( M4NO_ERROR != err) || (M4OSA_NULL == encHeader->pBuf) )
    981             {
    982                 M4OSA_TRACE1_1(
    983                     "M4VSS3GPP_intAudioMixingOpen: failed to get the encoder header (err 0x%x)",
    984                     err);
    985                 M4OSA_TRACE1_2(
    986                     "M4VSS3GPP_intAudioMixingOpen: encHeader->pBuf=0x%x, size=0x%x",
    987                     encHeader->pBuf, encHeader->Size);
    988             }
    989             else
    990             {
    991                 M4OSA_TRACE1_0(
    992                     "M4VSS3GPP_intAudioMixingOpen: send DSI for H264 stream to 3GP writer");
    993 
    994                 /**
    995                 * Allocate and copy the new DSI */
    996                 pC->ewc.pVideoOutputDsi =
    997                     (M4OSA_MemAddr8)M4OSA_32bitAlignedMalloc(encHeader->Size, M4VSS3GPP,
    998                     (M4OSA_Char *)"pC->ewc.pVideoOutputDsi (H264)");
    999 
   1000                 if( M4OSA_NULL == pC->ewc.pVideoOutputDsi )
   1001                 {
   1002                     M4OSA_TRACE1_0(
   1003                         "M4VSS3GPP_intAudioMixingOpen():\
   1004                         unable to allocate pVideoOutputDsi (H264), returning M4ERR_ALLOC");
   1005                     return M4ERR_ALLOC;
   1006                 }
   1007                 pC->ewc.uiVideoOutputDsiSize = (M4OSA_UInt16)encHeader->Size;
   1008                 memcpy((void *)pC->ewc.pVideoOutputDsi, (void *)encHeader->pBuf,
   1009                     encHeader->Size);
   1010             }
   1011 
   1012             err = M4VSS3GPP_intAudioMixingDestroyVideoEncoder(pC);
   1013 
   1014             if( M4NO_ERROR != err )
   1015             {
   1016                 M4OSA_TRACE1_1(
   1017                     "M4VSS3GPP_intAudioMixingOpen:\
   1018                     M4VSS3GPP_intAudioMixingDestroyVideoEncoder returned error 0x%x",
   1019                     err);
   1020             }
   1021         }
   1022         else
   1023         {
   1024             M4OSA_TRACE1_0(
   1025                 "M4VSS3GPP_intAudioMixingOpen: pC->ewc.pEncContext is NULL, cannot get the DSI");
   1026         }
   1027     }
   1028     else
   1029     {
   1030         M4OSA_TRACE3_1(
   1031             "M4VSS3GPP_intAudioMixingOpen: input clip video stream type = 0x%x",
   1032             pC->ewc.VideoStreamType);
   1033         pC->ewc.uiVideoOutputDsiSize =
   1034             (M4OSA_UInt16)pC->pInputClipCtxt->pVideoStream->
   1035             m_basicProperties.m_decoderSpecificInfoSize;
   1036         pC->ewc.pVideoOutputDsi = (M4OSA_MemAddr8)pC->pInputClipCtxt->pVideoStream->
   1037             m_basicProperties.m_pDecoderSpecificInfo;
   1038     }
   1039 
   1040     /**
   1041     * Copy the audio properties of the added clip to the output properties */
   1042     if( pC->bHasAudio )
   1043     {
   1044         if( pC->bRemoveOriginal == M4OSA_TRUE )
   1045         {
   1046             pC->ewc.uiNbChannels =
   1047                 pC->pAddedClipCtxt->pSettings->ClipProperties.uiNbChannels;
   1048             pC->ewc.uiAudioBitrate =
   1049                 pC->pAddedClipCtxt->pSettings->ClipProperties.uiAudioBitrate;
   1050             pC->ewc.uiSamplingFrequency = pC->pAddedClipCtxt->pSettings->
   1051                 ClipProperties.uiSamplingFrequency;
   1052             pC->ewc.uiSilencePcmSize =
   1053                 pC->pAddedClipCtxt->pSettings->ClipProperties.uiDecodedPcmSize;
   1054             pC->ewc.scale_audio = pC->ewc.uiSamplingFrequency / 1000.0;
   1055 
   1056             /* if output settings are differents from added clip settings,
   1057             we need to reencode BGM */
   1058             if( pC->pAddedClipCtxt->pSettings->ClipProperties.AudioStreamType
   1059                 != pSettings->outputAudioFormat
   1060                 || pC->pAddedClipCtxt->pSettings->
   1061                 ClipProperties.uiSamplingFrequency != outputASF
   1062                 || pC->pAddedClipCtxt->pSettings->
   1063                 ClipProperties.uiNbChannels
   1064                 != pSettings->outputNBChannels
   1065                 || pC->pAddedClipCtxt->pSettings->
   1066                 ClipProperties.AudioStreamType == M4VIDEOEDITING_kMP3 )
   1067             {
   1068                 /* Set reader DSI to NULL (unknown), we will use encoder DSI later */
   1069                 if( pC->pAddedClipCtxt->pAudioStream->
   1070                     m_basicProperties.m_pDecoderSpecificInfo != M4OSA_NULL )
   1071                 {
   1072 
   1073                     /*
   1074                      free(pC->pAddedClipCtxt->pAudioStream->\
   1075                        m_basicProperties.m_pDecoderSpecificInfo);
   1076                        */
   1077                     pC->pAddedClipCtxt->pAudioStream->
   1078                         m_basicProperties.m_decoderSpecificInfoSize = 0;
   1079                     pC->pAddedClipCtxt->pAudioStream->
   1080                         m_basicProperties.m_pDecoderSpecificInfo = M4OSA_NULL;
   1081                 }
   1082 
   1083                 pC->ewc.uiNbChannels =
   1084                     pC->pInputClipCtxt->pSettings->ClipProperties.uiNbChannels;
   1085                 pC->ewc.uiSamplingFrequency = pC->pInputClipCtxt->pSettings->
   1086                     ClipProperties.uiSamplingFrequency;
   1087                 pC->ewc.scale_audio = pC->ewc.uiSamplingFrequency / 1000.0;
   1088 
   1089                 if( pSettings->outputAudioFormat == M4VIDEOEDITING_kAMR_NB )
   1090                 {
   1091                     pC->ewc.AudioStreamType = M4SYS_kAMR;
   1092                     pC->ewc.pSilenceFrameData =
   1093                         (M4OSA_UInt8 *)M4VSS3GPP_AMR_AU_SILENCE_FRAME_048;
   1094                     pC->ewc.uiSilenceFrameSize =
   1095                         M4VSS3GPP_AMR_AU_SILENCE_FRAME_048_SIZE;
   1096                     pC->ewc.iSilenceFrameDuration =
   1097                         M4VSS3GPP_AMR_AU_SILENCE_FRAME_048_DURATION;
   1098                     pC->ewc.uiAudioBitrate = 12200;
   1099                     pC->ewc.uiSamplingFrequency = 8000;
   1100                     pC->ewc.uiSilencePcmSize = 320;
   1101                     pC->ewc.scale_audio = pC->ewc.uiSamplingFrequency / 1000.0;
   1102                 }
   1103                 else if( pSettings->outputAudioFormat == M4VIDEOEDITING_kAAC )
   1104                 {
   1105                     pC->ewc.AudioStreamType = M4SYS_kAAC;
   1106 
   1107                     if( pSettings->outputAudioBitrate
   1108                         == M4VIDEOEDITING_kUndefinedBitrate )
   1109                     {
   1110                         switch( pC->ewc.uiSamplingFrequency )
   1111                         {
   1112                             case 16000:
   1113                                 pC->ewc.uiAudioBitrate =
   1114                                     M4VIDEOEDITING_k24_KBPS;
   1115                                 break;
   1116 
   1117                             case 22050:
   1118                             case 24000:
   1119                                 pC->ewc.uiAudioBitrate =
   1120                                     M4VIDEOEDITING_k32_KBPS;
   1121                                 break;
   1122 
   1123                             case 32000:
   1124                                 pC->ewc.uiAudioBitrate =
   1125                                     M4VIDEOEDITING_k48_KBPS;
   1126                                 break;
   1127 
   1128                             case 44100:
   1129                             case 48000:
   1130                                 pC->ewc.uiAudioBitrate =
   1131                                     M4VIDEOEDITING_k64_KBPS;
   1132                                 break;
   1133 
   1134                             default:
   1135                                 pC->ewc.uiAudioBitrate =
   1136                                     M4VIDEOEDITING_k64_KBPS;
   1137                                 break;
   1138                         }
   1139 
   1140                         if( pC->ewc.uiNbChannels == 2 )
   1141                         {
   1142                             /* Output bitrate have to be doubled */
   1143                             pC->ewc.uiAudioBitrate += pC->ewc.uiAudioBitrate;
   1144                         }
   1145                     }
   1146                     else
   1147                     {
   1148                         pC->ewc.uiAudioBitrate = pSettings->outputAudioBitrate;
   1149                     }
   1150 
   1151                     if( pC->ewc.uiNbChannels == 1 )
   1152                     {
   1153                         pC->ewc.pSilenceFrameData =
   1154                             (M4OSA_UInt8 *)M4VSS3GPP_AAC_AU_SILENCE_MONO;
   1155                         pC->ewc.uiSilenceFrameSize =
   1156                             M4VSS3GPP_AAC_AU_SILENCE_MONO_SIZE;
   1157                     }
   1158                     else
   1159                     {
   1160                         pC->ewc.pSilenceFrameData =
   1161                             (M4OSA_UInt8 *)M4VSS3GPP_AAC_AU_SILENCE_STEREO;
   1162                         pC->ewc.uiSilenceFrameSize =
   1163                             M4VSS3GPP_AAC_AU_SILENCE_STEREO_SIZE;
   1164                     }
   1165                     pC->ewc.iSilenceFrameDuration =
   1166                         1024; /* AAC is always 1024/Freq sample duration */
   1167                 }
   1168             }
   1169             else
   1170             {
   1171                 switch( pC->pAddedClipCtxt->pSettings->
   1172                     ClipProperties.AudioStreamType )
   1173                 {
   1174                     case M4VIDEOEDITING_kAMR_NB:
   1175                         pC->ewc.AudioStreamType = M4SYS_kAMR;
   1176                         pC->ewc.pSilenceFrameData =
   1177                             (M4OSA_UInt8 *)M4VSS3GPP_AMR_AU_SILENCE_FRAME_048;
   1178                         pC->ewc.uiSilenceFrameSize =
   1179                             M4VSS3GPP_AMR_AU_SILENCE_FRAME_048_SIZE;
   1180                         pC->ewc.iSilenceFrameDuration =
   1181                             M4VSS3GPP_AMR_AU_SILENCE_FRAME_048_DURATION;
   1182                         break;
   1183 
   1184                     case M4VIDEOEDITING_kAAC:
   1185                     case M4VIDEOEDITING_kAACplus:
   1186                     case M4VIDEOEDITING_keAACplus:
   1187                         pC->ewc.AudioStreamType = M4SYS_kAAC;
   1188 
   1189                         if( pC->ewc.uiNbChannels == 1 )
   1190                         {
   1191                             pC->ewc.pSilenceFrameData =
   1192                                 (M4OSA_UInt8 *)M4VSS3GPP_AAC_AU_SILENCE_MONO;
   1193                             pC->ewc.uiSilenceFrameSize =
   1194                                 M4VSS3GPP_AAC_AU_SILENCE_MONO_SIZE;
   1195                         }
   1196                         else
   1197                         {
   1198                             pC->ewc.pSilenceFrameData =
   1199                                 (M4OSA_UInt8 *)M4VSS3GPP_AAC_AU_SILENCE_STEREO;
   1200                             pC->ewc.uiSilenceFrameSize =
   1201                                 M4VSS3GPP_AAC_AU_SILENCE_STEREO_SIZE;
   1202                         }
   1203                         pC->ewc.iSilenceFrameDuration =
   1204                             1024; /* AAC is always 1024/Freq sample duration */
   1205                         break;
   1206 
   1207                     case M4VIDEOEDITING_kEVRC:
   1208                         pC->ewc.AudioStreamType = M4SYS_kEVRC;
   1209                         pC->ewc.pSilenceFrameData = M4OSA_NULL;
   1210                         pC->ewc.uiSilenceFrameSize = 0;
   1211                         pC->ewc.iSilenceFrameDuration = 160; /* EVRC frames are 20 ms at 8000 Hz
   1212                                             (makes it easier to factorize amr and evrc code) */
   1213                         break;
   1214 
   1215                     case M4VIDEOEDITING_kPCM:
   1216                         /* Set reader DSI to NULL (unknown), we will use encoder DSI later */
   1217                         pC->pAddedClipCtxt->pAudioStream->
   1218                             m_basicProperties.m_decoderSpecificInfoSize = 0;
   1219                         pC->pAddedClipCtxt->pAudioStream->
   1220                             m_basicProperties.m_pDecoderSpecificInfo =
   1221                             M4OSA_NULL;
   1222 
   1223                         if( pC->pAddedClipCtxt->pSettings->
   1224                             ClipProperties.uiSamplingFrequency == 8000 )
   1225                         {
   1226                             pC->ewc.AudioStreamType = M4SYS_kAMR;
   1227                             pC->ewc.pSilenceFrameData = (M4OSA_UInt8
   1228                                 *)M4VSS3GPP_AMR_AU_SILENCE_FRAME_048;
   1229                             pC->ewc.uiSilenceFrameSize =
   1230                                 M4VSS3GPP_AMR_AU_SILENCE_FRAME_048_SIZE;
   1231                             pC->ewc.iSilenceFrameDuration =
   1232                                 M4VSS3GPP_AMR_AU_SILENCE_FRAME_048_DURATION;
   1233                             pC->ewc.uiAudioBitrate = M4VIDEOEDITING_k12_2_KBPS;
   1234                         }
   1235                         else if( pC->pAddedClipCtxt->pSettings->
   1236                             ClipProperties.uiSamplingFrequency == 16000 )
   1237                         {
   1238                             if( pC->ewc.uiNbChannels == 1 )
   1239                             {
   1240                                 pC->ewc.AudioStreamType = M4SYS_kAAC;
   1241                                 pC->ewc.pSilenceFrameData = (M4OSA_UInt8
   1242                                     *)M4VSS3GPP_AAC_AU_SILENCE_MONO;
   1243                                 pC->ewc.uiSilenceFrameSize =
   1244                                     M4VSS3GPP_AAC_AU_SILENCE_MONO_SIZE;
   1245                                 pC->ewc.iSilenceFrameDuration =
   1246                                     1024; /* AAC is always 1024/Freq sample duration */
   1247                                 pC->ewc.uiAudioBitrate =
   1248                                     M4VIDEOEDITING_k32_KBPS;
   1249                             }
   1250                             else
   1251                             {
   1252                                 pC->ewc.AudioStreamType = M4SYS_kAAC;
   1253                                 pC->ewc.pSilenceFrameData = (M4OSA_UInt8
   1254                                     *)M4VSS3GPP_AAC_AU_SILENCE_STEREO;
   1255                                 pC->ewc.uiSilenceFrameSize =
   1256                                     M4VSS3GPP_AAC_AU_SILENCE_STEREO_SIZE;
   1257                                 pC->ewc.iSilenceFrameDuration =
   1258                                     1024; /* AAC is always 1024/Freq sample duration */
   1259                                 pC->ewc.uiAudioBitrate =
   1260                                     M4VIDEOEDITING_k64_KBPS;
   1261                             }
   1262                         }
   1263                         else
   1264                         {
   1265                             pC->ewc.AudioStreamType = M4SYS_kAudioUnknown;
   1266                         }
   1267                         break;
   1268 
   1269                     default:
   1270                         pC->ewc.AudioStreamType = M4SYS_kAudioUnknown;
   1271                         break;
   1272                 }
   1273             }
   1274 
   1275             /* Add a link to audio dsi */
   1276             pC->ewc.uiAudioOutputDsiSize =
   1277                 (M4OSA_UInt16)pC->pAddedClipCtxt->pAudioStream->
   1278                 m_basicProperties.m_decoderSpecificInfoSize;
   1279             pC->ewc.pAudioOutputDsi = (M4OSA_MemAddr8)pC->pAddedClipCtxt->pAudioStream->
   1280                 m_basicProperties.m_pDecoderSpecificInfo;
   1281         }
   1282         else
   1283         {
   1284             pC->ewc.uiNbChannels =
   1285                 pC->pInputClipCtxt->pSettings->ClipProperties.uiNbChannels;
   1286             pC->ewc.uiAudioBitrate =
   1287                 pC->pInputClipCtxt->pSettings->ClipProperties.uiAudioBitrate;
   1288             pC->ewc.uiSamplingFrequency = pC->pInputClipCtxt->pSettings->
   1289                 ClipProperties.uiSamplingFrequency;
   1290             pC->ewc.uiSilencePcmSize =
   1291                 pC->pInputClipCtxt->pSettings->ClipProperties.uiDecodedPcmSize;
   1292             pC->ewc.scale_audio = pC->ewc.uiSamplingFrequency / 1000.0;
   1293 
   1294             switch( pC->pInputClipCtxt->pSettings->
   1295                 ClipProperties.AudioStreamType )
   1296             {
   1297                 case M4VIDEOEDITING_kAMR_NB:
   1298                     pC->ewc.AudioStreamType = M4SYS_kAMR;
   1299                     pC->ewc.pSilenceFrameData =
   1300                         (M4OSA_UInt8 *)M4VSS3GPP_AMR_AU_SILENCE_FRAME_048;
   1301                     pC->ewc.uiSilenceFrameSize =
   1302                         M4VSS3GPP_AMR_AU_SILENCE_FRAME_048_SIZE;
   1303                     pC->ewc.iSilenceFrameDuration =
   1304                         M4VSS3GPP_AMR_AU_SILENCE_FRAME_048_DURATION;
   1305                     break;
   1306 
   1307                 case M4VIDEOEDITING_kAAC:
   1308                 case M4VIDEOEDITING_kAACplus:
   1309                 case M4VIDEOEDITING_keAACplus:
   1310                     pC->ewc.AudioStreamType = M4SYS_kAAC;
   1311 
   1312                     if( pC->ewc.uiNbChannels == 1 )
   1313                     {
   1314                         pC->ewc.pSilenceFrameData =
   1315                             (M4OSA_UInt8 *)M4VSS3GPP_AAC_AU_SILENCE_MONO;
   1316                         pC->ewc.uiSilenceFrameSize =
   1317                             M4VSS3GPP_AAC_AU_SILENCE_MONO_SIZE;
   1318                     }
   1319                     else
   1320                     {
   1321                         pC->ewc.pSilenceFrameData =
   1322                             (M4OSA_UInt8 *)M4VSS3GPP_AAC_AU_SILENCE_STEREO;
   1323                         pC->ewc.uiSilenceFrameSize =
   1324                             M4VSS3GPP_AAC_AU_SILENCE_STEREO_SIZE;
   1325                     }
   1326                     pC->ewc.iSilenceFrameDuration =
   1327                         1024; /* AAC is always 1024/Freq sample duration */
   1328                     break;
   1329 
   1330                 default:
   1331                     pC->ewc.AudioStreamType = M4SYS_kAudioUnknown;
   1332                     M4OSA_TRACE1_0(
   1333                         "M4VSS3GPP_intAudioMixingOpen: No audio track in input file.");
   1334                     return M4VSS3GPP_ERR_AUDIO_CANNOT_BE_MIXED;
   1335                     break;
   1336             }
   1337 
   1338             /* Add a link to audio dsi */
   1339             pC->ewc.uiAudioOutputDsiSize =
   1340                 (M4OSA_UInt16)pC->pInputClipCtxt->pAudioStream->
   1341                 m_basicProperties.m_decoderSpecificInfoSize;
   1342             pC->ewc.pAudioOutputDsi = (M4OSA_MemAddr8)pC->pInputClipCtxt->pAudioStream->
   1343                 m_basicProperties.m_pDecoderSpecificInfo;
   1344         }
   1345     }
   1346 
   1347     /**
   1348     * Copy common 'silence frame stuff' to ClipContext */
   1349     pC->pInputClipCtxt->uiSilencePcmSize = pC->ewc.uiSilencePcmSize;
   1350     pC->pInputClipCtxt->pSilenceFrameData = pC->ewc.pSilenceFrameData;
   1351     pC->pInputClipCtxt->uiSilenceFrameSize = pC->ewc.uiSilenceFrameSize;
   1352     pC->pInputClipCtxt->iSilenceFrameDuration = pC->ewc.iSilenceFrameDuration;
   1353     pC->pInputClipCtxt->scale_audio = pC->ewc.scale_audio;
   1354 
   1355     pC->pInputClipCtxt->iAudioFrameCts =
   1356         -pC->pInputClipCtxt->iSilenceFrameDuration; /* Reset time */
   1357 
   1358     /**
   1359     * Copy common 'silence frame stuff' to ClipContext */
   1360     if( pC->bHasAudio )
   1361     {
   1362         pC->pAddedClipCtxt->uiSilencePcmSize = pC->ewc.uiSilencePcmSize;
   1363         pC->pAddedClipCtxt->pSilenceFrameData = pC->ewc.pSilenceFrameData;
   1364         pC->pAddedClipCtxt->uiSilenceFrameSize = pC->ewc.uiSilenceFrameSize;
   1365         pC->pAddedClipCtxt->iSilenceFrameDuration =
   1366             pC->ewc.iSilenceFrameDuration;
   1367         pC->pAddedClipCtxt->scale_audio = pC->ewc.scale_audio;
   1368 
   1369         pC->pAddedClipCtxt->iAudioFrameCts =
   1370             -pC->pAddedClipCtxt->iSilenceFrameDuration; /* Reset time */
   1371     }
   1372 
   1373     /**
   1374     * Check AddCts is lower than original clip duration */
   1375     if( ( M4OSA_NULL != pC->pInputClipCtxt->pVideoStream)
   1376         && (pC->iAddCts > (M4OSA_Int32)pC->pInputClipCtxt->pVideoStream->
   1377         m_basicProperties.m_duration) )
   1378     {
   1379         M4OSA_TRACE1_0(
   1380             "M4VSS3GPP_intAudioMixingOpen(): uiAddCts is larger than video duration,\
   1381             returning M4VSS3GPP_ERR_ADDCTS_HIGHER_THAN_VIDEO_DURATION");
   1382         return M4VSS3GPP_ERR_ADDCTS_HIGHER_THAN_VIDEO_DURATION;
   1383     }
   1384 
   1385     /**
   1386     * If the audio tracks are not compatible, replace input track by silence */
   1387     if( M4OSA_FALSE == pC->pInputClipCtxt->pSettings->
   1388         ClipProperties.bAudioIsCompatibleWithMasterClip )
   1389     {
   1390         M4VSS3GPP_intClipDeleteAudioTrack(pC->pInputClipCtxt);
   1391     }
   1392 
   1393     /**
   1394     * Check if audio mixing is required */
   1395     if( ( ( pC->bHasAudio) && (M4OSA_FALSE
   1396         == pC->pAddedClipCtxt->pSettings->ClipProperties.bAudioIsEditable))
   1397         || (M4OSA_TRUE == pC->bRemoveOriginal) ) /*||
   1398                                                  (pSettings->uiAddVolume >= 100)) */
   1399     {
   1400         pC->bAudioMixingIsNeeded = M4OSA_FALSE;
   1401     }
   1402     else
   1403     {
   1404         pC->bAudioMixingIsNeeded = M4OSA_TRUE;
   1405     }
   1406 
   1407     /**
   1408     * Check if output audio can support silence frames
   1409     Trick i use bAudioIsCompatibleWithMasterClip filed to store that  */
   1410     if( pC->bHasAudio )
   1411     {
   1412         pC->bSupportSilence = pC->pAddedClipCtxt->pSettings->
   1413             ClipProperties.bAudioIsCompatibleWithMasterClip;
   1414 
   1415         if( M4OSA_FALSE == pC->bSupportSilence )
   1416         {
   1417             if( pC->iAddCts > 0 )
   1418             {
   1419                 M4OSA_TRACE1_0(
   1420                     "M4VSS3GPP_intAudioMixingOpen():\
   1421                     iAddCts should be set to 0 with this audio track !");
   1422                 return M4VSS3GPP_ERR_FEATURE_UNSUPPORTED_WITH_AUDIO_TRACK;
   1423             }
   1424 
   1425             if( 0 < pC->uiEndLoop )
   1426             {
   1427                 M4OSA_TRACE1_0(
   1428                     "M4VSS3GPP_intAudioMixingOpen():\
   1429                     uiEndLoop should be set to 0 with this audio track !");
   1430                 return M4VSS3GPP_ERR_FEATURE_UNSUPPORTED_WITH_AUDIO_TRACK;
   1431             }
   1432         }
   1433     }
   1434     if( pC->b_DuckingNeedeed == M4OSA_FALSE)
   1435     {
   1436         /**
   1437         * Compute the factor to apply to sample to do the mixing */
   1438         pC->fAddedFactor = 0.50F;
   1439         pC->fOrigFactor = 0.50F;
   1440     }
   1441 
   1442 
   1443     /**
   1444     * Check if SSRC is needed */
   1445     if( M4OSA_TRUE == pC->b_SSRCneeded )
   1446     {
   1447         M4OSA_UInt32 numerator, denominator, ratio, ratioBuffer;
   1448 
   1449         /**
   1450         * Init the SSRC module */
   1451         SSRC_ReturnStatus_en
   1452             ReturnStatus; /* Function return status                       */
   1453         LVM_INT16 NrSamplesMin =
   1454             0; /* Minimal number of samples on the input or on the output */
   1455         LVM_INT32
   1456             ScratchSize; /* The size of the scratch memory               */
   1457         LVM_INT16
   1458             *pInputInScratch; /* Pointer to input in the scratch buffer       */
   1459         LVM_INT16
   1460             *
   1461             pOutputInScratch; /* Pointer to the output in the scratch buffer  */
   1462         SSRC_Params_t ssrcParams;          /* Memory for init parameters                    */
   1463 
   1464         switch( pC->pAddedClipCtxt->pSettings->
   1465             ClipProperties.uiSamplingFrequency )
   1466         {
   1467             case 8000:
   1468                 ssrcParams.SSRC_Fs_In = LVM_FS_8000;
   1469                 break;
   1470 
   1471             case 11025:
   1472                 ssrcParams.SSRC_Fs_In = LVM_FS_11025;
   1473                 break;
   1474 
   1475             case 12000:
   1476                 ssrcParams.SSRC_Fs_In = LVM_FS_12000;
   1477                 break;
   1478 
   1479             case 16000:
   1480                 ssrcParams.SSRC_Fs_In = LVM_FS_16000;
   1481                 break;
   1482 
   1483             case 22050:
   1484                 ssrcParams.SSRC_Fs_In = LVM_FS_22050;
   1485                 break;
   1486 
   1487             case 24000:
   1488                 ssrcParams.SSRC_Fs_In = LVM_FS_24000;
   1489                 break;
   1490 
   1491             case 32000:
   1492                 ssrcParams.SSRC_Fs_In = LVM_FS_32000;
   1493                 break;
   1494 
   1495             case 44100:
   1496                 ssrcParams.SSRC_Fs_In = LVM_FS_44100;
   1497                 break;
   1498 
   1499             case 48000:
   1500                 ssrcParams.SSRC_Fs_In = LVM_FS_48000;
   1501                 break;
   1502 
   1503             default:
   1504                 M4OSA_TRACE1_1(
   1505                     "M4VSS3GPP_intAudioMixingOpen: invalid added clip sampling frequency (%d Hz),\
   1506                     returning M4VSS3GPP_ERR_UNSUPPORTED_ADDED_AUDIO_STREAM",
   1507                     pC->pAddedClipCtxt->pSettings->
   1508                     ClipProperties.uiSamplingFrequency);
   1509                 return M4VSS3GPP_ERR_UNSUPPORTED_ADDED_AUDIO_STREAM;
   1510         }
   1511 
   1512         if( 1 == pC->pAddedClipCtxt->pSettings->ClipProperties.uiNbChannels )
   1513         {
   1514             ssrcParams.SSRC_NrOfChannels = LVM_MONO;
   1515         }
   1516         else
   1517         {
   1518             ssrcParams.SSRC_NrOfChannels = LVM_STEREO;
   1519         }
   1520 
   1521         switch( pC->ewc.uiSamplingFrequency )
   1522         {
   1523             case 8000:
   1524                 ssrcParams.SSRC_Fs_Out = LVM_FS_8000;
   1525                 break;
   1526 
   1527             case 16000:
   1528                 ssrcParams.SSRC_Fs_Out = LVM_FS_16000;
   1529                 break;
   1530 
   1531             case 22050:
   1532                 ssrcParams.SSRC_Fs_Out = LVM_FS_22050;
   1533                 break;
   1534 
   1535             case 24000:
   1536                 ssrcParams.SSRC_Fs_Out = LVM_FS_24000;
   1537                 break;
   1538 
   1539             case 32000:
   1540                 ssrcParams.SSRC_Fs_Out = LVM_FS_32000;
   1541                 break;
   1542 
   1543             case 44100:
   1544                 ssrcParams.SSRC_Fs_Out = LVM_FS_44100;
   1545                 break;
   1546 
   1547             case 48000:
   1548                 ssrcParams.SSRC_Fs_Out = LVM_FS_48000;
   1549                 break;
   1550 
   1551             default:
   1552                 M4OSA_TRACE1_1(
   1553                     "M4VSS3GPP_intAudioMixingOpen: invalid output sampling frequency (%d Hz),\
   1554                     returning M4VSS3GPP_ERR_AUDIO_CANNOT_BE_MIXED",
   1555                     pC->ewc.uiSamplingFrequency);
   1556                 return M4VSS3GPP_ERR_AUDIO_CANNOT_BE_MIXED;
   1557                 break;
   1558         }
   1559         ReturnStatus = 0;
   1560 
   1561         switch (ssrcParams.SSRC_Fs_In){
   1562         case LVM_FS_8000:
   1563             ssrcParams.NrSamplesIn = 320;
   1564             break;
   1565         case LVM_FS_11025:
   1566             ssrcParams.NrSamplesIn =441;
   1567             break;
   1568         case LVM_FS_12000:
   1569             ssrcParams.NrSamplesIn =    480;
   1570             break;
   1571         case LVM_FS_16000:
   1572             ssrcParams.NrSamplesIn =    640;
   1573             break;
   1574         case LVM_FS_22050:
   1575             ssrcParams.NrSamplesIn =    882;
   1576             break;
   1577         case LVM_FS_24000:
   1578             ssrcParams.NrSamplesIn =    960;
   1579             break;
   1580         case LVM_FS_32000:
   1581             ssrcParams.NrSamplesIn = 1280;
   1582             break;
   1583         case LVM_FS_44100:
   1584             ssrcParams.NrSamplesIn = 1764;
   1585             break;
   1586         case LVM_FS_48000:
   1587             ssrcParams.NrSamplesIn = 1920;
   1588             break;
   1589         default:
   1590             ReturnStatus = -1;
   1591             break;
   1592         }
   1593 
   1594         switch (ssrcParams.SSRC_Fs_Out){
   1595         case LVM_FS_8000:
   1596             ssrcParams.NrSamplesOut= 320;
   1597             break;
   1598         case LVM_FS_11025:
   1599             ssrcParams.NrSamplesOut =441;
   1600             break;
   1601         case LVM_FS_12000:
   1602             ssrcParams.NrSamplesOut=    480;
   1603             break;
   1604         case LVM_FS_16000:
   1605             ssrcParams.NrSamplesOut=    640;
   1606             break;
   1607         case LVM_FS_22050:
   1608             ssrcParams.NrSamplesOut=    882;
   1609             break;
   1610         case LVM_FS_24000:
   1611             ssrcParams.NrSamplesOut=    960;
   1612             break;
   1613         case LVM_FS_32000:
   1614             ssrcParams.NrSamplesOut = 1280;
   1615             break;
   1616         case LVM_FS_44100:
   1617             ssrcParams.NrSamplesOut= 1764;
   1618             break;
   1619         case LVM_FS_48000:
   1620             ssrcParams.NrSamplesOut = 1920;
   1621             break;
   1622         default:
   1623             ReturnStatus = -1;
   1624             break;
   1625         }
   1626         if( ReturnStatus != SSRC_OK )
   1627         {
   1628             M4OSA_TRACE1_1(
   1629                 "M4VSS3GPP_intAudioMixingOpen:\
   1630                 Error code %d returned by the SSRC_GetNrSamples function",
   1631                 ReturnStatus);
   1632             return M4VSS3GPP_ERR_AUDIO_CANNOT_BE_MIXED;
   1633         }
   1634 
   1635         NrSamplesMin =
   1636             (LVM_INT16)((ssrcParams.NrSamplesIn > ssrcParams.NrSamplesOut)
   1637             ? ssrcParams.NrSamplesOut : ssrcParams.NrSamplesIn);
   1638 
   1639         while( NrSamplesMin < M4VSS_SSRC_MINBLOCKSIZE )
   1640         { /* Don't take blocks smaller that the minimal block size */
   1641             ssrcParams.NrSamplesIn = (LVM_INT16)(ssrcParams.NrSamplesIn << 1);
   1642             ssrcParams.NrSamplesOut = (LVM_INT16)(ssrcParams.NrSamplesOut << 1);
   1643             NrSamplesMin = (LVM_INT16)(NrSamplesMin << 1);
   1644         }
   1645         pC->iSsrcNbSamplIn = (LVM_INT16)(
   1646             ssrcParams.
   1647             NrSamplesIn); /* multiplication by NrOfChannels is done below */
   1648         pC->iSsrcNbSamplOut = (LVM_INT16)(ssrcParams.NrSamplesOut);
   1649 
   1650         numerator =
   1651             pC->pAddedClipCtxt->pSettings->ClipProperties.uiSamplingFrequency
   1652             * pC->pAddedClipCtxt->pSettings->ClipProperties.uiNbChannels;
   1653         denominator =
   1654             pC->pInputClipCtxt->pSettings->ClipProperties.uiSamplingFrequency
   1655             * pC->pInputClipCtxt->pSettings->ClipProperties.uiNbChannels;
   1656 
   1657         if( numerator % denominator == 0 )
   1658         {
   1659             ratioBuffer = (M4OSA_UInt32)(numerator / denominator);
   1660         }
   1661         else
   1662         {
   1663             ratioBuffer = (M4OSA_UInt32)(numerator / denominator) + 1;
   1664         }
   1665 
   1666         ratio =
   1667             (M4OSA_UInt32)(( pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize
   1668             * ratioBuffer) / (pC->iSsrcNbSamplIn * sizeof(short)
   1669             * pC->pAddedClipCtxt->pSettings->
   1670             ClipProperties.uiNbChannels));
   1671 
   1672         if( ratio == 0 )
   1673         {
   1674             /* It means that the input size of SSRC bufferIn is bigger than the asked buffer */
   1675             pC->minimumBufferIn = pC->iSsrcNbSamplIn * sizeof(short)
   1676                 * pC->pAddedClipCtxt->pSettings->
   1677                 ClipProperties.uiNbChannels;
   1678         }
   1679         else
   1680         {
   1681             ratio++; /* We use the immediate superior integer */
   1682             pC->minimumBufferIn = ratio * (pC->iSsrcNbSamplIn * sizeof(short)
   1683                 * pC->pAddedClipCtxt->pSettings->
   1684                 ClipProperties.uiNbChannels);
   1685         }
   1686 
   1687         /**
   1688         * Allocate buffer for the input of the SSRC */
   1689         pC->pSsrcBufferIn =
   1690             (M4OSA_MemAddr8)M4OSA_32bitAlignedMalloc(pC->minimumBufferIn
   1691             + pC->pAddedClipCtxt->
   1692             AudioDecBufferOut.
   1693             m_bufferSize,
   1694             M4VSS3GPP, (M4OSA_Char *)"pSsrcBufferIn");
   1695 
   1696         if( M4OSA_NULL == pC->pSsrcBufferIn )
   1697         {
   1698             M4OSA_TRACE1_0(
   1699                 "M4VSS3GPP_intAudioMixingOpen():\
   1700                 unable to allocate pSsrcBufferIn, returning M4ERR_ALLOC");
   1701             return M4ERR_ALLOC;
   1702         }
   1703         pC->pPosInSsrcBufferIn = (M4OSA_MemAddr8)pC->pSsrcBufferIn;
   1704 
   1705         /**
   1706         * Allocate buffer for the output of the SSRC */
   1707         /* The "3" value below should be optimized ... one day ... */
   1708         pC->pSsrcBufferOut =
   1709             (M4OSA_MemAddr8)M4OSA_32bitAlignedMalloc(3 * pC->iSsrcNbSamplOut * sizeof(short)
   1710             * pC->ewc.uiNbChannels, M4VSS3GPP, (M4OSA_Char *)"pSsrcBufferOut");
   1711 
   1712         if( M4OSA_NULL == pC->pSsrcBufferOut )
   1713         {
   1714             M4OSA_TRACE1_0(
   1715                 "M4VSS3GPP_intAudioMixingOpen():\
   1716                 unable to allocate pSsrcBufferOut, returning M4ERR_ALLOC");
   1717             return M4ERR_ALLOC;
   1718         }
   1719         pC->pPosInSsrcBufferOut = pC->pSsrcBufferOut;
   1720 
   1721         /**
   1722         * Allocate temporary buffer needed in case of channel conversion */
   1723         if( pC->ChannelConversion > 0 )
   1724         {
   1725             /* The "3" value below should be optimized ... one day ... */
   1726             pC->pTempBuffer =
   1727                 (M4OSA_MemAddr8)M4OSA_32bitAlignedMalloc(3 * pC->iSsrcNbSamplOut
   1728                 * sizeof(short) * pC->pAddedClipCtxt->pSettings->
   1729                 ClipProperties.uiNbChannels, M4VSS3GPP, (M4OSA_Char *)"pSsrcBufferOut");
   1730 
   1731             if( M4OSA_NULL == pC->pTempBuffer )
   1732             {
   1733                 M4OSA_TRACE1_0(
   1734                     "M4VSS3GPP_intAudioMixingOpen():\
   1735                     unable to allocate pTempBuffer, returning M4ERR_ALLOC");
   1736                 return M4ERR_ALLOC;
   1737             }
   1738             pC->pPosInTempBuffer = pC->pTempBuffer;
   1739         }
   1740     }
   1741     else if( pC->ChannelConversion > 0 )
   1742     {
   1743         pC->minimumBufferIn =
   1744             pC->pAddedClipCtxt->AudioDecBufferOut.m_bufferSize;
   1745 
   1746         /**
   1747         * Allocate buffer for the input of the SSRC */
   1748         pC->pSsrcBufferIn =
   1749             (M4OSA_MemAddr8)M4OSA_32bitAlignedMalloc(pC->minimumBufferIn
   1750             + pC->pAddedClipCtxt->
   1751             AudioDecBufferOut.
   1752             m_bufferSize,
   1753             M4VSS3GPP, (M4OSA_Char *)"pSsrcBufferIn");
   1754 
   1755         if( M4OSA_NULL == pC->pSsrcBufferIn )
   1756         {
   1757             M4OSA_TRACE1_0(
   1758                 "M4VSS3GPP_intAudioMixingOpen(): \
   1759                 unable to allocate pSsrcBufferIn, returning M4ERR_ALLOC");
   1760             return M4ERR_ALLOC;
   1761         }
   1762         pC->pPosInSsrcBufferIn = (M4OSA_MemAddr8)pC->pSsrcBufferIn;
   1763 
   1764         /**
   1765         * Allocate buffer for the output of the SSRC */
   1766         /* The "3" value below should be optimized ... one day ... */
   1767         pC->pSsrcBufferOut = (M4OSA_MemAddr8)M4OSA_32bitAlignedMalloc(
   1768             pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize,
   1769             M4VSS3GPP, (M4OSA_Char *)"pSsrcBufferOut");
   1770 
   1771         if( M4OSA_NULL == pC->pSsrcBufferOut )
   1772         {
   1773             M4OSA_TRACE1_0(
   1774                 "M4VSS3GPP_intAudioMixingOpen():\
   1775                 unable to allocate pSsrcBufferOut, returning M4ERR_ALLOC");
   1776             return M4ERR_ALLOC;
   1777         }
   1778         pC->pPosInSsrcBufferOut = pC->pSsrcBufferOut;
   1779     }
   1780     else if( (pC->pAddedClipCtxt->pSettings->ClipProperties.AudioStreamType == M4VIDEOEDITING_kMP3)||
   1781          (pC->pAddedClipCtxt->pSettings->ClipProperties.AudioStreamType == M4VIDEOEDITING_kPCM))
   1782     {
   1783         M4OSA_UInt32 minbuffer = 0;
   1784 
   1785         if( pSettings->outputAudioFormat == M4VIDEOEDITING_kAAC )
   1786         {
   1787             pC->minimumBufferIn = 2048 * pC->ewc.uiNbChannels;
   1788             minbuffer = pC->minimumBufferIn;
   1789         }
   1790         else if( pSettings->outputAudioFormat == M4VIDEOEDITING_kAMR_NB )
   1791         {
   1792             pC->minimumBufferIn = 320;
   1793 
   1794             if( pC->pAddedClipCtxt->AudioDecBufferOut.m_bufferSize > 320 )
   1795             {
   1796                 minbuffer = pC->pAddedClipCtxt->AudioDecBufferOut.m_bufferSize;
   1797             }
   1798             else
   1799             {
   1800                 minbuffer = pC->minimumBufferIn; /* Not really possible ...*/
   1801             }
   1802         }
   1803         else
   1804         {
   1805             M4OSA_TRACE1_0("Bad output audio format, in case of MP3 replacing");
   1806             return M4ERR_PARAMETER;
   1807         }
   1808 
   1809         /**
   1810         * Allocate buffer for the input of the SSRC */
   1811         pC->pSsrcBufferIn =
   1812             (M4OSA_MemAddr8)M4OSA_32bitAlignedMalloc(2 * minbuffer, M4VSS3GPP,
   1813             (M4OSA_Char *)"pSsrcBufferIn");
   1814 
   1815         if( M4OSA_NULL == pC->pSsrcBufferIn )
   1816         {
   1817             M4OSA_TRACE1_0(
   1818                 "M4VSS3GPP_intAudioMixingOpen(): unable to allocate pSsrcBufferIn,\
   1819                 returning M4ERR_ALLOC");
   1820             return M4ERR_ALLOC;
   1821         }
   1822         pC->pPosInSsrcBufferIn = (M4OSA_MemAddr8)pC->pSsrcBufferIn;
   1823 
   1824         pC->pPosInSsrcBufferOut = pC->pPosInSsrcBufferIn;
   1825         pC->pSsrcBufferOut = pC->pSsrcBufferIn;
   1826     }
   1827 
   1828     /**
   1829     * Check if audio encoder is needed to do audio mixing or audio resampling */
   1830     if( M4OSA_TRUE == pC->bAudioMixingIsNeeded || M4VIDEOEDITING_kPCM
   1831         == pC->pAddedClipCtxt->pSettings->ClipProperties.AudioStreamType
   1832         || M4VIDEOEDITING_kMP3
   1833         == pC->pAddedClipCtxt->pSettings->ClipProperties.AudioStreamType
   1834         || pC->pAddedClipCtxt->pSettings->ClipProperties.AudioStreamType
   1835         != pSettings->outputAudioFormat
   1836         || pC->pAddedClipCtxt->pSettings->ClipProperties.uiSamplingFrequency
   1837         != outputASF
   1838         || pC->pAddedClipCtxt->pSettings->ClipProperties.uiNbChannels
   1839         != pSettings->outputNBChannels )
   1840     {
   1841         /**
   1842         * Init the audio encoder */
   1843         err = M4VSS3GPP_intCreateAudioEncoder(&pC->ewc, &pC->ShellAPI,
   1844             pC->ewc.uiAudioBitrate);
   1845 
   1846         if( M4NO_ERROR != err )
   1847         {
   1848             M4OSA_TRACE1_1(
   1849                 "M4VSS3GPP_intAudioMixingOpen(): M4VSS3GPP_intCreateAudioEncoder() returns 0x%x",
   1850                 err);
   1851             return err;
   1852         }
   1853 
   1854         /* In case of PCM, MP3 or audio replace with reencoding, use encoder DSI */
   1855         if( pC->ewc.uiAudioOutputDsiSize == 0 && (M4VIDEOEDITING_kPCM
   1856             == pC->pAddedClipCtxt->pSettings->ClipProperties.AudioStreamType
   1857             || M4VIDEOEDITING_kMP3 == pC->pAddedClipCtxt->pSettings->
   1858             ClipProperties.AudioStreamType
   1859             || pC->pAddedClipCtxt->pSettings->
   1860             ClipProperties.AudioStreamType
   1861             != pSettings->outputAudioFormat
   1862             || pC->pAddedClipCtxt->pSettings->
   1863             ClipProperties.uiSamplingFrequency != outputASF
   1864             || pC->pAddedClipCtxt->pSettings->
   1865             ClipProperties.uiNbChannels
   1866             != pSettings->outputNBChannels) )
   1867         {
   1868             pC->ewc.uiAudioOutputDsiSize =
   1869                 (M4OSA_UInt16)pC->ewc.pAudioEncDSI.infoSize;
   1870             pC->ewc.pAudioOutputDsi = pC->ewc.pAudioEncDSI.pInfo;
   1871         }
   1872     }
   1873 
   1874     /**
   1875     * Init the output 3GPP file */
   1876     /*11/12/2008 CR3283 add the max output file size for the MMS use case in VideoArtist*/
   1877     err = M4VSS3GPP_intCreate3GPPOutputFile(&pC->ewc, &pC->ShellAPI,
   1878         pC->pOsaFileWritPtr, pSettings->pOutputClipFile,
   1879         pC->pOsaFileReadPtr, pSettings->pTemporaryFile, 0);
   1880 
   1881     if( M4NO_ERROR != err )
   1882     {
   1883         M4OSA_TRACE1_1(
   1884             "M4VSS3GPP_intAudioMixingOpen(): M4VSS3GPP_intCreate3GPPOutputFile() returns 0x%x",
   1885             err);
   1886         return err;
   1887     }
   1888 
   1889     /**
   1890     * Return with no error */
   1891     M4OSA_TRACE3_0("M4VSS3GPP_intAudioMixingOpen(): returning M4NO_ERROR");
   1892     return M4NO_ERROR;
   1893 }
   1894 
   1895 /**
   1896  ******************************************************************************
   1897  * M4OSA_ERR M4VSS3GPP_intAudioMixingWriteSilence()
   1898  * @brief    Write an audio silence frame into the writer
   1899  * @note    Mainly used when padding with silence
   1900  * @param    pC            (IN) VSS audio mixing internal context
   1901  * @return    M4NO_ERROR:    No error
   1902  ******************************************************************************
   1903  */
   1904 static M4OSA_ERR M4VSS3GPP_intAudioMixingWriteSilence(
   1905     M4VSS3GPP_InternalAudioMixingContext *pC )
   1906 {
   1907     M4OSA_ERR err;
   1908 
   1909     err = pC->ShellAPI.pWriterDataFcts->pStartAU(pC->ewc.p3gpWriterContext,
   1910         M4VSS3GPP_WRITER_AUDIO_STREAM_ID, &pC->ewc.WriterAudioAU);
   1911 
   1912     if( M4NO_ERROR != err )
   1913     {
   1914         M4OSA_TRACE1_1("M4VSS3GPP_intAudioMixingWriteSilence:\
   1915          pWriterDataFcts->pStartAU(audio) returns 0x%x!", err);
   1916         return err;
   1917     }
   1918 
   1919     M4OSA_TRACE2_0("A #### silence AU");
   1920 
   1921     memcpy((void *)pC->ewc.WriterAudioAU.dataAddress,
   1922         (void *)pC->ewc.pSilenceFrameData, pC->ewc.uiSilenceFrameSize);
   1923 
   1924     pC->ewc.WriterAudioAU.size = pC->ewc.uiSilenceFrameSize;
   1925     pC->ewc.WriterAudioAU.CTS =
   1926         (M4OSA_Time)(pC->ewc.dATo * pC->ewc.scale_audio + 0.5);
   1927 
   1928     M4OSA_TRACE2_2("B ---- write : cts  = %ld [ 0x%x ]",
   1929         (M4OSA_Int32)(pC->ewc.dATo), pC->ewc.WriterAudioAU.size);
   1930 
   1931     err = pC->ShellAPI.pWriterDataFcts->pProcessAU(pC->ewc.p3gpWriterContext,
   1932         M4VSS3GPP_WRITER_AUDIO_STREAM_ID, &pC->ewc.WriterAudioAU);
   1933 
   1934     if( M4NO_ERROR != err )
   1935     {
   1936         M4OSA_TRACE1_1(
   1937             "M4VSS3GPP_intAudioMixingWriteSilence:\
   1938             pWriterDataFcts->pProcessAU(silence) returns 0x%x!",
   1939             err);
   1940         return err;
   1941     }
   1942 
   1943     pC->ewc.dATo += pC->ewc.iSilenceFrameDuration / pC->ewc.scale_audio;
   1944 
   1945     return M4NO_ERROR;
   1946 }
   1947 
   1948 /**
   1949  ******************************************************************************
   1950  * M4OSA_ERR M4VSS3GPP_intAudioMixingStepVideo(M4VSS3GPP_InternalAudioMixingContext *pC)
   1951  * @brief    Perform one step of video.
   1952  * @note
   1953  * @param    pC            (IN) VSS audio mixing internal context
   1954  * @return    M4NO_ERROR:    No error
   1955  ******************************************************************************
   1956  */
   1957 static M4OSA_ERR M4VSS3GPP_intAudioMixingStepVideo(
   1958     M4VSS3GPP_InternalAudioMixingContext *pC )
   1959 {
   1960     M4OSA_ERR err;
   1961     M4OSA_UInt16 offset;
   1962 
   1963     M4OSA_TRACE2_3("  VIDEO step : dVTo = %f  state = %d  offset = %ld",
   1964         pC->ewc.dOutputVidCts, pC->State, pC->pInputClipCtxt->iVoffset);
   1965 
   1966     /**
   1967     * Read the input video AU */
   1968     err = pC->pInputClipCtxt->ShellAPI.m_pReaderDataIt->m_pFctGetNextAu(
   1969         pC->pInputClipCtxt->pReaderContext,
   1970         (M4_StreamHandler *)pC->pInputClipCtxt->pVideoStream,
   1971         &pC->pInputClipCtxt->VideoAU);
   1972 
   1973     if( M4NO_ERROR != err )
   1974     {
   1975         M4OSA_TRACE3_1(
   1976             "M4VSS3GPP_intAudioMixingStepVideo(): m_pFctGetNextAu(video) returns 0x%x",
   1977             err);
   1978         return err;
   1979     }
   1980 
   1981     M4OSA_TRACE2_3("C .... read  : cts  = %.0f + %ld [ 0x%x ]",
   1982         pC->pInputClipCtxt->VideoAU.m_CTS, pC->pInputClipCtxt->iVoffset,
   1983         pC->pInputClipCtxt->VideoAU.m_size);
   1984 
   1985     /**
   1986     * Get the output AU to write into */
   1987     err = pC->ShellAPI.pWriterDataFcts->pStartAU(pC->ewc.p3gpWriterContext,
   1988         M4VSS3GPP_WRITER_VIDEO_STREAM_ID, &pC->ewc.WriterVideoAU);
   1989 
   1990     if( M4NO_ERROR != err )
   1991     {
   1992         M4OSA_TRACE1_1(
   1993             "M4VSS3GPP_intAudioMixingStepVideo: pWriterDataFcts->pStartAU(Video) returns 0x%x!",
   1994             err);
   1995         return err;
   1996     }
   1997 
   1998     offset = 0;
   1999     /* for h.264 stream do not read the 1st 4 bytes as they are header indicators */
   2000     if( pC->pInputClipCtxt->pVideoStream->m_basicProperties.m_streamType
   2001         == M4DA_StreamTypeVideoMpeg4Avc )
   2002     {
   2003         M4OSA_TRACE3_0(
   2004             "M4VSS3GPP_intAudioMixingStepVideo(): input stream type H264");
   2005         offset = 4;
   2006     }
   2007     pC->pInputClipCtxt->VideoAU.m_size  -=  offset;
   2008     /**
   2009     * Check that the video AU is not larger than expected */
   2010     if( pC->pInputClipCtxt->VideoAU.m_size > pC->ewc.uiVideoMaxAuSize )
   2011     {
   2012         M4OSA_TRACE1_2(
   2013             "M4VSS3GPP_intAudioMixingStepVideo: AU size greater than MaxAuSize (%d>%d)!\
   2014             returning M4VSS3GPP_ERR_INPUT_VIDEO_AU_TOO_LARGE",
   2015             pC->pInputClipCtxt->VideoAU.m_size, pC->ewc.uiVideoMaxAuSize);
   2016         return M4VSS3GPP_ERR_INPUT_VIDEO_AU_TOO_LARGE;
   2017     }
   2018 
   2019     /**
   2020     * Copy the input AU payload to the output AU */
   2021     memcpy((void *)pC->ewc.WriterVideoAU.dataAddress,
   2022         (void *)(pC->pInputClipCtxt->VideoAU.m_dataAddress + offset),
   2023         (pC->pInputClipCtxt->VideoAU.m_size));
   2024 
   2025     /**
   2026     * Copy the input AU parameters to the output AU */
   2027     pC->ewc.WriterVideoAU.size = pC->pInputClipCtxt->VideoAU.m_size;
   2028     pC->ewc.WriterVideoAU.CTS =
   2029         (M4OSA_UInt32)(pC->pInputClipCtxt->VideoAU.m_CTS + 0.5);
   2030     pC->ewc.WriterVideoAU.attribute = pC->pInputClipCtxt->VideoAU.m_attribute;
   2031 
   2032     /**
   2033     * Write the AU */
   2034     M4OSA_TRACE2_2("D ---- write : cts  = %lu [ 0x%x ]",
   2035         pC->ewc.WriterVideoAU.CTS, pC->ewc.WriterVideoAU.size);
   2036 
   2037     err = pC->ShellAPI.pWriterDataFcts->pProcessAU(pC->ewc.p3gpWriterContext,
   2038         M4VSS3GPP_WRITER_VIDEO_STREAM_ID, &pC->ewc.WriterVideoAU);
   2039 
   2040     if( M4NO_ERROR != err )
   2041     {
   2042         M4OSA_TRACE1_1(
   2043             "M4VSS3GPP_intAudioMixingStepVideo: pWriterDataFcts->pProcessAU(Video) returns 0x%x!",
   2044             err);
   2045         return err;
   2046     }
   2047 
   2048     /**
   2049     * Return with no error */
   2050     M4OSA_TRACE3_0("M4VSS3GPP_intAudioMixingStepVideo(): returning M4NO_ERROR");
   2051     return M4NO_ERROR;
   2052 }
   2053 
   2054 /**
   2055  ******************************************************************************
   2056  * M4OSA_ERR M4VSS3GPP_intAudioMixingStepAudioMix(M4VSS3GPP_InternalAudioMixingContext *pC)
   2057  * @brief    Perform one step of audio.
   2058  * @note
   2059  * @param    pC            (IN) VSS audio mixing internal context
   2060  * @return    M4NO_ERROR:    No error
   2061  ******************************************************************************
   2062  */
   2063 static M4OSA_ERR M4VSS3GPP_intAudioMixingStepAudioMix(
   2064     M4VSS3GPP_InternalAudioMixingContext *pC )
   2065 {
   2066     M4OSA_ERR err;
   2067 
   2068     M4OSA_TRACE2_3("  AUDIO mix  : dATo = %f  state = %d  offset = %ld",
   2069         pC->ewc.dATo, pC->State, pC->pInputClipCtxt->iAoffset);
   2070 
   2071     switch( pC->State )
   2072     {
   2073         /**********************************************************/
   2074         case M4VSS3GPP_kAudioMixingState_AUDIO_FIRST_SEGMENT:
   2075             {
   2076                 err = M4VSS3GPP_intAudioMixingCopyOrig(pC);
   2077 
   2078                 if( M4NO_ERROR != err )
   2079                 {
   2080                     M4OSA_TRACE1_1(
   2081                         "M4VSS3GPP_intAudioMixingStepAudioMix:\
   2082                         M4VSS3GPP_intAudioMixingCopyOrig(1) returns 0x%x!",
   2083                         err);
   2084                     return err;
   2085                 }
   2086 
   2087                 /**
   2088                 * Check if we reached the AddCts */
   2089                 if( pC->ewc.dATo >= pC->iAddCts )
   2090                 {
   2091                     /**
   2092                     * First segment is over, state transition to second and return OK */
   2093                     pC->State = M4VSS3GPP_kAudioMixingState_AUDIO_SECOND_SEGMENT;
   2094 
   2095                     /* Transition from reading state to encoding state */
   2096                     err = M4VSS3GPP_intAudioMixingTransition(pC);
   2097 
   2098                     if( M4NO_ERROR != err )
   2099                     {
   2100                         M4OSA_TRACE1_1(
   2101                             "M4VSS3GPP_intAudioMixingStepAudioMix(): pre-encode fails err = 0x%x",
   2102                             err);
   2103                         return err;
   2104                     }
   2105 
   2106                     /**
   2107                     * Return with no error so the step function will be called again */
   2108                     pC->pAddedClipCtxt->iAoffset =
   2109                         (M4OSA_Int32)(pC->ewc.dATo * pC->ewc.scale_audio + 0.5);
   2110 
   2111                     M4OSA_TRACE2_0(
   2112                         "M4VSS3GPP_intAudioMixingStepAudioMix(): returning M4NO_ERROR (1->2)");
   2113 
   2114                     return M4NO_ERROR;
   2115                 }
   2116             }
   2117             break;
   2118 
   2119             /**********************************************************/
   2120         case M4VSS3GPP_kAudioMixingState_AUDIO_SECOND_SEGMENT:
   2121             {
   2122                 if( M4OSA_TRUE == pC->bAudioMixingIsNeeded ) /**< Mix */
   2123                 {
   2124                     /**
   2125                     * Read the added audio AU */
   2126                     if( pC->ChannelConversion > 0 || pC->b_SSRCneeded == M4OSA_TRUE
   2127                         || pC->pAddedClipCtxt->pSettings->
   2128                         ClipProperties.AudioStreamType == M4VIDEOEDITING_kMP3 )
   2129                     {
   2130                         /* In case of sampling freq conversion and/or channel conversion,
   2131                            the read next AU will be    called by the
   2132                            M4VSS3GPP_intAudioMixingDoMixing function */
   2133                     }
   2134                     else
   2135                     {
   2136                         err =
   2137                             M4VSS3GPP_intClipReadNextAudioFrame(pC->pAddedClipCtxt);
   2138 
   2139                         M4OSA_TRACE2_3("E .... read  : cts  = %.0f + %.0f [ 0x%x ]",
   2140                             pC->pAddedClipCtxt->iAudioFrameCts
   2141                             / pC->pAddedClipCtxt->scale_audio,
   2142                             pC->pAddedClipCtxt->iAoffset
   2143                             / pC->pAddedClipCtxt->scale_audio,
   2144                             pC->pAddedClipCtxt->uiAudioFrameSize);
   2145 
   2146                         if( M4WAR_NO_MORE_AU == err )
   2147                         {
   2148                             /**
   2149                             * Decide what to do when audio is over */
   2150                             if( pC->uiEndLoop > 0 )
   2151                             {
   2152                                 /**
   2153                                 * Jump at the Begin loop time */
   2154                                 M4OSA_Int32 time = (M4OSA_Int32)(pC->uiBeginLoop);
   2155 
   2156                                 err = pC->pAddedClipCtxt->ShellAPI.m_pReader->
   2157                                     m_pFctJump(
   2158                                     pC->pAddedClipCtxt->pReaderContext,
   2159                                     (M4_StreamHandler
   2160                                     *)pC->pAddedClipCtxt->pAudioStream,
   2161                                     &time);
   2162 
   2163                                 if( M4NO_ERROR != err )
   2164                                 {
   2165                                     M4OSA_TRACE1_1(
   2166                                         "M4VSS3GPP_intAudioMixingStepAudioMix():\
   2167                                         m_pReader->m_pFctJump(audio returns 0x%x",
   2168                                         err);
   2169                                     return err;
   2170                                 }
   2171                             }
   2172                             else
   2173                             {
   2174                                 /* Transition from encoding state to reading state */
   2175                                 err = M4VSS3GPP_intAudioMixingTransition(pC);
   2176 
   2177                                 if( M4NO_ERROR != err )
   2178                                 {
   2179                                     M4OSA_TRACE1_1(
   2180                                         "M4VSS3GPP_intAudioMixingStepAudioMix():\
   2181                                         pre-encode fails err = 0x%x",
   2182                                         err);
   2183                                     return err;
   2184                                 }
   2185 
   2186                                 /**
   2187                                 * Second segment is over, state transition to third and
   2188                                  return OK */
   2189                                 pC->State =
   2190                                     M4VSS3GPP_kAudioMixingState_AUDIO_THIRD_SEGMENT;
   2191 
   2192                                 /**
   2193                                 * Return with no error so the step function will be
   2194                                  called again */
   2195                                 M4OSA_TRACE2_0(
   2196                                     "M4VSS3GPP_intAudioMixingStepAudioMix():\
   2197                                     returning M4NO_ERROR (2->3) a");
   2198                                 return M4NO_ERROR;
   2199                             }
   2200                         }
   2201                         else if( M4NO_ERROR != err )
   2202                         {
   2203                             M4OSA_TRACE1_1(
   2204                                 "M4VSS3GPP_intAudioMixingStepAudioMix():\
   2205                                 m_pFctGetNextAu(audio) returns 0x%x",
   2206                                 err);
   2207                             return err;
   2208                         }
   2209                     }
   2210 
   2211                     /**
   2212                     * Read the original audio AU */
   2213                     err = M4VSS3GPP_intClipReadNextAudioFrame(pC->pInputClipCtxt);
   2214 
   2215                     M4OSA_TRACE2_3("F .... read  : cts  = %.0f + %.0f [ 0x%x ]",
   2216                         pC->pInputClipCtxt->iAudioFrameCts
   2217                         / pC->pInputClipCtxt->scale_audio,
   2218                         pC->pInputClipCtxt->iAoffset
   2219                         / pC->pInputClipCtxt->scale_audio,
   2220                         pC->pInputClipCtxt->uiAudioFrameSize);
   2221 
   2222                     if( M4NO_ERROR != err )
   2223                     {
   2224                         M4OSA_TRACE3_1(
   2225                             "M4VSS3GPP_intAudioMixingStepAudioMix():\
   2226                             m_pFctGetNextAu(audio) returns 0x%x",
   2227                             err);
   2228                         return err;
   2229                     }
   2230 
   2231                     if( pC->ChannelConversion == 0
   2232                         && pC->b_SSRCneeded == M4OSA_FALSE
   2233                         && pC->pAddedClipCtxt->pSettings->
   2234                         ClipProperties.AudioStreamType != M4VIDEOEDITING_kMP3 )
   2235                     {
   2236                         /**
   2237                         * Get the output AU to write into */
   2238                         err = pC->ShellAPI.pWriterDataFcts->pStartAU(
   2239                             pC->ewc.p3gpWriterContext,
   2240                             M4VSS3GPP_WRITER_AUDIO_STREAM_ID,
   2241                             &pC->ewc.WriterAudioAU);
   2242 
   2243                         if( M4NO_ERROR != err )
   2244                         {
   2245                             M4OSA_TRACE1_1(
   2246                                 "M4VSS3GPP_intAudioMixingStepAudioMix:\
   2247                                 pWriterDataFcts->pStartAU(audio) returns 0x%x!",
   2248                                 err);
   2249                             return err;
   2250                         }
   2251                     }
   2252 
   2253                     /**
   2254                     * Perform the audio mixing */
   2255                     err = M4VSS3GPP_intAudioMixingDoMixing(pC);
   2256 
   2257                     if( err == M4VSS3GPP_WAR_END_OF_ADDED_AUDIO )
   2258                     {
   2259                         return M4NO_ERROR;
   2260                     }
   2261 
   2262                     if( M4NO_ERROR != err )
   2263                     {
   2264                         M4OSA_TRACE1_1(
   2265                             "M4VSS3GPP_intAudioMixingStepAudioMix:\
   2266                             M4VSS3GPP_intAudioMixingDoMixing returns 0x%x!",
   2267                             err);
   2268                         return err;
   2269                     }
   2270                 }
   2271                 else /**< No mix, just copy added audio */
   2272                 {
   2273                     err = M4VSS3GPP_intAudioMixingCopyAdded(pC);
   2274 
   2275                     if( M4WAR_NO_MORE_AU == err )
   2276                     {
   2277                         /**
   2278                         * Decide what to do when audio is over */
   2279                         if( pC->uiEndLoop > 0 )
   2280                         {
   2281                             /**
   2282                             * Jump at the Begin loop time */
   2283                             M4OSA_Int32 time = (M4OSA_Int32)(pC->uiBeginLoop);
   2284 
   2285                             err =
   2286                                 pC->pAddedClipCtxt->ShellAPI.m_pReader->m_pFctJump(
   2287                                 pC->pAddedClipCtxt->pReaderContext,
   2288                                 (M4_StreamHandler
   2289                                 *)pC->pAddedClipCtxt->pAudioStream,
   2290                                 &time);
   2291 
   2292                             if( M4NO_ERROR != err )
   2293                             {
   2294                                 M4OSA_TRACE1_1(
   2295                                     "M4VSS3GPP_intAudioMixingStepAudioMix():\
   2296                                     m_pReader->m_pFctJump(audio returns 0x%x",
   2297                                     err);
   2298                                 return err;
   2299                             }
   2300 
   2301                             /**
   2302                             * 'BZZZ' bug fix:
   2303                             * add a silence frame */
   2304                             err = M4VSS3GPP_intAudioMixingWriteSilence(pC);
   2305 
   2306                             if( M4NO_ERROR != err )
   2307                             {
   2308                                 M4OSA_TRACE1_1(
   2309                                     "M4VSS3GPP_intAudioMixingStepAudioMix():\
   2310                                     M4VSS3GPP_intAudioMixingWriteSilence returns 0x%x",
   2311                                     err);
   2312                                 return err;
   2313                             }
   2314 
   2315                             /**
   2316                             * Return with no error so the step function will be called again to
   2317                               read audio data */
   2318                             pC->pAddedClipCtxt->iAoffset =
   2319                                 (M4OSA_Int32)(pC->ewc.dATo * pC->ewc.scale_audio
   2320                                 + 0.5);
   2321 
   2322                             M4OSA_TRACE2_0(
   2323                                 "M4VSS3GPP_intAudioMixingStepAudioMix():\
   2324                                     returning M4NO_ERROR (loop)");
   2325                             return M4NO_ERROR;
   2326                         }
   2327                         else
   2328                         {
   2329                             /* Transition to begin cut */
   2330                             err = M4VSS3GPP_intAudioMixingTransition(pC);
   2331 
   2332                             if( M4NO_ERROR != err )
   2333                             {
   2334                                 M4OSA_TRACE1_1(
   2335                                     "M4VSS3GPP_intAudioMixingStepAudioMix():\
   2336                                     pre-encode fails err = 0x%x",
   2337                                     err);
   2338                                 return err;
   2339                             }
   2340 
   2341                             /**
   2342                             * Second segment is over, state transition to third */
   2343                             pC->State =
   2344                                 M4VSS3GPP_kAudioMixingState_AUDIO_THIRD_SEGMENT;
   2345 
   2346                             /**
   2347                             * Return with no error so the step function will be called again */
   2348                             M4OSA_TRACE2_0(
   2349                                 "M4VSS3GPP_intAudioMixingStepAudioMix():\
   2350                                 returning M4NO_ERROR (2->3) b");
   2351                             return M4NO_ERROR;
   2352                         }
   2353                     }
   2354                     else if( M4NO_ERROR != err )
   2355                     {
   2356                         M4OSA_TRACE1_1(
   2357                             "M4VSS3GPP_intAudioMixingStepAudioMix():\
   2358                             M4VSS3GPP_intAudioMixingCopyOrig(2) returns 0x%x",
   2359                             err);
   2360                         return err;
   2361                     }
   2362                 }
   2363 
   2364                 /**
   2365                 * Check if we reached the end of the video */
   2366                 if( pC->ewc.dATo >= pC->ewc.iOutputDuration )
   2367                 {
   2368                     M4OSA_TRACE3_0(
   2369                         "M4VSS3GPP_intAudioMixingStepAudioMix(): Video duration reached,\
   2370                         returning M4WAR_NO_MORE_AU");
   2371                     return M4WAR_NO_MORE_AU; /**< Simulate end of file error */
   2372                 }
   2373             }
   2374             break;
   2375 
   2376             /**********************************************************/
   2377         case M4VSS3GPP_kAudioMixingState_AUDIO_THIRD_SEGMENT:
   2378             {
   2379                 err = M4VSS3GPP_intAudioMixingCopyOrig(pC);
   2380 
   2381                 if( M4NO_ERROR != err )
   2382                 {
   2383                     M4OSA_TRACE1_1(
   2384                         "M4VSS3GPP_intAudioMixingStepAudioMix:\
   2385                         M4VSS3GPP_intAudioMixingCopyOrig(3) returns 0x%x!",
   2386                         err);
   2387                     return err;
   2388                 }
   2389 
   2390                 /**
   2391                 * Check if we reached the end of the video */
   2392                 if( pC->ewc.dATo >= pC->ewc.iOutputDuration )
   2393                 {
   2394                     M4OSA_TRACE3_0(
   2395                         "M4VSS3GPP_intAudioMixingStepAudioMix():\
   2396                         Video duration reached, returning M4WAR_NO_MORE_AU");
   2397                     return M4WAR_NO_MORE_AU; /**< Simulate end of file error */
   2398                 }
   2399             }
   2400             break;
   2401        default:
   2402             break;
   2403     }
   2404 
   2405     /**
   2406     * Return with no error */
   2407     M4OSA_TRACE3_0(
   2408         "M4VSS3GPP_intAudioMixingStepAudioMix(): returning M4NO_ERROR");
   2409     return M4NO_ERROR;
   2410 }
   2411 
   2412 /**
   2413  ******************************************************************************
   2414  * M4OSA_ERR M4VSS3GPP_intAudioMixingStepAudioReplace(M4VSS3GPP_InternalAudioMixingContext *pC)
   2415  * @brief    Perform one step of audio.
   2416  * @note
   2417  * @param    pC            (IN) VSS audio mixing internal context
   2418  * @return    M4NO_ERROR:    No error
   2419  ******************************************************************************
   2420  */
   2421 static M4OSA_ERR M4VSS3GPP_intAudioMixingStepAudioReplace(
   2422     M4VSS3GPP_InternalAudioMixingContext *pC )
   2423 {
   2424     M4OSA_ERR err;
   2425 
   2426     M4OSA_TRACE2_3("  AUDIO repl : dATo = %f  state = %d  offset = %ld",
   2427         pC->ewc.dATo, pC->State, pC->pInputClipCtxt->iAoffset);
   2428 
   2429     switch( pC->State )
   2430     {
   2431         /**********************************************************/
   2432         case M4VSS3GPP_kAudioMixingState_AUDIO_FIRST_SEGMENT:
   2433             {
   2434                 /**
   2435                 * Replace the SID (silence) payload in the writer AU */
   2436                 err = M4VSS3GPP_intAudioMixingWriteSilence(pC);
   2437 
   2438                 if( M4NO_ERROR != err )
   2439                 {
   2440                     M4OSA_TRACE1_1(
   2441                         "M4VSS3GPP_intAudioMixingStepAudioMix():\
   2442                         M4VSS3GPP_intAudioMixingWriteSilence returns 0x%x",
   2443                         err);
   2444                     return err;
   2445                 }
   2446 
   2447                 /**
   2448                 * Check if we reached the AddCts */
   2449                 if( pC->ewc.dATo >= pC->iAddCts )
   2450                 {
   2451                     /**
   2452                     * First segment is over, state transition to second and return OK */
   2453                     pC->State = M4VSS3GPP_kAudioMixingState_AUDIO_SECOND_SEGMENT;
   2454 
   2455                     /**
   2456                     * Return with no error so the step function will be called again */
   2457                     pC->pAddedClipCtxt->iAoffset =
   2458                         (M4OSA_Int32)(pC->ewc.dATo * pC->ewc.scale_audio + 0.5);
   2459 
   2460                     M4OSA_TRACE2_0("M4VSS3GPP_intAudioMixingStepAudioReplace():\
   2461                          returning M4NO_ERROR (1->2)");
   2462                     return M4NO_ERROR;
   2463                 }
   2464             }
   2465             break;
   2466 
   2467             /**********************************************************/
   2468         case M4VSS3GPP_kAudioMixingState_AUDIO_SECOND_SEGMENT:
   2469             {
   2470                 err = M4VSS3GPP_intAudioMixingCopyAdded(pC);
   2471 
   2472                 if( M4WAR_NO_MORE_AU == err )
   2473                 {
   2474                     /**
   2475                     * Decide what to do when audio is over */
   2476 
   2477                     if( pC->uiEndLoop > 0 )
   2478                     {
   2479                         /**
   2480                         * Jump at the Begin loop time */
   2481                         M4OSA_Int32 time = (M4OSA_Int32)(pC->uiBeginLoop);
   2482 
   2483                         err = pC->pAddedClipCtxt->ShellAPI.m_pReader->m_pFctJump(
   2484                             pC->pAddedClipCtxt->pReaderContext,
   2485                             (M4_StreamHandler
   2486                             *)pC->pAddedClipCtxt->pAudioStream, &time);
   2487 
   2488                         if( M4NO_ERROR != err )
   2489                         {
   2490                             M4OSA_TRACE1_1(
   2491                                 "M4VSS3GPP_intAudioMixingStepAudioReplace():\
   2492                                 m_pReader->m_pFctJump(audio returns 0x%x",
   2493                                 err);
   2494                             return err;
   2495                         }
   2496 
   2497                         /**
   2498                         * 'BZZZ' bug fix:
   2499                         * add a silence frame */
   2500                         err = M4VSS3GPP_intAudioMixingWriteSilence(pC);
   2501 
   2502                         if( M4NO_ERROR != err )
   2503                         {
   2504                             M4OSA_TRACE1_1(
   2505                                 "M4VSS3GPP_intAudioMixingStepAudioMix():\
   2506                                 M4VSS3GPP_intAudioMixingWriteSilence returns 0x%x",
   2507                                 err);
   2508                             return err;
   2509                         }
   2510 
   2511                         /**
   2512                         * Return with no error so the step function will be called again to
   2513                           read audio data */
   2514                         pC->pAddedClipCtxt->iAoffset =
   2515                             (M4OSA_Int32)(pC->ewc.dATo * pC->ewc.scale_audio + 0.5);
   2516 
   2517                         M4OSA_TRACE2_0(
   2518                             "M4VSS3GPP_intAudioMixingStepAudioReplace():\
   2519                             returning M4NO_ERROR (loop)");
   2520 
   2521                         return M4NO_ERROR;
   2522                     }
   2523                     else if( M4OSA_TRUE == pC->bSupportSilence )
   2524                     {
   2525                         /**
   2526                         * Second segment is over, state transition to third and return OK */
   2527                         pC->State = M4VSS3GPP_kAudioMixingState_AUDIO_THIRD_SEGMENT;
   2528 
   2529                         /**
   2530                         * Return with no error so the step function will be called again */
   2531                         M4OSA_TRACE2_0(
   2532                             "M4VSS3GPP_intAudioMixingStepAudioReplace():\
   2533                                  returning M4NO_ERROR (2->3)");
   2534                         return M4NO_ERROR;
   2535                     }
   2536                     else
   2537                     {
   2538                         /**
   2539                         * The third segment (silence) is only done if supported.
   2540                         * In other case, we finish here. */
   2541                         pC->State = M4VSS3GPP_kAudioMixingState_FINISHED;
   2542 
   2543                         /**
   2544                         * Return with no error so the step function will be called again */
   2545                         M4OSA_TRACE2_0(
   2546                             "M4VSS3GPP_intAudioMixingStepAudioReplace():\
   2547                                  returning M4NO_ERROR (2->F)");
   2548                         return M4NO_ERROR;
   2549                     }
   2550                 }
   2551                 else if( M4NO_ERROR != err )
   2552                 {
   2553                     M4OSA_TRACE1_1(
   2554                         "M4VSS3GPP_intAudioMixingStepAudioReplace():\
   2555                         M4VSS3GPP_intAudioMixingCopyOrig(2) returns 0x%x",
   2556                         err);
   2557                     return err;
   2558                 }
   2559 
   2560                 /**
   2561                 * Check if we reached the end of the clip */
   2562                 if( pC->ewc.dATo >= pC->ewc.iOutputDuration )
   2563                 {
   2564                     M4OSA_TRACE3_0(
   2565                         "M4VSS3GPP_intAudioMixingStepAudioReplace(): Clip duration reached,\
   2566                         returning M4WAR_NO_MORE_AU");
   2567                     return M4WAR_NO_MORE_AU; /**< Simulate end of file error */
   2568                 }
   2569             }
   2570             break;
   2571 
   2572             /**********************************************************/
   2573         case M4VSS3GPP_kAudioMixingState_AUDIO_THIRD_SEGMENT:
   2574             {
   2575                 /**
   2576                 * Replace the SID (silence) payload in the writer AU */
   2577                 err = M4VSS3GPP_intAudioMixingWriteSilence(pC);
   2578 
   2579                 if( M4NO_ERROR != err )
   2580                 {
   2581                     M4OSA_TRACE1_1(
   2582                         "M4VSS3GPP_intAudioMixingStepAudioMix():\
   2583                         M4VSS3GPP_intAudioMixingWriteSilence returns 0x%x",
   2584                         err);
   2585                     return err;
   2586                 }
   2587 
   2588                 /**
   2589                 * Check if we reached the end of the video */
   2590                 if( pC->ewc.dATo >= pC->ewc.iOutputDuration )
   2591                 {
   2592                     M4OSA_TRACE3_0(
   2593                         "M4VSS3GPP_intAudioMixingStepAudioReplace():\
   2594                         Video duration reached, returning M4WAR_NO_MORE_AU");
   2595                     return M4WAR_NO_MORE_AU; /**< Simulate end of file error */
   2596                 }
   2597             }
   2598             break;
   2599         default:
   2600             break;
   2601     }
   2602 
   2603     /**
   2604     * Return with no error */
   2605     M4OSA_TRACE3_0(
   2606         "M4VSS3GPP_intAudioMixingStepAudioReplace(): returning M4NO_ERROR");
   2607     return M4NO_ERROR;
   2608 }
   2609 
   2610 /**
   2611  ******************************************************************************
   2612  * M4OSA_ERR M4VSS3GPP_intAudioMixingCopyOrig(M4VSS3GPP_InternalAudioMixingContext *pC)
   2613  * @brief    Read one AU from the original audio file and write it to the output
   2614  * @note
   2615  * @param    pC    (IN) VSS audio mixing internal context
   2616  ******************************************************************************
   2617  */
   2618 static M4OSA_ERR M4VSS3GPP_intAudioMixingCopyOrig(
   2619     M4VSS3GPP_InternalAudioMixingContext *pC )
   2620 {
   2621     M4OSA_ERR err;
   2622 
   2623     /**
   2624     * Read the input original audio AU */
   2625     err = M4VSS3GPP_intClipReadNextAudioFrame(pC->pInputClipCtxt);
   2626 
   2627     M4OSA_TRACE2_3("G .... read  : cts  = %.0f + %.0f [ 0x%x ]",
   2628         pC->pInputClipCtxt->iAudioFrameCts / pC->pInputClipCtxt->scale_audio,
   2629         pC->pInputClipCtxt->iAoffset / pC->pInputClipCtxt->scale_audio,
   2630         pC->pInputClipCtxt->uiAudioFrameSize);
   2631 
   2632     if( M4NO_ERROR != err )
   2633     {
   2634         M4OSA_TRACE3_1(
   2635             "M4VSS3GPP_intAudioMixingCopyOrig(): m_pFctGetNextAu(audio) returns 0x%x",
   2636             err);
   2637         return err;
   2638     }
   2639 
   2640     /**
   2641     * Get the output AU to write into */
   2642     err = pC->ShellAPI.pWriterDataFcts->pStartAU(pC->ewc.p3gpWriterContext,
   2643         M4VSS3GPP_WRITER_AUDIO_STREAM_ID, &pC->ewc.WriterAudioAU);
   2644 
   2645     if( M4NO_ERROR != err )
   2646     {
   2647         M4OSA_TRACE1_1(
   2648             "M4VSS3GPP_intAudioMixingCopyOrig: pWriterDataFcts->pStartAU(audio) returns 0x%x!",
   2649             err);
   2650         return err;
   2651     }
   2652 
   2653     /**
   2654     * Copy the input AU properties to the output AU */
   2655     pC->ewc.WriterAudioAU.size = pC->pInputClipCtxt->uiAudioFrameSize;
   2656     pC->ewc.WriterAudioAU.CTS =
   2657         pC->pInputClipCtxt->iAudioFrameCts + pC->pInputClipCtxt->iAoffset;
   2658 
   2659     /**
   2660     * Copy the AU itself */
   2661     memcpy((void *)pC->ewc.WriterAudioAU.dataAddress,
   2662         (void *)pC->pInputClipCtxt->pAudioFramePtr, pC->ewc.WriterAudioAU.size);
   2663 
   2664     /**
   2665     * Write the mixed AU */
   2666     M4OSA_TRACE2_2("H ---- write : cts  = %ld [ 0x%x ]",
   2667         (M4OSA_Int32)(pC->ewc.WriterAudioAU.CTS / pC->ewc.scale_audio),
   2668         pC->ewc.WriterAudioAU.size);
   2669 
   2670     err = pC->ShellAPI.pWriterDataFcts->pProcessAU(pC->ewc.p3gpWriterContext,
   2671         M4VSS3GPP_WRITER_AUDIO_STREAM_ID, &pC->ewc.WriterAudioAU);
   2672 
   2673     if( M4NO_ERROR != err )
   2674     {
   2675         M4OSA_TRACE1_1(
   2676             "M4VSS3GPP_intAudioMixingCopyOrig: pWriterDataFcts->pProcessAU(audio) returns 0x%x!",
   2677             err);
   2678         return err;
   2679     }
   2680 
   2681     /**
   2682     * Increment the audio CTS for the next step */
   2683     pC->ewc.dATo += pC->ewc.iSilenceFrameDuration / pC->ewc.scale_audio;
   2684 
   2685     /**
   2686     * Return with no error */
   2687     M4OSA_TRACE3_0("M4VSS3GPP_intAudioMixingCopyOrig(): returning M4NO_ERROR");
   2688     return M4NO_ERROR;
   2689 }
   2690 
   2691 /**
   2692  ******************************************************************************
   2693  * M4OSA_ERR M4VSS3GPP_intAudioMixingCopyAdded(M4VSS3GPP_InternalAudioMixingContext *pC)
   2694  * @brief    Read one AU from the added audio file and write it to the output
   2695  * @note
   2696  * @param    pC    (IN) VSS audio mixing internal context
   2697  ******************************************************************************
   2698  */
   2699 static M4OSA_ERR M4VSS3GPP_intAudioMixingCopyAdded(
   2700     M4VSS3GPP_InternalAudioMixingContext *pC )
   2701 {
   2702     M4OSA_ERR err;
   2703 
   2704     if(pC->pAddedClipCtxt->pSettings->ClipProperties.AudioStreamType == M4VIDEOEDITING_kMP3 ||
   2705         pC->pAddedClipCtxt->pSettings->ClipProperties.AudioStreamType == M4VIDEOEDITING_kPCM ||
   2706         pC->b_SSRCneeded == M4OSA_TRUE ||
   2707         pC->ChannelConversion > 0)
   2708     {
   2709         M4ENCODER_AudioBuffer pEncInBuffer; /**< Encoder input buffer for api */
   2710         M4ENCODER_AudioBuffer
   2711             pEncOutBuffer; /**< Encoder output buffer for api */
   2712         M4OSA_Time
   2713             frameTimeDelta; /**< Duration of the encoded (then written) data */
   2714         M4OSA_MemAddr8 tempPosBuffer;
   2715 
   2716         err = M4VSS3GPP_intAudioMixingConvert(pC);
   2717 
   2718         if( err == M4VSS3GPP_WAR_END_OF_ADDED_AUDIO )
   2719         {
   2720             M4OSA_TRACE2_0(
   2721                 "M4VSS3GPP_intAudioMixingCopyAdded:\
   2722                 M4VSS3GPP_intAudioMixingConvert end of added file");
   2723             return M4NO_ERROR;
   2724         }
   2725         else if( err != M4NO_ERROR )
   2726         {
   2727             M4OSA_TRACE1_1("M4VSS3GPP_intAudioMixingCopyAdded:\
   2728                 M4VSS3GPP_intAudioMixingConvert returned 0x%x", err);
   2729             return err;
   2730         }
   2731 
   2732         /**
   2733         * Get the output AU to write into */
   2734         err = pC->ShellAPI.pWriterDataFcts->pStartAU(pC->ewc.p3gpWriterContext,
   2735             M4VSS3GPP_WRITER_AUDIO_STREAM_ID, &pC->ewc.WriterAudioAU);
   2736 
   2737         if( M4NO_ERROR != err )
   2738         {
   2739             M4OSA_TRACE1_1(
   2740                 "M4VSS3GPP_intAudioMixingStepAudioMix:\
   2741                 pWriterDataFcts->pStartAU(audio) returns 0x%x!",
   2742                 err);
   2743             return err;
   2744         }
   2745 
   2746         /* [Mono] or [Stereo interleaved] : all is in one buffer */
   2747         pEncInBuffer.pTableBuffer[0] = pC->pSsrcBufferOut;
   2748         pEncInBuffer.pTableBufferSize[0] =
   2749             pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize;
   2750         pEncInBuffer.pTableBuffer[1] = M4OSA_NULL;
   2751         pEncInBuffer.pTableBufferSize[1] = 0;
   2752 
   2753         /* Time in ms from data size, because it is PCM16 samples */
   2754         frameTimeDelta = pEncInBuffer.pTableBufferSize[0] / sizeof(short)
   2755             / pC->ewc.uiNbChannels;
   2756 
   2757         /**
   2758         * Prepare output buffer */
   2759         pEncOutBuffer.pTableBuffer[0] =
   2760             (M4OSA_MemAddr8)pC->ewc.WriterAudioAU.dataAddress;
   2761         pEncOutBuffer.pTableBufferSize[0] = 0;
   2762 
   2763         M4OSA_TRACE2_0("K **** blend AUs");
   2764         /**
   2765         * Encode the PCM audio */
   2766 
   2767         err = pC->ShellAPI.pAudioEncoderGlobalFcts->pFctStep(
   2768             pC->ewc.pAudioEncCtxt, &pEncInBuffer, &pEncOutBuffer);
   2769 
   2770         if( M4NO_ERROR != err )
   2771         {
   2772             M4OSA_TRACE1_1(
   2773                 "M4VSS3GPP_intAudioMixingDoMixing():\
   2774                 pAudioEncoderGlobalFcts->pFctStep returns 0x%x",
   2775                 err);
   2776             return err;
   2777         }
   2778 
   2779         /**
   2780         * Set AU cts and size */
   2781         pC->ewc.WriterAudioAU.size =
   2782             pEncOutBuffer.
   2783             pTableBufferSize[0]; /**< Get the size of encoded data */
   2784         pC->ewc.WriterAudioAU.CTS += frameTimeDelta;
   2785 
   2786         /* Update decoded buffer here */
   2787         if( M4OSA_TRUE == pC->b_SSRCneeded || pC->ChannelConversion > 0 )
   2788         {
   2789             tempPosBuffer = pC->pSsrcBufferOut
   2790                 + pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize;
   2791             memmove((void *)pC->pSsrcBufferOut, (void *)tempPosBuffer,
   2792                 pC->pPosInSsrcBufferOut - tempPosBuffer);
   2793             pC->pPosInSsrcBufferOut -=
   2794                 pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize;
   2795         }
   2796         else
   2797         {
   2798             tempPosBuffer = pC->pSsrcBufferIn + pC->minimumBufferIn;
   2799             memmove((void *)pC->pSsrcBufferIn, (void *)tempPosBuffer,
   2800                 pC->pPosInSsrcBufferIn - tempPosBuffer);
   2801             pC->pPosInSsrcBufferIn -= pC->minimumBufferIn;
   2802         }
   2803 
   2804         /**
   2805         * Write the mixed AU */
   2806         M4OSA_TRACE2_2("J ---- write : cts  = %ld [ 0x%x ]",
   2807             (M4OSA_Int32)(pC->ewc.WriterAudioAU.CTS / pC->ewc.scale_audio),
   2808             pC->ewc.WriterAudioAU.size);
   2809 
   2810         err =
   2811             pC->ShellAPI.pWriterDataFcts->pProcessAU(pC->ewc.p3gpWriterContext,
   2812             M4VSS3GPP_WRITER_AUDIO_STREAM_ID, &pC->ewc.WriterAudioAU);
   2813 
   2814         if( M4NO_ERROR != err )
   2815         {
   2816             M4OSA_TRACE1_1(
   2817                 "M4VSS3GPP_intAudioMixingCopyAdded:\
   2818                 pWriterDataFcts->pProcessAU(audio) returns 0x%x!",
   2819                 err);
   2820             return err;
   2821         }
   2822 
   2823         /**
   2824         * Increment the audio CTS for the next step */
   2825         pC->ewc.dATo += frameTimeDelta / pC->ewc.scale_audio;
   2826     }
   2827     else
   2828     {
   2829         /**
   2830         * Read the added audio AU */
   2831         err = M4VSS3GPP_intClipReadNextAudioFrame(pC->pAddedClipCtxt);
   2832 
   2833         M4OSA_TRACE2_3("I .... read  : cts  = %.0f + %.0f [ 0x%x ]",
   2834             pC->pAddedClipCtxt->iAudioFrameCts
   2835             / pC->pAddedClipCtxt->scale_audio,
   2836             pC->pAddedClipCtxt->iAoffset / pC->pAddedClipCtxt->scale_audio,
   2837             pC->pAddedClipCtxt->uiAudioFrameSize);
   2838 
   2839         if( M4NO_ERROR != err )
   2840         {
   2841             M4OSA_TRACE3_1(
   2842                 "M4VSS3GPP_intAudioMixingCopyAdded(): m_pFctGetNextAu(audio) returns 0x%x",
   2843                 err);
   2844             return err;
   2845         }
   2846 
   2847         /**
   2848         * Get the output AU to write into */
   2849         err = pC->ShellAPI.pWriterDataFcts->pStartAU(pC->ewc.p3gpWriterContext,
   2850             M4VSS3GPP_WRITER_AUDIO_STREAM_ID, &pC->ewc.WriterAudioAU);
   2851 
   2852         if( M4NO_ERROR != err )
   2853         {
   2854             M4OSA_TRACE1_1(
   2855                 "M4VSS3GPP_intAudioMixingCopyAdded:\
   2856                 pWriterDataFcts->pStartAU(audio) returns 0x%x!",
   2857                 err);
   2858             return err;
   2859         }
   2860 
   2861         /**
   2862         * Copy the input AU properties to the output AU */
   2863 
   2864         /** THE CHECK BELOW IS ADDED TO PREVENT ISSUES LINKED TO PRE-ALLOCATED MAX AU SIZE
   2865         max AU size is set based on M4VSS3GPP_AUDIO_MAX_AU_SIZE defined in file
   2866         M4VSS3GPP_InternalConfig.h, If this error occurs increase the limit set in this file
   2867         */
   2868         if( pC->pAddedClipCtxt->uiAudioFrameSize > pC->ewc.WriterAudioAU.size )
   2869         {
   2870             M4OSA_TRACE1_2(
   2871                 "ERROR: audio AU size (%d) to copy larger than allocated one (%d) => abort",
   2872                 pC->pAddedClipCtxt->uiAudioFrameSize,
   2873                 pC->ewc.WriterAudioAU.size);
   2874             M4OSA_TRACE1_0(
   2875                 "PLEASE CONTACT SUPPORT TO EXTEND MAX AU SIZE IN THE PRODUCT LIBRARY");
   2876             err = M4ERR_UNSUPPORTED_MEDIA_TYPE;
   2877             return err;
   2878         }
   2879         pC->ewc.WriterAudioAU.size = pC->pAddedClipCtxt->uiAudioFrameSize;
   2880         pC->ewc.WriterAudioAU.CTS =
   2881             pC->pAddedClipCtxt->iAudioFrameCts + pC->pAddedClipCtxt->iAoffset;
   2882 
   2883         /**
   2884         * Copy the AU itself */
   2885         memcpy((void *)pC->ewc.WriterAudioAU.dataAddress,
   2886             (void *)pC->pAddedClipCtxt->pAudioFramePtr, pC->ewc.WriterAudioAU.size);
   2887 
   2888         /**
   2889         * Write the mixed AU */
   2890         M4OSA_TRACE2_2("J ---- write : cts  = %ld [ 0x%x ]",
   2891             (M4OSA_Int32)(pC->ewc.WriterAudioAU.CTS / pC->ewc.scale_audio),
   2892             pC->ewc.WriterAudioAU.size);
   2893 
   2894         err =
   2895             pC->ShellAPI.pWriterDataFcts->pProcessAU(pC->ewc.p3gpWriterContext,
   2896             M4VSS3GPP_WRITER_AUDIO_STREAM_ID, &pC->ewc.WriterAudioAU);
   2897 
   2898         if( M4NO_ERROR != err )
   2899         {
   2900             M4OSA_TRACE1_1(
   2901                 "M4VSS3GPP_intAudioMixingCopyAdded:\
   2902                 pWriterDataFcts->pProcessAU(audio) returns 0x%x!",
   2903                 err);
   2904             return err;
   2905         }
   2906 
   2907         /**
   2908         * Increment the audio CTS for the next step */
   2909         pC->ewc.dATo += pC->ewc.iSilenceFrameDuration / pC->ewc.scale_audio;
   2910     }
   2911 
   2912     /**
   2913     * Return with no error */
   2914     M4OSA_TRACE3_0("M4VSS3GPP_intAudioMixingCopyAdded(): returning M4NO_ERROR");
   2915     return M4NO_ERROR;
   2916 }
   2917 
   2918 /**
   2919  ******************************************************************************
   2920  * M4OSA_ERR  M4VSS3GPP_intAudioMixingConvert(M4VSS3GPP_InternalAudioMixingContext *pC)
   2921  * @brief    Convert PCM of added track to the right ASF / nb of Channels
   2922  * @note
   2923  * @param    pC    (IN) VSS audio mixing internal context
   2924  * @return    M4NO_ERROR:    No error
   2925  ******************************************************************************
   2926  */
   2927 static M4OSA_ERR M4VSS3GPP_intAudioMixingConvert(
   2928     M4VSS3GPP_InternalAudioMixingContext *pC )
   2929 {
   2930     M4OSA_ERR err;
   2931     int ssrcErr; /**< Error while ssrc processing */
   2932     M4OSA_UInt32 uiChannelConvertorNbSamples =
   2933         pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize / sizeof(short)
   2934         / pC->pInputClipCtxt->pSettings->ClipProperties.uiNbChannels;
   2935     M4OSA_MemAddr8 tempPosBuffer;
   2936 
   2937     M4OSA_UInt32 outFrameCount = uiChannelConvertorNbSamples;
   2938     /* Do we need to feed SSRC buffer In ? */
   2939     /**
   2940     * RC: This is not really optimum (memmove). We should handle this with linked list. */
   2941     while( pC->pPosInSsrcBufferIn - pC->pSsrcBufferIn < (M4OSA_Int32)pC->minimumBufferIn )
   2942     {
   2943         /* We need to get more PCM data */
   2944         if (pC->bNoLooping == M4OSA_TRUE)
   2945         {
   2946             err = M4WAR_NO_MORE_AU;
   2947         }
   2948         else
   2949         {
   2950         err = M4VSS3GPP_intClipReadNextAudioFrame(pC->pAddedClipCtxt);
   2951         }
   2952         if(pC->bjumpflag)
   2953         {
   2954         /**
   2955             * Jump at the Begin loop time */
   2956             M4OSA_Int32 time = (M4OSA_Int32)(pC->uiBeginLoop);
   2957 
   2958             err =
   2959                 pC->pAddedClipCtxt->ShellAPI.m_pReader->m_pFctJump\
   2960                     (pC->pAddedClipCtxt->pReaderContext,
   2961                      (M4_StreamHandler*)pC->pAddedClipCtxt->pAudioStream, &time);
   2962             if (M4NO_ERROR != err)
   2963             {
   2964                 M4OSA_TRACE1_1("M4VSS3GPP_intAudioMixingConvert():\
   2965                      m_pReader->m_pFctJump(audio returns 0x%x", err);
   2966                 return err;
   2967             }
   2968             pC->bjumpflag = M4OSA_FALSE;
   2969         }
   2970         M4OSA_TRACE2_3("E .... read  : cts  = %.0f + %.0f [ 0x%x ]",
   2971              pC->pAddedClipCtxt->iAudioFrameCts / pC->pAddedClipCtxt->scale_audio,
   2972                  pC->pAddedClipCtxt->iAoffset / pC->pAddedClipCtxt->scale_audio,
   2973                      pC->pAddedClipCtxt->uiAudioFrameSize);
   2974         if( M4WAR_NO_MORE_AU == err )
   2975         {
   2976             if(pC->bNoLooping == M4OSA_TRUE)
   2977             {
   2978                 pC->uiEndLoop =0; /* Value 0 means no looping is required */
   2979             }
   2980             /**
   2981             * Decide what to do when audio is over */
   2982             if( pC->uiEndLoop > 0 )
   2983             {
   2984                 /**
   2985                 * Jump at the Begin loop time */
   2986                 M4OSA_Int32 time = (M4OSA_Int32)(pC->uiBeginLoop);
   2987 
   2988                 err = pC->pAddedClipCtxt->ShellAPI.m_pReader->m_pFctJump(
   2989                     pC->pAddedClipCtxt->pReaderContext,
   2990                     (M4_StreamHandler *)pC->pAddedClipCtxt->
   2991                     pAudioStream, &time);
   2992 
   2993                 if( M4NO_ERROR != err )
   2994                 {
   2995                     M4OSA_TRACE1_1(
   2996                         "M4VSS3GPP_intAudioMixingConvert():\
   2997                         m_pReader->m_pFctJump(audio returns 0x%x",
   2998                         err);
   2999                     return err;
   3000                 }
   3001             }
   3002             else
   3003             {
   3004                 /* Transition from encoding state to reading state */
   3005                 err = M4VSS3GPP_intAudioMixingTransition(pC);
   3006 
   3007                 if( M4NO_ERROR != err )
   3008                 {
   3009                     M4OSA_TRACE1_1(
   3010                         "M4VSS3GPP_intAudioMixingStepAudioMix(): pre-encode fails err = 0x%x",
   3011                         err);
   3012                     return err;
   3013                 }
   3014 
   3015                 /**
   3016                 * Second segment is over, state transition to third and return OK */
   3017                 pC->State = M4VSS3GPP_kAudioMixingState_AUDIO_THIRD_SEGMENT;
   3018 
   3019                 /**
   3020                 * Return with no error so the step function will be called again */
   3021                 M4OSA_TRACE2_0(
   3022                     "M4VSS3GPP_intAudioMixingConvert():\
   3023                     returning M4VSS3GPP_WAR_END_OF_ADDED_AUDIO (2->3) a");
   3024                 return M4VSS3GPP_WAR_END_OF_ADDED_AUDIO;
   3025             }
   3026         }
   3027         else if( M4NO_ERROR != err )
   3028         {
   3029             M4OSA_TRACE1_1(
   3030                 "M4VSS3GPP_intAudioMixingConvert(): m_pFctGetNextAu(audio) returns 0x%x",
   3031                 err);
   3032             return err;
   3033         }
   3034 
   3035         err = M4VSS3GPP_intClipDecodeCurrentAudioFrame(pC->pAddedClipCtxt);
   3036 
   3037         if( M4NO_ERROR != err )
   3038         {
   3039             M4OSA_TRACE1_1(
   3040                 "M4VSS3GPP_intAudioMixingDoMixing:\
   3041                 M4VSS3GPP_intClipDecodeCurrentAudioFrame(added) returns 0x%x",
   3042                 err);
   3043             return M4VSS3GPP_ERR_INPUT_AUDIO_CORRUPTED_AU;
   3044         }
   3045 
   3046         /* Copy decoded data into SSRC buffer in */
   3047         memcpy((void *)pC->pPosInSsrcBufferIn,
   3048             (void *)pC->pAddedClipCtxt->AudioDecBufferOut.m_dataAddress,
   3049             pC->pAddedClipCtxt->AudioDecBufferOut.m_bufferSize);
   3050         /* Update position pointer into SSRC buffer In */
   3051 
   3052         pC->pPosInSsrcBufferIn +=
   3053             pC->pAddedClipCtxt->AudioDecBufferOut.m_bufferSize;
   3054     }
   3055 
   3056     /* Do the resampling / channel conversion if needed (=feed buffer out) */
   3057     if( pC->b_SSRCneeded == M4OSA_TRUE )
   3058     {
   3059         pC->ChannelConversion = 0;
   3060         if( pC->ChannelConversion > 0 )
   3061         {
   3062             while( pC->pPosInTempBuffer - pC->pTempBuffer
   3063                 < (M4OSA_Int32)(pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize
   3064                 *pC->pAddedClipCtxt->pSettings->ClipProperties.uiNbChannels)
   3065                 / pC->ChannelConversion )
   3066                 /* We use ChannelConversion variable because in case 2, we need twice less data */
   3067             {
   3068                 ssrcErr = 0;
   3069                 memset((void *)pC->pPosInTempBuffer,0,
   3070                     (pC->iSsrcNbSamplOut * sizeof(short) * pC->ewc.uiNbChannels));
   3071 
   3072                 LVAudioresample_LowQuality((short*)pC->pPosInTempBuffer,
   3073                     (short*)pC->pSsrcBufferIn,
   3074                     pC->iSsrcNbSamplOut,
   3075                     pC->pLVAudioResampler);
   3076                 if( 0 != ssrcErr )
   3077                 {
   3078                     M4OSA_TRACE1_1(
   3079                         "M4VSS3GPP_intAudioMixingConvert: SSRC_Process returns 0x%x, returning ",
   3080                         ssrcErr);
   3081                     return ssrcErr;
   3082                 }
   3083 
   3084                 pC->pPosInTempBuffer += pC->iSsrcNbSamplOut * sizeof(short)
   3085                     * pC->pAddedClipCtxt->pSettings->
   3086                     ClipProperties.uiNbChannels;
   3087 
   3088                 /* Update SSRC bufferIn */
   3089                 tempPosBuffer =
   3090                     pC->pSsrcBufferIn + (pC->iSsrcNbSamplIn * sizeof(short)
   3091                     * pC->pAddedClipCtxt->pSettings->
   3092                     ClipProperties.uiNbChannels);
   3093                 memmove((void *)pC->pSsrcBufferIn, (void *)tempPosBuffer,
   3094                     pC->pPosInSsrcBufferIn - tempPosBuffer);
   3095                 pC->pPosInSsrcBufferIn -= pC->iSsrcNbSamplIn * sizeof(short)
   3096                     * pC->pAddedClipCtxt->pSettings->
   3097                     ClipProperties.uiNbChannels;
   3098             }
   3099         }
   3100         else
   3101         {
   3102             while( pC->pPosInSsrcBufferOut - pC->pSsrcBufferOut
   3103                 < (M4OSA_Int32)pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize )
   3104             {
   3105                 ssrcErr = 0;
   3106                 memset((void *)pC->pPosInSsrcBufferOut,0,
   3107                     (pC->iSsrcNbSamplOut * sizeof(short) * pC->ewc.uiNbChannels));
   3108 
   3109                 LVAudioresample_LowQuality((short*)pC->pPosInSsrcBufferOut,
   3110                     (short*)pC->pSsrcBufferIn,
   3111                     pC->iSsrcNbSamplOut,
   3112                     pC->pLVAudioResampler);
   3113                 if( 0 != ssrcErr )
   3114                 {
   3115                     M4OSA_TRACE1_1(
   3116                         "M4VSS3GPP_intAudioMixingConvert: SSRC_Process returns 0x%x, returning ",
   3117                         ssrcErr);
   3118                     return ssrcErr;
   3119                 }
   3120                 pC->pPosInSsrcBufferOut +=
   3121                     pC->iSsrcNbSamplOut * sizeof(short) * pC->ewc.uiNbChannels;
   3122 
   3123                 /* Update SSRC bufferIn */
   3124                 tempPosBuffer =
   3125                     pC->pSsrcBufferIn + (pC->iSsrcNbSamplIn * sizeof(short)
   3126                     * pC->pAddedClipCtxt->pSettings->
   3127                     ClipProperties.uiNbChannels);
   3128                 memmove((void *)pC->pSsrcBufferIn, (void *)tempPosBuffer,
   3129                     pC->pPosInSsrcBufferIn - tempPosBuffer);
   3130                 pC->pPosInSsrcBufferIn -= pC->iSsrcNbSamplIn * sizeof(short)
   3131                     * pC->pAddedClipCtxt->pSettings->
   3132                     ClipProperties.uiNbChannels;
   3133             }
   3134         }
   3135 
   3136         /* Convert Stereo<->Mono */
   3137         switch( pC->ChannelConversion )
   3138         {
   3139             case 0: /* No channel conversion */
   3140                 break;
   3141 
   3142             case 1: /* stereo to mono */
   3143                 if( pC->pPosInSsrcBufferOut - pC->pSsrcBufferOut
   3144                     < (M4OSA_Int32)pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize )
   3145                 {
   3146                     From2iToMono_16((short *)pC->pTempBuffer,
   3147                         (short *)pC->pSsrcBufferOut,
   3148                         (short)(uiChannelConvertorNbSamples));
   3149                     /* Update pTempBuffer */
   3150                     tempPosBuffer = pC->pTempBuffer
   3151                         + (uiChannelConvertorNbSamples * sizeof(short)
   3152                         * pC->pAddedClipCtxt->pSettings->
   3153                         ClipProperties.
   3154                         uiNbChannels); /* Buffer is in bytes */
   3155                     memmove((void *)pC->pTempBuffer, (void *)tempPosBuffer,
   3156                         pC->pPosInTempBuffer - tempPosBuffer);
   3157                     pC->pPosInTempBuffer -=
   3158                         (uiChannelConvertorNbSamples * sizeof(short)
   3159                         * pC->pAddedClipCtxt->pSettings->
   3160                         ClipProperties.uiNbChannels);
   3161                     pC->pPosInSsrcBufferOut +=
   3162                         pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize;
   3163                 }
   3164                 break;
   3165 
   3166             case 2: /* mono to stereo */
   3167                 if( pC->pPosInSsrcBufferOut - pC->pSsrcBufferOut
   3168                     < (M4OSA_Int32)pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize )
   3169                 {
   3170                     MonoTo2I_16((short *)pC->pTempBuffer,
   3171                         (short *)pC->pSsrcBufferOut,
   3172                         (short)uiChannelConvertorNbSamples);
   3173                     tempPosBuffer = pC->pTempBuffer
   3174                         + (uiChannelConvertorNbSamples * sizeof(short)
   3175                         * pC->pAddedClipCtxt->pSettings->
   3176                         ClipProperties.uiNbChannels);
   3177                     memmove((void *)pC->pTempBuffer, (void *)tempPosBuffer,
   3178                         pC->pPosInTempBuffer - tempPosBuffer);
   3179                     pC->pPosInTempBuffer -=
   3180                         (uiChannelConvertorNbSamples * sizeof(short)
   3181                         * pC->pAddedClipCtxt->pSettings->
   3182                         ClipProperties.uiNbChannels);
   3183                     pC->pPosInSsrcBufferOut +=
   3184                         pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize;
   3185                 }
   3186                 break;
   3187         }
   3188     }
   3189     else if( pC->ChannelConversion > 0 )
   3190     {
   3191         //M4OSA_UInt32 uiChannelConvertorNbSamples =
   3192         // pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize / sizeof(short) /
   3193         // pC->pInputClipCtxt->pSettings->ClipProperties.uiNbChannels;
   3194         /* Convert Stereo<->Mono */
   3195         switch( pC->ChannelConversion )
   3196         {
   3197             case 0: /* No channel conversion */
   3198                 break;
   3199 
   3200             case 1: /* stereo to mono */
   3201                 if( pC->pPosInSsrcBufferOut - pC->pSsrcBufferOut
   3202                     < (M4OSA_Int32)pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize )
   3203                 {
   3204                     From2iToMono_16((short *)pC->pSsrcBufferIn,
   3205                         (short *)pC->pSsrcBufferOut,
   3206                         (short)(uiChannelConvertorNbSamples));
   3207                     /* Update pTempBuffer */
   3208                     tempPosBuffer = pC->pSsrcBufferIn
   3209                         + (uiChannelConvertorNbSamples * sizeof(short)
   3210                         * pC->pAddedClipCtxt->pSettings->
   3211                         ClipProperties.
   3212                         uiNbChannels); /* Buffer is in bytes */
   3213                     memmove((void *)pC->pSsrcBufferIn, (void *)tempPosBuffer,
   3214                         pC->pPosInSsrcBufferIn - tempPosBuffer);
   3215                     pC->pPosInSsrcBufferIn -=
   3216                         (uiChannelConvertorNbSamples * sizeof(short)
   3217                         * pC->pAddedClipCtxt->pSettings->
   3218                         ClipProperties.uiNbChannels);
   3219                     pC->pPosInSsrcBufferOut +=
   3220                         pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize;
   3221                 }
   3222                 break;
   3223 
   3224             case 2: /* mono to stereo */
   3225                 if( pC->pPosInSsrcBufferOut - pC->pSsrcBufferOut
   3226                     < (M4OSA_Int32)pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize )
   3227                 {
   3228                     MonoTo2I_16((short *)pC->pSsrcBufferIn,
   3229                         (short *)pC->pSsrcBufferOut,
   3230                         (short)uiChannelConvertorNbSamples);
   3231                     tempPosBuffer = pC->pSsrcBufferIn
   3232                         + (uiChannelConvertorNbSamples * sizeof(short)
   3233                         * pC->pAddedClipCtxt->pSettings->
   3234                         ClipProperties.uiNbChannels);
   3235                     memmove((void *)pC->pSsrcBufferIn, (void *)tempPosBuffer,
   3236                         pC->pPosInSsrcBufferIn - tempPosBuffer);
   3237                     pC->pPosInSsrcBufferIn -=
   3238                         (uiChannelConvertorNbSamples * sizeof(short)
   3239                         * pC->pAddedClipCtxt->pSettings->
   3240                         ClipProperties.uiNbChannels);
   3241                     pC->pPosInSsrcBufferOut +=
   3242                         pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize;
   3243                 }
   3244                 break;
   3245         }
   3246     }
   3247     else
   3248     {
   3249         /* No channel conversion nor sampl. freq. conversion needed, just buffer management */
   3250         pC->pPosInSsrcBufferOut = pC->pPosInSsrcBufferIn;
   3251     }
   3252 
   3253     return M4NO_ERROR;
   3254 }
   3255 
   3256 M4OSA_Int32 M4VSS3GPP_getDecibelSound( M4OSA_UInt32 value )
   3257     {
   3258     int dbSound = 1;
   3259 
   3260     if( value == 0 )
   3261         return 0;
   3262 
   3263     if( value > 0x4000 && value <= 0x8000 )      // 32768
   3264         dbSound = 90;
   3265 
   3266     else if( value > 0x2000 && value <= 0x4000 ) // 16384
   3267         dbSound = 84;
   3268 
   3269     else if( value > 0x1000 && value <= 0x2000 ) // 8192
   3270         dbSound = 78;
   3271 
   3272     else if( value > 0x0800 && value <= 0x1000 ) // 4028
   3273         dbSound = 72;
   3274 
   3275     else if( value > 0x0400 && value <= 0x0800 ) // 2048
   3276         dbSound = 66;
   3277 
   3278     else if( value > 0x0200 && value <= 0x0400 ) // 1024
   3279         dbSound = 60;
   3280 
   3281     else if( value > 0x0100 && value <= 0x0200 ) // 512
   3282         dbSound = 54;
   3283 
   3284     else if( value > 0x0080 && value <= 0x0100 ) // 256
   3285         dbSound = 48;
   3286 
   3287     else if( value > 0x0040 && value <= 0x0080 ) // 128
   3288         dbSound = 42;
   3289 
   3290     else if( value > 0x0020 && value <= 0x0040 ) // 64
   3291         dbSound = 36;
   3292 
   3293     else if( value > 0x0010 && value <= 0x0020 ) // 32
   3294         dbSound = 30;
   3295 
   3296     else if( value > 0x0008 && value <= 0x0010 ) //16
   3297         dbSound = 24;
   3298 
   3299     else if( value > 0x0007 && value <= 0x0008 ) //8
   3300         dbSound = 24;
   3301 
   3302     else if( value > 0x0003 && value <= 0x0007 ) // 4
   3303         dbSound = 18;
   3304 
   3305     else if( value > 0x0001 && value <= 0x0003 ) //2
   3306         dbSound = 12;
   3307 
   3308     else if( value > 0x000 && value <= 0x0001 )  // 1
   3309         dbSound = 6;
   3310 
   3311     else
   3312         dbSound = 0;
   3313 
   3314     return dbSound;
   3315     }
   3316 /**
   3317  ******************************************************************************
   3318  * M4OSA_ERR  M4VSS3GPP_intAudioMixingDoMixing(M4VSS3GPP_InternalAudioMixingContext *pC)
   3319  * @brief    Mix the current audio AUs (decoder, mix, encode)
   3320  * @note
   3321  * @param    pC    (IN) VSS audio mixing internal context
   3322  * @return    M4NO_ERROR:    No error
   3323  ******************************************************************************
   3324  */
   3325 static M4OSA_ERR M4VSS3GPP_intAudioMixingDoMixing(
   3326     M4VSS3GPP_InternalAudioMixingContext *pC )
   3327 {
   3328     M4OSA_ERR err;
   3329     M4OSA_Int16 *pPCMdata1;
   3330     M4OSA_Int16 *pPCMdata2;
   3331     M4OSA_UInt32 uiPCMsize;
   3332 
   3333     M4ENCODER_AudioBuffer pEncInBuffer;  /**< Encoder input buffer for api */
   3334     M4ENCODER_AudioBuffer pEncOutBuffer; /**< Encoder output buffer for api */
   3335     M4OSA_Time
   3336         frameTimeDelta; /**< Duration of the encoded (then written) data */
   3337     M4OSA_MemAddr8 tempPosBuffer;
   3338     /* ducking variable */
   3339     M4OSA_UInt16 loopIndex = 0;
   3340     M4OSA_Int16 *pPCM16Sample = M4OSA_NULL;
   3341     M4OSA_Int32 peakDbValue = 0;
   3342     M4OSA_Int32 previousDbValue = 0;
   3343     M4OSA_UInt32 i;
   3344 
   3345     /**
   3346     * Decode original audio track AU */
   3347 
   3348     err = M4VSS3GPP_intClipDecodeCurrentAudioFrame(pC->pInputClipCtxt);
   3349 
   3350     if( M4NO_ERROR != err )
   3351     {
   3352         M4OSA_TRACE1_1(
   3353             "M4VSS3GPP_intAudioMixingDoMixing:\
   3354             M4VSS3GPP_intClipDecodeCurrentAudioFrame(orig) returns 0x%x",
   3355             err);
   3356         return M4VSS3GPP_ERR_INPUT_AUDIO_CORRUPTED_AU;
   3357     }
   3358 
   3359     if( M4OSA_TRUE == pC->b_SSRCneeded || pC->ChannelConversion > 0
   3360         || pC->pAddedClipCtxt->pSettings->ClipProperties.AudioStreamType
   3361         == M4VIDEOEDITING_kMP3 )
   3362     {
   3363         err = M4VSS3GPP_intAudioMixingConvert(pC);
   3364 
   3365         if( err == M4VSS3GPP_WAR_END_OF_ADDED_AUDIO )
   3366         {
   3367             return err;
   3368         }
   3369 
   3370         if( err != M4NO_ERROR )
   3371         {
   3372             M4OSA_TRACE1_1(
   3373                 "M4VSS3GPP_intAudioMixingDoMixing: M4VSS3GPP_intAudioMixingConvert returned 0x%x",
   3374                 err);
   3375             return M4VSS3GPP_ERR_AUDIO_DECODED_PCM_SIZE_ISSUE;
   3376         }
   3377 
   3378         /**
   3379         * Get the output AU to write into */
   3380         err = pC->ShellAPI.pWriterDataFcts->pStartAU(pC->ewc.p3gpWriterContext,
   3381             M4VSS3GPP_WRITER_AUDIO_STREAM_ID, &pC->ewc.WriterAudioAU);
   3382 
   3383         if( M4NO_ERROR != err )
   3384         {
   3385             M4OSA_TRACE1_1(
   3386                 "M4VSS3GPP_intAudioMixingStepAudioMix:\
   3387                 pWriterDataFcts->pStartAU(audio) returns 0x%x!",
   3388                 err);
   3389             return err;
   3390         }
   3391 
   3392         pPCMdata2 = (M4OSA_Int16 *)pC->pSsrcBufferOut;
   3393     }
   3394     else
   3395     {
   3396         /**
   3397         * Decode added audio track AU */
   3398         err = M4VSS3GPP_intClipDecodeCurrentAudioFrame(pC->pAddedClipCtxt);
   3399 
   3400         if( M4NO_ERROR != err )
   3401         {
   3402             M4OSA_TRACE1_1(
   3403                 "M4VSS3GPP_intAudioMixingDoMixing:\
   3404                 M4VSS3GPP_intClipDecodeCurrentAudioFrame(added) returns 0x%x",
   3405                 err);
   3406             return M4VSS3GPP_ERR_INPUT_AUDIO_CORRUPTED_AU;
   3407         }
   3408 
   3409         /**
   3410         * Check both clips decoded the same amount of PCM samples */
   3411         if( pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize
   3412             != pC->pAddedClipCtxt->AudioDecBufferOut.m_bufferSize )
   3413         {
   3414             M4OSA_TRACE1_0(
   3415                 "M4VSS3GPP_intAudioMixingDoMixing:\
   3416                 both clips AU must have the same decoded PCM size!");
   3417             return M4VSS3GPP_ERR_AUDIO_DECODED_PCM_SIZE_ISSUE;
   3418         }
   3419         pPCMdata2 = (M4OSA_Int16 *)pC->pAddedClipCtxt->AudioDecBufferOut.m_dataAddress;
   3420     }
   3421 
   3422     /**
   3423     * Mix the two decoded PCM audios */
   3424     pPCMdata1 =
   3425         (M4OSA_Int16 *)pC->pInputClipCtxt->AudioDecBufferOut.m_dataAddress;
   3426     uiPCMsize = pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize
   3427         / 2; /*buffer size (bytes) to number of sample (int16)*/
   3428 
   3429     if( pC->b_DuckingNeedeed )
   3430     {
   3431         loopIndex = 0;
   3432         peakDbValue = 0;
   3433         previousDbValue = peakDbValue;
   3434 
   3435         pPCM16Sample = (M4OSA_Int16 *)pC->pInputClipCtxt->
   3436             AudioDecBufferOut.m_dataAddress;
   3437 
   3438         //Calculate the peak value
   3439          while( loopIndex
   3440              < pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize
   3441             / sizeof(M4OSA_Int16) )
   3442         {
   3443             if( pPCM16Sample[loopIndex] >= 0 )
   3444             {
   3445                 peakDbValue = previousDbValue > pPCM16Sample[loopIndex]
   3446                 ? previousDbValue : pPCM16Sample[loopIndex];
   3447                 previousDbValue = peakDbValue;
   3448             }
   3449             else
   3450             {
   3451                 peakDbValue = previousDbValue > -pPCM16Sample[loopIndex]
   3452                 ? previousDbValue : -pPCM16Sample[loopIndex];
   3453                 previousDbValue = peakDbValue;
   3454             }
   3455             loopIndex++;
   3456         }
   3457 
   3458         pC->audioVolumeArray[pC->audVolArrIndex] =
   3459             M4VSS3GPP_getDecibelSound(peakDbValue);
   3460 
   3461         /* WINDOW_SIZE is 10 by default and check for threshold is done after 10 cycles */
   3462         if( pC->audVolArrIndex >= WINDOW_SIZE - 1 )
   3463         {
   3464             pC->bDoDucking =
   3465                 M4VSS3GPP_isThresholdBreached((M4OSA_Int32 *)&(pC->audioVolumeArray),
   3466                 pC->audVolArrIndex, pC->InDucking_threshold);
   3467 
   3468             pC->audVolArrIndex = 0;
   3469         }
   3470         else
   3471         {
   3472             pC->audVolArrIndex++;
   3473         }
   3474 
   3475         /*
   3476         *Below logic controls the mixing weightage for Background Track and Primary Track
   3477         *for the duration of window under analysis to give fade-out for Background and fade-in
   3478         *for primary
   3479         *
   3480         *Current fading factor is distributed in equal range over the defined window size.
   3481         *
   3482         *For a window size = 25 (500 ms (window under analysis) / 20 ms (sample duration))
   3483         *
   3484         */
   3485 
   3486         if( pC->bDoDucking )
   3487         {
   3488             if( pC->duckingFactor
   3489                 > pC->InDucking_lowVolume ) // FADE OUT BG Track
   3490             {
   3491                     // decrement ducking factor in total steps in factor of low volume steps to reach
   3492                     // low volume level
   3493                 pC->duckingFactor -= (pC->InDucking_lowVolume);
   3494             }
   3495             else
   3496             {
   3497                 pC->duckingFactor = pC->InDucking_lowVolume;
   3498             }
   3499         }
   3500         else
   3501         {
   3502             if( pC->duckingFactor < 1.0 ) // FADE IN BG Track
   3503             {
   3504                 // increment ducking factor in total steps of low volume factor to reach
   3505                 // orig.volume level
   3506                 pC->duckingFactor += (pC->InDucking_lowVolume);
   3507             }
   3508         else
   3509            {
   3510                 pC->duckingFactor = 1.0;
   3511             }
   3512         }
   3513         /* endif - ducking_enable */
   3514 
   3515         /* Mixing Logic */
   3516 
   3517         while( uiPCMsize-- > 0 )
   3518         {
   3519             M4OSA_Int32 temp;
   3520 
   3521            /* set vol factor for BT and PT */
   3522             *pPCMdata2 = (M4OSA_Int16)(*pPCMdata2 * pC->fBTVolLevel);
   3523 
   3524             *pPCMdata1 = (M4OSA_Int16)(*pPCMdata1 * pC->fPTVolLevel);
   3525 
   3526             /* mix the two samples */
   3527 
   3528             *pPCMdata2 = (M4OSA_Int16)(( *pPCMdata2) * (pC->duckingFactor));
   3529             *pPCMdata1 = (M4OSA_Int16)(*pPCMdata2 / 2 + *pPCMdata1 / 2);
   3530 
   3531 
   3532             if( *pPCMdata1 < 0 )
   3533             {
   3534                 temp = -( *pPCMdata1)
   3535                     * 2; // bring to same Amplitude level as it was original
   3536 
   3537                 if( temp > 32767 )
   3538                 {
   3539                     *pPCMdata1 = -32766; // less then max allowed value
   3540                 }
   3541                 else
   3542                 {
   3543                     *pPCMdata1 = (M4OSA_Int16)(-temp);
   3544                }
   3545         }
   3546         else
   3547         {
   3548             temp = ( *pPCMdata1)
   3549                 * 2; // bring to same Amplitude level as it was original
   3550 
   3551             if( temp > 32768 )
   3552             {
   3553                 *pPCMdata1 = 32767; // less than max allowed value
   3554             }
   3555             else
   3556             {
   3557                 *pPCMdata1 = (M4OSA_Int16)temp;
   3558             }
   3559         }
   3560 
   3561             pPCMdata2++;
   3562             pPCMdata1++;
   3563         }
   3564     }
   3565     else
   3566     {
   3567         while( uiPCMsize-- > 0 )
   3568        {
   3569         /* mix the two samples */
   3570             *pPCMdata1 = (M4OSA_Int16)(*pPCMdata1 * pC->fOrigFactor * pC->fPTVolLevel
   3571                + *pPCMdata2 * pC->fAddedFactor * pC->fBTVolLevel );
   3572 
   3573             pPCMdata1++;
   3574             pPCMdata2++;
   3575         }
   3576     }
   3577 
   3578     /* Update pC->pSsrcBufferOut buffer */
   3579 
   3580     if( M4OSA_TRUE == pC->b_SSRCneeded || pC->ChannelConversion > 0 )
   3581     {
   3582         tempPosBuffer = pC->pSsrcBufferOut
   3583             + pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize;
   3584         memmove((void *)pC->pSsrcBufferOut, (void *)tempPosBuffer,
   3585             pC->pPosInSsrcBufferOut - tempPosBuffer);
   3586         pC->pPosInSsrcBufferOut -=
   3587             pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize;
   3588     }
   3589     else if( pC->pAddedClipCtxt->pSettings->ClipProperties.AudioStreamType
   3590         == M4VIDEOEDITING_kMP3 )
   3591     {
   3592         tempPosBuffer = pC->pSsrcBufferIn
   3593             + pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize;
   3594         memmove((void *)pC->pSsrcBufferIn, (void *)tempPosBuffer,
   3595             pC->pPosInSsrcBufferIn - tempPosBuffer);
   3596         pC->pPosInSsrcBufferIn -=
   3597             pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize;
   3598     }
   3599 
   3600     /* [Mono] or [Stereo interleaved] : all is in one buffer */
   3601     pEncInBuffer.pTableBuffer[0] =
   3602         pC->pInputClipCtxt->AudioDecBufferOut.m_dataAddress;
   3603     pEncInBuffer.pTableBufferSize[0] =
   3604         pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize;
   3605     pEncInBuffer.pTableBuffer[1] = M4OSA_NULL;
   3606     pEncInBuffer.pTableBufferSize[1] = 0;
   3607 
   3608     /* Time in ms from data size, because it is PCM16 samples */
   3609     frameTimeDelta =
   3610         pEncInBuffer.pTableBufferSize[0] / sizeof(short) / pC->ewc.uiNbChannels;
   3611 
   3612     /**
   3613     * Prepare output buffer */
   3614     pEncOutBuffer.pTableBuffer[0] =
   3615         (M4OSA_MemAddr8)pC->ewc.WriterAudioAU.dataAddress;
   3616     pEncOutBuffer.pTableBufferSize[0] = 0;
   3617 
   3618     M4OSA_TRACE2_0("K **** blend AUs");
   3619 
   3620     /**
   3621     * Encode the PCM audio */
   3622     err = pC->ShellAPI.pAudioEncoderGlobalFcts->pFctStep(pC->ewc.pAudioEncCtxt,
   3623         &pEncInBuffer, &pEncOutBuffer);
   3624 
   3625     if( M4NO_ERROR != err )
   3626     {
   3627         M4OSA_TRACE1_1(
   3628             "M4VSS3GPP_intAudioMixingDoMixing(): pAudioEncoderGlobalFcts->pFctStep returns 0x%x",
   3629             err);
   3630         return err;
   3631     }
   3632 
   3633     /**
   3634     * Set AU cts and size */
   3635     pC->ewc.WriterAudioAU.size =
   3636         pEncOutBuffer.pTableBufferSize[0]; /**< Get the size of encoded data */
   3637     pC->ewc.WriterAudioAU.CTS += frameTimeDelta;
   3638 
   3639     /**
   3640     * Write the AU */
   3641     M4OSA_TRACE2_2("L ---- write : cts  = %ld [ 0x%x ]",
   3642         (M4OSA_Int32)(pC->ewc.WriterAudioAU.CTS / pC->ewc.scale_audio),
   3643         pC->ewc.WriterAudioAU.size);
   3644 
   3645     err = pC->ShellAPI.pWriterDataFcts->pProcessAU(pC->ewc.p3gpWriterContext,
   3646         M4VSS3GPP_WRITER_AUDIO_STREAM_ID, &pC->ewc.WriterAudioAU);
   3647 
   3648     if( M4NO_ERROR != err )
   3649     {
   3650         M4OSA_TRACE1_1(
   3651             "M4VSS3GPP_intAudioMixingDoMixing: pWriterDataFcts->pProcessAU returns 0x%x!",
   3652             err);
   3653         return err;
   3654     }
   3655 
   3656     /**
   3657     * Increment the audio CTS for the next step */
   3658     pC->ewc.dATo += frameTimeDelta / pC->ewc.scale_audio;
   3659 
   3660     /**
   3661     * Return with no error */
   3662     M4OSA_TRACE3_0("M4VSS3GPP_intAudioMixingDoMixing(): returning M4NO_ERROR");
   3663     return M4NO_ERROR;
   3664 }
   3665 
   3666 /**
   3667  ******************************************************************************
   3668  * M4OSA_ERR  M4VSS3GPP_intAudioMixingTransition(M4VSS3GPP_InternalAudioMixingContext *pC)
   3669  * @brief    Decode/encode a few AU backward to initiate the encoder for later Mix segment.
   3670  * @note
   3671  * @param    pC    (IN) VSS audio mixing internal context
   3672  * @return    M4NO_ERROR:    No error
   3673  ******************************************************************************
   3674  */
   3675 static M4OSA_ERR M4VSS3GPP_intAudioMixingTransition(
   3676     M4VSS3GPP_InternalAudioMixingContext *pC )
   3677 {
   3678     M4OSA_ERR err;
   3679 
   3680     M4ENCODER_AudioBuffer pEncInBuffer;  /**< Encoder input buffer for api */
   3681     M4ENCODER_AudioBuffer pEncOutBuffer; /**< Encoder output buffer for api */
   3682     M4OSA_Time
   3683         frameTimeDelta = 0; /**< Duration of the encoded (then written) data */
   3684 
   3685     M4OSA_Int32 iTargetCts, iCurrentCts;
   3686 
   3687     /**
   3688     * 'BZZZ' bug fix:
   3689     * add a silence frame */
   3690     err = M4VSS3GPP_intAudioMixingWriteSilence(pC);
   3691 
   3692     if( M4NO_ERROR != err )
   3693     {
   3694         M4OSA_TRACE1_1(
   3695             "M4VSS3GPP_intAudioMixingTransition():\
   3696             M4VSS3GPP_intAudioMixingWriteSilence returns 0x%x",
   3697             err);
   3698         return err;
   3699     }
   3700 
   3701     iCurrentCts = (M4OSA_Int32)(pC->ewc.dATo * pC->ewc.scale_audio + 0.5);
   3702 
   3703     /* Do not do pre-encode step if there is no mixing (remove, 100 %, or not editable) */
   3704     if( M4OSA_FALSE == pC->bAudioMixingIsNeeded )
   3705     {
   3706         /**
   3707         * Advance in the original audio stream to reach the current time
   3708         * (We don't want iAudioCTS to be modified by the jump function,
   3709         * so we have to use a local variable). */
   3710         err = M4VSS3GPP_intClipJumpAudioAt(pC->pInputClipCtxt, &iCurrentCts);
   3711 
   3712         if( M4NO_ERROR != err )
   3713         {
   3714             M4OSA_TRACE1_1("M4VSS3GPP_intAudioMixingTransition:\
   3715              M4VSS3GPP_intClipJumpAudioAt() returns 0x%x!", err);
   3716             return err;
   3717         }
   3718     }
   3719     else
   3720     {
   3721         /**< don't try to pre-decode if clip is at its beginning... */
   3722         if( iCurrentCts > 0 )
   3723         {
   3724             /**
   3725             * Get the output AU to write into */
   3726             err = pC->ShellAPI.pWriterDataFcts->pStartAU(
   3727                 pC->ewc.p3gpWriterContext, M4VSS3GPP_WRITER_AUDIO_STREAM_ID,
   3728                 &pC->ewc.WriterAudioAU);
   3729 
   3730             if( M4NO_ERROR != err )
   3731             {
   3732                 M4OSA_TRACE1_1(
   3733                     "M4VSS3GPP_intAudioMixingTransition:\
   3734                     pWriterDataFcts->pStartAU(audio) returns 0x%x!",
   3735                     err);
   3736                 return err;
   3737             }
   3738 
   3739             /**
   3740             * Jump a few AUs backward */
   3741             iTargetCts = iCurrentCts - M4VSS3GPP_NB_AU_PREFETCH
   3742                 * pC->ewc.iSilenceFrameDuration;
   3743 
   3744             if( iTargetCts < 0 )
   3745             {
   3746                 iTargetCts = 0; /**< Sanity check */
   3747             }
   3748 
   3749             err = M4VSS3GPP_intClipJumpAudioAt(pC->pInputClipCtxt, &iTargetCts);
   3750 
   3751             if( M4NO_ERROR != err )
   3752             {
   3753                 M4OSA_TRACE1_1(
   3754                     "M4VSS3GPP_intAudioMixingTransition: DECODE_ENCODE-prefetch:\
   3755                     M4VSS3GPP_intClipJumpAudioAt returns 0x%x!",
   3756                     err);
   3757                 return err;
   3758             }
   3759 
   3760             /**
   3761             * Decode/encode up to the wanted position */
   3762             while( pC->pInputClipCtxt->iAudioFrameCts < iCurrentCts )
   3763             {
   3764                 err = M4VSS3GPP_intClipReadNextAudioFrame(pC->pInputClipCtxt);
   3765 
   3766                 M4OSA_TRACE2_3("M .... read  : cts  = %.0f + %.0f [ 0x%x ]",
   3767                     pC->pInputClipCtxt->iAudioFrameCts
   3768                     / pC->pInputClipCtxt->scale_audio,
   3769                     pC->pInputClipCtxt->iAoffset
   3770                     / pC->pInputClipCtxt->scale_audio,
   3771                     pC->pInputClipCtxt->uiAudioFrameSize);
   3772 
   3773                 if( M4OSA_ERR_IS_ERROR(err) )
   3774                 {
   3775                     M4OSA_TRACE1_1(
   3776                         "M4VSS3GPP_intAudioMixingTransition: DECODE_ENCODE-prefetch:\
   3777                         M4VSS3GPP_intClipReadNextAudioFrame(b) returns 0x%x!",
   3778                         err);
   3779                     return err;
   3780                 }
   3781 
   3782                 err = M4VSS3GPP_intClipDecodeCurrentAudioFrame(
   3783                     pC->pInputClipCtxt);
   3784 
   3785                 if( M4NO_ERROR != err )
   3786                 {
   3787                     M4OSA_TRACE1_1(
   3788                         "M4VSS3GPP_intAudioMixingTransition: DECODE_ENCODE-prefetch:\
   3789                         M4VSS3GPP_intClipDecodeCurrentAudioFrame returns 0x%x!",
   3790                         err);
   3791                     return err;
   3792                 }
   3793 
   3794                 /* [Mono] or [Stereo interleaved] : all is in one buffer */
   3795                 pEncInBuffer.pTableBuffer[0] =
   3796                     pC->pInputClipCtxt->AudioDecBufferOut.m_dataAddress;
   3797                 pEncInBuffer.pTableBufferSize[0] =
   3798                     pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize;
   3799                 pEncInBuffer.pTableBuffer[1] = M4OSA_NULL;
   3800                 pEncInBuffer.pTableBufferSize[1] = 0;
   3801 
   3802                 /* Time in ms from data size, because it is PCM16 samples */
   3803                 frameTimeDelta =
   3804                     pEncInBuffer.pTableBufferSize[0] / sizeof(short)
   3805                     / pC->ewc.uiNbChannels;
   3806 
   3807                 /**
   3808                 * Prepare output buffer */
   3809                 pEncOutBuffer.pTableBuffer[0] =
   3810                     (M4OSA_MemAddr8)pC->ewc.WriterAudioAU.dataAddress;
   3811                 pEncOutBuffer.pTableBufferSize[0] = 0;
   3812 
   3813                 M4OSA_TRACE2_0("N **** pre-encode");
   3814 
   3815                 /**
   3816                 * Encode the PCM audio */
   3817                 err = pC->ShellAPI.pAudioEncoderGlobalFcts->pFctStep(
   3818                     pC->ewc.pAudioEncCtxt, &pEncInBuffer, &pEncOutBuffer);
   3819 
   3820                 if( M4NO_ERROR != err )
   3821                 {
   3822                     M4OSA_TRACE1_1(
   3823                         "M4VSS3GPP_intAudioMixingTransition():\
   3824                         pAudioEncoderGlobalFcts->pFctStep returns 0x%x",
   3825                         err);
   3826                     return err;
   3827                 }
   3828             }
   3829 
   3830             /**
   3831             * Set AU cts and size */
   3832             pC->ewc.WriterAudioAU.size = pEncOutBuffer.pTableBufferSize[
   3833                 0]; /**< Get the size of encoded data */
   3834                 pC->ewc.WriterAudioAU.CTS += frameTimeDelta;
   3835 
   3836                 /**
   3837                 * Write the AU */
   3838                 M4OSA_TRACE2_2("O ---- write : cts  = %ld [ 0x%x ]",
   3839                     (M4OSA_Int32)(pC->ewc.WriterAudioAU.CTS / pC->ewc.scale_audio),
   3840                     pC->ewc.WriterAudioAU.size);
   3841 
   3842                 err = pC->ShellAPI.pWriterDataFcts->pProcessAU(
   3843                     pC->ewc.p3gpWriterContext, M4VSS3GPP_WRITER_AUDIO_STREAM_ID,
   3844                     &pC->ewc.WriterAudioAU);
   3845 
   3846                 if( M4NO_ERROR != err )
   3847                 {
   3848                     M4OSA_TRACE1_1(
   3849                         "M4VSS3GPP_intAudioMixingTransition:\
   3850                         pWriterDataFcts->pProcessAU returns 0x%x!",    err);
   3851                     return err;
   3852                 }
   3853 
   3854                 /**
   3855                 * Increment the audio CTS for the next step */
   3856                 pC->ewc.dATo += pC->ewc.iSilenceFrameDuration / pC->ewc.scale_audio;
   3857         }
   3858     }
   3859 
   3860     return M4NO_ERROR;
   3861 }
   3862 
   3863 /**
   3864  ******************************************************************************
   3865  * M4OSA_ERR M4VSS3GPP_intAudioMixingCreateVideoEncoder()
   3866  * @brief    Creates the video encoder
   3867  * @note
   3868  ******************************************************************************
   3869  */
   3870 static M4OSA_ERR M4VSS3GPP_intAudioMixingCreateVideoEncoder(
   3871     M4VSS3GPP_InternalAudioMixingContext *pC )
   3872 {
   3873     M4OSA_ERR err;
   3874     M4ENCODER_AdvancedParams EncParams;
   3875 
   3876     /**
   3877     * Simulate a writer interface with our specific function */
   3878     pC->ewc.OurWriterDataInterface.pProcessAU =
   3879         M4VSS3GPP_intProcessAU; /**< This function is VSS 3GPP specific,
   3880                                 but it follow the writer interface */
   3881     pC->ewc.OurWriterDataInterface.pStartAU =
   3882         M4VSS3GPP_intStartAU; /**< This function is VSS 3GPP specific,
   3883                               but it follow the writer interface */
   3884     pC->ewc.OurWriterDataInterface.pWriterContext =
   3885         (M4WRITER_Context)
   3886         pC; /**< We give the internal context as writer context */
   3887 
   3888     /**
   3889     * Get the encoder interface, if not already done */
   3890     if( M4OSA_NULL == pC->ShellAPI.pVideoEncoderGlobalFcts )
   3891     {
   3892         err = M4VSS3GPP_setCurrentVideoEncoder(&pC->ShellAPI,
   3893             pC->ewc.VideoStreamType);
   3894         M4OSA_TRACE1_1(
   3895             "M4VSS3GPP_intAudioMixingCreateVideoEncoder: setCurrentEncoder returns 0x%x",
   3896             err);
   3897         M4ERR_CHECK_RETURN(err);
   3898     }
   3899 
   3900     /**
   3901     * Set encoder shell parameters according to VSS settings */
   3902 
   3903     /* Common parameters */
   3904     EncParams.InputFormat = M4ENCODER_kIYUV420;
   3905     EncParams.FrameWidth = pC->ewc.uiVideoWidth;
   3906     EncParams.FrameHeight = pC->ewc.uiVideoHeight;
   3907     EncParams.uiTimeScale = pC->ewc.uiVideoTimeScale;
   3908     EncParams.videoProfile = pC->ewc.outputVideoProfile;
   3909     EncParams.videoLevel = pC->ewc.outputVideoLevel;
   3910 
   3911     /* No strict regulation in video editor */
   3912     /* Because of the effects and transitions we should allow more flexibility */
   3913     /* Also it prevents to drop important frames
   3914       (with a bad result on sheduling and block effetcs) */
   3915     EncParams.bInternalRegulation = M4OSA_FALSE;
   3916     EncParams.FrameRate = M4ENCODER_kVARIABLE_FPS;
   3917 
   3918     /**
   3919     * Other encoder settings (defaults) */
   3920     EncParams.uiHorizontalSearchRange = 0;     /* use default */
   3921     EncParams.uiVerticalSearchRange = 0;       /* use default */
   3922     EncParams.bErrorResilience = M4OSA_FALSE;  /* no error resilience */
   3923     EncParams.uiIVopPeriod = 0;                /* use default */
   3924     EncParams.uiMotionEstimationTools = 0;     /* M4V_MOTION_EST_TOOLS_ALL */
   3925     EncParams.bAcPrediction = M4OSA_TRUE;      /* use AC prediction */
   3926     EncParams.uiStartingQuantizerValue = 10;   /* initial QP = 10 */
   3927     EncParams.bDataPartitioning = M4OSA_FALSE; /* no data partitioning */
   3928 
   3929     switch( pC->ewc.VideoStreamType )
   3930     {
   3931         case M4SYS_kH263:
   3932 
   3933             EncParams.Format = M4ENCODER_kH263;
   3934 
   3935             EncParams.uiStartingQuantizerValue = 10;
   3936             EncParams.uiRateFactor = 1; /* default */
   3937 
   3938             EncParams.bErrorResilience = M4OSA_FALSE;
   3939             EncParams.bDataPartitioning = M4OSA_FALSE;
   3940             break;
   3941 
   3942         case M4SYS_kMPEG_4:
   3943 
   3944             EncParams.Format = M4ENCODER_kMPEG4;
   3945 
   3946             EncParams.uiStartingQuantizerValue = 8;
   3947             EncParams.uiRateFactor = 1;
   3948 
   3949             if( M4OSA_FALSE == pC->ewc.bVideoDataPartitioning )
   3950             {
   3951                 EncParams.bErrorResilience = M4OSA_FALSE;
   3952                 EncParams.bDataPartitioning = M4OSA_FALSE;
   3953             }
   3954             else
   3955             {
   3956                 EncParams.bErrorResilience = M4OSA_TRUE;
   3957                 EncParams.bDataPartitioning = M4OSA_TRUE;
   3958             }
   3959             break;
   3960 
   3961         case M4SYS_kH264:
   3962             M4OSA_TRACE1_0(
   3963                 "M4VSS3GPP_intAudioMixingCreateVideoEncoder: M4SYS_H264");
   3964 
   3965             EncParams.Format = M4ENCODER_kH264;
   3966 
   3967             EncParams.uiStartingQuantizerValue = 10;
   3968             EncParams.uiRateFactor = 1; /* default */
   3969 
   3970             EncParams.bErrorResilience = M4OSA_FALSE;
   3971             EncParams.bDataPartitioning = M4OSA_FALSE;
   3972             break;
   3973 
   3974         default:
   3975             M4OSA_TRACE1_1(
   3976                 "M4VSS3GPP_intAudioMixingCreateVideoEncoder: Unknown videoStreamType 0x%x",
   3977                 pC->ewc.VideoStreamType);
   3978             return M4VSS3GPP_ERR_EDITING_UNSUPPORTED_VIDEO_FORMAT;
   3979     }
   3980 
   3981     EncParams.Bitrate =
   3982         pC->pInputClipCtxt->pSettings->ClipProperties.uiVideoBitrate;
   3983 
   3984     M4OSA_TRACE1_0(
   3985         "M4VSS3GPP_intAudioMixingCreateVideoEncoder: calling encoder pFctInit");
   3986     /**
   3987     * Init the video encoder (advanced settings version of the encoder Open function) */
   3988     err = pC->ShellAPI.pVideoEncoderGlobalFcts->pFctInit(&pC->ewc.pEncContext,
   3989         &pC->ewc.OurWriterDataInterface, M4VSS3GPP_intVPP, pC,
   3990         pC->ShellAPI.pCurrentVideoEncoderExternalAPI,
   3991         pC->ShellAPI.pCurrentVideoEncoderUserData);
   3992 
   3993     if( M4NO_ERROR != err )
   3994     {
   3995         M4OSA_TRACE1_1(
   3996             "M4VSS3GPP_intAudioMixingCreateVideoEncoder:\
   3997             pVideoEncoderGlobalFcts->pFctInit returns 0x%x",
   3998             err);
   3999         return err;
   4000     }
   4001 
   4002     pC->ewc.encoderState = M4VSS3GPP_kEncoderClosed;
   4003     M4OSA_TRACE1_0(
   4004         "M4VSS3GPP_intAudioMixingCreateVideoEncoder: calling encoder pFctOpen");
   4005     M4OSA_TRACE1_2("vss: audio mix encoder open profile :%d, level %d",
   4006         EncParams.videoProfile, EncParams.videoLevel);
   4007     err = pC->ShellAPI.pVideoEncoderGlobalFcts->pFctOpen(pC->ewc.pEncContext,
   4008         &pC->ewc.WriterVideoAU, &EncParams);
   4009 
   4010     if( M4NO_ERROR != err )
   4011     {
   4012         M4OSA_TRACE1_1(
   4013             "M4VSS3GPP_intAudioMixingCreateVideoEncoder:\
   4014             pVideoEncoderGlobalFcts->pFctOpen returns 0x%x",
   4015             err);
   4016         return err;
   4017     }
   4018 
   4019     pC->ewc.encoderState = M4VSS3GPP_kEncoderStopped;
   4020     M4OSA_TRACE1_0(
   4021         "M4VSS3GPP_intAudioMixingCreateVideoEncoder: calling encoder pFctStart");
   4022 
   4023     if( M4OSA_NULL != pC->ShellAPI.pVideoEncoderGlobalFcts->pFctStart )
   4024     {
   4025         err = pC->ShellAPI.pVideoEncoderGlobalFcts->pFctStart(
   4026             pC->ewc.pEncContext);
   4027 
   4028         if( M4NO_ERROR != err )
   4029         {
   4030             M4OSA_TRACE1_1(
   4031                 "M4VSS3GPP_intAudioMixingCreateVideoEncoder:\
   4032                 pVideoEncoderGlobalFcts->pFctStart returns 0x%x",
   4033                 err);
   4034             return err;
   4035         }
   4036     }
   4037 
   4038     pC->ewc.encoderState = M4VSS3GPP_kEncoderRunning;
   4039 
   4040     /**
   4041     *    Return */
   4042     M4OSA_TRACE3_0(
   4043         "M4VSS3GPP_intAudioMixingCreateVideoEncoder: returning M4NO_ERROR");
   4044     return M4NO_ERROR;
   4045 }
   4046 
   4047 /**
   4048  ******************************************************************************
   4049  * M4OSA_ERR M4VSS3GPP_intAudioMixingDestroyVideoEncoder()
   4050  * @brief    Destroy the video encoder
   4051  * @note
   4052  ******************************************************************************
   4053  */
   4054 static M4OSA_ERR M4VSS3GPP_intAudioMixingDestroyVideoEncoder(
   4055     M4VSS3GPP_InternalAudioMixingContext *pC )
   4056 {
   4057     M4OSA_ERR err = M4NO_ERROR;
   4058 
   4059     if( M4OSA_NULL != pC->ewc.pEncContext )
   4060     {
   4061         if( M4VSS3GPP_kEncoderRunning == pC->ewc.encoderState )
   4062         {
   4063             if( pC->ShellAPI.pVideoEncoderGlobalFcts->pFctStop != M4OSA_NULL )
   4064             {
   4065                 err = pC->ShellAPI.pVideoEncoderGlobalFcts->pFctStop(
   4066                     pC->ewc.pEncContext);
   4067 
   4068                 if( M4NO_ERROR != err )
   4069                 {
   4070                     M4OSA_TRACE1_1(
   4071                         "M4VSS3GPP_intAudioMixingDestroyVideoEncoder:\
   4072                         pVideoEncoderGlobalFcts->pFctStop returns 0x%x",
   4073                         err);
   4074                 }
   4075             }
   4076 
   4077             pC->ewc.encoderState = M4VSS3GPP_kEncoderStopped;
   4078         }
   4079 
   4080         /* Has the encoder actually been opened? Don't close it if that's not the case. */
   4081         if( M4VSS3GPP_kEncoderStopped == pC->ewc.encoderState )
   4082         {
   4083             err = pC->ShellAPI.pVideoEncoderGlobalFcts->pFctClose(
   4084                 pC->ewc.pEncContext);
   4085 
   4086             if( M4NO_ERROR != err )
   4087             {
   4088                 M4OSA_TRACE1_1(
   4089                     "M4VSS3GPP_intAudioMixingDestroyVideoEncoder:\
   4090                     pVideoEncoderGlobalFcts->pFctClose returns 0x%x",
   4091                     err);
   4092             }
   4093 
   4094             pC->ewc.encoderState = M4VSS3GPP_kEncoderClosed;
   4095         }
   4096 
   4097         err = pC->ShellAPI.pVideoEncoderGlobalFcts->pFctCleanup(
   4098             pC->ewc.pEncContext);
   4099 
   4100         if( M4NO_ERROR != err )
   4101         {
   4102             M4OSA_TRACE1_1(
   4103                 "M4VSS3GPP_intAudioMixingDestroyVideoEncoder:\
   4104                 pVideoEncoderGlobalFcts->pFctCleanup returns 0x%x!",
   4105                 err);
   4106             /**< We do not return the error here because we still have stuff to free */
   4107         }
   4108 
   4109         pC->ewc.encoderState = M4VSS3GPP_kNoEncoder;
   4110         /**
   4111         * Reset variable */
   4112         pC->ewc.pEncContext = M4OSA_NULL;
   4113     }
   4114 
   4115     M4OSA_TRACE3_1(
   4116         "M4VSS3GPP_intAudioMixingDestroyVideoEncoder: returning 0x%x", err);
   4117     return err;
   4118 }
   4119 
   4120 M4OSA_Bool M4VSS3GPP_isThresholdBreached( M4OSA_Int32 *averageValue,
   4121                                          M4OSA_Int32 storeCount, M4OSA_Int32 thresholdValue )
   4122 {
   4123     M4OSA_Bool result = 0;
   4124     int i;
   4125     int finalValue = 0;
   4126 
   4127     for ( i = 0; i < storeCount; i++ )
   4128         finalValue += averageValue[i];
   4129 
   4130     finalValue = finalValue / storeCount;
   4131 
   4132 
   4133     if( finalValue > thresholdValue )
   4134         result = M4OSA_TRUE;
   4135     else
   4136         result = M4OSA_FALSE;
   4137 
   4138     return result;
   4139 }
   4140