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