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_EditAudio.c
19 * @brief Video Studio Service 3GPP edit API implementation.
20 * @note
21 ******************************************************************************
22 */
23
24 /****************/
25 /*** Includes ***/
26 /****************/
27
28 #include "NXPSW_CompilerSwitches.h"
29 /**
30 * Our header */
31 #include "M4VSS3GPP_API.h"
32 #include "M4VSS3GPP_InternalTypes.h"
33 #include "M4VSS3GPP_InternalFunctions.h"
34 #include "M4VSS3GPP_InternalConfig.h"
35 #include "M4VSS3GPP_ErrorCodes.h"
36
37 /**
38 * OSAL headers */
39 #include "M4OSA_Memory.h" /**< OSAL memory management */
40 #include "M4OSA_Debug.h" /**< OSAL debug management */
41
42 #define PWR_FXP_FRACT_MAX (32768)
43
44 /************************************************************************/
45 /* Static local functions */
46 /************************************************************************/
47 static M4OSA_ERR M4VSS3GPP_intCheckAudioMode( M4VSS3GPP_InternalEditContext
48 *pC );
49 static M4OSA_Void M4VSS3GPP_intCheckAudioEffects( M4VSS3GPP_InternalEditContext
50 *pC, M4OSA_UInt8 uiClipNumber );
51 static M4OSA_ERR M4VSS3GPP_intApplyAudioEffect( M4VSS3GPP_InternalEditContext
52 *pC, M4OSA_UInt8 uiClip1orClip2,
53 M4OSA_Int16 *pPCMdata,
54 M4OSA_UInt32 uiPCMsize );
55 static M4OSA_ERR M4VSS3GPP_intAudioTransition( M4VSS3GPP_InternalEditContext
56 *pC, M4OSA_Int16 *pPCMdata1,
57 M4OSA_Int16 *pPCMdata2,
58 M4OSA_UInt32 uiPCMsize );
59
60 /**
61 ******************************************************************************
62 * M4OSA_ERR M4VSS3GPP_intEditJumpMP3()
63 * @brief One step of jumping processing for the MP3 clip.
64 * @note On one step, the jump of several AU is done
65 * @param pC (IN/OUT) Internal edit context
66 ******************************************************************************
67 */
M4VSS3GPP_intEditJumpMP3(M4VSS3GPP_InternalEditContext * pC)68 M4OSA_ERR M4VSS3GPP_intEditJumpMP3( M4VSS3GPP_InternalEditContext *pC )
69 {
70 M4OSA_ERR err;
71 M4VSS3GPP_ClipContext *pClip = pC->pC1; /**< shortcut */
72 M4OSA_Int32 JumpCts;
73
74 JumpCts = pClip->iActualAudioBeginCut;
75
76 err = M4VSS3GPP_intClipJumpAudioAt(pClip, &JumpCts);
77
78 if( M4NO_ERROR != err )
79 {
80 M4OSA_TRACE1_1(
81 "M4VSS3GPP_intOpenClip: M4VSS3GPP_intClipJumpAudioAt(A) returns 0x%x!",
82 err);
83 return err;
84 }
85
86 if( JumpCts >= pClip->iActualAudioBeginCut )
87 {
88 pC->State = M4VSS3GPP_kEditState_MP3;
89
90 /**
91 * Update clip offset with the audio begin cut */
92 pClip->iAoffset = -JumpCts;
93
94 /**
95 * The audio is currently in reading mode */
96 pClip->Astatus = M4VSS3GPP_kClipStatus_READ;
97 }
98 return M4NO_ERROR;
99 }
100
101 /**
102 ******************************************************************************
103 * M4OSA_ERR M4VSS3GPP_intEditStepMP3()
104 * @brief One step of audio processing for the MP3 clip
105 * @param pC (IN/OUT) Internal edit context
106 ******************************************************************************
107 */
M4VSS3GPP_intEditStepMP3(M4VSS3GPP_InternalEditContext * pC)108 M4OSA_ERR M4VSS3GPP_intEditStepMP3( M4VSS3GPP_InternalEditContext *pC )
109 {
110 M4OSA_ERR err;
111 M4VSS3GPP_ClipContext *pClip = pC->pC1; /**< shortcut */
112
113 /**
114 * Copy the input AU to the output AU */
115 err = pC->pOsaFileWritPtr->writeData(pC->ewc.p3gpWriterContext,
116 pClip->pAudioFramePtr, (M4OSA_UInt32)pClip->uiAudioFrameSize);
117
118 /**
119 * Read the next audio frame */
120 err = M4VSS3GPP_intClipReadNextAudioFrame(pClip);
121
122 if( M4OSA_ERR_IS_ERROR(err) )
123 {
124 M4OSA_TRACE1_1(
125 "M4VSS3GPP_intEditStepMP3: READ_WRITE:\
126 M4VSS3GPP_intClipReadNextAudioFrame returns 0x%x!", err);
127 return err;
128 }
129 else
130 {
131 /**
132 * Update current time (to=tc+T) */
133 pC->ewc.dATo =
134 ( pClip->iAudioFrameCts + pClip->iAoffset) / pClip->scale_audio;
135
136 if( (M4OSA_Int32)(pClip->iAudioFrameCts / pClip->scale_audio + 0.5)
137 >= pClip->iEndTime )
138 {
139 M4READER_Buffer mp3tagBuffer;
140
141 /**
142 * The duration is better respected if the first AU and last AU are both above
143 the cut time */
144 err = pC->pOsaFileWritPtr->writeData(pC->ewc.p3gpWriterContext,
145 pClip->pAudioFramePtr,
146 (M4OSA_UInt32)pClip->uiAudioFrameSize);
147
148 /* The ID3v1 tag is always at the end of the mp3 file so the end of the cutting
149 process is waited */
150 /* before writing the metadata in the output file*/
151
152 /* Retrieve the data of the ID3v1 Tag */
153 err = pClip->ShellAPI.m_pReader->m_pFctGetOption(
154 pClip->pReaderContext, M4READER_kOptionID_Mp3Id3v1Tag,
155 (M4OSA_DataOption) &mp3tagBuffer);
156
157 if( M4NO_ERROR != err )
158 {
159 M4OSA_TRACE1_1(
160 "M4VSS3GPP_intEditStepMP3: M4MP3R_getOption returns 0x%x",
161 err);
162 return err;
163 }
164
165 /* Write the data of the ID3v1 Tag in the output file */
166 if( 0 != mp3tagBuffer.m_uiBufferSize )
167 {
168 err = pC->pOsaFileWritPtr->writeData(pC->ewc.p3gpWriterContext,
169 (M4OSA_MemAddr8)mp3tagBuffer.m_pData, mp3tagBuffer.m_uiBufferSize);
170 /**
171 * Free before the error checking anyway */
172 free(mp3tagBuffer.m_pData);
173
174 /**
175 * Error checking */
176 if( M4NO_ERROR != err )
177 {
178 M4OSA_TRACE1_1(
179 "M4VSS3GPP_intEditStepMP3:\
180 pOsaFileWritPtr->writeData(ID3v1Tag) returns 0x%x", err);
181 return err;
182 }
183
184 mp3tagBuffer.m_uiBufferSize = 0;
185 mp3tagBuffer.m_pData = M4OSA_NULL;
186 }
187
188 /* The End Cut has been reached */
189 err = M4VSS3GPP_intReachedEndOfAudio(pC);
190
191 if( M4NO_ERROR != err )
192 {
193 M4OSA_TRACE1_1(
194 "M4VSS3GPP_intEditStepMP3 : M4VSS3GPP_intReachedEndOfAudio returns 0x%x",
195 err);
196 return err;
197 }
198 }
199
200 if( ( M4WAR_NO_MORE_AU == err) && (M4OSA_FALSE
201 == pC->bSupportSilence) ) /**< Reached end of clip */
202 {
203 err = M4VSS3GPP_intReachedEndOfAudio(
204 pC); /**< Clip done, do the next one */
205
206 if( M4NO_ERROR != err )
207 {
208 M4OSA_TRACE1_1(
209 "M4VSS3GPP_intEditStepMP3: READ_WRITE:\
210 M4VSS3GPP_intReachedEndOfAudio returns 0x%x",
211 err);
212 return err;
213 }
214 }
215 }
216
217 /**
218 * Return with no error */
219 M4OSA_TRACE3_0("M4VSS3GPP_intEditStepMP3: returning M4NO_ERROR");
220 return M4NO_ERROR;
221 }
222 /**
223 ******************************************************************************
224 * M4OSA_ERR M4VSS3GPP_intEditStepAudio()
225 * @brief One step of audio processing
226 * @param pC (IN/OUT) Internal edit context
227 ******************************************************************************
228 */
M4VSS3GPP_intEditStepAudio(M4VSS3GPP_InternalEditContext * pC)229 M4OSA_ERR M4VSS3GPP_intEditStepAudio( M4VSS3GPP_InternalEditContext *pC )
230 {
231 M4OSA_ERR err;
232 int32_t auTimeStamp = -1;
233
234 M4ENCODER_AudioBuffer pEncInBuffer; /**< Encoder input buffer for api */
235 M4ENCODER_AudioBuffer pEncOutBuffer; /**< Encoder output buffer for api */
236 M4OSA_Time
237 frameTimeDelta; /**< Duration of the encoded (then written) data */
238 M4OSA_Bool bStopAudio;
239
240 /**
241 * Check if we reached end cut */
242 if( ( pC->ewc.dATo - pC->pC1->iAoffset / pC->pC1->scale_audio + 0.5)
243 >= pC->pC1->iEndTime )
244 {
245 /**
246 * Audio is done for this clip */
247 err = M4VSS3GPP_intReachedEndOfAudio(pC);
248
249 /* RC: to know when a file has been processed */
250 if( M4NO_ERROR != err && err != M4VSS3GPP_WAR_SWITCH_CLIP )
251 {
252 M4OSA_TRACE1_1(
253 "M4VSS3GPP_intEditStepAudio: M4VSS3GPP_intReachedEndOfAudio returns 0x%x",
254 err);
255 }
256
257 return err;
258 }
259
260 /**
261 * Check Audio Mode, depending on the current output CTS */
262 err = M4VSS3GPP_intCheckAudioMode(
263 pC); /**< This function change the pC->Astate variable! */
264
265 if( M4NO_ERROR != err )
266 {
267 M4OSA_TRACE1_1(
268 "M4VSS3GPP_intEditStepAudio: M4VSS3GPP_intCheckAudioMode returns 0x%x!",
269 err);
270 return err;
271 }
272
273 M4OSA_TRACE2_3(" AUDIO step : dATo = %f state = %d offset = %ld",
274 pC->ewc.dATo, pC->Astate, pC->pC1->iAoffset);
275
276 bStopAudio = M4OSA_FALSE;
277
278 switch( pC->Astate )
279 {
280 /* _________________ */
281 /*| |*/
282 /*| READ_WRITE MODE |*/
283 /*|_________________|*/
284
285 case M4VSS3GPP_kEditAudioState_READ_WRITE:
286 {
287 M4OSA_TRACE3_0("M4VSS3GPP_intEditStepAudio READ_WRITE");
288
289 /**
290 * Get the output AU to write into */
291 err = pC->ShellAPI.pWriterDataFcts->pStartAU(
292 pC->ewc.p3gpWriterContext, M4VSS3GPP_WRITER_AUDIO_STREAM_ID,
293 &pC->ewc.WriterAudioAU);
294
295 if( M4NO_ERROR != err )
296 {
297 M4OSA_TRACE1_1(
298 "M4VSS3GPP_intEditStepAudio:\
299 READ_WRITE: pWriterDataFcts->pStartAU returns 0x%x!",
300 err);
301 return err;
302 }
303
304 /**
305 * Compute output audio CTS */
306 pC->ewc.WriterAudioAU.CTS =
307 pC->pC1->iAudioFrameCts + pC->pC1->iAoffset;
308
309 /**
310 * BZZZ bug fix (read-write case):
311 * Replace the first AMR AU of the stream with a silence AU.
312 * It removes annoying "BZZZ" audio glitch.
313 * It is not needed if there is a begin cut.
314 * It is not needed for the first clip.
315 * Because of another bugfix (2005-03-24), the first AU written may be
316 * the second one which CTS is 20. Hence the cts<21 test.
317 * (the BZZZ effect occurs even with the second AU!) */
318 if( ( M4OSA_FALSE == pC->pC1->bFirstAuWritten)
319 && (0 != pC->uiCurrentClip) && (pC->pC1->iAudioFrameCts
320 < (pC->ewc.iSilenceFrameDuration + 1)) )
321 {
322 /**
323 * Copy a silence AU to the output */
324 pC->ewc.WriterAudioAU.size = pC->ewc.uiSilenceFrameSize;
325 memcpy((void *)pC->ewc.WriterAudioAU.dataAddress,
326 (void *)pC->ewc.pSilenceFrameData, pC->ewc.uiSilenceFrameSize);
327 M4OSA_TRACE2_0("A #### silence AU");
328 }
329 else if( (M4OSA_UInt32)pC->pC1->uiAudioFrameSize
330 < pC->ewc.uiAudioMaxAuSize )
331 {
332 /**
333 * Copy the input AU to the output AU */
334 pC->ewc.WriterAudioAU.size =
335 (M4OSA_UInt32)pC->pC1->uiAudioFrameSize;
336 memcpy((void *)pC->ewc.WriterAudioAU.dataAddress,
337 (void *)pC->pC1->pAudioFramePtr, pC->ewc.WriterAudioAU.size);
338 }
339 else
340 {
341 M4OSA_TRACE1_2(
342 "M4VSS3GPP_intEditStepAudio: READ_WRITE: AU size greater than MaxAuSize \
343 (%d>%d)! returning M4VSS3GPP_ERR_INPUT_AUDIO_AU_TOO_LARGE",
344 pC->pC1->uiAudioFrameSize, pC->ewc.uiAudioMaxAuSize);
345 return M4VSS3GPP_ERR_INPUT_AUDIO_AU_TOO_LARGE;
346 }
347
348 /**
349 * This boolean is only used to fix the BZZ bug... */
350 pC->pC1->bFirstAuWritten = M4OSA_TRUE;
351
352 M4OSA_TRACE2_2("B ---- write : cts = %ld [ 0x%x ]",
353 (M4OSA_Int32)(pC->ewc.WriterAudioAU.CTS / pC->ewc.scale_audio),
354 pC->ewc.WriterAudioAU.size);
355
356 /**
357 * Write the AU */
358 err = pC->ShellAPI.pWriterDataFcts->pProcessAU(
359 pC->ewc.p3gpWriterContext, M4VSS3GPP_WRITER_AUDIO_STREAM_ID,
360 &pC->ewc.WriterAudioAU);
361
362 if( M4NO_ERROR != err )
363 {
364 /*11/12/2008 CR 3283 MMS use case for VideoArtist
365 the warning M4WAR_WRITER_STOP_REQ is returned when the targeted output file
366 size is reached
367 The editing is then finished,
368 the warning M4VSS3GPP_WAR_EDITING_DONE is returned*/
369 if( M4WAR_WRITER_STOP_REQ == err )
370 {
371 M4OSA_TRACE1_0(
372 "M4VSS3GPP_intEditStepAudio: File was cut to avoid oversize");
373 return M4VSS3GPP_WAR_EDITING_DONE;
374 }
375 else
376 {
377 M4OSA_TRACE1_1(
378 "M4VSS3GPP_intEditStepAudio:\
379 READ_WRITE: pWriterDataFcts->pProcessAU returns 0x%x!",
380 err);
381 return err;
382 }
383 }
384
385 /**
386 * Audio is now in read mode (there may be a "if(status!=READ)" here,
387 but it is removed for optimization) */
388 pC->pC1->Astatus = M4VSS3GPP_kClipStatus_READ;
389
390 /**
391 * Read the next audio frame */
392 err = M4VSS3GPP_intClipReadNextAudioFrame(pC->pC1);
393
394 M4OSA_TRACE2_3("C .... read : cts = %.0f + %.0f [ 0x%x ]",
395 pC->pC1->iAudioFrameCts / pC->pC1->scale_audio,
396 pC->pC1->iAoffset / pC->pC1->scale_audio,
397 pC->pC1->uiAudioFrameSize);
398
399 if( M4OSA_ERR_IS_ERROR(err) )
400 {
401 M4OSA_TRACE1_1(
402 "M4VSS3GPP_intEditStepAudio: READ_WRITE:\
403 M4VSS3GPP_intClipReadNextAudioFrame returns 0x%x!",
404 err);
405 return err;
406 }
407 else
408 {
409 /**
410 * Update current time (to=tc+T) */
411 pC->ewc.dATo = ( pC->pC1->iAudioFrameCts + pC->pC1->iAoffset)
412 / pC->pC1->scale_audio;
413
414 if( ( M4WAR_NO_MORE_AU == err)
415 && (M4OSA_FALSE == pC->bSupportSilence) )
416 {
417 /**
418 * If output is other than AMR or AAC
419 (i.e. EVRC,we can't write silence into it)
420 * So we simply end here.*/
421 bStopAudio = M4OSA_TRUE;
422 }
423 }
424 }
425 break;
426
427 /* ____________________ */
428 /*| |*/
429 /*| DECODE_ENCODE MODE |*/
430 /*|____________________|*/
431
432 case M4VSS3GPP_kEditAudioState_DECODE_ENCODE:
433 {
434 M4OSA_TRACE3_0("M4VSS3GPP_intEditStepAudio DECODE_ENCODE");
435
436 /**
437 * Get the output AU to write into */
438 err = pC->ShellAPI.pWriterDataFcts->pStartAU(
439 pC->ewc.p3gpWriterContext, M4VSS3GPP_WRITER_AUDIO_STREAM_ID,
440 &pC->ewc.WriterAudioAU);
441
442 if( M4NO_ERROR != err )
443 {
444 M4OSA_TRACE1_1(
445 "M4VSS3GPP_intEditStepAudio: DECODE_ENCODE:\
446 pWriterDataFcts->pStartAU returns 0x%x!",
447 err);
448 return err;
449 }
450
451 /**
452 * If we were reading the clip, we must jump a few AU backward to decode/encode
453 (without writing result) from that point. */
454 if( M4VSS3GPP_kClipStatus_READ == pC->pC1->Astatus )
455 {
456 M4OSA_Int32 iTargetCts, iCurrentCts;
457
458 if( 0
459 != pC->pC1->
460 iAudioFrameCts ) /**<don't try to pre-decode if clip is at its beginning. */
461 {
462 /**
463 * Jump a few AUs backward */
464 iCurrentCts = pC->pC1->iAudioFrameCts;
465 iTargetCts = iCurrentCts - M4VSS3GPP_NB_AU_PREFETCH
466 * pC->ewc.iSilenceFrameDuration;
467
468 if( iTargetCts < 0 )
469 {
470 iTargetCts = 0; /**< Sanity check */
471 }
472
473 err = M4VSS3GPP_intClipJumpAudioAt(pC->pC1, &iTargetCts);
474
475 if( M4NO_ERROR != err )
476 {
477 M4OSA_TRACE1_1(
478 "M4VSS3GPP_intEditStepAudio: DECODE_ENCODE-prefetch:\
479 M4VSS3GPP_intClipJumpAudioAt returns 0x%x!",
480 err);
481 return err;
482 }
483
484 err = M4VSS3GPP_intClipReadNextAudioFrame(
485 pC->pC1); /**< read AU where we jumped */
486
487 M4OSA_TRACE2_3("D .... read : cts = %.0f + %.0f [ 0x%x ]",
488 pC->pC1->iAudioFrameCts / pC->pC1->scale_audio,
489 pC->pC1->iAoffset / pC->pC1->scale_audio,
490 pC->pC1->uiAudioFrameSize);
491
492 if( M4OSA_ERR_IS_ERROR(err) )
493 {
494 M4OSA_TRACE1_1(
495 "M4VSS3GPP_intEditStepAudio: DECODE_ENCODE-prefetch:\
496 M4VSS3GPP_intClipReadNextAudioFrame(a) returns 0x%x!",
497 err);
498 return err;
499 }
500
501 /**
502 * Decode/encode up to the wanted position */
503 while( pC->pC1->iAudioFrameCts < iCurrentCts )
504 {
505 err = M4VSS3GPP_intClipDecodeCurrentAudioFrame(pC->pC1);
506
507 if( M4NO_ERROR != err )
508 {
509 M4OSA_TRACE1_1(
510 "M4VSS3GPP_intEditStepAudio: DECODE_ENCODE-prefetch: \
511 M4VSS3GPP_intClipDecodeCurrentAudioFrame returns 0x%x!",
512 err);
513 return err;
514 }
515
516 /* [Mono] or [Stereo interleaved] : all is in one buffer */
517 pEncInBuffer.pTableBuffer[0] =
518 pC->pC1->AudioDecBufferOut.m_dataAddress;
519 pEncInBuffer.pTableBufferSize[0] =
520 pC->pC1->AudioDecBufferOut.m_bufferSize;
521 pEncInBuffer.pTableBuffer[1] = M4OSA_NULL;
522 pEncInBuffer.pTableBufferSize[1] = 0;
523
524 /* Time in ms from data size, because it is PCM16 samples */
525 frameTimeDelta =
526 pEncInBuffer.pTableBufferSize[0] / sizeof(short)
527 / pC->ewc.uiNbChannels;
528
529 /**
530 * Prepare output buffer */
531 pEncOutBuffer.pTableBuffer[0] =
532 (M4OSA_MemAddr8)pC->ewc.WriterAudioAU.dataAddress;
533 pEncOutBuffer.pTableBufferSize[0] = 0;
534
535 M4OSA_TRACE2_0("E **** pre-encode");
536 #ifdef M4VSS_SUPPORT_OMX_CODECS
537 /*OMX Audio decoder used.
538 * OMX Audio dec shell does internal buffering and hence does not return
539 a PCM buffer for every decodeStep call.*
540 * So PCM buffer sizes might be 0. In this case donot call encode Step*/
541
542 if( 0 != pEncInBuffer.pTableBufferSize[0] )
543 {
544 #endif
545 /**
546 * Encode the PCM audio */
547
548 err =
549 pC->ShellAPI.pAudioEncoderGlobalFcts->pFctStep(
550 pC->ewc.pAudioEncCtxt,
551 &pEncInBuffer, &pEncOutBuffer);
552
553 if( ( M4NO_ERROR != err)
554 && (M4WAR_NO_MORE_AU != err) )
555 {
556 M4OSA_TRACE1_1(
557 "M4VSS3GPP_intEditStepAudio():\
558 pAudioEncoderGlobalFcts->pFctStep returns 0x%x",
559 err);
560 return err;
561 }
562 #ifdef M4VSS_SUPPORT_OMX_CODECS
563
564 } //if(0 != pEncInBuffer.pTableBufferSize[0])
565
566 #endif
567 pC->pC1->pAudioFramePtr = M4OSA_NULL;
568
569 // Get timestamp of last read AU
570 pC->pC1->ShellAPI.m_pAudioDecoder->m_pFctGetOptionAudioDec(
571 pC->pC1->pAudioDecCtxt, M4AD_kOptionID_AuCTS,
572 (M4OSA_DataOption) &auTimeStamp);
573
574 if (auTimeStamp == -1) {
575 M4OSA_TRACE1_0("M4VSS3GPP_intEditStepAudio: \
576 invalid audio timestamp returned");
577 return M4WAR_INVALID_TIME;
578 }
579
580 pC->pC1->iAudioFrameCts = auTimeStamp;
581
582 }
583 }
584
585 /**
586 * Audio is now OK for decoding */
587 pC->pC1->Astatus = M4VSS3GPP_kClipStatus_DECODE;
588 }
589
590 /**
591 * Decode the input audio */
592 err = M4VSS3GPP_intClipDecodeCurrentAudioFrame(pC->pC1);
593
594 if( M4NO_ERROR != err )
595 {
596 M4OSA_TRACE1_1(
597 "M4VSS3GPP_intEditStepAudio: DECODE_ENCODE:\
598 M4VSS3GPP_intClipDecodeCurrentAudioFrame returns 0x%x",
599 err);
600 return err;
601 }
602
603 pC->pC1->pAudioFramePtr = M4OSA_NULL;
604
605 // Get timestamp of last read AU
606 pC->pC1->ShellAPI.m_pAudioDecoder->m_pFctGetOptionAudioDec(
607 pC->pC1->pAudioDecCtxt, M4AD_kOptionID_AuCTS,
608 (M4OSA_DataOption) &auTimeStamp);
609
610 if (auTimeStamp == -1) {
611 M4OSA_TRACE1_0("M4VSS3GPP_intEditStepAudio: invalid audio \
612 timestamp returned");
613 return M4WAR_INVALID_TIME;
614 }
615
616 pC->pC1->iAudioFrameCts = auTimeStamp;
617
618 /**
619 * Apply the effect */
620 if( pC->iClip1ActiveEffect >= 0 )
621 {
622 err = M4VSS3GPP_intApplyAudioEffect(pC, 1, (M4OSA_Int16
623 *)pC->pC1->AudioDecBufferOut.m_dataAddress,
624 pC->pC1->AudioDecBufferOut.m_bufferSize);
625
626 if( M4NO_ERROR != err )
627 {
628 M4OSA_TRACE1_1(
629 "M4VSS3GPP_intEditStepAudio: DECODE_ENCODE:\
630 M4VSS3GPP_intEndAudioEffect returns 0x%x",
631 err);
632 return err;
633 }
634 }
635
636 /**
637 * Compute output audio CTS */
638 pC->ewc.WriterAudioAU.CTS =
639 pC->pC1->iAudioFrameCts + pC->pC1->iAoffset;
640
641 /* May happen with corrupted input files (which have stts entries not
642 multiple of SilenceFrameDuration) */
643 if( pC->ewc.WriterAudioAU.CTS < 0 )
644 {
645 pC->ewc.WriterAudioAU.CTS = 0;
646 }
647
648 /**
649 * BZZZ bug fix (decode-encode case):
650 * (Yes, the Bzz bug may also occur when we re-encode. It doesn't
651 * occur at the decode before the encode, but at the playback!)
652 * Replace the first AMR AU of the encoded stream with a silence AU.
653 * It removes annoying "BZZZ" audio glitch.
654 * It is not needed if there is a begin cut.
655 * It is not needed for the first clip.
656 * Because of another bugfix (2005-03-24), the first AU written may be
657 * the second one which CTS is 20. Hence the cts<21 test.
658 * (the BZZZ effect occurs even with the second AU!) */
659 if( ( M4OSA_FALSE == pC->pC1->bFirstAuWritten)
660 && (0 != pC->uiCurrentClip) && (pC->pC1->iAudioFrameCts
661 < (pC->ewc.iSilenceFrameDuration + 1)) )
662 {
663 /**
664 * Copy a silence AMR AU to the output */
665 pC->ewc.WriterAudioAU.size = pC->ewc.uiSilenceFrameSize;
666 memcpy((void *)pC->ewc.WriterAudioAU.dataAddress,
667 (void *)pC->ewc.pSilenceFrameData, pC->ewc.uiSilenceFrameSize);
668 M4OSA_TRACE2_0("G #### silence AU");
669 }
670 else
671 {
672 /**
673 * Encode the filtered PCM audio directly into the output AU */
674
675 /* [Mono] or [Stereo interleaved] : all is in one buffer */
676 pEncInBuffer.pTableBuffer[0] =
677 pC->pC1->AudioDecBufferOut.m_dataAddress;
678 pEncInBuffer.pTableBufferSize[0] =
679 pC->pC1->AudioDecBufferOut.m_bufferSize;
680 pEncInBuffer.pTableBuffer[1] = M4OSA_NULL;
681 pEncInBuffer.pTableBufferSize[1] = 0;
682
683 /* Time in ms from data size, because it is PCM16 samples */
684 frameTimeDelta =
685 pEncInBuffer.pTableBufferSize[0] / sizeof(short)
686 / pC->ewc.uiNbChannels;
687
688 /**
689 * Prepare output buffer */
690 pEncOutBuffer.pTableBuffer[0] =
691 (M4OSA_MemAddr8)pC->ewc.WriterAudioAU.dataAddress;
692 pEncOutBuffer.pTableBufferSize[0] = 0;
693
694 M4OSA_TRACE2_0("H ++++ encode AU");
695
696 #ifdef M4VSS_SUPPORT_OMX_CODECS
697 /*OMX Audio decoder used.
698 * OMX Audio dec shell does internal buffering and hence does not return
699 a PCM buffer for every decodeStep call.*
700 * So PCM buffer sizes might be 0. In this case donot call encode Step*/
701
702 if( 0 != pEncInBuffer.pTableBufferSize[0] )
703 {
704
705 #endif
706
707 /**
708 * Encode the PCM audio */
709
710 err = pC->ShellAPI.pAudioEncoderGlobalFcts->pFctStep(
711 pC->ewc.pAudioEncCtxt,
712 &pEncInBuffer, &pEncOutBuffer);
713
714 if( ( M4NO_ERROR != err) && (M4WAR_NO_MORE_AU != err) )
715 {
716 M4OSA_TRACE1_1(
717 "M4VSS3GPP_intEditStepAudio():\
718 pAudioEncoderGlobalFcts->pFctStep returns 0x%x",
719 err);
720 return err;
721 }
722 #ifdef M4VSS_SUPPORT_OMX_CODECS
723
724 }
725
726 #endif
727
728 /**
729 * Set AU size */
730
731 pC->ewc.WriterAudioAU.size = pEncOutBuffer.pTableBufferSize[
732 0]; /**< Get the size of encoded data */
733 }
734
735 /**
736 * This boolean is only used to fix the BZZ bug... */
737 pC->pC1->bFirstAuWritten = M4OSA_TRUE;
738
739 M4OSA_TRACE2_2("I ---- write : cts = %ld [ 0x%x ]",
740 (M4OSA_Int32)(pC->ewc.WriterAudioAU.CTS / pC->ewc.scale_audio),
741 pC->ewc.WriterAudioAU.size);
742
743 /**
744 * Write the AU */
745 err = pC->ShellAPI.pWriterDataFcts->pProcessAU(
746 pC->ewc.p3gpWriterContext, M4VSS3GPP_WRITER_AUDIO_STREAM_ID,
747 &pC->ewc.WriterAudioAU);
748
749 if( M4NO_ERROR != err )
750 {
751 /*11/12/2008 CR 3283 MMS use case for VideoArtist
752 the warning M4WAR_WRITER_STOP_REQ is returned when the targeted output file
753 size is reached
754 The editing is then finished,
755 the warning M4VSS3GPP_WAR_EDITING_DONE is returned*/
756 if( M4WAR_WRITER_STOP_REQ == err )
757 {
758 M4OSA_TRACE1_0(
759 "M4VSS3GPP_intEditStepAudio: File was cut to avoid oversize");
760 return M4VSS3GPP_WAR_EDITING_DONE;
761 }
762 else
763 {
764 M4OSA_TRACE1_1(
765 "M4VSS3GPP_intEditStepAudio: DECODE_ENCODE:\
766 pWriterDataFcts->pProcessAU returns 0x%x!",
767 err);
768 return err;
769 }
770 }
771
772 /**
773 * Read the next audio frame */
774 err = M4VSS3GPP_intClipReadNextAudioFrame(pC->pC1);
775
776 M4OSA_TRACE2_3("J .... read : cts = %.0f + %.0f [ 0x%x ]",
777 pC->pC1->iAudioFrameCts / pC->pC1->scale_audio,
778 pC->pC1->iAoffset / pC->pC1->scale_audio,
779 pC->pC1->uiAudioFrameSize);
780
781 if( M4OSA_ERR_IS_ERROR(err) )
782 {
783 M4OSA_TRACE1_1(
784 "M4VSS3GPP_intEditStepAudio: DECODE_ENCODE:\
785 M4VSS3GPP_intClipReadNextAudioFrame returns 0x%x!",
786 err);
787 return err;
788 }
789 else
790 {
791 /**
792 * Update current time (to=tc+T) */
793 pC->ewc.dATo = ( pC->pC1->iAudioFrameCts + pC->pC1->iAoffset)
794 / pC->pC1->scale_audio;
795
796 if( ( M4WAR_NO_MORE_AU == err)
797 && (M4OSA_FALSE == pC->bSupportSilence) )
798 {
799 /**
800 * If output is other than AMR or AAC
801 (i.e. EVRC,we can't write silence into it)
802 * So we simply end here.*/
803 bStopAudio = M4OSA_TRUE;
804 }
805 }
806 }
807 break;
808
809 /* _________________ */
810 /*| |*/
811 /*| TRANSITION MODE |*/
812 /*|_________________|*/
813
814 case M4VSS3GPP_kEditAudioState_TRANSITION:
815 {
816 M4OSA_TRACE3_0("M4VSS3GPP_intEditStepAudio TRANSITION");
817
818 /**
819 * Get the output AU to write into */
820 err = pC->ShellAPI.pWriterDataFcts->pStartAU(
821 pC->ewc.p3gpWriterContext, M4VSS3GPP_WRITER_AUDIO_STREAM_ID,
822 &pC->ewc.WriterAudioAU);
823
824 if( M4NO_ERROR != err )
825 {
826 M4OSA_TRACE1_1(
827 "M4VSS3GPP_intEditStepAudio: TRANSITION:\
828 pWriterDataFcts->pStartAU returns 0x%x!",
829 err);
830 return err;
831 }
832
833 /**
834 * If we were reading the clip, we must jump a few AU backward to decode/encode
835 (without writing result) from that point. */
836 if( M4VSS3GPP_kClipStatus_READ == pC->pC1->Astatus )
837 {
838 M4OSA_Int32 iTargetCts, iCurrentCts;
839
840 if( 0
841 != pC->pC1->
842 iAudioFrameCts ) /**<don't try to pre-decode if clip is at its beginning.*/
843 {
844 /**
845 * Jump a few AUs backward */
846 iCurrentCts = pC->pC1->iAudioFrameCts;
847 iTargetCts = iCurrentCts - M4VSS3GPP_NB_AU_PREFETCH
848 * pC->ewc.iSilenceFrameDuration;
849
850 if( iTargetCts < 0 )
851 {
852 iTargetCts = 0; /**< Sanity check */
853 }
854
855 err = M4VSS3GPP_intClipJumpAudioAt(pC->pC1, &iTargetCts);
856
857 if( M4NO_ERROR != err )
858 {
859 M4OSA_TRACE1_1(
860 "M4VSS3GPP_intEditStepAudio: TRANSITION-prefetch:\
861 M4VSS3GPP_intClipJumpAudioAt returns 0x%x!",
862 err);
863 return err;
864 }
865
866 err = M4VSS3GPP_intClipReadNextAudioFrame(
867 pC->pC1); /**< read AU where we jumped */
868
869 M4OSA_TRACE2_3("K .... read : cts = %.0f + %.0f [ 0x%x ]",
870 pC->pC1->iAudioFrameCts / pC->pC1->scale_audio,
871 pC->pC1->iAoffset / pC->pC1->scale_audio,
872 pC->pC1->uiAudioFrameSize);
873
874 if( M4OSA_ERR_IS_ERROR(err) )
875 {
876 M4OSA_TRACE1_1(
877 "M4VSS3GPP_intEditStepAudio: TRANSITION-prefetch:\
878 M4VSS3GPP_intClipReadNextAudioFrame(a) returns 0x%x!",
879 err);
880 return err;
881 }
882
883 /**
884 * Decode/encode up to the wanted position */
885 while( pC->pC1->iAudioFrameCts < iCurrentCts )
886 {
887 err = M4VSS3GPP_intClipDecodeCurrentAudioFrame(pC->pC1);
888
889 if( M4NO_ERROR != err )
890 {
891 M4OSA_TRACE1_1(
892 "M4VSS3GPP_intEditStepAudio: TRANSITION-prefetch:\
893 M4VSS3GPP_intClipDecodeCurrentAudioFrame returns 0x%x!",
894 err);
895 return err;
896 }
897
898 /* [Mono] or [Stereo interleaved] : all is in one buffer */
899 pEncInBuffer.pTableBuffer[0] =
900 pC->pC1->AudioDecBufferOut.m_dataAddress;
901 pEncInBuffer.pTableBufferSize[0] =
902 pC->pC1->AudioDecBufferOut.m_bufferSize;
903 pEncInBuffer.pTableBuffer[1] = M4OSA_NULL;
904 pEncInBuffer.pTableBufferSize[1] = 0;
905
906 /* Time in ms from data size, because it is PCM16 samples */
907 frameTimeDelta =
908 pEncInBuffer.pTableBufferSize[0] / sizeof(short)
909 / pC->ewc.uiNbChannels;
910
911 /**
912 * Prepare output buffer */
913 pEncOutBuffer.pTableBuffer[0] =
914 (M4OSA_MemAddr8)pC->ewc.WriterAudioAU.dataAddress;
915 pEncOutBuffer.pTableBufferSize[0] = 0;
916
917 M4OSA_TRACE2_0("L **** pre-encode");
918 #ifdef M4VSS_SUPPORT_OMX_CODECS
919 /*OMX Audio decoder used.
920 * OMX Audio dec shell does internal buffering and hence does not return
921 a PCM buffer for every decodeStep call.*
922 * So PCM buffer sizes might be 0. In this case donot call encode Step*/
923
924 if( 0 != pEncInBuffer.pTableBufferSize[0] )
925 {
926
927 #endif
928 /**
929 * Encode the PCM audio */
930
931 err =
932 pC->ShellAPI.pAudioEncoderGlobalFcts->pFctStep(
933 pC->ewc.pAudioEncCtxt,
934 &pEncInBuffer, &pEncOutBuffer);
935
936 if( ( M4NO_ERROR != err)
937 && (M4WAR_NO_MORE_AU != err) )
938 {
939 M4OSA_TRACE1_1(
940 "M4VSS3GPP_intEditStepAudio():\
941 pAudioEncoderGlobalFcts->pFctStep returns 0x%x",
942 err);
943 return err;
944 }
945 #ifdef M4VSS_SUPPORT_OMX_CODECS
946
947 }
948
949 #endif
950
951 err = M4VSS3GPP_intClipReadNextAudioFrame(pC->pC1);
952
953 M4OSA_TRACE2_3(
954 "M .... read : cts = %.0f + %.0f [ 0x%x ]",
955 pC->pC1->iAudioFrameCts / pC->pC1->scale_audio,
956 pC->pC1->iAoffset / pC->pC1->scale_audio,
957 pC->pC1->uiAudioFrameSize);
958
959 if( M4OSA_ERR_IS_ERROR(err) )
960 {
961 M4OSA_TRACE1_1(
962 "M4VSS3GPP_intEditStepAudio: TRANSITION-prefetch:\
963 M4VSS3GPP_intClipReadNextAudioFrame(b) returns 0x%x!",
964 err);
965 return err;
966 }
967 }
968 }
969
970 /**
971 * Audio is now OK for decoding */
972 pC->pC1->Astatus = M4VSS3GPP_kClipStatus_DECODE;
973 }
974
975 /**
976 * Decode the first input audio */
977 err = M4VSS3GPP_intClipDecodeCurrentAudioFrame(pC->pC1);
978
979 if( M4NO_ERROR != err )
980 {
981 M4OSA_TRACE1_1(
982 "M4VSS3GPP_intEditStepAudio: TRANSITION:\
983 M4VSS3GPP_intClipDecodeCurrentAudioFrame(C1) returns 0x%x",
984 err);
985 return err;
986 }
987
988 /**
989 * Decode the second input audio */
990 err = M4VSS3GPP_intClipDecodeCurrentAudioFrame(pC->pC2);
991
992 if( M4NO_ERROR != err )
993 {
994 M4OSA_TRACE1_1(
995 "M4VSS3GPP_intEditStepAudio: TRANSITION:\
996 M4VSS3GPP_intClipDecodeCurrentAudioFrame(C2) returns 0x%x",
997 err);
998 return err;
999 }
1000
1001 /**
1002 * Check both clips decoded the same amount of PCM samples */
1003 if( pC->pC1->AudioDecBufferOut.m_bufferSize
1004 != pC->pC2->AudioDecBufferOut.m_bufferSize )
1005 {
1006 M4OSA_TRACE1_2(
1007 "ERR : AudioTransition: both clips AU must have the same decoded\
1008 PCM size! pc1 size=0x%x, pC2 size = 0x%x",
1009 pC->pC1->AudioDecBufferOut.m_bufferSize,
1010 pC->pC2->AudioDecBufferOut.m_bufferSize);
1011 #ifdef M4VSS_SUPPORT_OMX_CODECS
1012 /*OMX Audio decoder used.
1013 * OMX Audio dec shell does internal buffering and hence does not return
1014 a PCM buffer for every decodeStep call.*
1015 * So PCM buffer sizes might be 0 or different for clip1 and clip2.
1016 * So no need to return error in this case */
1017
1018 M4OSA_TRACE1_2(
1019 "M4VSS3GPP_intEditStepAudio: , pc1 AudBuff size=0x%x,\
1020 pC2 AudBuff size = 0x%x",
1021 pC->pC1->AudioDecBufferOut.m_bufferSize,
1022 pC->pC2->AudioDecBufferOut.m_bufferSize);
1023
1024 #else
1025
1026 return M4VSS3GPP_ERR_AUDIO_DECODED_PCM_SIZE_ISSUE;
1027
1028 #endif // M4VSS_SUPPORT_OMX_CODECS
1029
1030 }
1031
1032 /**
1033 * Apply the audio effect on clip1 */
1034 if( pC->iClip1ActiveEffect >= 0 )
1035 {
1036 err = M4VSS3GPP_intApplyAudioEffect(pC, 1, (M4OSA_Int16
1037 *)pC->pC1->AudioDecBufferOut.m_dataAddress,
1038 pC->pC1->AudioDecBufferOut.m_bufferSize);
1039
1040 if( M4NO_ERROR != err )
1041 {
1042 M4OSA_TRACE1_1(
1043 "M4VSS3GPP_intEditStepAudio: TRANSITION:\
1044 M4VSS3GPP_intApplyAudioEffect(C1) returns 0x%x",
1045 err);
1046 return err;
1047 }
1048 }
1049
1050 /**
1051 * Apply the audio effect on clip2 */
1052 if( pC->iClip2ActiveEffect >= 0 )
1053 {
1054 err = M4VSS3GPP_intApplyAudioEffect(pC, 2, (M4OSA_Int16
1055 *)pC->pC2->AudioDecBufferOut.m_dataAddress,
1056 pC->pC2->AudioDecBufferOut.m_bufferSize);
1057
1058 if( M4NO_ERROR != err )
1059 {
1060 M4OSA_TRACE1_1(
1061 "M4VSS3GPP_intEditStepAudio: TRANSITION:\
1062 M4VSS3GPP_intApplyAudioEffect(C2) returns 0x%x",
1063 err);
1064 return err;
1065 }
1066 }
1067
1068 /**
1069 * Apply the transition effect */
1070 err = M4VSS3GPP_intAudioTransition(pC,
1071 (M4OSA_Int16 *)pC->pC1->AudioDecBufferOut.m_dataAddress,
1072 (M4OSA_Int16 *)pC->pC2->AudioDecBufferOut.m_dataAddress,
1073 pC->pC1->AudioDecBufferOut.m_bufferSize);
1074
1075 if( M4NO_ERROR != err )
1076 {
1077 M4OSA_TRACE1_1(
1078 "M4VSS3GPP_intEditStepAudio: TRANSITION:\
1079 M4VSS3GPP_intAudioTransition returns 0x%x",
1080 err);
1081 return err;
1082 }
1083
1084 /* [Mono] or [Stereo interleaved] : all is in one buffer */
1085 pEncInBuffer.pTableBuffer[0] =
1086 pC->pC1->AudioDecBufferOut.m_dataAddress;
1087 pEncInBuffer.pTableBufferSize[0] =
1088 pC->pC1->AudioDecBufferOut.m_bufferSize;
1089 pEncInBuffer.pTableBuffer[1] = M4OSA_NULL;
1090 pEncInBuffer.pTableBufferSize[1] = 0;
1091
1092 /* Time in ms from data size, because it is PCM16 samples */
1093 frameTimeDelta = pEncInBuffer.pTableBufferSize[0] / sizeof(short)
1094 / pC->ewc.uiNbChannels;
1095
1096 /**
1097 * Prepare output buffer */
1098 pEncOutBuffer.pTableBuffer[0] =
1099 (M4OSA_MemAddr8)pC->ewc.WriterAudioAU.dataAddress;
1100 pEncOutBuffer.pTableBufferSize[0] = 0;
1101
1102 M4OSA_TRACE2_0("N **** blend AUs");
1103
1104 #ifdef M4VSS_SUPPORT_OMX_CODECS
1105 /*OMX Audio decoder used.
1106 * OMX Audio dec shell does internal buffering and hence does not return
1107 a PCM buffer for every decodeStep call.*
1108 * So PCM buffer sizes might be 0. In this case donot call encode Step*/
1109
1110 if( 0 != pEncInBuffer.pTableBufferSize[0] )
1111 {
1112
1113 #endif
1114
1115 /**
1116 * Encode the PCM audio */
1117
1118 err = pC->ShellAPI.pAudioEncoderGlobalFcts->pFctStep(
1119 pC->ewc.pAudioEncCtxt, &pEncInBuffer, &pEncOutBuffer);
1120
1121 if( ( M4NO_ERROR != err) && (M4WAR_NO_MORE_AU != err) )
1122 {
1123 M4OSA_TRACE1_1(
1124 "M4VSS3GPP_intEditStepAudio():\
1125 pAudioEncoderGlobalFcts->pFctStep returns 0x%x",
1126 err);
1127 return err;
1128 }
1129 #ifdef M4VSS_SUPPORT_OMX_CODECS
1130
1131 }
1132
1133 #endif
1134
1135 /**
1136 * Set AU cts and size */
1137
1138 pC->ewc.WriterAudioAU.size = pEncOutBuffer.pTableBufferSize[
1139 0]; /**< Get the size of encoded data */
1140 pC->ewc.WriterAudioAU.CTS += frameTimeDelta;
1141
1142 M4OSA_TRACE2_2("O ---- write : cts = %ld [ 0x%x ]",
1143 (M4OSA_Int32)(pC->ewc.WriterAudioAU.CTS / pC->ewc.scale_audio),
1144 pC->ewc.WriterAudioAU.size);
1145
1146 /**
1147 * Write the AU */
1148 err = pC->ShellAPI.pWriterDataFcts->pProcessAU(
1149 pC->ewc.p3gpWriterContext, M4VSS3GPP_WRITER_AUDIO_STREAM_ID,
1150 &pC->ewc.WriterAudioAU);
1151
1152 if( M4NO_ERROR != err )
1153 {
1154 /*11/12/2008 CR 3283 MMS use case for VideoArtist
1155 the warning M4WAR_WRITER_STOP_REQ is returned when the targeted output
1156 file size is reached
1157 The editing is then finished,the warning M4VSS3GPP_WAR_EDITING_DONE
1158 is returned*/
1159 if( M4WAR_WRITER_STOP_REQ == err )
1160 {
1161 M4OSA_TRACE1_0(
1162 "M4VSS3GPP_intEditStepAudio: File was cut to avoid oversize");
1163 return M4VSS3GPP_WAR_EDITING_DONE;
1164 }
1165 else
1166 {
1167 M4OSA_TRACE1_1(
1168 "M4VSS3GPP_intEditStepAudio: TRANSITION:\
1169 pWriterDataFcts->pProcessAU returns 0x%x!",
1170 err);
1171 return err;
1172 }
1173 }
1174
1175 /**
1176 * Read the next audio frame */
1177 err = M4VSS3GPP_intClipReadNextAudioFrame(pC->pC1);
1178
1179 M4OSA_TRACE2_3("P .... read : cts = %.0f + %.0f [ 0x%x ]",
1180 pC->pC1->iAudioFrameCts / pC->pC1->scale_audio,
1181 pC->pC1->iAoffset / pC->pC1->scale_audio,
1182 pC->pC1->uiAudioFrameSize);
1183
1184 if( M4OSA_ERR_IS_ERROR(err) )
1185 {
1186 M4OSA_TRACE1_1(
1187 "M4VSS3GPP_intEditStepAudio: TRANSITION:\
1188 M4VSS3GPP_intClipReadNextAudioFrame(C1) returns 0x%x!",
1189 err);
1190 return err;
1191 }
1192 else
1193 {
1194 M4OSA_ERR secondaryError;
1195
1196 /**
1197 * Update current time (to=tc+T) */
1198 pC->ewc.dATo = ( pC->pC1->iAudioFrameCts + pC->pC1->iAoffset)
1199 / pC->pC1->scale_audio;
1200
1201 /**
1202 * Read the next audio frame in the second clip */
1203 secondaryError = M4VSS3GPP_intClipReadNextAudioFrame(pC->pC2);
1204
1205 M4OSA_TRACE2_3("Q .... read : cts = %.0f + %.0f [ 0x%x ]",
1206 pC->pC2->iAudioFrameCts / pC->pC2->scale_audio,
1207 pC->pC2->iAoffset / pC->pC2->scale_audio,
1208 pC->pC2->uiAudioFrameSize);
1209
1210 if( M4OSA_ERR_IS_ERROR(secondaryError) )
1211 {
1212 M4OSA_TRACE1_1(
1213 "M4VSS3GPP_intEditStepAudio: TRANSITION:\
1214 M4VSS3GPP_intClipReadNextAudioFrame(C2) returns 0x%x!",
1215 secondaryError);
1216 return err;
1217 }
1218
1219 if( ( ( M4WAR_NO_MORE_AU == err)
1220 || (M4WAR_NO_MORE_AU == secondaryError))
1221 && (M4OSA_FALSE == pC->bSupportSilence) )
1222 {
1223 /**
1224 * If output is other than AMR or AAC
1225 (i.e. EVRC,we can't write silence into it)
1226 * So we simply end here.*/
1227 bStopAudio = M4OSA_TRUE;
1228 }
1229 }
1230 }
1231 break;
1232
1233 /* ____________ */
1234 /*| |*/
1235 /*| ERROR CASE |*/
1236 /*|____________|*/
1237
1238 default:
1239
1240 M4OSA_TRACE3_1(
1241 "M4VSS3GPP_intEditStepAudio: invalid internal state (0x%x), \
1242 returning M4VSS3GPP_ERR_INTERNAL_STATE",
1243 pC->Astate);
1244 return M4VSS3GPP_ERR_INTERNAL_STATE;
1245 }
1246
1247 /**
1248 * Check if we are forced to stop audio */
1249 if( M4OSA_TRUE == bStopAudio )
1250 {
1251 /**
1252 * Audio is done for this clip */
1253 err = M4VSS3GPP_intReachedEndOfAudio(pC);
1254
1255 if( M4NO_ERROR != err )
1256 {
1257 M4OSA_TRACE1_1(
1258 "M4VSS3GPP_intEditStepAudio: M4VSS3GPP_intReachedEndOfAudio returns 0x%x",
1259 err);
1260 return err;
1261 }
1262 }
1263
1264 /**
1265 * Return with no error */
1266 M4OSA_TRACE3_0("M4VSS3GPP_intEditStepAudio: returning M4NO_ERROR");
1267 return M4NO_ERROR;
1268 }
1269
1270 /**
1271 ******************************************************************************
1272 * M4OSA_ERR M4VSS3GPP_intCheckAudioMode()
1273 * @brief Check which audio process mode we must use, depending on the output CTS.
1274 * @param pC (IN/OUT) Internal edit context
1275 ******************************************************************************
1276 */
M4VSS3GPP_intCheckAudioMode(M4VSS3GPP_InternalEditContext * pC)1277 static M4OSA_ERR M4VSS3GPP_intCheckAudioMode( M4VSS3GPP_InternalEditContext
1278 *pC )
1279 {
1280 M4OSA_ERR err;
1281 const M4OSA_Int32 TD = pC->pTransitionList[pC->
1282 uiCurrentClip].uiTransitionDuration; /**< Transition duration */
1283
1284 const M4VSS3GPP_EditAudioState previousAstate = pC->Astate;
1285
1286 /**
1287 * Check if Clip1 is on its begin cut, or in its begin effect or end effect zone */
1288 M4VSS3GPP_intCheckAudioEffects(pC, 1);
1289
1290 /**
1291 * Check if we are in the transition with next clip */
1292 if( ( TD > 0) && ((M4OSA_Int32)(pC->ewc.dATo - pC->pC1->iAoffset
1293 / pC->pC1->scale_audio + 0.5) >= (pC->pC1->iEndTime - TD)) )
1294 {
1295 /**
1296 * We are in a transition */
1297 pC->Astate = M4VSS3GPP_kEditAudioState_TRANSITION;
1298 pC->bTransitionEffect = M4OSA_TRUE;
1299
1300 /**
1301 * Do we enter the transition section ? */
1302 if( M4VSS3GPP_kEditAudioState_TRANSITION != previousAstate )
1303 {
1304 /**
1305 * Open second clip for transition, if not yet opened */
1306 if( M4OSA_NULL == pC->pC2 )
1307 {
1308 err = M4VSS3GPP_intOpenClip(pC, &pC->pC2,
1309 &pC->pClipList[pC->uiCurrentClip + 1]);
1310
1311 if( M4NO_ERROR != err )
1312 {
1313 M4OSA_TRACE1_1(
1314 "M4VSS3GPP_intCheckAudioMode: M4VSS3GPP_intOpenClip() returns 0x%x!",
1315 err);
1316 return err;
1317 }
1318
1319 /**
1320 * In case of short transition and bad luck (...), there may be no video AU
1321 * in the transition. In that case, the second clip has not been opened.
1322 * So we must update the video offset here. */
1323 // Decorrelate input and output encoding timestamp to handle encoder prefetch
1324 /**< Add current video output CTS to the clip offset */
1325 pC->pC2->iVoffset += (M4OSA_UInt32)pC->ewc.dInputVidCts;
1326 }
1327
1328 /**
1329 * Add current audio output CTS to the clip offset
1330 * (video offset has already been set when doing the video transition) */
1331 pC->pC2->iAoffset +=
1332 (M4OSA_UInt32)(pC->ewc.dATo * pC->ewc.scale_audio + 0.5);
1333
1334 /**
1335 * 2005-03-24: BugFix for audio-video synchro:
1336 * There may be a portion of the duration of an audio AU of desynchro at each assembly.
1337 * It leads to an audible desynchro when there are a lot of clips assembled.
1338 * This bug fix allows to resynch the audio track when the delta is higher
1339 * than one audio AU duration.
1340 * We Step one AU in the second clip and we change the audio offset accordingly. */
1341 if( ( pC->pC2->iAoffset
1342 - (M4OSA_Int32)(pC->pC2->iVoffset *pC->pC2->scale_audio + 0.5))
1343 > pC->ewc.iSilenceFrameDuration )
1344 {
1345 /**
1346 * Advance one AMR frame */
1347 err = M4VSS3GPP_intClipReadNextAudioFrame(pC->pC2);
1348
1349 M4OSA_TRACE2_3("Z .... read : cts = %.0f + %.0f [ 0x%x ]",
1350 pC->pC2->iAudioFrameCts / pC->pC2->scale_audio,
1351 pC->pC2->iAoffset / pC->pC2->scale_audio,
1352 pC->pC2->uiAudioFrameSize);
1353
1354 if( M4OSA_ERR_IS_ERROR(err) )
1355 {
1356 M4OSA_TRACE1_1(
1357 "M4VSS3GPP_intCheckAudioMode:\
1358 M4VSS3GPP_intClipReadNextAudioFrame returns 0x%x!",
1359 err);
1360 return err;
1361 }
1362 /**
1363 * Update audio offset accordingly*/
1364 pC->pC2->iAoffset -= pC->ewc.iSilenceFrameDuration;
1365 }
1366 }
1367
1368 /**
1369 * Check begin and end effects for clip2 */
1370 M4VSS3GPP_intCheckAudioEffects(pC, 2);
1371 }
1372 else
1373 {
1374 /**
1375 * We are not in a transition */
1376 pC->bTransitionEffect = M4OSA_FALSE;
1377
1378 /**
1379 * Check if current mode is Read/Write or Decode/Encode */
1380 if( pC->iClip1ActiveEffect >= 0 )
1381 {
1382 pC->Astate = M4VSS3GPP_kEditAudioState_DECODE_ENCODE;
1383 }
1384 else
1385 {
1386 pC->Astate = M4VSS3GPP_kEditAudioState_READ_WRITE;
1387 }
1388 }
1389
1390 /**
1391 * Check if we create/destroy an encoder */
1392 if( ( M4VSS3GPP_kEditAudioState_READ_WRITE == previousAstate)
1393 && /**< read mode */
1394 (M4VSS3GPP_kEditAudioState_READ_WRITE != pC->Astate) ) /**< encode mode */
1395 {
1396 M4OSA_UInt32 uiAudioBitrate;
1397
1398 /* Compute max bitrate depending on input files bitrates and transitions */
1399 if( pC->Astate == M4VSS3GPP_kEditAudioState_TRANSITION )
1400 {
1401 /* Max of the two blended files */
1402 if( pC->pC1->pSettings->ClipProperties.uiAudioBitrate
1403 > pC->pC2->pSettings->ClipProperties.uiAudioBitrate )
1404 uiAudioBitrate =
1405 pC->pC1->pSettings->ClipProperties.uiAudioBitrate;
1406 else
1407 uiAudioBitrate =
1408 pC->pC2->pSettings->ClipProperties.uiAudioBitrate;
1409 }
1410 else
1411 {
1412 /* Same as input file */
1413 uiAudioBitrate = pC->pC1->pSettings->ClipProperties.uiAudioBitrate;
1414 }
1415
1416 /**
1417 * Create the encoder */
1418 err = M4VSS3GPP_intCreateAudioEncoder(&pC->ewc, &pC->ShellAPI,
1419 uiAudioBitrate);
1420
1421 if( M4NO_ERROR != err )
1422 {
1423 M4OSA_TRACE1_1(
1424 "M4VSS3GPP_intCheckAudioMode: M4VSS3GPP_intResetAudioEncoder() returns 0x%x!",
1425 err);
1426 return err;
1427 }
1428 }
1429
1430 /**
1431 * Return with no error */
1432 M4OSA_TRACE3_0("M4VSS3GPP_intCheckAudioMode(): returning M4NO_ERROR");
1433 return M4NO_ERROR;
1434 }
1435
1436 /**
1437 ******************************************************************************
1438 * M4OSA_Void M4VSS3GPP_intCheckAudioEffects()
1439 * @brief Check which audio effect must be applied at the current time
1440 ******************************************************************************
1441 */
M4VSS3GPP_intCheckAudioEffects(M4VSS3GPP_InternalEditContext * pC,M4OSA_UInt8 uiClipNumber)1442 static M4OSA_Void M4VSS3GPP_intCheckAudioEffects( M4VSS3GPP_InternalEditContext
1443 *pC, M4OSA_UInt8 uiClipNumber )
1444 {
1445 M4OSA_UInt8 uiClipIndex;
1446 M4OSA_UInt8 uiFxIndex;
1447 M4VSS3GPP_ClipContext *pClip;
1448 M4VSS3GPP_EffectSettings *pFx;
1449 M4OSA_Int32 BC, EC;
1450 M4OSA_Int8 *piClipActiveEffect;
1451 M4OSA_Int32 t;
1452
1453 if( 1 == uiClipNumber )
1454 {
1455 uiClipIndex = pC->uiCurrentClip;
1456 pClip = pC->pC1;
1457 piClipActiveEffect = &(pC->iClip1ActiveEffect);
1458 }
1459 else /**< (2 == uiClipNumber) */
1460 {
1461 uiClipIndex = pC->uiCurrentClip + 1;
1462 pClip = pC->pC2;
1463 piClipActiveEffect = &(pC->iClip2ActiveEffect);
1464 }
1465
1466 /**
1467 * Shortcuts for code readability */
1468 BC = pClip->iActualAudioBeginCut;
1469 EC = pClip->iEndTime;
1470
1471 /**
1472 Change the absolut time to clip related time
1473 RC t = (M4OSA_Int32)(pC->ewc.dATo - pClip->iAoffset/pClip->scale_audio + 0.5);
1474 < rounding */;
1475 t = (M4OSA_Int32)(pC->ewc.dATo/*- pClip->iAoffset/pClip->scale_audio*/
1476 + 0.5); /**< rounding */
1477 ;
1478
1479 /**
1480 * Default: no effect active */
1481 *piClipActiveEffect = -1;
1482
1483 /**
1484 * Check the three effects */
1485 // RC for (uiFxIndex=0; uiFxIndex<pC->pClipList[uiClipIndex].nbEffects; uiFxIndex++)
1486 for ( uiFxIndex = 0; uiFxIndex < pC->nbEffects; uiFxIndex++ )
1487 {
1488 /** Shortcut, reverse order because of priority between effects
1489 ( EndEffect always clean ) */
1490 pFx = &(pC->pEffectsList[pC->nbEffects - 1 - uiFxIndex]);
1491
1492 if( M4VSS3GPP_kAudioEffectType_None != pFx->AudioEffectType )
1493 {
1494 /**
1495 * Check if there is actually a video effect */
1496 if( ( t >= (M4OSA_Int32)(/*BC +*/pFx->uiStartTime))
1497 && /**< Are we after the start time of the effect? */
1498 (t < (M4OSA_Int32)(/*BC +*/pFx->uiStartTime + pFx->
1499 uiDuration)) ) /**< Are we into the effect duration? */
1500 {
1501 /**
1502 * Set the active effect */
1503 *piClipActiveEffect = pC->nbEffects - 1 - uiFxIndex;
1504
1505 /**
1506 * The first effect has the highest priority, then the second one,
1507 then the thirs one.
1508 * Hence, as soon as we found an active effect, we can get out of this loop */
1509 uiFxIndex = pC->nbEffects; /** get out of the for loop */
1510 }
1511 /**
1512 * Bugfix: The duration of the end effect has been set according to the
1513 announced clip duration.
1514 * If the announced duration is smaller than the real one, the end effect
1515 won't be applied at
1516 * the very end of the clip. To solve this issue we force the end effect. */
1517
1518 }
1519 }
1520
1521 return;
1522 }
1523
1524 /**
1525 ******************************************************************************
1526 * M4OSA_ERR M4VSS3GPP_intApplyAudioEffect()
1527 * @brief Apply audio effect to pPCMdata
1528 * @param pC (IN/OUT) Internal edit context
1529 * @param uiClip1orClip2 (IN/OUT) 1 for first clip, 2 for second clip
1530 * @param pPCMdata (IN/OUT) Input and Output PCM audio data
1531 * @param uiPCMsize (IN) Size of pPCMdata
1532 * @return M4NO_ERROR: No error
1533 ******************************************************************************
1534 */
M4VSS3GPP_intApplyAudioEffect(M4VSS3GPP_InternalEditContext * pC,M4OSA_UInt8 uiClip1orClip2,M4OSA_Int16 * pPCMdata,M4OSA_UInt32 uiPCMsize)1535 static M4OSA_ERR M4VSS3GPP_intApplyAudioEffect( M4VSS3GPP_InternalEditContext
1536 *pC, M4OSA_UInt8 uiClip1orClip2,
1537 M4OSA_Int16 *pPCMdata,
1538 M4OSA_UInt32 uiPCMsize )
1539 {
1540 M4VSS3GPP_ClipContext *pClip;
1541 M4VSS3GPP_ClipSettings *pClipSettings;
1542 M4VSS3GPP_EffectSettings *pFx;
1543 M4OSA_Int32
1544 i32sample; /**< we will cast each Int16 sample into this Int32 variable */
1545 M4OSA_Int32 iPos;
1546 M4OSA_Int32 iDur;
1547
1548 M4OSA_DEBUG_IF2(( 1 != uiClip1orClip2) && (2 != uiClip1orClip2),
1549 M4ERR_PARAMETER,
1550 "M4VSS3GPP_intBeginAudioEffect: uiClip1orClip2 invalid");
1551
1552 if( 1 == uiClip1orClip2 )
1553 {
1554 pClip = pC->pC1;
1555 pClipSettings = &(pC->pClipList[pC->
1556 uiCurrentClip]); /**< Get a shortcut to the clip settings */
1557 // RC pFx = &(pClipSettings->Effects[pC->iClip1ActiveEffect]);/**< Get a shortcut
1558 // to the active effect */
1559 pFx = &(pC->
1560 pEffectsList[pC->
1561 iClip1ActiveEffect]); /**< Get a shortcut to the active effect */
1562 M4OSA_DEBUG_IF2(( pC->iClip1ActiveEffect < 0)
1563 || (pC->iClip1ActiveEffect > 2), M4ERR_PARAMETER,
1564 "M4VSS3GPP_intApplyAudioEffect: iClip1ActiveEffect invalid");
1565 }
1566 else /**< if (2==uiClip1orClip2) */
1567 {
1568 pClip = pC->pC2;
1569 pClipSettings = &(pC->pClipList[pC->uiCurrentClip
1570 + 1]); /**< Get a shortcut to the clip settings */
1571 // RC pFx = &(pClipSettings->Effects[pC->iClip2ActiveEffect]);/**< Get a shortcut
1572 // to the active effect */
1573 pFx = &(pC->
1574 pEffectsList[pC->
1575 iClip2ActiveEffect]); /**< Get a shortcut to the active effect */
1576 M4OSA_DEBUG_IF2(( pC->iClip2ActiveEffect < 0)
1577 || (pC->iClip2ActiveEffect > 2), M4ERR_PARAMETER,
1578 "M4VSS3GPP_intApplyAudioEffect: iClip2ActiveEffect invalid");
1579 }
1580
1581 iDur = (M4OSA_Int32)pFx->uiDuration;
1582
1583 /**
1584 * Compute how far from the beginning of the effect we are, in clip-base time.
1585 * It is done with integers because the offset and begin cut have been rounded already. */
1586 iPos =
1587 (M4OSA_Int32)(pC->ewc.dATo + 0.5 - pClip->iAoffset / pClip->scale_audio)
1588 - pClip->iActualAudioBeginCut - pFx->uiStartTime;
1589
1590 /**
1591 * Sanity check */
1592 if( iPos > iDur )
1593 {
1594 iPos = iDur;
1595 }
1596 else if( iPos < 0 )
1597 {
1598 iPos = 0;
1599 }
1600
1601 /**
1602 * At this point, iPos is the effect progress, in a 0 to iDur base */
1603 switch( pFx->AudioEffectType )
1604 {
1605 case M4VSS3GPP_kAudioEffectType_FadeIn:
1606
1607 /**
1608 * Original samples are signed 16bits.
1609 * We convert it to signed 32bits and multiply it by iPos.
1610 * So we must assure that iPos is not higher that 16bits max.
1611 * iPos max value is iDur, so we test iDur. */
1612 while( iDur > PWR_FXP_FRACT_MAX )
1613 {
1614 iDur >>=
1615 2; /**< divide by 2 would be more logical (instead of 4),
1616 but we have enough dynamic..) */
1617 iPos >>= 2; /**< idem */
1618 }
1619
1620 /**
1621 * From buffer size (bytes) to number of sample (int16): divide by two */
1622 uiPCMsize >>= 1;
1623
1624 /**
1625 * Loop on samples */
1626 while( uiPCMsize-- > 0 ) /**< decrementing to optimize */
1627 {
1628 i32sample = *pPCMdata;
1629 i32sample *= iPos;
1630 i32sample /= iDur;
1631 *pPCMdata++ = (M4OSA_Int16)i32sample;
1632 }
1633
1634 break;
1635
1636 case M4VSS3GPP_kAudioEffectType_FadeOut:
1637
1638 /**
1639 * switch from 0->Dur to Dur->0 in order to do fadeOUT instead of fadeIN */
1640 iPos = iDur - iPos;
1641
1642 /**
1643 * Original samples are signed 16bits.
1644 * We convert it to signed 32bits and multiply it by iPos.
1645 * So we must assure that iPos is not higher that 16bits max.
1646 * iPos max value is iDur, so we test iDur. */
1647 while( iDur > PWR_FXP_FRACT_MAX )
1648 {
1649 iDur >>=
1650 2; /**< divide by 2 would be more logical (instead of 4),
1651 but we have enough dynamic..) */
1652 iPos >>= 2; /**< idem */
1653 }
1654
1655 /**
1656 * From buffer size (bytes) to number of sample (int16): divide by two */
1657 uiPCMsize >>= 1;
1658
1659 /**
1660 * Loop on samples, apply the fade factor on each */
1661 while( uiPCMsize-- > 0 ) /**< decrementing counter to optimize */
1662 {
1663 i32sample = *pPCMdata;
1664 i32sample *= iPos;
1665 i32sample /= iDur;
1666 *pPCMdata++ = (M4OSA_Int16)i32sample;
1667 }
1668
1669 break;
1670
1671 default:
1672 M4OSA_TRACE1_1(
1673 "M4VSS3GPP_intApplyAudioEffect: unknown audio effect type (0x%x),\
1674 returning M4VSS3GPP_ERR_INVALID_AUDIO_EFFECT_TYPE",
1675 pFx->AudioEffectType);
1676 return M4VSS3GPP_ERR_INVALID_AUDIO_EFFECT_TYPE;
1677 }
1678
1679 /**
1680 * Return */
1681 M4OSA_TRACE3_0("M4VSS3GPP_intApplyAudioEffect: returning M4NO_ERROR");
1682 return M4NO_ERROR;
1683 }
1684
1685 /**
1686 ******************************************************************************
1687 * M4OSA_ERR M4VSS3GPP_intAudioTransition()
1688 * @brief Apply transition effect to two PCM buffer
1689 * @note The result of the transition is put in the first buffer.
1690 * I know it's not beautiful, but it fits my current needs, and it's efficient!
1691 * So why bother with a third output buffer?
1692 * @param pC (IN/OUT) Internal edit context
1693 * @param pPCMdata1 (IN/OUT) First input and Output PCM audio data
1694 * @param pPCMdata2 (IN) Second input PCM audio data
1695 * @param uiPCMsize (IN) Size of both PCM buffers
1696 * @return M4NO_ERROR: No error
1697 ******************************************************************************
1698 */
M4VSS3GPP_intAudioTransition(M4VSS3GPP_InternalEditContext * pC,M4OSA_Int16 * pPCMdata1,M4OSA_Int16 * pPCMdata2,M4OSA_UInt32 uiPCMsize)1699 static M4OSA_ERR M4VSS3GPP_intAudioTransition( M4VSS3GPP_InternalEditContext
1700 *pC, M4OSA_Int16 *pPCMdata1,
1701 M4OSA_Int16 *pPCMdata2,
1702 M4OSA_UInt32 uiPCMsize )
1703 {
1704 M4OSA_Int32 i32sample1,
1705 i32sample2; /**< we will cast each Int16 sample into this Int32 variable */
1706 M4OSA_Int32 iPos1, iPos2;
1707 M4OSA_Int32 iDur = (M4OSA_Int32)pC->
1708 pTransitionList[pC->uiCurrentClip].uiTransitionDuration;
1709
1710 /**
1711 * Compute how far from the end cut we are, in clip-base time.
1712 * It is done with integers because the offset and begin cut have been rounded already. */
1713 iPos1 = pC->pC1->iEndTime - (M4OSA_Int32)(pC->ewc.dATo
1714 + 0.5 - pC->pC1->iAoffset / pC->pC1->scale_audio);
1715
1716 /**
1717 * Sanity check */
1718 if( iPos1 > iDur )
1719 {
1720 iPos1 = iDur;
1721 }
1722 else if( iPos1 < 0 )
1723 {
1724 iPos1 = 0;
1725 }
1726
1727 /**
1728 * Position of second clip in the transition */
1729 iPos2 = iDur - iPos1;
1730
1731 /**
1732 * At this point, iPos2 is the transition progress, in a 0 to iDur base.
1733 * iPos1 is the transition progress, in a iDUr to 0 base. */
1734 switch( pC->pTransitionList[pC->uiCurrentClip].AudioTransitionType )
1735 {
1736 case M4VSS3GPP_kAudioTransitionType_CrossFade:
1737
1738 /**
1739 * Original samples are signed 16bits.
1740 * We convert it to signed 32bits and multiply it by iPos.
1741 * So we must assure that iPos is not higher that 16bits max.
1742 * iPos max value is iDur, so we test iDur. */
1743 while( iDur > PWR_FXP_FRACT_MAX )
1744 {
1745 iDur >>=
1746 2; /**< divide by 2 would be more logical (instead of 4),
1747 but we have enough dynamic..) */
1748 iPos1 >>= 2; /**< idem */
1749 iPos2 >>= 2; /**< idem */
1750 }
1751
1752 /**
1753 * From buffer size (bytes) to number of sample (int16): divide by two */
1754 uiPCMsize >>= 1;
1755
1756 /**
1757 * Loop on samples, apply the fade factor on each */
1758 while( uiPCMsize-- > 0 ) /**< decrementing counter to optimize */
1759 {
1760 i32sample1 = *pPCMdata1; /**< Get clip1 sample */
1761 i32sample1 *= iPos1; /**< multiply by fade numerator */
1762 i32sample1 /= iDur; /**< divide by fade denominator */
1763
1764 i32sample2 = *pPCMdata2; /**< Get clip2 sample */
1765 i32sample2 *= iPos2; /**< multiply by fade numerator */
1766 i32sample2 /= iDur; /**< divide by fade denominator */
1767
1768 *pPCMdata1++ = (M4OSA_Int16)(i32sample1
1769 + i32sample2); /**< mix the two samples */
1770 pPCMdata2++; /**< don't forget to increment the second buffer */
1771 }
1772 break;
1773
1774 case M4VSS3GPP_kAudioTransitionType_None:
1775 /**
1776 * This is a stupid-non optimized version of the None transition...
1777 * We copy the PCM frames */
1778 if( iPos1 < (iDur >> 1) ) /**< second half of transition */
1779 {
1780 /**
1781 * Copy the input PCM to the output buffer */
1782 memcpy((void *)pPCMdata1,
1783 (void *)pPCMdata2, uiPCMsize);
1784 }
1785 /**
1786 * the output must be put in the first buffer.
1787 * For the first half of the non-transition it's already the case!
1788 * So we have nothing to do here...
1789 */
1790
1791 break;
1792
1793 default:
1794 M4OSA_TRACE1_1(
1795 "M4VSS3GPP_intAudioTransition: unknown transition type (0x%x),\
1796 returning M4VSS3GPP_ERR_INVALID_AUDIO_TRANSITION_TYPE",
1797 pC->pTransitionList[pC->uiCurrentClip].AudioTransitionType);
1798 return M4VSS3GPP_ERR_INVALID_AUDIO_TRANSITION_TYPE;
1799 }
1800
1801 /**
1802 * Return */
1803 M4OSA_TRACE3_0("M4VSS3GPP_intAudioTransition: returning M4NO_ERROR");
1804 return M4NO_ERROR;
1805 }
1806
1807 /**
1808 ******************************************************************************
1809 * M4OSA_ERR M4VSS3GPP_intCreateAudioEncoder()
1810 * @brief Reset the audio encoder (Create it if needed)
1811 * @note
1812 ******************************************************************************
1813 */
M4VSS3GPP_intCreateAudioEncoder(M4VSS3GPP_EncodeWriteContext * pC_ewc,M4VSS3GPP_MediaAndCodecCtxt * pC_ShellAPI,M4OSA_UInt32 uiAudioBitrate)1814 M4OSA_ERR M4VSS3GPP_intCreateAudioEncoder( M4VSS3GPP_EncodeWriteContext *pC_ewc,
1815 M4VSS3GPP_MediaAndCodecCtxt *pC_ShellAPI,
1816 M4OSA_UInt32 uiAudioBitrate )
1817 {
1818 M4OSA_ERR err;
1819
1820 /**
1821 * If an encoder already exist, we destroy it */
1822 if( M4OSA_NULL != pC_ewc->pAudioEncCtxt )
1823 {
1824 err = pC_ShellAPI->pAudioEncoderGlobalFcts->pFctClose(
1825 pC_ewc->pAudioEncCtxt);
1826
1827 if( M4NO_ERROR != err )
1828 {
1829 M4OSA_TRACE1_1(
1830 "M4VSS3GPP_intResetAudioEncoder: pAudioEncoderGlobalFcts->pFctClose returns 0x%x",
1831 err);
1832 /**< don't return, we still have stuff to free */
1833 }
1834
1835 err = pC_ShellAPI->pAudioEncoderGlobalFcts->pFctCleanUp(
1836 pC_ewc->pAudioEncCtxt);
1837
1838 if( M4NO_ERROR != err )
1839 {
1840 M4OSA_TRACE1_1(
1841 "M4VSS3GPP_intResetAudioEncoder:\
1842 pAudioEncoderGlobalFcts->pFctCleanUp returns 0x%x", err);
1843 /**< don't return, we still have stuff to free */
1844 }
1845
1846 pC_ewc->pAudioEncCtxt = M4OSA_NULL;
1847 }
1848
1849 /**
1850 * Creates a new encoder */
1851 switch( pC_ewc->AudioStreamType )
1852 {
1853 //EVRC
1854 // case M4SYS_kEVRC:
1855 //
1856 // err = M4VSS3GPP_setCurrentAudioEncoder(&pC->ShellAPI,
1857 // pC_ewc->AudioStreamType);
1858 // M4ERR_CHECK_RETURN(err);
1859 //
1860 // pC_ewc->AudioEncParams.Format = M4ENCODER_kEVRC;
1861 // pC_ewc->AudioEncParams.Frequency = M4ENCODER_k8000Hz;
1862 // pC_ewc->AudioEncParams.ChannelNum = M4ENCODER_kMono;
1863 // pC_ewc->AudioEncParams.Bitrate = M4VSS3GPP_EVRC_DEFAULT_BITRATE;
1864 // break;
1865
1866 case M4SYS_kAMR:
1867
1868 err = M4VSS3GPP_setCurrentAudioEncoder(pC_ShellAPI,
1869 pC_ewc->AudioStreamType);
1870 M4ERR_CHECK_RETURN(err);
1871
1872 pC_ewc->AudioEncParams.Format = M4ENCODER_kAMRNB;
1873 pC_ewc->AudioEncParams.Frequency = M4ENCODER_k8000Hz;
1874 pC_ewc->AudioEncParams.ChannelNum = M4ENCODER_kMono;
1875 pC_ewc->AudioEncParams.Bitrate = M4VSS3GPP_AMR_DEFAULT_BITRATE;
1876 pC_ewc->AudioEncParams.SpecifParam.AmrSID = M4ENCODER_kAmrNoSID;
1877 break;
1878
1879 case M4SYS_kAAC:
1880
1881 err = M4VSS3GPP_setCurrentAudioEncoder(pC_ShellAPI,
1882 pC_ewc->AudioStreamType);
1883 M4ERR_CHECK_RETURN(err);
1884
1885 pC_ewc->AudioEncParams.Format = M4ENCODER_kAAC;
1886
1887 switch( pC_ewc->uiSamplingFrequency )
1888 {
1889 case 8000:
1890 pC_ewc->AudioEncParams.Frequency = M4ENCODER_k8000Hz;
1891 break;
1892
1893 case 16000:
1894 pC_ewc->AudioEncParams.Frequency = M4ENCODER_k16000Hz;
1895 break;
1896
1897 case 22050:
1898 pC_ewc->AudioEncParams.Frequency = M4ENCODER_k22050Hz;
1899 break;
1900
1901 case 24000:
1902 pC_ewc->AudioEncParams.Frequency = M4ENCODER_k24000Hz;
1903 break;
1904
1905 case 32000:
1906 pC_ewc->AudioEncParams.Frequency = M4ENCODER_k32000Hz;
1907 break;
1908
1909 case 44100:
1910 pC_ewc->AudioEncParams.Frequency = M4ENCODER_k44100Hz;
1911 break;
1912
1913 case 48000:
1914 pC_ewc->AudioEncParams.Frequency = M4ENCODER_k48000Hz;
1915 break;
1916
1917 default:
1918 M4OSA_TRACE1_1(
1919 "M4VSS3GPP_intCreateAudioEncoder: invalid input AAC sampling frequency\
1920 (%d Hz), returning M4VSS3GPP_ERR_AUDIO_DECODER_INIT_FAILED",
1921 pC_ewc->uiSamplingFrequency);
1922 return M4VSS3GPP_ERR_AUDIO_DECODER_INIT_FAILED;
1923 }
1924 pC_ewc->AudioEncParams.ChannelNum = (pC_ewc->uiNbChannels == 1)
1925 ? M4ENCODER_kMono : M4ENCODER_kStereo;
1926 pC_ewc->AudioEncParams.SpecifParam.AacParam.Regulation =
1927 M4ENCODER_kAacRegulNone; //M4ENCODER_kAacBitReservoir
1928 /* unused */
1929 pC_ewc->AudioEncParams.SpecifParam.AacParam.bIS = M4OSA_FALSE;
1930 pC_ewc->AudioEncParams.SpecifParam.AacParam.bMS = M4OSA_FALSE;
1931 pC_ewc->AudioEncParams.SpecifParam.AacParam.bPNS = M4OSA_FALSE;
1932 pC_ewc->AudioEncParams.SpecifParam.AacParam.bTNS = M4OSA_FALSE;
1933 /* TODO change into highspeed asap */
1934 pC_ewc->AudioEncParams.SpecifParam.AacParam.bHighSpeed =
1935 M4OSA_FALSE;
1936
1937 /* Quantify value (ceil one) */
1938 if( uiAudioBitrate <= 16000 )
1939 pC_ewc->AudioEncParams.Bitrate = 16000;
1940
1941 else if( uiAudioBitrate <= 24000 )
1942 pC_ewc->AudioEncParams.Bitrate = 24000;
1943
1944 else if( uiAudioBitrate <= 32000 )
1945 pC_ewc->AudioEncParams.Bitrate = 32000;
1946
1947 else if( uiAudioBitrate <= 48000 )
1948 pC_ewc->AudioEncParams.Bitrate = 48000;
1949
1950 else if( uiAudioBitrate <= 64000 )
1951 pC_ewc->AudioEncParams.Bitrate = 64000;
1952
1953 else
1954 pC_ewc->AudioEncParams.Bitrate = 96000;
1955
1956 /* Special requirement of our encoder */
1957 if( ( pC_ewc->uiNbChannels == 2)
1958 && (pC_ewc->AudioEncParams.Bitrate < 32000) )
1959 pC_ewc->AudioEncParams.Bitrate = 32000;
1960
1961 break;
1962
1963 default:
1964 M4OSA_TRACE1_1(
1965 "M4VSS3GPP_intResetAudioEncoder: Undefined output audio format (%d),\
1966 returning M4VSS3GPP_ERR_EDITING_UNSUPPORTED_AUDIO_FORMAT",
1967 pC_ewc->AudioStreamType);
1968 return M4VSS3GPP_ERR_EDITING_UNSUPPORTED_AUDIO_FORMAT;
1969 }
1970
1971 /* Initialise the audio encoder */
1972 #ifdef M4VSS_SUPPORT_OMX_CODECS
1973
1974 M4OSA_TRACE3_1(
1975 "M4VSS3GPP_intResetAudioEncoder:\
1976 pAudioEncoderGlobalFcts->pFctInit called with userdata 0x%x",
1977 pC_ShellAPI->pCurrentAudioEncoderUserData);
1978 err = pC_ShellAPI->pAudioEncoderGlobalFcts->pFctInit(&pC_ewc->pAudioEncCtxt,
1979 pC_ShellAPI->pCurrentAudioEncoderUserData);
1980
1981 #else
1982
1983 err = pC_ShellAPI->pAudioEncoderGlobalFcts->pFctInit(&pC_ewc->pAudioEncCtxt,
1984 M4OSA_NULL /* no HW encoder */);
1985
1986 #endif
1987
1988 if( M4NO_ERROR != err )
1989 {
1990 M4OSA_TRACE1_1(
1991 "M4VSS3GPP_intResetAudioEncoder: pAudioEncoderGlobalFcts->pFctInit returns 0x%x",
1992 err);
1993 return err;
1994 }
1995
1996 /* Open the audio encoder */
1997 err = pC_ShellAPI->pAudioEncoderGlobalFcts->pFctOpen(pC_ewc->pAudioEncCtxt,
1998 &pC_ewc->AudioEncParams, &pC_ewc->pAudioEncDSI,
1999 M4OSA_NULL /* no grabbing */);
2000
2001 if( M4NO_ERROR != err )
2002 {
2003 M4OSA_TRACE1_1(
2004 "M4VSS3GPP_intResetAudioEncoder: pAudioEncoderGlobalFcts->pFctOpen returns 0x%x",
2005 err);
2006 return err;
2007 }
2008
2009 /**
2010 * Return with no error */
2011 M4OSA_TRACE3_0("M4VSS3GPP_intResetAudioEncoder: returning M4NO_ERROR");
2012 return M4NO_ERROR;
2013 }
2014