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