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