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