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