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