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