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