M4VSS3GPP_AudioMixing.c revision 7c9d8018755adf1857571125ba1b3598c96ea506
1/* 2 * Copyright (C) 2004-2011 NXP Software 3 * Copyright (C) 2011 The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17/** 18 ****************************************************************************** 19 * @file M4VSS3GPP_AudioMixing.c 20 * @brief Video Studio Service 3GPP audio mixing implementation. 21 * @note 22 ****************************************************************************** 23 */ 24 25/****************/ 26/*** Includes ***/ 27/****************/ 28 29#include "NXPSW_CompilerSwitches.h" 30/** 31 * Our headers */ 32#include "M4VSS3GPP_API.h" 33#include "M4VSS3GPP_InternalTypes.h" 34#include "M4VSS3GPP_InternalFunctions.h" 35#include "M4VSS3GPP_ErrorCodes.h" 36 37/* Put the definition of silence frames here */ 38#define M4VSS3GPP_SILENCE_FRAMES 39#include "M4VSS3GPP_InternalConfig.h" 40 41/** 42 * OSAL headers */ 43#include "M4OSA_Memory.h" /**< OSAL memory management */ 44#include "M4OSA_Debug.h" /**< OSAL debug management */ 45 46 47#include "gLVAudioResampler.h" 48/** 49 ****************************************************************************** 50 * @brief Static functions 51 ****************************************************************************** 52 */ 53static M4OSA_ERR 54M4VSS3GPP_intAudioMixingOpen( M4VSS3GPP_InternalAudioMixingContext *pC, 55 M4VSS3GPP_AudioMixingSettings *pSettings ); 56static M4OSA_ERR M4VSS3GPP_intAudioMixingStepVideo( 57 M4VSS3GPP_InternalAudioMixingContext *pC ); 58static M4OSA_ERR M4VSS3GPP_intAudioMixingStepAudioMix( 59 M4VSS3GPP_InternalAudioMixingContext *pC ); 60static M4OSA_ERR M4VSS3GPP_intAudioMixingStepAudioReplace( 61 M4VSS3GPP_InternalAudioMixingContext *pC ); 62static M4OSA_ERR M4VSS3GPP_intAudioMixingCopyOrig( 63 M4VSS3GPP_InternalAudioMixingContext *pC ); 64static M4OSA_ERR M4VSS3GPP_intAudioMixingCopyAdded( 65 M4VSS3GPP_InternalAudioMixingContext *pC ); 66static M4OSA_ERR M4VSS3GPP_intAudioMixingConvert( 67 M4VSS3GPP_InternalAudioMixingContext *pC ); 68static M4OSA_ERR M4VSS3GPP_intAudioMixingDoMixing( 69 M4VSS3GPP_InternalAudioMixingContext *pC ); 70static M4OSA_ERR M4VSS3GPP_intAudioMixingWriteSilence( 71 M4VSS3GPP_InternalAudioMixingContext *pC ); 72static M4OSA_ERR M4VSS3GPP_intAudioMixingTransition( 73 M4VSS3GPP_InternalAudioMixingContext *pC ); 74static M4OSA_ERR M4VSS3GPP_intAudioMixingCreateVideoEncoder( 75 M4VSS3GPP_InternalAudioMixingContext *pC ); 76static M4OSA_ERR M4VSS3GPP_intAudioMixingDestroyVideoEncoder( 77 M4VSS3GPP_InternalAudioMixingContext *pC ); 78static M4OSA_Bool M4VSS3GPP_isThresholdBreached( M4OSA_Int32 *averageValue, 79 M4OSA_Int32 storeCount, 80 M4OSA_Int32 thresholdValue ); 81/** 82 * Internal warning */ 83#define M4VSS3GPP_WAR_END_OF_ADDED_AUDIO M4OSA_ERR_CREATE( M4_WAR, M4VSS3GPP, 0x0030) 84 85/* A define used with SSRC 1.04 and above to avoid taking 86blocks smaller that the minimal block size */ 87#define M4VSS_SSRC_MINBLOCKSIZE 600 88 89/** 90 ****************************************************************************** 91 * M4OSA_ERR M4VSS3GPP_audioMixingInit(M4VSS3GPP_AudioMixingContext* pContext, 92 * M4VSS3GPP_AudioMixingSettings* pSettings) 93 * @brief Initializes the VSS audio mixing operation (allocates an execution context). 94 * @note 95 * @param pContext (OUT) Pointer on the VSS audio mixing context to allocate 96 * @param pSettings (IN) Pointer to valid audio mixing settings 97 * @param pFileReadPtrFct (IN) Pointer to OSAL file reader functions 98 * @param pFileWritePtrFct (IN) Pointer to OSAL file writer functions 99 * @return M4NO_ERROR: No error 100 * @return M4ERR_PARAMETER: At least one parameter is M4OSA_NULL (debug only) 101 * @return M4ERR_ALLOC: There is no more available memory 102 ****************************************************************************** 103 */ 104 105M4OSA_ERR M4VSS3GPP_audioMixingInit( M4VSS3GPP_AudioMixingContext *pContext, 106 M4VSS3GPP_AudioMixingSettings *pSettings, 107 M4OSA_FileReadPointer *pFileReadPtrFct, 108 M4OSA_FileWriterPointer *pFileWritePtrFct ) 109{ 110 M4VSS3GPP_InternalAudioMixingContext *pC; 111 M4OSA_ERR err; 112 113 M4OSA_TRACE3_2( 114 "M4VSS3GPP_audioMixingInit called with pContext=0x%x, pSettings=0x%x", 115 pContext, pSettings); 116 117 /** 118 * Check input parameters */ 119 M4OSA_DEBUG_IF2((M4OSA_NULL == pContext), M4ERR_PARAMETER, 120 "M4VSS3GPP_audioMixingInit: pContext is M4OSA_NULL"); 121 M4OSA_DEBUG_IF2((M4OSA_NULL == pSettings), M4ERR_PARAMETER, 122 "M4VSS3GPP_audioMixingInit: pSettings is M4OSA_NULL"); 123 M4OSA_DEBUG_IF2((M4OSA_NULL == pFileReadPtrFct), M4ERR_PARAMETER, 124 "M4VSS3GPP_audioMixingInit: pFileReadPtrFct is M4OSA_NULL"); 125 M4OSA_DEBUG_IF2((M4OSA_NULL == pFileWritePtrFct), M4ERR_PARAMETER, 126 "M4VSS3GPP_audioMixingInit: pFileWritePtrFct is M4OSA_NULL"); 127 128 if( pSettings->uiBeginLoop > pSettings->uiEndLoop ) 129 { 130 M4OSA_TRACE1_0( 131 "M4VSS3GPP_audioMixingInit: Begin loop time is higher than end loop time!"); 132 return M4VSS3GPP_ERR_BEGINLOOP_HIGHER_ENDLOOP; 133 } 134 135 /** 136 * Allocate the VSS audio mixing context and return it to the user */ 137 pC = (M4VSS3GPP_InternalAudioMixingContext 138 *)M4OSA_malloc(sizeof(M4VSS3GPP_InternalAudioMixingContext), 139 M4VSS3GPP,(M4OSA_Char *)"M4VSS3GPP_InternalAudioMixingContext"); 140 *pContext = pC; 141 142 if( M4OSA_NULL == pC ) 143 { 144 M4OSA_TRACE1_0( 145 "M4VSS3GPP_audioMixingInit(): unable to allocate \ 146 M4VSS3GPP_InternalAudioMixingContext,returning M4ERR_ALLOC"); 147 return M4ERR_ALLOC; 148 } 149 150 /* Initialization of context Variables */ 151 M4OSA_memset((M4OSA_MemAddr8)pC , 152 sizeof(M4VSS3GPP_InternalAudioMixingContext),0); 153 /** 154 * Copy this setting in context */ 155 pC->iAddCts = pSettings->uiAddCts; 156 pC->bRemoveOriginal = pSettings->bRemoveOriginal; 157 pC->b_DuckingNeedeed = pSettings->b_DuckingNeedeed; 158 pC->InDucking_threshold = pSettings->InDucking_threshold; 159 pC->fBTVolLevel = pSettings->fBTVolLevel; 160 pC->fPTVolLevel = pSettings->fPTVolLevel; 161 pC->InDucking_lowVolume = pSettings->InDucking_lowVolume; 162 pC->bDoDucking = M4OSA_FALSE; 163 pC->bLoop = pSettings->bLoop; 164 pC->bNoLooping = M4OSA_FALSE; 165 pC->bjumpflag = M4OSA_TRUE; 166 /** 167 * Init some context variables */ 168 169 pC->pInputClipCtxt = M4OSA_NULL; 170 pC->pAddedClipCtxt = M4OSA_NULL; 171 pC->fOrigFactor = 1.0F; 172 pC->fAddedFactor = 0.0F; 173 pC->bSupportSilence = M4OSA_FALSE; 174 pC->bHasAudio = M4OSA_FALSE; 175 pC->bAudioMixingIsNeeded = M4OSA_FALSE; 176 177 /* Init PC->ewc members */ 178 // Decorrelate input and output encoding timestamp to handle encoder prefetch 179 pC->ewc.VideoStreamType = M4SYS_kVideoUnknown; 180 pC->ewc.bVideoDataPartitioning = M4OSA_FALSE; 181 pC->ewc.pVideoOutputDsi = M4OSA_NULL; 182 pC->ewc.bActivateEmp = M4OSA_FALSE; 183 pC->ewc.AudioStreamType = M4SYS_kAudioUnknown; 184 pC->ewc.uiNbChannels = 1; 185 pC->ewc.pAudioOutputDsi = M4OSA_NULL; 186 pC->ewc.pAudioEncCtxt = M4OSA_NULL; 187 pC->ewc.pAudioEncDSI.pInfo = M4OSA_NULL; 188 pC->ewc.pSilenceFrameData = M4OSA_NULL; 189 pC->ewc.pEncContext = M4OSA_NULL; 190 pC->ewc.pDummyAuBuffer = M4OSA_NULL; 191 pC->ewc.p3gpWriterContext = M4OSA_NULL; 192 /** 193 * Set the OSAL filesystem function set */ 194 pC->pOsaFileReadPtr = pFileReadPtrFct; 195 pC->pOsaFileWritPtr = pFileWritePtrFct; 196 197 /** 198 * Ssrc stuff */ 199 pC->b_SSRCneeded = M4OSA_FALSE; 200 pC->pSsrcBufferIn = M4OSA_NULL; 201 pC->pSsrcBufferOut = M4OSA_NULL; 202 pC->pTempBuffer = M4OSA_NULL; 203 pC->pPosInTempBuffer = M4OSA_NULL; 204 pC->pPosInSsrcBufferIn = M4OSA_NULL; 205 pC->pPosInSsrcBufferOut = M4OSA_NULL; 206 pC->SsrcScratch = M4OSA_NULL; 207 pC->uiBeginLoop = pSettings->uiBeginLoop; 208 pC->uiEndLoop = pSettings->uiEndLoop; 209 210 /* 211 * Reset pointers for media and codecs interfaces */ 212 err = M4VSS3GPP_clearInterfaceTables(&pC->ShellAPI); 213 M4ERR_CHECK_RETURN(err); 214 215 /* Call the media and codecs subscription module */ 216 err = M4VSS3GPP_subscribeMediaAndCodec(&pC->ShellAPI); 217 M4ERR_CHECK_RETURN(err); 218 219 /** 220 * Open input clip, added clip and output clip and proceed with the settings */ 221 err = M4VSS3GPP_intAudioMixingOpen(pC, pSettings); 222 M4ERR_CHECK_RETURN(err); 223 224 /** 225 * Update main state automaton */ 226 if( M4OSA_NULL != pC->pInputClipCtxt->pVideoStream ) 227 pC->State = M4VSS3GPP_kAudioMixingState_VIDEO; 228 else 229 pC->State = M4VSS3GPP_kAudioMixingState_AUDIO_FIRST_SEGMENT; 230 231 pC->ewc.iOutputDuration = (M4OSA_Int32)pC->pInputClipCtxt->pSettings-> 232 ClipProperties.uiClipDuration; 233 /*gInputParams.lvBTChannelCount*/ 234 pC->pLVAudioResampler = (M4OSA_Int32)LVAudioResamplerCreate(16, 235 pC->pAddedClipCtxt->pSettings->ClipProperties.uiNbChannels, 236 /* gInputParams.lvOutSampleRate*/pSettings->outputASF, 1); 237 LVAudiosetSampleRate(pC->pLVAudioResampler, 238 /*gInputParams.lvInSampleRate*/ 239 pC->pAddedClipCtxt->pSettings->ClipProperties.uiSamplingFrequency); 240 241 LVAudiosetVolume(pC->pLVAudioResampler, 242 (M4OSA_Int16)(0x1000 ), 243 (M4OSA_Int16)(0x1000 )); 244 245 /** 246 * Return with no error */ 247 M4OSA_TRACE3_0("M4VSS3GPP_audioMixingInit(): returning M4NO_ERROR"); 248 return M4NO_ERROR; 249} 250 251/** 252 ****************************************************************************** 253 * M4OSA_ERR M4VSS3GPP_audioMixingStep(M4VSS3GPP_AudioMixingContext pContext) 254 * @brief Perform one step of audio mixing. 255 * @note 256 * @param pContext (IN) VSS audio mixing context 257 * @return M4NO_ERROR: No error 258 * @return M4ERR_PARAMETER: pContext is M4OSA_NULL (debug only) 259 * @param pProgress (OUT) Progress percentage (0 to 100) of the finalization operation 260 * @return M4ERR_STATE: VSS is not in an appropriate state for this function to be called 261 * @return M4VSS3GPP_WAR_END_OF_AUDIO_MIXING: Audio mixing is over, user should now call 262 * M4VSS3GPP_audioMixingCleanUp() 263 ****************************************************************************** 264 */ 265M4OSA_ERR M4VSS3GPP_audioMixingStep( M4VSS3GPP_AudioMixingContext pContext, 266 M4OSA_UInt8 *pProgress ) 267{ 268 M4OSA_ERR err; 269 M4VSS3GPP_InternalAudioMixingContext *pC = 270 (M4VSS3GPP_InternalAudioMixingContext *)pContext; 271 272 M4OSA_TRACE3_1("M4VSS3GPP_audioMixingStep called with pContext=0x%x", 273 pContext); 274 275 /** 276 * Check input parameters */ 277 M4OSA_DEBUG_IF2((M4OSA_NULL == pContext), M4ERR_PARAMETER, 278 "M4VSS3GPP_audioMixingStep: pContext is M4OSA_NULL"); 279 280 /** 281 * State automaton */ 282 switch( pC->State ) 283 { 284 case M4VSS3GPP_kAudioMixingState_VIDEO: 285 err = M4VSS3GPP_intAudioMixingStepVideo(pC); 286 287 /** 288 * Compute the progress percentage 289 * Note: audio and video CTS are not initialized before 290 * the call of M4VSS3GPP_intAudioMixingStepVideo */ 291 292 /* P4ME00003276: First 0-50% segment is dedicated to state : 293 M4VSS3GPP_kAudioMixingState_VIDEO */ 294 *pProgress = (M4OSA_UInt8)(50 * (pC->ewc.WriterVideoAU.CTS) 295 / pC->pInputClipCtxt->pVideoStream-> 296 m_basicProperties.m_duration); 297 298 /** 299 * There may be no audio track (Remove audio track feature). 300 * In that case we double the current percentage */ 301 if( M4SYS_kAudioUnknown == pC->ewc.WriterAudioStream.streamType ) 302 { 303 ( *pProgress) <<= 1; /**< x2 */ 304 } 305 else if( *pProgress >= 50 ) 306 { 307 *pProgress = 308 49; /**< Video processing is not greater than 50% */ 309 } 310 311 if( M4WAR_NO_MORE_AU == err ) 312 { 313 if( pC->bHasAudio ) 314 { 315 /** 316 * Video is over, state transition to audio and return OK */ 317 if( pC->iAddCts > 0 ) 318 pC->State = 319 M4VSS3GPP_kAudioMixingState_AUDIO_FIRST_SEGMENT; 320 else 321 pC->State = 322 M4VSS3GPP_kAudioMixingState_AUDIO_SECOND_SEGMENT; 323 } 324 else 325 { 326 /** 327 * No audio, state transition to FINISHED */ 328 pC->State = M4VSS3GPP_kAudioMixingState_FINISHED; 329 } 330 331 return M4NO_ERROR; 332 } 333 else if( M4NO_ERROR != err ) 334 { 335 M4OSA_TRACE1_1( 336 "M4VSS3GPP_audioMixingStep: M4VSS3GPP_intAudioMixingStepVideo returns 0x%x!", 337 err); 338 return err; 339 } 340 else 341 { 342 return M4NO_ERROR; 343 } 344 break; 345 346 case M4VSS3GPP_kAudioMixingState_AUDIO_FIRST_SEGMENT: 347 case M4VSS3GPP_kAudioMixingState_AUDIO_SECOND_SEGMENT: 348 case M4VSS3GPP_kAudioMixingState_AUDIO_THIRD_SEGMENT: 349 if( pC->pAddedClipCtxt->iAudioFrameCts 350 != -pC->pAddedClipCtxt->iSilenceFrameDuration 351 && (pC->pAddedClipCtxt->iAudioFrameCts - 0.5) 352 / pC->pAddedClipCtxt->scale_audio > pC->uiEndLoop 353 && pC->uiEndLoop > 0 ) 354 { 355 if(pC->bLoop == M4OSA_FALSE) 356 { 357 pC->bNoLooping = M4OSA_TRUE; 358 } 359 else 360 { 361 M4OSA_Int32 jumpCTS = (M4OSA_Int32)(pC->uiBeginLoop); 362 363 err = pC->pAddedClipCtxt->ShellAPI.m_pReader->m_pFctJump( 364 pC->pAddedClipCtxt->pReaderContext, 365 (M4_StreamHandler *)pC->pAddedClipCtxt-> 366 pAudioStream, &jumpCTS); 367 368 if( err != M4NO_ERROR ) 369 { 370 M4OSA_TRACE1_1( 371 "M4VSS3GPP_audioMixingStep: error when jumping in added audio clip: 0x%x", 372 err); 373 return err; 374 } 375 /** 376 * Use offset to give a correct CTS ... */ 377 pC->pAddedClipCtxt->iAoffset = 378 (M4OSA_Int32)(pC->ewc.dATo * pC->ewc.scale_audio + 0.5); 379 } 380 381 } 382 383 if( M4OSA_FALSE == pC->bRemoveOriginal ) 384 { 385 err = M4VSS3GPP_intAudioMixingStepAudioMix(pC); 386 } 387 else 388 { 389 err = M4VSS3GPP_intAudioMixingStepAudioReplace(pC); 390 } 391 392 /** 393 * Compute the progress percentage 394 * Note: audio and video CTS are not initialized before 395 * the call of M4VSS3GPP_intAudioMixingStepAudio */ 396 if( 0 != pC->ewc.iOutputDuration ) 397 { 398 /* P4ME00003276: Second 50-100% segment is dedicated to states : 399 M4VSS3GPP_kAudioMixingState_AUDIO... */ 400 /* For Audio the progress computation is based on dAto and offset, 401 it is more accurate */ 402 *pProgress = (M4OSA_UInt8)(50 403 + (50 * pC->ewc.dATo - pC->pInputClipCtxt->iVoffset) 404 / (pC->ewc.iOutputDuration)); /**< 50 for 100/2 **/ 405 406 if( *pProgress >= 100 ) 407 { 408 *pProgress = 409 99; /**< It's not really finished, I prefer to return less than 100% */ 410 } 411 } 412 else 413 { 414 *pProgress = 99; 415 } 416 417 if( M4WAR_NO_MORE_AU == err ) 418 { 419 /** 420 * Audio is over, state transition to FINISHED */ 421 pC->State = M4VSS3GPP_kAudioMixingState_FINISHED; 422 return M4NO_ERROR; 423 } 424 else if( M4NO_ERROR != err ) 425 { 426 M4OSA_TRACE1_1( 427 "M4VSS3GPP_audioMixingStep: M4VSS3GPP_intAudioMixingStepAudio returns 0x%x!", 428 err); 429 return err; 430 } 431 else 432 { 433 return M4NO_ERROR; 434 } 435 break; 436 437 case M4VSS3GPP_kAudioMixingState_FINISHED: 438 439 /** 440 * Progress percentage: finalize finished -> 100% */ 441 *pProgress = 100; 442 443 /** 444 * Audio mixing is finished, return correct warning */ 445 return M4VSS3GPP_WAR_END_OF_AUDIO_MIXING; 446 447 default: 448 M4OSA_TRACE1_1( 449 "M4VSS3GPP_audioMixingStep: State error (0x%x)! Returning M4ERR_STATE", 450 pC->State); 451 return M4ERR_STATE; 452 } 453} 454 455/** 456 ****************************************************************************** 457 * M4OSA_ERR M4VSS3GPP_audioMixingCleanUp(M4VSS3GPP_AudioMixingContext pContext) 458 * @brief Free all resources used by the VSS audio mixing operation. 459 * @note The context is no more valid after this call 460 * @param pContext (IN) VSS audio mixing context 461 * @return M4NO_ERROR: No error 462 * @return M4ERR_PARAMETER: pContext is M4OSA_NULL (debug only) 463 ****************************************************************************** 464 */ 465M4OSA_ERR M4VSS3GPP_audioMixingCleanUp( M4VSS3GPP_AudioMixingContext pContext ) 466{ 467 M4VSS3GPP_InternalAudioMixingContext *pC = 468 (M4VSS3GPP_InternalAudioMixingContext *)pContext; 469 M4OSA_ERR err; 470 M4OSA_UInt32 lastCTS; 471 472 M4OSA_TRACE3_1("M4VSS3GPP_audioMixingCleanUp called with pContext=0x%x", 473 pContext); 474 475 /** 476 * Check input parameters */ 477 M4OSA_DEBUG_IF2((M4OSA_NULL == pContext), M4ERR_PARAMETER, 478 "M4VSS3GPP_audioMixingCleanUp: pContext is M4OSA_NULL"); 479 480 /** 481 * Check input parameter */ 482 if( M4OSA_NULL == pContext ) 483 { 484 M4OSA_TRACE1_0( 485 "M4VSS3GPP_audioMixingCleanUp(): M4VSS3GPP_audioMixingCleanUp: pContext is\ 486 M4OSA_NULL, returning M4ERR_PARAMETER"); 487 return M4ERR_PARAMETER; 488 } 489 490 /** 491 * Close Input 3GPP file */ 492 if( M4OSA_NULL != pC->pInputClipCtxt ) 493 { 494 M4VSS3GPP_intClipCleanUp(pC->pInputClipCtxt); 495 pC->pInputClipCtxt = M4OSA_NULL; 496 } 497 498 /** 499 * Close Added 3GPP file */ 500 if( M4OSA_NULL != pC->pAddedClipCtxt ) 501 { 502 M4VSS3GPP_intClipCleanUp(pC->pAddedClipCtxt); 503 pC->pAddedClipCtxt = M4OSA_NULL; 504 } 505 506 /** 507 * Close the 3GP writer. In normal use case it has already been closed, 508 but not in abort use case */ 509 if( M4OSA_NULL != pC->ewc.p3gpWriterContext ) 510 { 511 /* Update last Video CTS */ 512 lastCTS = pC->ewc.iOutputDuration; 513 514 err = pC->ShellAPI.pWriterGlobalFcts->pFctSetOption( 515 pC->ewc.p3gpWriterContext, 516 (M4OSA_UInt32)M4WRITER_kMaxFileDuration, &lastCTS); 517 518 if( M4NO_ERROR != err ) 519 { 520 M4OSA_TRACE1_1( 521 "M4VSS3GPP_audioMixingCleanUp: SetOption(M4WRITER_kMaxFileDuration) returns 0x%x", 522 err); 523 } 524 525 err = pC->ShellAPI.pWriterGlobalFcts->pFctCloseWrite( 526 pC->ewc.p3gpWriterContext); 527 528 if( M4NO_ERROR != err ) 529 { 530 M4OSA_TRACE1_1( 531 "M4VSS3GPP_audioMixingCleanUp: pWriterGlobalFcts->pFctCloseWrite returns 0x%x!", 532 err); 533 /**< don't return the error because we have other things to free! */ 534 } 535 pC->ewc.p3gpWriterContext = M4OSA_NULL; 536 } 537 538 /** 539 * Free the Audio encoder context */ 540 if( M4OSA_NULL != pC->ewc.pAudioEncCtxt ) 541 { 542 err = pC->ShellAPI.pAudioEncoderGlobalFcts->pFctClose( 543 pC->ewc.pAudioEncCtxt); 544 545 if( M4NO_ERROR != err ) 546 { 547 M4OSA_TRACE1_1( 548 "M4VSS3GPP_audioMixingCleanUp: pAudioEncoderGlobalFcts->pFctClose returns 0x%x", 549 err); 550 /**< don't return, we still have stuff to free */ 551 } 552 553 err = pC->ShellAPI.pAudioEncoderGlobalFcts->pFctCleanUp( 554 pC->ewc.pAudioEncCtxt); 555 556 if( M4NO_ERROR != err ) 557 { 558 M4OSA_TRACE1_1( 559 "M4VSS3GPP_audioMixingCleanUp: pAudioEncoderGlobalFcts->pFctCleanUp returns 0x%x", 560 err); 561 /**< don't return, we still have stuff to free */ 562 } 563 564 pC->ewc.pAudioEncCtxt = M4OSA_NULL; 565 } 566 567 /** 568 * Free the ssrc stuff */ 569 570 if( M4OSA_NULL != pC->SsrcScratch ) 571 { 572 M4OSA_free((M4OSA_MemAddr32)pC->SsrcScratch); 573 pC->SsrcScratch = M4OSA_NULL; 574 } 575 576 if( M4OSA_NULL != pC->pSsrcBufferIn ) 577 { 578 M4OSA_free((M4OSA_MemAddr32)pC->pSsrcBufferIn); 579 pC->pSsrcBufferIn = M4OSA_NULL; 580 } 581 582 if( M4OSA_NULL != pC->pSsrcBufferOut 583 && (M4OSA_TRUE == pC->b_SSRCneeded || pC->ChannelConversion > 0) ) 584 { 585 M4OSA_free((M4OSA_MemAddr32)pC->pSsrcBufferOut); 586 pC->pSsrcBufferOut = M4OSA_NULL; 587 } 588 589 if( M4OSA_NULL != pC->pTempBuffer ) 590 { 591 M4OSA_free((M4OSA_MemAddr32)pC->pTempBuffer); 592 pC->pTempBuffer = M4OSA_NULL; 593 } 594 595 /** 596 * Free the shells interfaces */ 597 M4VSS3GPP_unRegisterAllWriters(&pC->ShellAPI); 598 M4VSS3GPP_unRegisterAllEncoders(&pC->ShellAPI); 599 M4VSS3GPP_unRegisterAllReaders(&pC->ShellAPI); 600 M4VSS3GPP_unRegisterAllDecoders(&pC->ShellAPI); 601 602 /** 603 * Free the context */ 604 M4OSA_free((M4OSA_MemAddr32)pContext); 605 pContext = M4OSA_NULL; 606 607 /** 608 * Return with no error */ 609 M4OSA_TRACE3_0("M4VSS3GPP_audioMixingCleanUp(): returning M4NO_ERROR"); 610 return M4NO_ERROR; 611} 612 613/******************************************************************************/ 614/******************************************************************************/ 615/********* STATIC FUNCTIONS **********/ 616/******************************************************************************/ 617/******************************************************************************/ 618 619/** 620 ****************************************************************************** 621 * M4OSA_ERR M4VSS3GPP_intAudioMixingOpen() 622 * @brief Initializes the VSS audio mixing operation (allocates an execution context). 623 * @note 624 * @param pContext (OUT) Pointer on the VSS audio mixing context to allocate 625 * @param pSettings (IN) Pointer to valid audio mixing settings 626 * @return M4NO_ERROR: No error 627 * @return M4ERR_PARAMETER: At least one parameter is M4OSA_NULL (debug only) 628 * @return M4ERR_ALLOC: There is no more available memory 629 ****************************************************************************** 630 */ 631static M4OSA_ERR 632M4VSS3GPP_intAudioMixingOpen( M4VSS3GPP_InternalAudioMixingContext *pC, 633 M4VSS3GPP_AudioMixingSettings *pSettings ) 634{ 635 M4OSA_ERR err; 636 M4OSA_UInt32 outputASF = 0; 637 M4ENCODER_Header *encHeader; 638 639 M4OSA_TRACE3_2( 640 "M4VSS3GPP_intAudioMixingOpen called with pContext=0x%x, pSettings=0x%x", 641 pC, pSettings); 642 643 /** 644 * The Add Volume must be (strictly) superior than zero */ 645 if( pSettings->uiAddVolume == 0 ) 646 { 647 M4OSA_TRACE1_0( 648 "M4VSS3GPP_intAudioMixingOpen(): AddVolume is zero,\ 649 returning M4VSS3GPP_ERR_ADDVOLUME_EQUALS_ZERO"); 650 return M4VSS3GPP_ERR_ADDVOLUME_EQUALS_ZERO; 651 } 652 /* 653 else if(pSettings->uiAddVolume >= 100) // If volume is set to 100, no more original audio ... 654 { 655 pC->bRemoveOriginal = M4OSA_TRUE; 656 } 657 */ 658 /** 659 * Build the input clip settings */ 660 pC->InputClipSettings.pFile = 661 pSettings->pOriginalClipFile; /**< Input 3GPP file descriptor */ 662 pC->InputClipSettings.FileType = M4VIDEOEDITING_kFileType_3GPP; 663 pC->InputClipSettings.uiBeginCutTime = 664 0; /**< No notion of cut for the audio mixing feature */ 665 pC->InputClipSettings.uiEndCutTime = 666 0; /**< No notion of cut for the audio mixing feature */ 667 668 /** 669 * Open the original Audio/Video 3GPP clip */ 670 err = M4VSS3GPP_intClipInit(&pC->pInputClipCtxt, pC->pOsaFileReadPtr); 671 672 if( M4NO_ERROR != err ) 673 { 674 M4OSA_TRACE1_1( 675 "M4VSS3GPP_intAudioMixingOpen(): M4VSS3GPP_intClipInit(orig) returns 0x%x", 676 err); 677 return err; 678 } 679 680 err = M4VSS3GPP_intClipOpen(pC->pInputClipCtxt, &pC->InputClipSettings, 681 M4OSA_FALSE, M4OSA_FALSE, M4OSA_TRUE); 682 683 if( M4NO_ERROR != err ) 684 { 685 M4OSA_TRACE1_1( 686 "M4VSS3GPP_intAudioMixingOpen(): M4VSS3GPP_intClipOpen(orig) returns 0x%x", 687 err); 688 return err; 689 } 690 691 if( M4OSA_NULL == pC->pInputClipCtxt->pAudioStream ) 692 { 693 pC->bRemoveOriginal = M4OSA_TRUE; 694 } 695 /** 696 * If there is no video, it's an error */ 697 if( M4OSA_NULL == pC->pInputClipCtxt->pVideoStream ) 698 { 699 M4OSA_TRACE1_0( 700 "M4VSS3GPP_intAudioMixingOpen(): no video stream in clip,\ 701 returning M4VSS3GPP_ERR_NO_SUPPORTED_STREAM_IN_FILE"); 702 return M4VSS3GPP_ERR_NO_SUPPORTED_STREAM_IN_FILE; 703 } 704 705 /** 706 * Compute clip properties */ 707 err = M4VSS3GPP_intBuildAnalysis(pC->pInputClipCtxt, 708 &pC->pInputClipCtxt->pSettings->ClipProperties); 709 710 if( M4NO_ERROR != err ) 711 { 712 M4OSA_TRACE1_1( 713 "M4VSS3GPP_intAudioMixingOpen(): M4VSS3GPP_intBuildAnalysis(orig) returns 0x%x", 714 err); 715 return err; 716 } 717 718 /** 719 * Build the added clip settings */ 720 pC->AddedClipSettings.pFile = 721 pSettings->pAddedAudioTrackFile; /**< Added file descriptor */ 722 pC->AddedClipSettings.FileType = pSettings->AddedAudioFileType; 723 pC->AddedClipSettings.uiBeginCutTime = 724 0; /**< No notion of cut for the audio mixing feature */ 725 pC->AddedClipSettings.uiEndCutTime = 0;/**< No notion of cut for the audio mixing feature */ 726 pC->AddedClipSettings.ClipProperties.uiNbChannels= 727 pSettings->uiNumChannels; 728 pC->AddedClipSettings.ClipProperties.uiSamplingFrequency= pSettings->uiSamplingFrequency; 729 730 if( M4OSA_NULL != pC->AddedClipSettings.pFile ) 731 { 732 /** 733 * Open the added Audio clip */ 734 err = M4VSS3GPP_intClipInit(&pC->pAddedClipCtxt, pC->pOsaFileReadPtr); 735 736 if( M4NO_ERROR != err ) 737 { 738 M4OSA_TRACE1_1( 739 "M4VSS3GPP_intAudioMixingOpen(): M4VSS3GPP_intClipInit(added) returns 0x%x", 740 err); 741 return err; 742 } 743 744 err = M4VSS3GPP_intClipOpen(pC->pAddedClipCtxt, &pC->AddedClipSettings, 745 M4OSA_FALSE, M4OSA_FALSE, M4OSA_TRUE); 746 747 if( M4NO_ERROR != err ) 748 { 749 M4OSA_TRACE1_1( 750 "M4VSS3GPP_intAudioMixingOpen(): M4VSS3GPP_intClipOpen(added) returns 0x%x", 751 err); 752 return err; 753 } 754 755 /** 756 * If there is no audio, it's an error */ 757 if( M4OSA_NULL == pC->pAddedClipCtxt->pAudioStream ) 758 { 759 M4OSA_TRACE1_0( 760 "M4VSS3GPP_intAudioMixingOpen(): no audio nor video stream in clip,\ 761 returning M4VSS3GPP_ERR_NO_SUPPORTED_STREAM_IN_FILE"); 762 return M4VSS3GPP_ERR_NO_SUPPORTED_STREAM_IN_FILE; 763 } 764 765 /** 766 * Compute clip properties */ 767 err = M4VSS3GPP_intBuildAnalysis(pC->pAddedClipCtxt, 768 &pC->pAddedClipCtxt->pSettings->ClipProperties); 769 770 if( M4NO_ERROR != err ) 771 { 772 M4OSA_TRACE1_1( 773 "M4VSS3GPP_intAudioMixingOpen(): M4VSS3GPP_intBuildAnalysis(added) returns 0x%x", 774 err); 775 return err; 776 } 777 778 switch( pSettings->outputASF ) 779 { 780 case M4VIDEOEDITING_k8000_ASF: 781 outputASF = 8000; 782 break; 783 784 case M4VIDEOEDITING_k16000_ASF: 785 outputASF = 16000; 786 break; 787 788 case M4VIDEOEDITING_k22050_ASF: 789 outputASF = 22050; 790 break; 791 792 case M4VIDEOEDITING_k24000_ASF: 793 outputASF = 24000; 794 break; 795 796 case M4VIDEOEDITING_k32000_ASF: 797 outputASF = 32000; 798 break; 799 800 case M4VIDEOEDITING_k44100_ASF: 801 outputASF = 44100; 802 break; 803 804 case M4VIDEOEDITING_k48000_ASF: 805 outputASF = 48000; 806 break; 807 808 default: 809 M4OSA_TRACE1_0("Bad parameter in output ASF "); 810 return M4ERR_PARAMETER; 811 break; 812 } 813 814 if( pC->bRemoveOriginal == M4OSA_TRUE 815 && (pC->pAddedClipCtxt->pSettings->ClipProperties.AudioStreamType 816 == M4VIDEOEDITING_kMP3 || pC->pAddedClipCtxt->pSettings-> 817 ClipProperties.AudioStreamType == M4VIDEOEDITING_kPCM 818 || pC->pAddedClipCtxt->pSettings-> 819 ClipProperties.AudioStreamType 820 != pSettings->outputAudioFormat 821 || pC->pAddedClipCtxt->pSettings-> 822 ClipProperties.uiSamplingFrequency != outputASF 823 || pC->pAddedClipCtxt->pSettings-> 824 ClipProperties.uiNbChannels 825 != pSettings->outputNBChannels) ) 826 { 827 828 if( pSettings->outputAudioFormat == M4VIDEOEDITING_kAMR_NB ) 829 { 830 pSettings->outputASF = M4VIDEOEDITING_k8000_ASF; 831 pSettings->outputNBChannels = 1; 832 pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize = 320; 833 } 834 else if( pSettings->outputAudioFormat == M4VIDEOEDITING_kAAC ) 835 { 836 pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize = 837 2048 * pSettings->outputNBChannels; 838 } 839 840 pC->pInputClipCtxt->pSettings->ClipProperties.uiSamplingFrequency = 841 outputASF; 842 843 if( outputASF != pC->pAddedClipCtxt->pSettings-> 844 ClipProperties.uiSamplingFrequency ) 845 { 846 /* We need to call SSRC in order to align ASF and/or nb of channels */ 847 /* Moreover, audio encoder may be needed in case of audio replacing... */ 848 pC->b_SSRCneeded = M4OSA_TRUE; 849 } 850 851 if( pSettings->outputNBChannels 852 < pC->pAddedClipCtxt->pSettings->ClipProperties.uiNbChannels ) 853 { 854 /* Stereo to Mono */ 855 pC->ChannelConversion = 1; 856 } 857 else if( pSettings->outputNBChannels 858 > pC->pAddedClipCtxt->pSettings->ClipProperties.uiNbChannels ) 859 { 860 /* Mono to Stereo */ 861 pC->ChannelConversion = 2; 862 } 863 864 pC->pInputClipCtxt->pSettings->ClipProperties.uiNbChannels = 865 pSettings->outputNBChannels; 866 } 867 868 /** 869 * Check compatibility chart */ 870 err = M4VSS3GPP_intAudioMixingCompatibility(pC, 871 &pC->pInputClipCtxt->pSettings->ClipProperties, 872 &pC->pAddedClipCtxt->pSettings->ClipProperties); 873 874 if( M4NO_ERROR != err ) 875 { 876 M4OSA_TRACE1_1( 877 "M4VSS3GPP_intAudioMixingOpen():\ 878 M4VSS3GPP_intAudioMixingCompatibility returns 0x%x", 879 err); 880 return err; 881 } 882 883 /** 884 * Check loop parameters */ 885 if( pC->uiBeginLoop > pC->pAddedClipCtxt->pSettings-> 886 ClipProperties.uiClipAudioDuration ) 887 { 888 M4OSA_TRACE1_0( 889 "M4VSS3GPP_intAudioMixingOpen():\ 890 begin loop time is higher than added clip audio duration"); 891 return M4VSS3GPP_ERR_BEGINLOOP_HIGHER_ENDLOOP; 892 } 893 894 /** 895 * Ok, let's go with this audio track */ 896 pC->bHasAudio = M4OSA_TRUE; 897 } 898 else 899 { 900 /* No added file, force remove original */ 901 pC->AddedClipSettings.FileType = M4VIDEOEDITING_kFileType_Unsupported; 902 pC->bRemoveOriginal = M4OSA_TRUE; 903 pC->bHasAudio = M4OSA_FALSE; 904 } 905 906 /** 907 * Copy the video properties of the input clip to the output properties */ 908 pC->ewc.uiVideoBitrate = 909 pC->pInputClipCtxt->pSettings->ClipProperties.uiVideoBitrate; 910 pC->ewc.uiVideoWidth = 911 pC->pInputClipCtxt->pSettings->ClipProperties.uiVideoWidth; 912 pC->ewc.uiVideoHeight = 913 pC->pInputClipCtxt->pSettings->ClipProperties.uiVideoHeight; 914 pC->ewc.uiVideoTimeScale = 915 pC->pInputClipCtxt->pSettings->ClipProperties.uiVideoTimeScale; 916 pC->ewc.bVideoDataPartitioning = 917 pC->pInputClipCtxt->pSettings->ClipProperties.bMPEG4dataPartition; 918 919 switch( pC->pInputClipCtxt->pSettings->ClipProperties.VideoStreamType ) 920 { 921 case M4VIDEOEDITING_kH263: 922 pC->ewc.VideoStreamType = M4SYS_kH263; 923 break; 924 925 case M4VIDEOEDITING_kMPEG4_EMP: 926 pC->ewc.bActivateEmp = M4OSA_TRUE; /* no break */ 927 928 case M4VIDEOEDITING_kMPEG4: 929 pC->ewc.VideoStreamType = M4SYS_kMPEG_4; 930 break; 931 932 case M4VIDEOEDITING_kH264: 933 pC->ewc.VideoStreamType = M4SYS_kH264; 934 break; 935 936 default: 937 pC->ewc.VideoStreamType = M4SYS_kVideoUnknown; 938 break; 939 } 940 941 /* Add a link to video dsi */ 942 if( M4SYS_kH264 == pC->ewc.VideoStreamType ) 943 { 944 945 /* For H.264 encoder case 946 * Fetch the DSI from the shell video encoder, and feed it to the writer */ 947 948 M4OSA_TRACE3_0("M4VSS3GPP_intAudioMixingOpen: get DSI for H264 stream"); 949 950 if( M4OSA_NULL == pC->ewc.pEncContext ) 951 { 952 M4OSA_TRACE1_0( 953 "M4VSS3GPP_intAudioMixingOpen: pC->ewc.pEncContext is NULL"); 954 err = M4VSS3GPP_intAudioMixingCreateVideoEncoder(pC); 955 956 if( M4NO_ERROR != err ) 957 { 958 M4OSA_TRACE1_1( 959 "M4VSS3GPP_intAudioMixingOpen:\ 960 M4VSS3GPP_intAudioMixingCreateVideoEncoder returned error 0x%x", 961 err); 962 } 963 } 964 965 if( M4OSA_NULL != pC->ewc.pEncContext ) 966 { 967 err = pC->ShellAPI.pVideoEncoderGlobalFcts->pFctGetOption( 968 pC->ewc.pEncContext, M4ENCODER_kOptionID_EncoderHeader, 969 (M4OSA_DataOption) &encHeader); 970 971 if( ( M4NO_ERROR != err) || (M4OSA_NULL == encHeader->pBuf) ) 972 { 973 M4OSA_TRACE1_1( 974 "M4VSS3GPP_intAudioMixingOpen: failed to get the encoder header (err 0x%x)", 975 err); 976 M4OSA_TRACE1_2( 977 "M4VSS3GPP_intAudioMixingOpen: encHeader->pBuf=0x%x, size=0x%x", 978 encHeader->pBuf, encHeader->Size); 979 } 980 else 981 { 982 M4OSA_TRACE1_0( 983 "M4VSS3GPP_intAudioMixingOpen: send DSI for H264 stream to 3GP writer"); 984 985 /** 986 * Allocate and copy the new DSI */ 987 pC->ewc.pVideoOutputDsi = 988 (M4OSA_MemAddr8)M4OSA_malloc(encHeader->Size, M4VSS3GPP, 989 (M4OSA_Char *)"pC->ewc.pVideoOutputDsi (H264)"); 990 991 if( M4OSA_NULL == pC->ewc.pVideoOutputDsi ) 992 { 993 M4OSA_TRACE1_0( 994 "M4VSS3GPP_intAudioMixingOpen():\ 995 unable to allocate pVideoOutputDsi (H264), returning M4ERR_ALLOC"); 996 return M4ERR_ALLOC; 997 } 998 pC->ewc.uiVideoOutputDsiSize = (M4OSA_UInt16)encHeader->Size; 999 M4OSA_memcpy(pC->ewc.pVideoOutputDsi, encHeader->pBuf, 1000 encHeader->Size); 1001 } 1002 1003 err = M4VSS3GPP_intAudioMixingDestroyVideoEncoder(pC); 1004 1005 if( M4NO_ERROR != err ) 1006 { 1007 M4OSA_TRACE1_1( 1008 "M4VSS3GPP_intAudioMixingOpen:\ 1009 M4VSS3GPP_intAudioMixingDestroyVideoEncoder returned error 0x%x", 1010 err); 1011 } 1012 } 1013 else 1014 { 1015 M4OSA_TRACE1_0( 1016 "M4VSS3GPP_intAudioMixingOpen: pC->ewc.pEncContext is NULL, cannot get the DSI"); 1017 } 1018 } 1019 else 1020 { 1021 M4OSA_TRACE3_1( 1022 "M4VSS3GPP_intAudioMixingOpen: input clip video stream type = 0x%x", 1023 pC->ewc.VideoStreamType); 1024 pC->ewc.uiVideoOutputDsiSize = 1025 (M4OSA_UInt16)pC->pInputClipCtxt->pVideoStream-> 1026 m_basicProperties.m_decoderSpecificInfoSize; 1027 pC->ewc.pVideoOutputDsi = (M4OSA_MemAddr8)pC->pInputClipCtxt->pVideoStream-> 1028 m_basicProperties.m_pDecoderSpecificInfo; 1029 } 1030 1031 /** 1032 * Copy the audio properties of the added clip to the output properties */ 1033 if( pC->bHasAudio ) 1034 { 1035 if( pC->bRemoveOriginal == M4OSA_TRUE ) 1036 { 1037 pC->ewc.uiNbChannels = 1038 pC->pAddedClipCtxt->pSettings->ClipProperties.uiNbChannels; 1039 pC->ewc.uiAudioBitrate = 1040 pC->pAddedClipCtxt->pSettings->ClipProperties.uiAudioBitrate; 1041 pC->ewc.uiSamplingFrequency = pC->pAddedClipCtxt->pSettings-> 1042 ClipProperties.uiSamplingFrequency; 1043 pC->ewc.uiSilencePcmSize = 1044 pC->pAddedClipCtxt->pSettings->ClipProperties.uiDecodedPcmSize; 1045 pC->ewc.scale_audio = pC->ewc.uiSamplingFrequency / 1000.0; 1046 1047 /* if output settings are differents from added clip settings, 1048 we need to reencode BGM */ 1049 if( pC->pAddedClipCtxt->pSettings->ClipProperties.AudioStreamType 1050 != pSettings->outputAudioFormat 1051 || pC->pAddedClipCtxt->pSettings-> 1052 ClipProperties.uiSamplingFrequency != outputASF 1053 || pC->pAddedClipCtxt->pSettings-> 1054 ClipProperties.uiNbChannels 1055 != pSettings->outputNBChannels 1056 || pC->pAddedClipCtxt->pSettings-> 1057 ClipProperties.AudioStreamType == M4VIDEOEDITING_kMP3 ) 1058 { 1059 /* Set reader DSI to NULL (unknown), we will use encoder DSI later */ 1060 if( pC->pAddedClipCtxt->pAudioStream-> 1061 m_basicProperties.m_pDecoderSpecificInfo != M4OSA_NULL ) 1062 { 1063 1064 /* 1065 M4OSA_free((M4OSA_MemAddr32)pC->pAddedClipCtxt->pAudioStream->\ 1066 m_basicProperties.m_pDecoderSpecificInfo); 1067 */ 1068 pC->pAddedClipCtxt->pAudioStream-> 1069 m_basicProperties.m_decoderSpecificInfoSize = 0; 1070 pC->pAddedClipCtxt->pAudioStream-> 1071 m_basicProperties.m_pDecoderSpecificInfo = M4OSA_NULL; 1072 } 1073 1074 pC->ewc.uiNbChannels = 1075 pC->pInputClipCtxt->pSettings->ClipProperties.uiNbChannels; 1076 pC->ewc.uiSamplingFrequency = pC->pInputClipCtxt->pSettings-> 1077 ClipProperties.uiSamplingFrequency; 1078 pC->ewc.scale_audio = pC->ewc.uiSamplingFrequency / 1000.0; 1079 1080 if( pSettings->outputAudioFormat == M4VIDEOEDITING_kAMR_NB ) 1081 { 1082 pC->ewc.AudioStreamType = M4SYS_kAMR; 1083 pC->ewc.pSilenceFrameData = 1084 (M4OSA_UInt8 *)M4VSS3GPP_AMR_AU_SILENCE_FRAME_048; 1085 pC->ewc.uiSilenceFrameSize = 1086 M4VSS3GPP_AMR_AU_SILENCE_FRAME_048_SIZE; 1087 pC->ewc.iSilenceFrameDuration = 1088 M4VSS3GPP_AMR_AU_SILENCE_FRAME_048_DURATION; 1089 pC->ewc.uiAudioBitrate = 12200; 1090 pC->ewc.uiSamplingFrequency = 8000; 1091 pC->ewc.uiSilencePcmSize = 320; 1092 pC->ewc.scale_audio = pC->ewc.uiSamplingFrequency / 1000.0; 1093 } 1094 else if( pSettings->outputAudioFormat == M4VIDEOEDITING_kAAC ) 1095 { 1096 pC->ewc.AudioStreamType = M4SYS_kAAC; 1097 1098 if( pSettings->outputAudioBitrate 1099 == M4VIDEOEDITING_kUndefinedBitrate ) 1100 { 1101 switch( pC->ewc.uiSamplingFrequency ) 1102 { 1103 case 16000: 1104 pC->ewc.uiAudioBitrate = 1105 M4VIDEOEDITING_k24_KBPS; 1106 break; 1107 1108 case 22050: 1109 case 24000: 1110 pC->ewc.uiAudioBitrate = 1111 M4VIDEOEDITING_k32_KBPS; 1112 break; 1113 1114 case 32000: 1115 pC->ewc.uiAudioBitrate = 1116 M4VIDEOEDITING_k48_KBPS; 1117 break; 1118 1119 case 44100: 1120 case 48000: 1121 pC->ewc.uiAudioBitrate = 1122 M4VIDEOEDITING_k64_KBPS; 1123 break; 1124 1125 default: 1126 pC->ewc.uiAudioBitrate = 1127 M4VIDEOEDITING_k64_KBPS; 1128 break; 1129 } 1130 1131 if( pC->ewc.uiNbChannels == 2 ) 1132 { 1133 /* Output bitrate have to be doubled */ 1134 pC->ewc.uiAudioBitrate += pC->ewc.uiAudioBitrate; 1135 } 1136 } 1137 else 1138 { 1139 pC->ewc.uiAudioBitrate = pSettings->outputAudioBitrate; 1140 } 1141 1142 if( pC->ewc.uiNbChannels == 1 ) 1143 { 1144 pC->ewc.pSilenceFrameData = 1145 (M4OSA_UInt8 *)M4VSS3GPP_AAC_AU_SILENCE_MONO; 1146 pC->ewc.uiSilenceFrameSize = 1147 M4VSS3GPP_AAC_AU_SILENCE_MONO_SIZE; 1148 } 1149 else 1150 { 1151 pC->ewc.pSilenceFrameData = 1152 (M4OSA_UInt8 *)M4VSS3GPP_AAC_AU_SILENCE_STEREO; 1153 pC->ewc.uiSilenceFrameSize = 1154 M4VSS3GPP_AAC_AU_SILENCE_STEREO_SIZE; 1155 } 1156 pC->ewc.iSilenceFrameDuration = 1157 1024; /* AAC is always 1024/Freq sample duration */ 1158 } 1159 } 1160 else 1161 { 1162 switch( pC->pAddedClipCtxt->pSettings-> 1163 ClipProperties.AudioStreamType ) 1164 { 1165 case M4VIDEOEDITING_kAMR_NB: 1166 pC->ewc.AudioStreamType = M4SYS_kAMR; 1167 pC->ewc.pSilenceFrameData = 1168 (M4OSA_UInt8 *)M4VSS3GPP_AMR_AU_SILENCE_FRAME_048; 1169 pC->ewc.uiSilenceFrameSize = 1170 M4VSS3GPP_AMR_AU_SILENCE_FRAME_048_SIZE; 1171 pC->ewc.iSilenceFrameDuration = 1172 M4VSS3GPP_AMR_AU_SILENCE_FRAME_048_DURATION; 1173 break; 1174 1175 case M4VIDEOEDITING_kAAC: 1176 case M4VIDEOEDITING_kAACplus: 1177 case M4VIDEOEDITING_keAACplus: 1178 pC->ewc.AudioStreamType = M4SYS_kAAC; 1179 1180 if( pC->ewc.uiNbChannels == 1 ) 1181 { 1182 pC->ewc.pSilenceFrameData = 1183 (M4OSA_UInt8 *)M4VSS3GPP_AAC_AU_SILENCE_MONO; 1184 pC->ewc.uiSilenceFrameSize = 1185 M4VSS3GPP_AAC_AU_SILENCE_MONO_SIZE; 1186 } 1187 else 1188 { 1189 pC->ewc.pSilenceFrameData = 1190 (M4OSA_UInt8 *)M4VSS3GPP_AAC_AU_SILENCE_STEREO; 1191 pC->ewc.uiSilenceFrameSize = 1192 M4VSS3GPP_AAC_AU_SILENCE_STEREO_SIZE; 1193 } 1194 pC->ewc.iSilenceFrameDuration = 1195 1024; /* AAC is always 1024/Freq sample duration */ 1196 break; 1197 1198 case M4VIDEOEDITING_kEVRC: 1199 pC->ewc.AudioStreamType = M4SYS_kEVRC; 1200 pC->ewc.pSilenceFrameData = M4OSA_NULL; 1201 pC->ewc.uiSilenceFrameSize = 0; 1202 pC->ewc.iSilenceFrameDuration = 160; /* EVRC frames are 20 ms at 8000 Hz 1203 (makes it easier to factorize amr and evrc code) */ 1204 break; 1205 1206 case M4VIDEOEDITING_kPCM: 1207 /* Set reader DSI to NULL (unknown), we will use encoder DSI later */ 1208 pC->pAddedClipCtxt->pAudioStream-> 1209 m_basicProperties.m_decoderSpecificInfoSize = 0; 1210 pC->pAddedClipCtxt->pAudioStream-> 1211 m_basicProperties.m_pDecoderSpecificInfo = 1212 M4OSA_NULL; 1213 1214 if( pC->pAddedClipCtxt->pSettings-> 1215 ClipProperties.uiSamplingFrequency == 8000 ) 1216 { 1217 pC->ewc.AudioStreamType = M4SYS_kAMR; 1218 pC->ewc.pSilenceFrameData = (M4OSA_UInt8 1219 *)M4VSS3GPP_AMR_AU_SILENCE_FRAME_048; 1220 pC->ewc.uiSilenceFrameSize = 1221 M4VSS3GPP_AMR_AU_SILENCE_FRAME_048_SIZE; 1222 pC->ewc.iSilenceFrameDuration = 1223 M4VSS3GPP_AMR_AU_SILENCE_FRAME_048_DURATION; 1224 pC->ewc.uiAudioBitrate = M4VIDEOEDITING_k12_2_KBPS; 1225 } 1226 else if( pC->pAddedClipCtxt->pSettings-> 1227 ClipProperties.uiSamplingFrequency == 16000 ) 1228 { 1229 if( pC->ewc.uiNbChannels == 1 ) 1230 { 1231 pC->ewc.AudioStreamType = M4SYS_kAAC; 1232 pC->ewc.pSilenceFrameData = (M4OSA_UInt8 1233 *)M4VSS3GPP_AAC_AU_SILENCE_MONO; 1234 pC->ewc.uiSilenceFrameSize = 1235 M4VSS3GPP_AAC_AU_SILENCE_MONO_SIZE; 1236 pC->ewc.iSilenceFrameDuration = 1237 1024; /* AAC is always 1024/Freq sample duration */ 1238 pC->ewc.uiAudioBitrate = 1239 M4VIDEOEDITING_k32_KBPS; 1240 } 1241 else 1242 { 1243 pC->ewc.AudioStreamType = M4SYS_kAAC; 1244 pC->ewc.pSilenceFrameData = (M4OSA_UInt8 1245 *)M4VSS3GPP_AAC_AU_SILENCE_STEREO; 1246 pC->ewc.uiSilenceFrameSize = 1247 M4VSS3GPP_AAC_AU_SILENCE_STEREO_SIZE; 1248 pC->ewc.iSilenceFrameDuration = 1249 1024; /* AAC is always 1024/Freq sample duration */ 1250 pC->ewc.uiAudioBitrate = 1251 M4VIDEOEDITING_k64_KBPS; 1252 } 1253 } 1254 else 1255 { 1256 pC->ewc.AudioStreamType = M4SYS_kAudioUnknown; 1257 } 1258 break; 1259 1260 default: 1261 pC->ewc.AudioStreamType = M4SYS_kAudioUnknown; 1262 break; 1263 } 1264 } 1265 1266 /* Add a link to audio dsi */ 1267 pC->ewc.uiAudioOutputDsiSize = 1268 (M4OSA_UInt16)pC->pAddedClipCtxt->pAudioStream-> 1269 m_basicProperties.m_decoderSpecificInfoSize; 1270 pC->ewc.pAudioOutputDsi = (M4OSA_MemAddr8)pC->pAddedClipCtxt->pAudioStream-> 1271 m_basicProperties.m_pDecoderSpecificInfo; 1272 } 1273 else 1274 { 1275 pC->ewc.uiNbChannels = 1276 pC->pInputClipCtxt->pSettings->ClipProperties.uiNbChannels; 1277 pC->ewc.uiAudioBitrate = 1278 pC->pInputClipCtxt->pSettings->ClipProperties.uiAudioBitrate; 1279 pC->ewc.uiSamplingFrequency = pC->pInputClipCtxt->pSettings-> 1280 ClipProperties.uiSamplingFrequency; 1281 pC->ewc.uiSilencePcmSize = 1282 pC->pInputClipCtxt->pSettings->ClipProperties.uiDecodedPcmSize; 1283 pC->ewc.scale_audio = pC->ewc.uiSamplingFrequency / 1000.0; 1284 1285 switch( pC->pInputClipCtxt->pSettings-> 1286 ClipProperties.AudioStreamType ) 1287 { 1288 case M4VIDEOEDITING_kAMR_NB: 1289 pC->ewc.AudioStreamType = M4SYS_kAMR; 1290 pC->ewc.pSilenceFrameData = 1291 (M4OSA_UInt8 *)M4VSS3GPP_AMR_AU_SILENCE_FRAME_048; 1292 pC->ewc.uiSilenceFrameSize = 1293 M4VSS3GPP_AMR_AU_SILENCE_FRAME_048_SIZE; 1294 pC->ewc.iSilenceFrameDuration = 1295 M4VSS3GPP_AMR_AU_SILENCE_FRAME_048_DURATION; 1296 break; 1297 1298 case M4VIDEOEDITING_kAAC: 1299 case M4VIDEOEDITING_kAACplus: 1300 case M4VIDEOEDITING_keAACplus: 1301 pC->ewc.AudioStreamType = M4SYS_kAAC; 1302 1303 if( pC->ewc.uiNbChannels == 1 ) 1304 { 1305 pC->ewc.pSilenceFrameData = 1306 (M4OSA_UInt8 *)M4VSS3GPP_AAC_AU_SILENCE_MONO; 1307 pC->ewc.uiSilenceFrameSize = 1308 M4VSS3GPP_AAC_AU_SILENCE_MONO_SIZE; 1309 } 1310 else 1311 { 1312 pC->ewc.pSilenceFrameData = 1313 (M4OSA_UInt8 *)M4VSS3GPP_AAC_AU_SILENCE_STEREO; 1314 pC->ewc.uiSilenceFrameSize = 1315 M4VSS3GPP_AAC_AU_SILENCE_STEREO_SIZE; 1316 } 1317 pC->ewc.iSilenceFrameDuration = 1318 1024; /* AAC is always 1024/Freq sample duration */ 1319 break; 1320 1321 default: 1322 pC->ewc.AudioStreamType = M4SYS_kAudioUnknown; 1323 M4OSA_TRACE1_0( 1324 "M4VSS3GPP_intAudioMixingOpen: No audio track in input file."); 1325 return M4VSS3GPP_ERR_AUDIO_CANNOT_BE_MIXED; 1326 break; 1327 } 1328 1329 /* Add a link to audio dsi */ 1330 pC->ewc.uiAudioOutputDsiSize = 1331 (M4OSA_UInt16)pC->pInputClipCtxt->pAudioStream-> 1332 m_basicProperties.m_decoderSpecificInfoSize; 1333 pC->ewc.pAudioOutputDsi = (M4OSA_MemAddr8)pC->pInputClipCtxt->pAudioStream-> 1334 m_basicProperties.m_pDecoderSpecificInfo; 1335 } 1336 } 1337 1338 /** 1339 * Copy common 'silence frame stuff' to ClipContext */ 1340 pC->pInputClipCtxt->uiSilencePcmSize = pC->ewc.uiSilencePcmSize; 1341 pC->pInputClipCtxt->pSilenceFrameData = pC->ewc.pSilenceFrameData; 1342 pC->pInputClipCtxt->uiSilenceFrameSize = pC->ewc.uiSilenceFrameSize; 1343 pC->pInputClipCtxt->iSilenceFrameDuration = pC->ewc.iSilenceFrameDuration; 1344 pC->pInputClipCtxt->scale_audio = pC->ewc.scale_audio; 1345 1346 pC->pInputClipCtxt->iAudioFrameCts = 1347 -pC->pInputClipCtxt->iSilenceFrameDuration; /* Reset time */ 1348 1349 /** 1350 * Copy common 'silence frame stuff' to ClipContext */ 1351 if( pC->bHasAudio ) 1352 { 1353 pC->pAddedClipCtxt->uiSilencePcmSize = pC->ewc.uiSilencePcmSize; 1354 pC->pAddedClipCtxt->pSilenceFrameData = pC->ewc.pSilenceFrameData; 1355 pC->pAddedClipCtxt->uiSilenceFrameSize = pC->ewc.uiSilenceFrameSize; 1356 pC->pAddedClipCtxt->iSilenceFrameDuration = 1357 pC->ewc.iSilenceFrameDuration; 1358 pC->pAddedClipCtxt->scale_audio = pC->ewc.scale_audio; 1359 1360 pC->pAddedClipCtxt->iAudioFrameCts = 1361 -pC->pAddedClipCtxt->iSilenceFrameDuration; /* Reset time */ 1362 } 1363 1364 /** 1365 * Check AddCts is lower than original clip duration */ 1366 if( ( M4OSA_NULL != pC->pInputClipCtxt->pVideoStream) 1367 && (pC->iAddCts > (M4OSA_Int32)pC->pInputClipCtxt->pVideoStream-> 1368 m_basicProperties.m_duration) ) 1369 { 1370 M4OSA_TRACE1_0( 1371 "M4VSS3GPP_intAudioMixingOpen(): uiAddCts is larger than video duration,\ 1372 returning M4VSS3GPP_ERR_ADDCTS_HIGHER_THAN_VIDEO_DURATION"); 1373 return M4VSS3GPP_ERR_ADDCTS_HIGHER_THAN_VIDEO_DURATION; 1374 } 1375 1376 /** 1377 * If the audio tracks are not compatible, replace input track by silence */ 1378 if( M4OSA_FALSE == pC->pInputClipCtxt->pSettings-> 1379 ClipProperties.bAudioIsCompatibleWithMasterClip ) 1380 { 1381 M4VSS3GPP_intClipDeleteAudioTrack(pC->pInputClipCtxt); 1382 } 1383 1384 /** 1385 * Check if audio mixing is required */ 1386 if( ( ( pC->bHasAudio) && (M4OSA_FALSE 1387 == pC->pAddedClipCtxt->pSettings->ClipProperties.bAudioIsEditable)) 1388 || (M4OSA_TRUE == pC->bRemoveOriginal) ) /*|| 1389 (pSettings->uiAddVolume >= 100)) */ 1390 { 1391 pC->bAudioMixingIsNeeded = M4OSA_FALSE; 1392 } 1393 else 1394 { 1395 pC->bAudioMixingIsNeeded = M4OSA_TRUE; 1396 } 1397 1398 /** 1399 * Check if output audio can support silence frames 1400 Trick i use bAudioIsCompatibleWithMasterClip filed to store that */ 1401 if( pC->bHasAudio ) 1402 { 1403 pC->bSupportSilence = pC->pAddedClipCtxt->pSettings-> 1404 ClipProperties.bAudioIsCompatibleWithMasterClip; 1405 1406 if( M4OSA_FALSE == pC->bSupportSilence ) 1407 { 1408 if( pC->iAddCts > 0 ) 1409 { 1410 M4OSA_TRACE1_0( 1411 "M4VSS3GPP_intAudioMixingOpen():\ 1412 iAddCts should be set to 0 with this audio track !"); 1413 return M4VSS3GPP_ERR_FEATURE_UNSUPPORTED_WITH_AUDIO_TRACK; 1414 } 1415 1416 if( 0 < pC->uiEndLoop ) 1417 { 1418 M4OSA_TRACE1_0( 1419 "M4VSS3GPP_intAudioMixingOpen():\ 1420 uiEndLoop should be set to 0 with this audio track !"); 1421 return M4VSS3GPP_ERR_FEATURE_UNSUPPORTED_WITH_AUDIO_TRACK; 1422 } 1423 } 1424 } 1425#if 0 1426 /** 1427 * Compute the volume factors */ 1428 if( (M4OSA_TRUE 1429 == pC->bRemoveOriginal) ) 1430 { 1431 /** 1432 * In the remove original case, we keep only the added audio */ 1433 pC->fAddedFactor = 1.0F; 1434 pC->fOrigFactor = 0.0F; 1435 } 1436 else 1437 { 1438 /** 1439 * Compute the factor to apply to sample to do the mixing */ 1440 pC->fAddedFactor = pSettings->uiAddVolume / 100.0F; 1441 pC->fOrigFactor = 1.0F - pC->fAddedFactor; 1442 } 1443#endif 1444 if( pC->b_DuckingNeedeed == M4OSA_FALSE) 1445 { 1446 /** 1447 * Compute the factor to apply to sample to do the mixing */ 1448 pC->fAddedFactor = 0.50F; 1449 pC->fOrigFactor = 0.50F; 1450 } 1451 1452 1453 /** 1454 * Check if SSRC is needed */ 1455 if( M4OSA_TRUE == pC->b_SSRCneeded ) 1456 { 1457 M4OSA_UInt32 numerator, denominator, ratio, ratioBuffer; 1458 1459 /** 1460 * Init the SSRC module */ 1461 SSRC_ReturnStatus_en 1462 ReturnStatus; /* Function return status */ 1463 LVM_INT16 NrSamplesMin = 1464 0; /* Minimal number of samples on the input or on the output */ 1465 LVM_INT32 1466 ScratchSize; /* The size of the scratch memory */ 1467 LVM_INT16 1468 *pInputInScratch; /* Pointer to input in the scratch buffer */ 1469 LVM_INT16 1470 * 1471 pOutputInScratch; /* Pointer to the output in the scratch buffer */ 1472 SSRC_Params_t ssrcParams; /* Memory for init parameters */ 1473 1474 switch( pC->pAddedClipCtxt->pSettings-> 1475 ClipProperties.uiSamplingFrequency ) 1476 { 1477 case 8000: 1478 ssrcParams.SSRC_Fs_In = LVM_FS_8000; 1479 break; 1480 1481 case 11025: 1482 ssrcParams.SSRC_Fs_In = LVM_FS_11025; 1483 break; 1484 1485 case 12000: 1486 ssrcParams.SSRC_Fs_In = LVM_FS_12000; 1487 break; 1488 1489 case 16000: 1490 ssrcParams.SSRC_Fs_In = LVM_FS_16000; 1491 break; 1492 1493 case 22050: 1494 ssrcParams.SSRC_Fs_In = LVM_FS_22050; 1495 break; 1496 1497 case 24000: 1498 ssrcParams.SSRC_Fs_In = LVM_FS_24000; 1499 break; 1500 1501 case 32000: 1502 ssrcParams.SSRC_Fs_In = LVM_FS_32000; 1503 break; 1504 1505 case 44100: 1506 ssrcParams.SSRC_Fs_In = LVM_FS_44100; 1507 break; 1508 1509 case 48000: 1510 ssrcParams.SSRC_Fs_In = LVM_FS_48000; 1511 break; 1512 1513 default: 1514 M4OSA_TRACE1_1( 1515 "M4VSS3GPP_intAudioMixingOpen: invalid added clip sampling frequency (%d Hz),\ 1516 returning M4VSS3GPP_ERR_UNSUPPORTED_ADDED_AUDIO_STREAM", 1517 pC->pAddedClipCtxt->pSettings-> 1518 ClipProperties.uiSamplingFrequency); 1519 return M4VSS3GPP_ERR_UNSUPPORTED_ADDED_AUDIO_STREAM; 1520 } 1521 1522 if( 1 == pC->pAddedClipCtxt->pSettings->ClipProperties.uiNbChannels ) 1523 { 1524 ssrcParams.SSRC_NrOfChannels = LVM_MONO; 1525 } 1526 else 1527 { 1528 ssrcParams.SSRC_NrOfChannels = LVM_STEREO; 1529 } 1530 1531 switch( pC->ewc.uiSamplingFrequency ) 1532 { 1533 case 8000: 1534 ssrcParams.SSRC_Fs_Out = LVM_FS_8000; 1535 break; 1536 1537 case 16000: 1538 ssrcParams.SSRC_Fs_Out = LVM_FS_16000; 1539 break; 1540 1541 case 22050: 1542 ssrcParams.SSRC_Fs_Out = LVM_FS_22050; 1543 break; 1544 1545 case 24000: 1546 ssrcParams.SSRC_Fs_Out = LVM_FS_24000; 1547 break; 1548 1549 case 32000: 1550 ssrcParams.SSRC_Fs_Out = LVM_FS_32000; 1551 break; 1552 1553 case 44100: 1554 ssrcParams.SSRC_Fs_Out = LVM_FS_44100; 1555 break; 1556 1557 case 48000: 1558 ssrcParams.SSRC_Fs_Out = LVM_FS_48000; 1559 break; 1560 1561 default: 1562 M4OSA_TRACE1_1( 1563 "M4VSS3GPP_intAudioMixingOpen: invalid output sampling frequency (%d Hz),\ 1564 returning M4VSS3GPP_ERR_AUDIO_CANNOT_BE_MIXED", 1565 pC->ewc.uiSamplingFrequency); 1566 return M4VSS3GPP_ERR_AUDIO_CANNOT_BE_MIXED; 1567 break; 1568 } 1569 ReturnStatus = 0; 1570 1571 switch (ssrcParams.SSRC_Fs_In){ 1572 case LVM_FS_8000: 1573 ssrcParams.NrSamplesIn = 320; 1574 break; 1575 case LVM_FS_11025: 1576 ssrcParams.NrSamplesIn =441; 1577 break; 1578 case LVM_FS_12000: 1579 ssrcParams.NrSamplesIn = 480; 1580 break; 1581 case LVM_FS_16000: 1582 ssrcParams.NrSamplesIn = 640; 1583 break; 1584 case LVM_FS_22050: 1585 ssrcParams.NrSamplesIn = 882; 1586 break; 1587 case LVM_FS_24000: 1588 ssrcParams.NrSamplesIn = 960; 1589 break; 1590 case LVM_FS_32000: 1591 ssrcParams.NrSamplesIn = 1280; 1592 break; 1593 case LVM_FS_44100: 1594 ssrcParams.NrSamplesIn = 1764; 1595 break; 1596 case LVM_FS_48000: 1597 ssrcParams.NrSamplesIn = 1920; 1598 break; 1599 default: 1600 ReturnStatus = -1; 1601 break; 1602 } 1603 1604 switch (ssrcParams.SSRC_Fs_Out){ 1605 case LVM_FS_8000: 1606 ssrcParams.NrSamplesOut= 320; 1607 break; 1608 case LVM_FS_11025: 1609 ssrcParams.NrSamplesOut =441; 1610 break; 1611 case LVM_FS_12000: 1612 ssrcParams.NrSamplesOut= 480; 1613 break; 1614 case LVM_FS_16000: 1615 ssrcParams.NrSamplesOut= 640; 1616 break; 1617 case LVM_FS_22050: 1618 ssrcParams.NrSamplesOut= 882; 1619 break; 1620 case LVM_FS_24000: 1621 ssrcParams.NrSamplesOut= 960; 1622 break; 1623 case LVM_FS_32000: 1624 ssrcParams.NrSamplesOut = 1280; 1625 break; 1626 case LVM_FS_44100: 1627 ssrcParams.NrSamplesOut= 1764; 1628 break; 1629 case LVM_FS_48000: 1630 ssrcParams.NrSamplesOut = 1920; 1631 break; 1632 default: 1633 ReturnStatus = -1; 1634 break; 1635 } 1636 if( ReturnStatus != SSRC_OK ) 1637 { 1638 M4OSA_TRACE1_1( 1639 "M4VSS3GPP_intAudioMixingOpen:\ 1640 Error code %d returned by the SSRC_GetNrSamples function", 1641 ReturnStatus); 1642 return M4VSS3GPP_ERR_AUDIO_CANNOT_BE_MIXED; 1643 } 1644 1645 NrSamplesMin = 1646 (LVM_INT16)((ssrcParams.NrSamplesIn > ssrcParams.NrSamplesOut) 1647 ? ssrcParams.NrSamplesOut : ssrcParams.NrSamplesIn); 1648 1649 while( NrSamplesMin < M4VSS_SSRC_MINBLOCKSIZE ) 1650 { /* Don't take blocks smaller that the minimal block size */ 1651 ssrcParams.NrSamplesIn = (LVM_INT16)(ssrcParams.NrSamplesIn << 1); 1652 ssrcParams.NrSamplesOut = (LVM_INT16)(ssrcParams.NrSamplesOut << 1); 1653 NrSamplesMin = (LVM_INT16)(NrSamplesMin << 1); 1654 } 1655 pC->iSsrcNbSamplIn = (LVM_INT16)( 1656 ssrcParams. 1657 NrSamplesIn); /* multiplication by NrOfChannels is done below */ 1658 pC->iSsrcNbSamplOut = (LVM_INT16)(ssrcParams.NrSamplesOut); 1659 1660 numerator = 1661 pC->pAddedClipCtxt->pSettings->ClipProperties.uiSamplingFrequency 1662 * pC->pAddedClipCtxt->pSettings->ClipProperties.uiNbChannels; 1663 denominator = 1664 pC->pInputClipCtxt->pSettings->ClipProperties.uiSamplingFrequency 1665 * pC->pInputClipCtxt->pSettings->ClipProperties.uiNbChannels; 1666 1667 if( numerator % denominator == 0 ) 1668 { 1669 ratioBuffer = (M4OSA_UInt32)(numerator / denominator); 1670 } 1671 else 1672 { 1673 ratioBuffer = (M4OSA_UInt32)(numerator / denominator) + 1; 1674 } 1675 1676 ratio = 1677 (M4OSA_UInt32)(( pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize 1678 * ratioBuffer) / (pC->iSsrcNbSamplIn * sizeof(short) 1679 * pC->pAddedClipCtxt->pSettings-> 1680 ClipProperties.uiNbChannels)); 1681 1682 if( ratio == 0 ) 1683 { 1684 /* It means that the input size of SSRC bufferIn is bigger than the asked buffer */ 1685 pC->minimumBufferIn = pC->iSsrcNbSamplIn * sizeof(short) 1686 * pC->pAddedClipCtxt->pSettings-> 1687 ClipProperties.uiNbChannels; 1688 } 1689 else 1690 { 1691 ratio++; /* We use the immediate superior integer */ 1692 pC->minimumBufferIn = ratio * (pC->iSsrcNbSamplIn * sizeof(short) 1693 * pC->pAddedClipCtxt->pSettings-> 1694 ClipProperties.uiNbChannels); 1695 } 1696 1697 /** 1698 * Allocate buffer for the input of the SSRC */ 1699 pC->pSsrcBufferIn = 1700 (M4OSA_MemAddr8)M4OSA_malloc(pC->minimumBufferIn 1701 + pC->pAddedClipCtxt-> 1702 AudioDecBufferOut. 1703 m_bufferSize, 1704 M4VSS3GPP, (M4OSA_Char *)"pSsrcBufferIn"); 1705 1706 if( M4OSA_NULL == pC->pSsrcBufferIn ) 1707 { 1708 M4OSA_TRACE1_0( 1709 "M4VSS3GPP_intAudioMixingOpen():\ 1710 unable to allocate pSsrcBufferIn, returning M4ERR_ALLOC"); 1711 return M4ERR_ALLOC; 1712 } 1713 pC->pPosInSsrcBufferIn = (M4OSA_MemAddr8)pC->pSsrcBufferIn; 1714 1715 /** 1716 * Allocate buffer for the output of the SSRC */ 1717 /* The "3" value below should be optimized ... one day ... */ 1718 pC->pSsrcBufferOut = 1719 (M4OSA_MemAddr8)M4OSA_malloc(3 * pC->iSsrcNbSamplOut * sizeof(short) 1720 * pC->ewc.uiNbChannels, M4VSS3GPP, (M4OSA_Char *)"pSsrcBufferOut"); 1721 1722 if( M4OSA_NULL == pC->pSsrcBufferOut ) 1723 { 1724 M4OSA_TRACE1_0( 1725 "M4VSS3GPP_intAudioMixingOpen():\ 1726 unable to allocate pSsrcBufferOut, returning M4ERR_ALLOC"); 1727 return M4ERR_ALLOC; 1728 } 1729 pC->pPosInSsrcBufferOut = pC->pSsrcBufferOut; 1730 1731 /** 1732 * Allocate temporary buffer needed in case of channel conversion */ 1733 if( pC->ChannelConversion > 0 ) 1734 { 1735 /* The "3" value below should be optimized ... one day ... */ 1736 pC->pTempBuffer = 1737 (M4OSA_MemAddr8)M4OSA_malloc(3 * pC->iSsrcNbSamplOut 1738 * sizeof(short) * pC->pAddedClipCtxt->pSettings-> 1739 ClipProperties.uiNbChannels, M4VSS3GPP, (M4OSA_Char *)"pSsrcBufferOut"); 1740 1741 if( M4OSA_NULL == pC->pTempBuffer ) 1742 { 1743 M4OSA_TRACE1_0( 1744 "M4VSS3GPP_intAudioMixingOpen():\ 1745 unable to allocate pTempBuffer, returning M4ERR_ALLOC"); 1746 return M4ERR_ALLOC; 1747 } 1748 pC->pPosInTempBuffer = pC->pTempBuffer; 1749 } 1750 } 1751 else if( pC->ChannelConversion > 0 ) 1752 { 1753 pC->minimumBufferIn = 1754 pC->pAddedClipCtxt->AudioDecBufferOut.m_bufferSize; 1755 1756 /** 1757 * Allocate buffer for the input of the SSRC */ 1758 pC->pSsrcBufferIn = 1759 (M4OSA_MemAddr8)M4OSA_malloc(pC->minimumBufferIn 1760 + pC->pAddedClipCtxt-> 1761 AudioDecBufferOut. 1762 m_bufferSize, 1763 M4VSS3GPP, (M4OSA_Char *)"pSsrcBufferIn"); 1764 1765 if( M4OSA_NULL == pC->pSsrcBufferIn ) 1766 { 1767 M4OSA_TRACE1_0( 1768 "M4VSS3GPP_intAudioMixingOpen(): \ 1769 unable to allocate pSsrcBufferIn, returning M4ERR_ALLOC"); 1770 return M4ERR_ALLOC; 1771 } 1772 pC->pPosInSsrcBufferIn = (M4OSA_MemAddr8)pC->pSsrcBufferIn; 1773 1774 /** 1775 * Allocate buffer for the output of the SSRC */ 1776 /* The "3" value below should be optimized ... one day ... */ 1777 pC->pSsrcBufferOut = (M4OSA_MemAddr8)M4OSA_malloc( 1778 pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize, 1779 M4VSS3GPP, (M4OSA_Char *)"pSsrcBufferOut"); 1780 1781 if( M4OSA_NULL == pC->pSsrcBufferOut ) 1782 { 1783 M4OSA_TRACE1_0( 1784 "M4VSS3GPP_intAudioMixingOpen():\ 1785 unable to allocate pSsrcBufferOut, returning M4ERR_ALLOC"); 1786 return M4ERR_ALLOC; 1787 } 1788 pC->pPosInSsrcBufferOut = pC->pSsrcBufferOut; 1789 } 1790 else if( (pC->pAddedClipCtxt->pSettings->ClipProperties.AudioStreamType == M4VIDEOEDITING_kMP3)|| 1791 (pC->pAddedClipCtxt->pSettings->ClipProperties.AudioStreamType == M4VIDEOEDITING_kPCM)) 1792 { 1793 M4OSA_UInt32 minbuffer = 0; 1794 1795 if( pSettings->outputAudioFormat == M4VIDEOEDITING_kAAC ) 1796 { 1797 pC->minimumBufferIn = 2048 * pC->ewc.uiNbChannels; 1798 minbuffer = pC->minimumBufferIn; 1799 } 1800 else if( pSettings->outputAudioFormat == M4VIDEOEDITING_kAMR_NB ) 1801 { 1802 pC->minimumBufferIn = 320; 1803 1804 if( pC->pAddedClipCtxt->AudioDecBufferOut.m_bufferSize > 320 ) 1805 { 1806 minbuffer = pC->pAddedClipCtxt->AudioDecBufferOut.m_bufferSize; 1807 } 1808 else 1809 { 1810 minbuffer = pC->minimumBufferIn; /* Not really possible ...*/ 1811 } 1812 } 1813 else 1814 { 1815 M4OSA_TRACE1_0("Bad output audio format, in case of MP3 replacing"); 1816 return M4ERR_PARAMETER; 1817 } 1818 1819 /** 1820 * Allocate buffer for the input of the SSRC */ 1821 pC->pSsrcBufferIn = 1822 (M4OSA_MemAddr8)M4OSA_malloc(2 * minbuffer, M4VSS3GPP, 1823 (M4OSA_Char *)"pSsrcBufferIn"); 1824 1825 if( M4OSA_NULL == pC->pSsrcBufferIn ) 1826 { 1827 M4OSA_TRACE1_0( 1828 "M4VSS3GPP_intAudioMixingOpen(): unable to allocate pSsrcBufferIn,\ 1829 returning M4ERR_ALLOC"); 1830 return M4ERR_ALLOC; 1831 } 1832 pC->pPosInSsrcBufferIn = (M4OSA_MemAddr8)pC->pSsrcBufferIn; 1833 1834 pC->pPosInSsrcBufferOut = pC->pPosInSsrcBufferIn; 1835 pC->pSsrcBufferOut = pC->pSsrcBufferIn; 1836 } 1837 1838 /** 1839 * Check if audio encoder is needed to do audio mixing or audio resampling */ 1840 if( M4OSA_TRUE == pC->bAudioMixingIsNeeded || M4VIDEOEDITING_kPCM 1841 == pC->pAddedClipCtxt->pSettings->ClipProperties.AudioStreamType 1842 || M4VIDEOEDITING_kMP3 1843 == pC->pAddedClipCtxt->pSettings->ClipProperties.AudioStreamType 1844 || pC->pAddedClipCtxt->pSettings->ClipProperties.AudioStreamType 1845 != pSettings->outputAudioFormat 1846 || pC->pAddedClipCtxt->pSettings->ClipProperties.uiSamplingFrequency 1847 != outputASF 1848 || pC->pAddedClipCtxt->pSettings->ClipProperties.uiNbChannels 1849 != pSettings->outputNBChannels ) 1850 { 1851 /** 1852 * Init the audio encoder */ 1853 err = M4VSS3GPP_intCreateAudioEncoder(&pC->ewc, &pC->ShellAPI, 1854 pC->ewc.uiAudioBitrate); 1855 1856 if( M4NO_ERROR != err ) 1857 { 1858 M4OSA_TRACE1_1( 1859 "M4VSS3GPP_intAudioMixingOpen(): M4VSS3GPP_intCreateAudioEncoder() returns 0x%x", 1860 err); 1861 return err; 1862 } 1863 1864 /* In case of PCM, MP3 or audio replace with reencoding, use encoder DSI */ 1865 if( pC->ewc.uiAudioOutputDsiSize == 0 && (M4VIDEOEDITING_kPCM 1866 == pC->pAddedClipCtxt->pSettings->ClipProperties.AudioStreamType 1867 || M4VIDEOEDITING_kMP3 == pC->pAddedClipCtxt->pSettings-> 1868 ClipProperties.AudioStreamType 1869 || pC->pAddedClipCtxt->pSettings-> 1870 ClipProperties.AudioStreamType 1871 != pSettings->outputAudioFormat 1872 || pC->pAddedClipCtxt->pSettings-> 1873 ClipProperties.uiSamplingFrequency != outputASF 1874 || pC->pAddedClipCtxt->pSettings-> 1875 ClipProperties.uiNbChannels 1876 != pSettings->outputNBChannels) ) 1877 { 1878 pC->ewc.uiAudioOutputDsiSize = 1879 (M4OSA_UInt16)pC->ewc.pAudioEncDSI.infoSize; 1880 pC->ewc.pAudioOutputDsi = pC->ewc.pAudioEncDSI.pInfo; 1881 } 1882 } 1883 1884 /** 1885 * Init the output 3GPP file */ 1886 /*11/12/2008 CR3283 add the max output file size for the MMS use case in VideoArtist*/ 1887 err = M4VSS3GPP_intCreate3GPPOutputFile(&pC->ewc, &pC->ShellAPI, 1888 pC->pOsaFileWritPtr, pSettings->pOutputClipFile, 1889 pC->pOsaFileReadPtr, pSettings->pTemporaryFile, 0); 1890 1891 if( M4NO_ERROR != err ) 1892 { 1893 M4OSA_TRACE1_1( 1894 "M4VSS3GPP_intAudioMixingOpen(): M4VSS3GPP_intCreate3GPPOutputFile() returns 0x%x", 1895 err); 1896 return err; 1897 } 1898 1899 /** 1900 * Return with no error */ 1901 M4OSA_TRACE3_0("M4VSS3GPP_intAudioMixingOpen(): returning M4NO_ERROR"); 1902 return M4NO_ERROR; 1903} 1904 1905/** 1906 ****************************************************************************** 1907 * M4OSA_ERR M4VSS3GPP_intAudioMixingWriteSilence() 1908 * @brief Write an audio silence frame into the writer 1909 * @note Mainly used when padding with silence 1910 * @param pC (IN) VSS audio mixing internal context 1911 * @return M4NO_ERROR: No error 1912 ****************************************************************************** 1913 */ 1914static M4OSA_ERR M4VSS3GPP_intAudioMixingWriteSilence( 1915 M4VSS3GPP_InternalAudioMixingContext *pC ) 1916{ 1917 M4OSA_ERR err; 1918 1919 err = pC->ShellAPI.pWriterDataFcts->pStartAU(pC->ewc.p3gpWriterContext, 1920 M4VSS3GPP_WRITER_AUDIO_STREAM_ID, &pC->ewc.WriterAudioAU); 1921 1922 if( M4NO_ERROR != err ) 1923 { 1924 M4OSA_TRACE1_1("M4VSS3GPP_intAudioMixingWriteSilence:\ 1925 pWriterDataFcts->pStartAU(audio) returns 0x%x!", err); 1926 return err; 1927 } 1928 1929 M4OSA_TRACE2_0("A #### silence AU"); 1930 1931 M4OSA_memcpy((M4OSA_MemAddr8)pC->ewc.WriterAudioAU.dataAddress, 1932 (M4OSA_MemAddr8)pC->ewc.pSilenceFrameData, pC->ewc.uiSilenceFrameSize); 1933 1934 pC->ewc.WriterAudioAU.size = pC->ewc.uiSilenceFrameSize; 1935 pC->ewc.WriterAudioAU.CTS = 1936 (M4OSA_Time)(pC->ewc.dATo * pC->ewc.scale_audio + 0.5); 1937 1938 M4OSA_TRACE2_2("B ---- write : cts = %ld [ 0x%x ]", 1939 (M4OSA_Int32)(pC->ewc.dATo), pC->ewc.WriterAudioAU.size); 1940 1941 err = pC->ShellAPI.pWriterDataFcts->pProcessAU(pC->ewc.p3gpWriterContext, 1942 M4VSS3GPP_WRITER_AUDIO_STREAM_ID, &pC->ewc.WriterAudioAU); 1943 1944 if( M4NO_ERROR != err ) 1945 { 1946 M4OSA_TRACE1_1( 1947 "M4VSS3GPP_intAudioMixingWriteSilence:\ 1948 pWriterDataFcts->pProcessAU(silence) returns 0x%x!", 1949 err); 1950 return err; 1951 } 1952 1953 pC->ewc.dATo += pC->ewc.iSilenceFrameDuration / pC->ewc.scale_audio; 1954 1955 return M4NO_ERROR; 1956} 1957 1958/** 1959 ****************************************************************************** 1960 * M4OSA_ERR M4VSS3GPP_intAudioMixingStepVideo(M4VSS3GPP_InternalAudioMixingContext *pC) 1961 * @brief Perform one step of video. 1962 * @note 1963 * @param pC (IN) VSS audio mixing internal context 1964 * @return M4NO_ERROR: No error 1965 ****************************************************************************** 1966 */ 1967static M4OSA_ERR M4VSS3GPP_intAudioMixingStepVideo( 1968 M4VSS3GPP_InternalAudioMixingContext *pC ) 1969{ 1970 M4OSA_ERR err; 1971 M4OSA_UInt16 offset; 1972 1973 M4OSA_TRACE2_3(" VIDEO step : dVTo = %f state = %d offset = %ld", 1974 pC->ewc.dOutputVidCts, pC->State, pC->pInputClipCtxt->iVoffset); 1975 1976 /** 1977 * Read the input video AU */ 1978 err = pC->pInputClipCtxt->ShellAPI.m_pReaderDataIt->m_pFctGetNextAu( 1979 pC->pInputClipCtxt->pReaderContext, 1980 (M4_StreamHandler *)pC->pInputClipCtxt->pVideoStream, 1981 &pC->pInputClipCtxt->VideoAU); 1982 1983 if( M4NO_ERROR != err ) 1984 { 1985 M4OSA_TRACE3_1( 1986 "M4VSS3GPP_intAudioMixingStepVideo(): m_pFctGetNextAu(video) returns 0x%x", 1987 err); 1988 return err; 1989 } 1990 1991 M4OSA_TRACE2_3("C .... read : cts = %.0f + %ld [ 0x%x ]", 1992 pC->pInputClipCtxt->VideoAU.m_CTS, pC->pInputClipCtxt->iVoffset, 1993 pC->pInputClipCtxt->VideoAU.m_size); 1994 1995 /** 1996 * Get the output AU to write into */ 1997 err = pC->ShellAPI.pWriterDataFcts->pStartAU(pC->ewc.p3gpWriterContext, 1998 M4VSS3GPP_WRITER_VIDEO_STREAM_ID, &pC->ewc.WriterVideoAU); 1999 2000 if( M4NO_ERROR != err ) 2001 { 2002 M4OSA_TRACE1_1( 2003 "M4VSS3GPP_intAudioMixingStepVideo: pWriterDataFcts->pStartAU(Video) returns 0x%x!", 2004 err); 2005 return err; 2006 } 2007 2008 offset = 0; 2009 /* for h.264 stream do not read the 1st 4 bytes as they are header indicators */ 2010 if( pC->pInputClipCtxt->pVideoStream->m_basicProperties.m_streamType 2011 == M4DA_StreamTypeVideoMpeg4Avc ) 2012 { 2013 M4OSA_TRACE3_0( 2014 "M4VSS3GPP_intAudioMixingStepVideo(): input stream type H264"); 2015 offset = 4; 2016 } 2017 pC->pInputClipCtxt->VideoAU.m_size -= offset; 2018 /** 2019 * Check that the video AU is not larger than expected */ 2020 if( pC->pInputClipCtxt->VideoAU.m_size > pC->ewc.uiVideoMaxAuSize ) 2021 { 2022 M4OSA_TRACE1_2( 2023 "M4VSS3GPP_intAudioMixingStepVideo: AU size greater than MaxAuSize (%d>%d)!\ 2024 returning M4VSS3GPP_ERR_INPUT_VIDEO_AU_TOO_LARGE", 2025 pC->pInputClipCtxt->VideoAU.m_size, pC->ewc.uiVideoMaxAuSize); 2026 return M4VSS3GPP_ERR_INPUT_VIDEO_AU_TOO_LARGE; 2027 } 2028 2029 /** 2030 * Copy the input AU payload to the output AU */ 2031 M4OSA_memcpy((M4OSA_MemAddr8)pC->ewc.WriterVideoAU.dataAddress, 2032 (M4OSA_MemAddr8)(pC->pInputClipCtxt->VideoAU.m_dataAddress + offset), 2033 (pC->pInputClipCtxt->VideoAU.m_size)); 2034 2035 /** 2036 * Copy the input AU parameters to the output AU */ 2037 pC->ewc.WriterVideoAU.size = pC->pInputClipCtxt->VideoAU.m_size; 2038 pC->ewc.WriterVideoAU.CTS = 2039 (M4OSA_UInt32)(pC->pInputClipCtxt->VideoAU.m_CTS + 0.5); 2040 pC->ewc.WriterVideoAU.attribute = pC->pInputClipCtxt->VideoAU.m_attribute; 2041 2042 /** 2043 * Write the AU */ 2044 M4OSA_TRACE2_2("D ---- write : cts = %lu [ 0x%x ]", 2045 pC->ewc.WriterVideoAU.CTS, pC->ewc.WriterVideoAU.size); 2046 2047 err = pC->ShellAPI.pWriterDataFcts->pProcessAU(pC->ewc.p3gpWriterContext, 2048 M4VSS3GPP_WRITER_VIDEO_STREAM_ID, &pC->ewc.WriterVideoAU); 2049 2050 if( M4NO_ERROR != err ) 2051 { 2052 M4OSA_TRACE1_1( 2053 "M4VSS3GPP_intAudioMixingStepVideo: pWriterDataFcts->pProcessAU(Video) returns 0x%x!", 2054 err); 2055 return err; 2056 } 2057 2058 /** 2059 * Return with no error */ 2060 M4OSA_TRACE3_0("M4VSS3GPP_intAudioMixingStepVideo(): returning M4NO_ERROR"); 2061 return M4NO_ERROR; 2062} 2063 2064/** 2065 ****************************************************************************** 2066 * M4OSA_ERR M4VSS3GPP_intAudioMixingStepAudioMix(M4VSS3GPP_InternalAudioMixingContext *pC) 2067 * @brief Perform one step of audio. 2068 * @note 2069 * @param pC (IN) VSS audio mixing internal context 2070 * @return M4NO_ERROR: No error 2071 ****************************************************************************** 2072 */ 2073static M4OSA_ERR M4VSS3GPP_intAudioMixingStepAudioMix( 2074 M4VSS3GPP_InternalAudioMixingContext *pC ) 2075{ 2076 M4OSA_ERR err; 2077 2078 M4OSA_TRACE2_3(" AUDIO mix : dATo = %f state = %d offset = %ld", 2079 pC->ewc.dATo, pC->State, pC->pInputClipCtxt->iAoffset); 2080 2081 switch( pC->State ) 2082 { 2083 /**********************************************************/ 2084 case M4VSS3GPP_kAudioMixingState_AUDIO_FIRST_SEGMENT: 2085 { 2086 err = M4VSS3GPP_intAudioMixingCopyOrig(pC); 2087 2088 if( M4NO_ERROR != err ) 2089 { 2090 M4OSA_TRACE1_1( 2091 "M4VSS3GPP_intAudioMixingStepAudioMix:\ 2092 M4VSS3GPP_intAudioMixingCopyOrig(1) returns 0x%x!", 2093 err); 2094 return err; 2095 } 2096 2097 /** 2098 * Check if we reached the AddCts */ 2099 if( pC->ewc.dATo >= pC->iAddCts ) 2100 { 2101 /** 2102 * First segment is over, state transition to second and return OK */ 2103 pC->State = M4VSS3GPP_kAudioMixingState_AUDIO_SECOND_SEGMENT; 2104 2105 /* Transition from reading state to encoding state */ 2106 err = M4VSS3GPP_intAudioMixingTransition(pC); 2107 2108 if( M4NO_ERROR != err ) 2109 { 2110 M4OSA_TRACE1_1( 2111 "M4VSS3GPP_intAudioMixingStepAudioMix(): pre-encode fails err = 0x%x", 2112 err); 2113 return err; 2114 } 2115 2116 /** 2117 * Return with no error so the step function will be called again */ 2118 pC->pAddedClipCtxt->iAoffset = 2119 (M4OSA_Int32)(pC->ewc.dATo * pC->ewc.scale_audio + 0.5); 2120 2121 M4OSA_TRACE2_0( 2122 "M4VSS3GPP_intAudioMixingStepAudioMix(): returning M4NO_ERROR (1->2)"); 2123 2124 return M4NO_ERROR; 2125 } 2126 } 2127 break; 2128 2129 /**********************************************************/ 2130 case M4VSS3GPP_kAudioMixingState_AUDIO_SECOND_SEGMENT: 2131 { 2132 if( M4OSA_TRUE == pC->bAudioMixingIsNeeded ) /**< Mix */ 2133 { 2134 /** 2135 * Read the added audio AU */ 2136 if( pC->ChannelConversion > 0 || pC->b_SSRCneeded == M4OSA_TRUE 2137 || pC->pAddedClipCtxt->pSettings-> 2138 ClipProperties.AudioStreamType == M4VIDEOEDITING_kMP3 ) 2139 { 2140 /* In case of sampling freq conversion and/or channel conversion, 2141 the read next AU will be called by the 2142 M4VSS3GPP_intAudioMixingDoMixing function */ 2143 } 2144 else 2145 { 2146 err = 2147 M4VSS3GPP_intClipReadNextAudioFrame(pC->pAddedClipCtxt); 2148 2149 M4OSA_TRACE2_3("E .... read : cts = %.0f + %.0f [ 0x%x ]", 2150 pC->pAddedClipCtxt->iAudioFrameCts 2151 / pC->pAddedClipCtxt->scale_audio, 2152 pC->pAddedClipCtxt->iAoffset 2153 / pC->pAddedClipCtxt->scale_audio, 2154 pC->pAddedClipCtxt->uiAudioFrameSize); 2155 2156 if( M4WAR_NO_MORE_AU == err ) 2157 { 2158 /** 2159 * Decide what to do when audio is over */ 2160 if( pC->uiEndLoop > 0 ) 2161 { 2162 /** 2163 * Jump at the Begin loop time */ 2164 M4OSA_Int32 time = (M4OSA_Int32)(pC->uiBeginLoop); 2165 2166 err = pC->pAddedClipCtxt->ShellAPI.m_pReader-> 2167 m_pFctJump( 2168 pC->pAddedClipCtxt->pReaderContext, 2169 (M4_StreamHandler 2170 *)pC->pAddedClipCtxt->pAudioStream, 2171 &time); 2172 2173 if( M4NO_ERROR != err ) 2174 { 2175 M4OSA_TRACE1_1( 2176 "M4VSS3GPP_intAudioMixingStepAudioMix():\ 2177 m_pReader->m_pFctJump(audio returns 0x%x", 2178 err); 2179 return err; 2180 } 2181 } 2182 else 2183 { 2184 /* Transition from encoding state to reading state */ 2185 err = M4VSS3GPP_intAudioMixingTransition(pC); 2186 2187 if( M4NO_ERROR != err ) 2188 { 2189 M4OSA_TRACE1_1( 2190 "M4VSS3GPP_intAudioMixingStepAudioMix():\ 2191 pre-encode fails err = 0x%x", 2192 err); 2193 return err; 2194 } 2195 2196 /** 2197 * Second segment is over, state transition to third and 2198 return OK */ 2199 pC->State = 2200 M4VSS3GPP_kAudioMixingState_AUDIO_THIRD_SEGMENT; 2201 2202 /** 2203 * Return with no error so the step function will be 2204 called again */ 2205 M4OSA_TRACE2_0( 2206 "M4VSS3GPP_intAudioMixingStepAudioMix():\ 2207 returning M4NO_ERROR (2->3) a"); 2208 return M4NO_ERROR; 2209 } 2210 } 2211 else if( M4NO_ERROR != err ) 2212 { 2213 M4OSA_TRACE1_1( 2214 "M4VSS3GPP_intAudioMixingStepAudioMix():\ 2215 m_pFctGetNextAu(audio) returns 0x%x", 2216 err); 2217 return err; 2218 } 2219 } 2220 2221 /** 2222 * Read the original audio AU */ 2223 err = M4VSS3GPP_intClipReadNextAudioFrame(pC->pInputClipCtxt); 2224 2225 M4OSA_TRACE2_3("F .... read : cts = %.0f + %.0f [ 0x%x ]", 2226 pC->pInputClipCtxt->iAudioFrameCts 2227 / pC->pInputClipCtxt->scale_audio, 2228 pC->pInputClipCtxt->iAoffset 2229 / pC->pInputClipCtxt->scale_audio, 2230 pC->pInputClipCtxt->uiAudioFrameSize); 2231 2232 if( M4NO_ERROR != err ) 2233 { 2234 M4OSA_TRACE3_1( 2235 "M4VSS3GPP_intAudioMixingStepAudioMix():\ 2236 m_pFctGetNextAu(audio) returns 0x%x", 2237 err); 2238 return err; 2239 } 2240 2241 if( pC->ChannelConversion == 0 2242 && pC->b_SSRCneeded == M4OSA_FALSE 2243 && pC->pAddedClipCtxt->pSettings-> 2244 ClipProperties.AudioStreamType != M4VIDEOEDITING_kMP3 ) 2245 { 2246 /** 2247 * Get the output AU to write into */ 2248 err = pC->ShellAPI.pWriterDataFcts->pStartAU( 2249 pC->ewc.p3gpWriterContext, 2250 M4VSS3GPP_WRITER_AUDIO_STREAM_ID, 2251 &pC->ewc.WriterAudioAU); 2252 2253 if( M4NO_ERROR != err ) 2254 { 2255 M4OSA_TRACE1_1( 2256 "M4VSS3GPP_intAudioMixingStepAudioMix:\ 2257 pWriterDataFcts->pStartAU(audio) returns 0x%x!", 2258 err); 2259 return err; 2260 } 2261 } 2262 2263 /** 2264 * Perform the audio mixing */ 2265 err = M4VSS3GPP_intAudioMixingDoMixing(pC); 2266 2267 if( err == M4VSS3GPP_WAR_END_OF_ADDED_AUDIO ) 2268 { 2269 return M4NO_ERROR; 2270 } 2271 2272 if( M4NO_ERROR != err ) 2273 { 2274 M4OSA_TRACE1_1( 2275 "M4VSS3GPP_intAudioMixingStepAudioMix:\ 2276 M4VSS3GPP_intAudioMixingDoMixing returns 0x%x!", 2277 err); 2278 return err; 2279 } 2280 } 2281 else /**< No mix, just copy added audio */ 2282 { 2283 err = M4VSS3GPP_intAudioMixingCopyAdded(pC); 2284 2285 if( M4WAR_NO_MORE_AU == err ) 2286 { 2287 /** 2288 * Decide what to do when audio is over */ 2289 if( pC->uiEndLoop > 0 ) 2290 { 2291 /** 2292 * Jump at the Begin loop time */ 2293 M4OSA_Int32 time = (M4OSA_Int32)(pC->uiBeginLoop); 2294 2295 err = 2296 pC->pAddedClipCtxt->ShellAPI.m_pReader->m_pFctJump( 2297 pC->pAddedClipCtxt->pReaderContext, 2298 (M4_StreamHandler 2299 *)pC->pAddedClipCtxt->pAudioStream, 2300 &time); 2301 2302 if( M4NO_ERROR != err ) 2303 { 2304 M4OSA_TRACE1_1( 2305 "M4VSS3GPP_intAudioMixingStepAudioMix():\ 2306 m_pReader->m_pFctJump(audio returns 0x%x", 2307 err); 2308 return err; 2309 } 2310 2311 /** 2312 * 'BZZZ' bug fix: 2313 * add a silence frame */ 2314 err = M4VSS3GPP_intAudioMixingWriteSilence(pC); 2315 2316 if( M4NO_ERROR != err ) 2317 { 2318 M4OSA_TRACE1_1( 2319 "M4VSS3GPP_intAudioMixingStepAudioMix():\ 2320 M4VSS3GPP_intAudioMixingWriteSilence returns 0x%x", 2321 err); 2322 return err; 2323 } 2324 2325 /** 2326 * Return with no error so the step function will be called again to 2327 read audio data */ 2328 pC->pAddedClipCtxt->iAoffset = 2329 (M4OSA_Int32)(pC->ewc.dATo * pC->ewc.scale_audio 2330 + 0.5); 2331 2332 M4OSA_TRACE2_0( 2333 "M4VSS3GPP_intAudioMixingStepAudioMix():\ 2334 returning M4NO_ERROR (loop)"); 2335 return M4NO_ERROR; 2336 } 2337 else 2338 { 2339 /* Transition to begin cut */ 2340 err = M4VSS3GPP_intAudioMixingTransition(pC); 2341 2342 if( M4NO_ERROR != err ) 2343 { 2344 M4OSA_TRACE1_1( 2345 "M4VSS3GPP_intAudioMixingStepAudioMix():\ 2346 pre-encode fails err = 0x%x", 2347 err); 2348 return err; 2349 } 2350 2351 /** 2352 * Second segment is over, state transition to third */ 2353 pC->State = 2354 M4VSS3GPP_kAudioMixingState_AUDIO_THIRD_SEGMENT; 2355 2356 /** 2357 * Return with no error so the step function will be called again */ 2358 M4OSA_TRACE2_0( 2359 "M4VSS3GPP_intAudioMixingStepAudioMix():\ 2360 returning M4NO_ERROR (2->3) b"); 2361 return M4NO_ERROR; 2362 } 2363 } 2364 else if( M4NO_ERROR != err ) 2365 { 2366 M4OSA_TRACE1_1( 2367 "M4VSS3GPP_intAudioMixingStepAudioMix():\ 2368 M4VSS3GPP_intAudioMixingCopyOrig(2) returns 0x%x", 2369 err); 2370 return err; 2371 } 2372 } 2373 2374 /** 2375 * Check if we reached the end of the video */ 2376 if( pC->ewc.dATo >= pC->ewc.iOutputDuration ) 2377 { 2378 M4OSA_TRACE3_0( 2379 "M4VSS3GPP_intAudioMixingStepAudioMix(): Video duration reached,\ 2380 returning M4WAR_NO_MORE_AU"); 2381 return M4WAR_NO_MORE_AU; /**< Simulate end of file error */ 2382 } 2383 } 2384 break; 2385 2386 /**********************************************************/ 2387 case M4VSS3GPP_kAudioMixingState_AUDIO_THIRD_SEGMENT: 2388 { 2389 err = M4VSS3GPP_intAudioMixingCopyOrig(pC); 2390 2391 if( M4NO_ERROR != err ) 2392 { 2393 M4OSA_TRACE1_1( 2394 "M4VSS3GPP_intAudioMixingStepAudioMix:\ 2395 M4VSS3GPP_intAudioMixingCopyOrig(3) returns 0x%x!", 2396 err); 2397 return err; 2398 } 2399 2400 /** 2401 * Check if we reached the end of the video */ 2402 if( pC->ewc.dATo >= pC->ewc.iOutputDuration ) 2403 { 2404 M4OSA_TRACE3_0( 2405 "M4VSS3GPP_intAudioMixingStepAudioMix():\ 2406 Video duration reached, returning M4WAR_NO_MORE_AU"); 2407 return M4WAR_NO_MORE_AU; /**< Simulate end of file error */ 2408 } 2409 } 2410 break; 2411 default: 2412 break; 2413 } 2414 2415 /** 2416 * Return with no error */ 2417 M4OSA_TRACE3_0( 2418 "M4VSS3GPP_intAudioMixingStepAudioMix(): returning M4NO_ERROR"); 2419 return M4NO_ERROR; 2420} 2421 2422/** 2423 ****************************************************************************** 2424 * M4OSA_ERR M4VSS3GPP_intAudioMixingStepAudioReplace(M4VSS3GPP_InternalAudioMixingContext *pC) 2425 * @brief Perform one step of audio. 2426 * @note 2427 * @param pC (IN) VSS audio mixing internal context 2428 * @return M4NO_ERROR: No error 2429 ****************************************************************************** 2430 */ 2431static M4OSA_ERR M4VSS3GPP_intAudioMixingStepAudioReplace( 2432 M4VSS3GPP_InternalAudioMixingContext *pC ) 2433{ 2434 M4OSA_ERR err; 2435 2436 M4OSA_TRACE2_3(" AUDIO repl : dATo = %f state = %d offset = %ld", 2437 pC->ewc.dATo, pC->State, pC->pInputClipCtxt->iAoffset); 2438 2439 switch( pC->State ) 2440 { 2441 /**********************************************************/ 2442 case M4VSS3GPP_kAudioMixingState_AUDIO_FIRST_SEGMENT: 2443 { 2444 /** 2445 * Replace the SID (silence) payload in the writer AU */ 2446 err = M4VSS3GPP_intAudioMixingWriteSilence(pC); 2447 2448 if( M4NO_ERROR != err ) 2449 { 2450 M4OSA_TRACE1_1( 2451 "M4VSS3GPP_intAudioMixingStepAudioMix():\ 2452 M4VSS3GPP_intAudioMixingWriteSilence returns 0x%x", 2453 err); 2454 return err; 2455 } 2456 2457 /** 2458 * Check if we reached the AddCts */ 2459 if( pC->ewc.dATo >= pC->iAddCts ) 2460 { 2461 /** 2462 * First segment is over, state transition to second and return OK */ 2463 pC->State = M4VSS3GPP_kAudioMixingState_AUDIO_SECOND_SEGMENT; 2464 2465 /** 2466 * Return with no error so the step function will be called again */ 2467 pC->pAddedClipCtxt->iAoffset = 2468 (M4OSA_Int32)(pC->ewc.dATo * pC->ewc.scale_audio + 0.5); 2469 2470 M4OSA_TRACE2_0("M4VSS3GPP_intAudioMixingStepAudioReplace():\ 2471 returning M4NO_ERROR (1->2)"); 2472 return M4NO_ERROR; 2473 } 2474 } 2475 break; 2476 2477 /**********************************************************/ 2478 case M4VSS3GPP_kAudioMixingState_AUDIO_SECOND_SEGMENT: 2479 { 2480 err = M4VSS3GPP_intAudioMixingCopyAdded(pC); 2481 2482 if( M4WAR_NO_MORE_AU == err ) 2483 { 2484 /** 2485 * Decide what to do when audio is over */ 2486 2487 if( pC->uiEndLoop > 0 ) 2488 { 2489 /** 2490 * Jump at the Begin loop time */ 2491 M4OSA_Int32 time = (M4OSA_Int32)(pC->uiBeginLoop); 2492 2493 err = pC->pAddedClipCtxt->ShellAPI.m_pReader->m_pFctJump( 2494 pC->pAddedClipCtxt->pReaderContext, 2495 (M4_StreamHandler 2496 *)pC->pAddedClipCtxt->pAudioStream, &time); 2497 2498 if( M4NO_ERROR != err ) 2499 { 2500 M4OSA_TRACE1_1( 2501 "M4VSS3GPP_intAudioMixingStepAudioReplace():\ 2502 m_pReader->m_pFctJump(audio returns 0x%x", 2503 err); 2504 return err; 2505 } 2506 2507 /** 2508 * 'BZZZ' bug fix: 2509 * add a silence frame */ 2510 err = M4VSS3GPP_intAudioMixingWriteSilence(pC); 2511 2512 if( M4NO_ERROR != err ) 2513 { 2514 M4OSA_TRACE1_1( 2515 "M4VSS3GPP_intAudioMixingStepAudioMix():\ 2516 M4VSS3GPP_intAudioMixingWriteSilence returns 0x%x", 2517 err); 2518 return err; 2519 } 2520 2521 /** 2522 * Return with no error so the step function will be called again to 2523 read audio data */ 2524 pC->pAddedClipCtxt->iAoffset = 2525 (M4OSA_Int32)(pC->ewc.dATo * pC->ewc.scale_audio + 0.5); 2526 2527 M4OSA_TRACE2_0( 2528 "M4VSS3GPP_intAudioMixingStepAudioReplace():\ 2529 returning M4NO_ERROR (loop)"); 2530 2531 return M4NO_ERROR; 2532 } 2533 else if( M4OSA_TRUE == pC->bSupportSilence ) 2534 { 2535 /** 2536 * Second segment is over, state transition to third and return OK */ 2537 pC->State = M4VSS3GPP_kAudioMixingState_AUDIO_THIRD_SEGMENT; 2538 2539 /** 2540 * Return with no error so the step function will be called again */ 2541 M4OSA_TRACE2_0( 2542 "M4VSS3GPP_intAudioMixingStepAudioReplace():\ 2543 returning M4NO_ERROR (2->3)"); 2544 return M4NO_ERROR; 2545 } 2546 else 2547 { 2548 /** 2549 * The third segment (silence) is only done if supported. 2550 * In other case, we finish here. */ 2551 pC->State = M4VSS3GPP_kAudioMixingState_FINISHED; 2552 2553 /** 2554 * Return with no error so the step function will be called again */ 2555 M4OSA_TRACE2_0( 2556 "M4VSS3GPP_intAudioMixingStepAudioReplace():\ 2557 returning M4NO_ERROR (2->F)"); 2558 return M4NO_ERROR; 2559 } 2560 } 2561 else if( M4NO_ERROR != err ) 2562 { 2563 M4OSA_TRACE1_1( 2564 "M4VSS3GPP_intAudioMixingStepAudioReplace():\ 2565 M4VSS3GPP_intAudioMixingCopyOrig(2) returns 0x%x", 2566 err); 2567 return err; 2568 } 2569 2570 /** 2571 * Check if we reached the end of the clip */ 2572 if( pC->ewc.dATo >= pC->ewc.iOutputDuration ) 2573 { 2574 M4OSA_TRACE3_0( 2575 "M4VSS3GPP_intAudioMixingStepAudioReplace(): Clip duration reached,\ 2576 returning M4WAR_NO_MORE_AU"); 2577 return M4WAR_NO_MORE_AU; /**< Simulate end of file error */ 2578 } 2579 } 2580 break; 2581 2582 /**********************************************************/ 2583 case M4VSS3GPP_kAudioMixingState_AUDIO_THIRD_SEGMENT: 2584 { 2585 /** 2586 * Replace the SID (silence) payload in the writer AU */ 2587 err = M4VSS3GPP_intAudioMixingWriteSilence(pC); 2588 2589 if( M4NO_ERROR != err ) 2590 { 2591 M4OSA_TRACE1_1( 2592 "M4VSS3GPP_intAudioMixingStepAudioMix():\ 2593 M4VSS3GPP_intAudioMixingWriteSilence returns 0x%x", 2594 err); 2595 return err; 2596 } 2597 2598 /** 2599 * Check if we reached the end of the video */ 2600 if( pC->ewc.dATo >= pC->ewc.iOutputDuration ) 2601 { 2602 M4OSA_TRACE3_0( 2603 "M4VSS3GPP_intAudioMixingStepAudioReplace():\ 2604 Video duration reached, returning M4WAR_NO_MORE_AU"); 2605 return M4WAR_NO_MORE_AU; /**< Simulate end of file error */ 2606 } 2607 } 2608 break; 2609 default: 2610 break; 2611 } 2612 2613 /** 2614 * Return with no error */ 2615 M4OSA_TRACE3_0( 2616 "M4VSS3GPP_intAudioMixingStepAudioReplace(): returning M4NO_ERROR"); 2617 return M4NO_ERROR; 2618} 2619 2620/** 2621 ****************************************************************************** 2622 * M4OSA_ERR M4VSS3GPP_intAudioMixingCopyOrig(M4VSS3GPP_InternalAudioMixingContext *pC) 2623 * @brief Read one AU from the original audio file and write it to the output 2624 * @note 2625 * @param pC (IN) VSS audio mixing internal context 2626 ****************************************************************************** 2627 */ 2628static M4OSA_ERR M4VSS3GPP_intAudioMixingCopyOrig( 2629 M4VSS3GPP_InternalAudioMixingContext *pC ) 2630{ 2631 M4OSA_ERR err; 2632 2633 /** 2634 * Read the input original audio AU */ 2635 err = M4VSS3GPP_intClipReadNextAudioFrame(pC->pInputClipCtxt); 2636 2637 M4OSA_TRACE2_3("G .... read : cts = %.0f + %.0f [ 0x%x ]", 2638 pC->pInputClipCtxt->iAudioFrameCts / pC->pInputClipCtxt->scale_audio, 2639 pC->pInputClipCtxt->iAoffset / pC->pInputClipCtxt->scale_audio, 2640 pC->pInputClipCtxt->uiAudioFrameSize); 2641 2642 if( M4NO_ERROR != err ) 2643 { 2644 M4OSA_TRACE3_1( 2645 "M4VSS3GPP_intAudioMixingCopyOrig(): m_pFctGetNextAu(audio) returns 0x%x", 2646 err); 2647 return err; 2648 } 2649 2650 /** 2651 * Get the output AU to write into */ 2652 err = pC->ShellAPI.pWriterDataFcts->pStartAU(pC->ewc.p3gpWriterContext, 2653 M4VSS3GPP_WRITER_AUDIO_STREAM_ID, &pC->ewc.WriterAudioAU); 2654 2655 if( M4NO_ERROR != err ) 2656 { 2657 M4OSA_TRACE1_1( 2658 "M4VSS3GPP_intAudioMixingCopyOrig: pWriterDataFcts->pStartAU(audio) returns 0x%x!", 2659 err); 2660 return err; 2661 } 2662 2663 /** 2664 * Copy the input AU properties to the output AU */ 2665 pC->ewc.WriterAudioAU.size = pC->pInputClipCtxt->uiAudioFrameSize; 2666 pC->ewc.WriterAudioAU.CTS = 2667 pC->pInputClipCtxt->iAudioFrameCts + pC->pInputClipCtxt->iAoffset; 2668 2669 /** 2670 * Copy the AU itself */ 2671 M4OSA_memcpy((M4OSA_MemAddr8)pC->ewc.WriterAudioAU.dataAddress, 2672 pC->pInputClipCtxt->pAudioFramePtr, pC->ewc.WriterAudioAU.size); 2673 2674 /** 2675 * Write the mixed AU */ 2676 M4OSA_TRACE2_2("H ---- write : cts = %ld [ 0x%x ]", 2677 (M4OSA_Int32)(pC->ewc.WriterAudioAU.CTS / pC->ewc.scale_audio), 2678 pC->ewc.WriterAudioAU.size); 2679 2680 err = pC->ShellAPI.pWriterDataFcts->pProcessAU(pC->ewc.p3gpWriterContext, 2681 M4VSS3GPP_WRITER_AUDIO_STREAM_ID, &pC->ewc.WriterAudioAU); 2682 2683 if( M4NO_ERROR != err ) 2684 { 2685 M4OSA_TRACE1_1( 2686 "M4VSS3GPP_intAudioMixingCopyOrig: pWriterDataFcts->pProcessAU(audio) returns 0x%x!", 2687 err); 2688 return err; 2689 } 2690 2691 /** 2692 * Increment the audio CTS for the next step */ 2693 pC->ewc.dATo += pC->ewc.iSilenceFrameDuration / pC->ewc.scale_audio; 2694 2695 /** 2696 * Return with no error */ 2697 M4OSA_TRACE3_0("M4VSS3GPP_intAudioMixingCopyOrig(): returning M4NO_ERROR"); 2698 return M4NO_ERROR; 2699} 2700 2701/** 2702 ****************************************************************************** 2703 * M4OSA_ERR M4VSS3GPP_intAudioMixingCopyAdded(M4VSS3GPP_InternalAudioMixingContext *pC) 2704 * @brief Read one AU from the added audio file and write it to the output 2705 * @note 2706 * @param pC (IN) VSS audio mixing internal context 2707 ****************************************************************************** 2708 */ 2709static M4OSA_ERR M4VSS3GPP_intAudioMixingCopyAdded( 2710 M4VSS3GPP_InternalAudioMixingContext *pC ) 2711{ 2712 M4OSA_ERR err; 2713 2714 if(pC->pAddedClipCtxt->pSettings->ClipProperties.AudioStreamType == M4VIDEOEDITING_kMP3 || 2715 pC->pAddedClipCtxt->pSettings->ClipProperties.AudioStreamType == M4VIDEOEDITING_kPCM || 2716 pC->b_SSRCneeded == M4OSA_TRUE || 2717 pC->ChannelConversion > 0) 2718 { 2719 M4ENCODER_AudioBuffer pEncInBuffer; /**< Encoder input buffer for api */ 2720 M4ENCODER_AudioBuffer 2721 pEncOutBuffer; /**< Encoder output buffer for api */ 2722 M4OSA_Time 2723 frameTimeDelta; /**< Duration of the encoded (then written) data */ 2724 M4OSA_MemAddr8 tempPosBuffer; 2725 2726 err = M4VSS3GPP_intAudioMixingConvert(pC); 2727 2728 if( err == M4VSS3GPP_WAR_END_OF_ADDED_AUDIO ) 2729 { 2730 M4OSA_TRACE2_0( 2731 "M4VSS3GPP_intAudioMixingCopyAdded:\ 2732 M4VSS3GPP_intAudioMixingConvert end of added file"); 2733 return M4NO_ERROR; 2734 } 2735 else if( err != M4NO_ERROR ) 2736 { 2737 M4OSA_TRACE1_1("M4VSS3GPP_intAudioMixingCopyAdded:\ 2738 M4VSS3GPP_intAudioMixingConvert returned 0x%x", err); 2739 return err; 2740 } 2741 2742 /** 2743 * Get the output AU to write into */ 2744 err = pC->ShellAPI.pWriterDataFcts->pStartAU(pC->ewc.p3gpWriterContext, 2745 M4VSS3GPP_WRITER_AUDIO_STREAM_ID, &pC->ewc.WriterAudioAU); 2746 2747 if( M4NO_ERROR != err ) 2748 { 2749 M4OSA_TRACE1_1( 2750 "M4VSS3GPP_intAudioMixingStepAudioMix:\ 2751 pWriterDataFcts->pStartAU(audio) returns 0x%x!", 2752 err); 2753 return err; 2754 } 2755 2756 /* [Mono] or [Stereo interleaved] : all is in one buffer */ 2757 pEncInBuffer.pTableBuffer[0] = pC->pSsrcBufferOut; 2758 pEncInBuffer.pTableBufferSize[0] = 2759 pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize; 2760 pEncInBuffer.pTableBuffer[1] = M4OSA_NULL; 2761 pEncInBuffer.pTableBufferSize[1] = 0; 2762 2763 /* Time in ms from data size, because it is PCM16 samples */ 2764 frameTimeDelta = pEncInBuffer.pTableBufferSize[0] / sizeof(short) 2765 / pC->ewc.uiNbChannels; 2766 2767 /** 2768 * Prepare output buffer */ 2769 pEncOutBuffer.pTableBuffer[0] = 2770 (M4OSA_MemAddr8)pC->ewc.WriterAudioAU.dataAddress; 2771 pEncOutBuffer.pTableBufferSize[0] = 0; 2772 2773 M4OSA_TRACE2_0("K **** blend AUs"); 2774#if 0 2775 2776 { 2777 M4OSA_Char filename[13]; 2778 M4OSA_Context pGIFFileInDebug = M4OSA_NULL; 2779 M4OSA_FilePosition pos = 0; 2780 2781 sprintf(filename, "toto.pcm"); 2782 2783 err = pC->pOsaFileWritPtr->openWrite(&pGIFFileInDebug, filename, 2784 M4OSA_kFileWrite | M4OSA_kFileAppend); 2785 2786 if( err != M4NO_ERROR ) 2787 { 2788 M4OSA_TRACE1_2("Can't open input gif file %s, error: 0x%x\n", 2789 pFile, err); 2790 return err; 2791 } 2792 2793 err = pC->pOsaFileWritPtr->seek(pGIFFileInDebug, M4OSA_kFileSeekEnd, 2794 &pos); 2795 2796 if( err != M4NO_ERROR ) 2797 { 2798 M4OSA_TRACE1_2("Can't seek input gif file %s, error: 0x%x\n", 2799 pFile, err); 2800 return err; 2801 } 2802 2803 err = pC->pOsaFileWritPtr->writeData(pGIFFileInDebug, 2804 pC->pSsrcBufferOut, 2805 pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize); 2806 2807 if( err != M4NO_ERROR ) 2808 { 2809 M4OSA_TRACE1_2("Can't write input gif file %s, error: 0x%x\n", 2810 pFile, err); 2811 return err; 2812 } 2813 2814 err = pC->pOsaFileWritPtr->closeWrite(pGIFFileInDebug); 2815 2816 if( err != M4NO_ERROR ) 2817 { 2818 M4OSA_TRACE1_2("Can't close input gif file %s, error: 0x%x\n", 2819 pFile, err); 2820 return err; 2821 } 2822 } 2823 2824#endif 2825 /** 2826 * Encode the PCM audio */ 2827 2828 err = pC->ShellAPI.pAudioEncoderGlobalFcts->pFctStep( 2829 pC->ewc.pAudioEncCtxt, &pEncInBuffer, &pEncOutBuffer); 2830 2831 if( M4NO_ERROR != err ) 2832 { 2833 M4OSA_TRACE1_1( 2834 "M4VSS3GPP_intAudioMixingDoMixing():\ 2835 pAudioEncoderGlobalFcts->pFctStep returns 0x%x", 2836 err); 2837 return err; 2838 } 2839 2840 /** 2841 * Set AU cts and size */ 2842 pC->ewc.WriterAudioAU.size = 2843 pEncOutBuffer. 2844 pTableBufferSize[0]; /**< Get the size of encoded data */ 2845 pC->ewc.WriterAudioAU.CTS += frameTimeDelta; 2846 2847 /* Update decoded buffer here */ 2848 if( M4OSA_TRUE == pC->b_SSRCneeded || pC->ChannelConversion > 0 ) 2849 { 2850 tempPosBuffer = pC->pSsrcBufferOut 2851 + pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize; 2852 M4OSA_memmove(pC->pSsrcBufferOut, tempPosBuffer, 2853 pC->pPosInSsrcBufferOut - tempPosBuffer); 2854 pC->pPosInSsrcBufferOut -= 2855 pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize; 2856 } 2857 else 2858 { 2859 tempPosBuffer = pC->pSsrcBufferIn + pC->minimumBufferIn; 2860 M4OSA_memmove(pC->pSsrcBufferIn, tempPosBuffer, 2861 pC->pPosInSsrcBufferIn - tempPosBuffer); 2862 pC->pPosInSsrcBufferIn -= pC->minimumBufferIn; 2863 } 2864 2865 /** 2866 * Write the mixed AU */ 2867 M4OSA_TRACE2_2("J ---- write : cts = %ld [ 0x%x ]", 2868 (M4OSA_Int32)(pC->ewc.WriterAudioAU.CTS / pC->ewc.scale_audio), 2869 pC->ewc.WriterAudioAU.size); 2870 2871 err = 2872 pC->ShellAPI.pWriterDataFcts->pProcessAU(pC->ewc.p3gpWriterContext, 2873 M4VSS3GPP_WRITER_AUDIO_STREAM_ID, &pC->ewc.WriterAudioAU); 2874 2875 if( M4NO_ERROR != err ) 2876 { 2877 M4OSA_TRACE1_1( 2878 "M4VSS3GPP_intAudioMixingCopyAdded:\ 2879 pWriterDataFcts->pProcessAU(audio) returns 0x%x!", 2880 err); 2881 return err; 2882 } 2883 2884 /** 2885 * Increment the audio CTS for the next step */ 2886 pC->ewc.dATo += frameTimeDelta / pC->ewc.scale_audio; 2887 } 2888 else 2889 { 2890 /** 2891 * Read the added audio AU */ 2892 err = M4VSS3GPP_intClipReadNextAudioFrame(pC->pAddedClipCtxt); 2893 2894 M4OSA_TRACE2_3("I .... read : cts = %.0f + %.0f [ 0x%x ]", 2895 pC->pAddedClipCtxt->iAudioFrameCts 2896 / pC->pAddedClipCtxt->scale_audio, 2897 pC->pAddedClipCtxt->iAoffset / pC->pAddedClipCtxt->scale_audio, 2898 pC->pAddedClipCtxt->uiAudioFrameSize); 2899 2900 if( M4NO_ERROR != err ) 2901 { 2902 M4OSA_TRACE3_1( 2903 "M4VSS3GPP_intAudioMixingCopyAdded(): m_pFctGetNextAu(audio) returns 0x%x", 2904 err); 2905 return err; 2906 } 2907 2908 /** 2909 * Get the output AU to write into */ 2910 err = pC->ShellAPI.pWriterDataFcts->pStartAU(pC->ewc.p3gpWriterContext, 2911 M4VSS3GPP_WRITER_AUDIO_STREAM_ID, &pC->ewc.WriterAudioAU); 2912 2913 if( M4NO_ERROR != err ) 2914 { 2915 M4OSA_TRACE1_1( 2916 "M4VSS3GPP_intAudioMixingCopyAdded:\ 2917 pWriterDataFcts->pStartAU(audio) returns 0x%x!", 2918 err); 2919 return err; 2920 } 2921 2922 /** 2923 * Copy the input AU properties to the output AU */ 2924 2925 /** THE CHECK BELOW IS ADDED TO PREVENT ISSUES LINKED TO PRE-ALLOCATED MAX AU SIZE 2926 max AU size is set based on M4VSS3GPP_AUDIO_MAX_AU_SIZE defined in file 2927 M4VSS3GPP_InternalConfig.h, If this error occurs increase the limit set in this file 2928 */ 2929 if( pC->pAddedClipCtxt->uiAudioFrameSize > pC->ewc.WriterAudioAU.size ) 2930 { 2931 M4OSA_TRACE1_2( 2932 "ERROR: audio AU size (%d) to copy larger than allocated one (%d) => abort", 2933 pC->pAddedClipCtxt->uiAudioFrameSize, 2934 pC->ewc.WriterAudioAU.size); 2935 M4OSA_TRACE1_0( 2936 "PLEASE CONTACT SUPPORT TO EXTEND MAX AU SIZE IN THE PRODUCT LIBRARY"); 2937 err = M4ERR_UNSUPPORTED_MEDIA_TYPE; 2938 return err; 2939 } 2940 pC->ewc.WriterAudioAU.size = pC->pAddedClipCtxt->uiAudioFrameSize; 2941 pC->ewc.WriterAudioAU.CTS = 2942 pC->pAddedClipCtxt->iAudioFrameCts + pC->pAddedClipCtxt->iAoffset; 2943 2944 /** 2945 * Copy the AU itself */ 2946 M4OSA_memcpy((M4OSA_MemAddr8)pC->ewc.WriterAudioAU.dataAddress, 2947 pC->pAddedClipCtxt->pAudioFramePtr, pC->ewc.WriterAudioAU.size); 2948 2949 /** 2950 * Write the mixed AU */ 2951 M4OSA_TRACE2_2("J ---- write : cts = %ld [ 0x%x ]", 2952 (M4OSA_Int32)(pC->ewc.WriterAudioAU.CTS / pC->ewc.scale_audio), 2953 pC->ewc.WriterAudioAU.size); 2954 2955 err = 2956 pC->ShellAPI.pWriterDataFcts->pProcessAU(pC->ewc.p3gpWriterContext, 2957 M4VSS3GPP_WRITER_AUDIO_STREAM_ID, &pC->ewc.WriterAudioAU); 2958 2959 if( M4NO_ERROR != err ) 2960 { 2961 M4OSA_TRACE1_1( 2962 "M4VSS3GPP_intAudioMixingCopyAdded:\ 2963 pWriterDataFcts->pProcessAU(audio) returns 0x%x!", 2964 err); 2965 return err; 2966 } 2967 2968 /** 2969 * Increment the audio CTS for the next step */ 2970 pC->ewc.dATo += pC->ewc.iSilenceFrameDuration / pC->ewc.scale_audio; 2971 } 2972 2973 /** 2974 * Return with no error */ 2975 M4OSA_TRACE3_0("M4VSS3GPP_intAudioMixingCopyAdded(): returning M4NO_ERROR"); 2976 return M4NO_ERROR; 2977} 2978 2979/** 2980 ****************************************************************************** 2981 * M4OSA_ERR M4VSS3GPP_intAudioMixingConvert(M4VSS3GPP_InternalAudioMixingContext *pC) 2982 * @brief Convert PCM of added track to the right ASF / nb of Channels 2983 * @note 2984 * @param pC (IN) VSS audio mixing internal context 2985 * @return M4NO_ERROR: No error 2986 ****************************************************************************** 2987 */ 2988static M4OSA_ERR M4VSS3GPP_intAudioMixingConvert( 2989 M4VSS3GPP_InternalAudioMixingContext *pC ) 2990{ 2991 M4OSA_ERR err; 2992 int ssrcErr; /**< Error while ssrc processing */ 2993 M4OSA_UInt32 uiChannelConvertorNbSamples = 2994 pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize / sizeof(short) 2995 / pC->pInputClipCtxt->pSettings->ClipProperties.uiNbChannels; 2996 M4OSA_MemAddr8 tempPosBuffer; 2997 2998 M4OSA_UInt32 outFrameCount = uiChannelConvertorNbSamples; 2999 /* Do we need to feed SSRC buffer In ? */ 3000 /** 3001 * RC: This is not really optimum (memmove). We should handle this with linked list. */ 3002 while( pC->pPosInSsrcBufferIn - pC->pSsrcBufferIn < (M4OSA_Int32)pC->minimumBufferIn ) 3003 { 3004 /* We need to get more PCM data */ 3005 if (pC->bNoLooping == M4OSA_TRUE) 3006 { 3007 err = M4WAR_NO_MORE_AU; 3008 } 3009 else 3010 { 3011 err = M4VSS3GPP_intClipReadNextAudioFrame(pC->pAddedClipCtxt); 3012 } 3013 if(pC->bjumpflag) 3014 { 3015 /** 3016 * Jump at the Begin loop time */ 3017 M4OSA_Int32 time = (M4OSA_Int32)(pC->uiBeginLoop); 3018 3019 err = 3020 pC->pAddedClipCtxt->ShellAPI.m_pReader->m_pFctJump\ 3021 (pC->pAddedClipCtxt->pReaderContext, 3022 (M4_StreamHandler*)pC->pAddedClipCtxt->pAudioStream, &time); 3023 if (M4NO_ERROR != err) 3024 { 3025 M4OSA_TRACE1_1("M4VSS3GPP_intAudioMixingConvert():\ 3026 m_pReader->m_pFctJump(audio returns 0x%x", err); 3027 return err; 3028 } 3029 pC->bjumpflag = M4OSA_FALSE; 3030 } 3031 M4OSA_TRACE2_3("E .... read : cts = %.0f + %.0f [ 0x%x ]", 3032 pC->pAddedClipCtxt->iAudioFrameCts / pC->pAddedClipCtxt->scale_audio, 3033 pC->pAddedClipCtxt->iAoffset / pC->pAddedClipCtxt->scale_audio, 3034 pC->pAddedClipCtxt->uiAudioFrameSize); 3035 if( M4WAR_NO_MORE_AU == err ) 3036 { 3037 if(pC->bNoLooping == M4OSA_TRUE) 3038 { 3039 pC->uiEndLoop =0; /* Value 0 means no looping is required */ 3040 } 3041 /** 3042 * Decide what to do when audio is over */ 3043 if( pC->uiEndLoop > 0 ) 3044 { 3045 /** 3046 * Jump at the Begin loop time */ 3047 M4OSA_Int32 time = (M4OSA_Int32)(pC->uiBeginLoop); 3048 3049 err = pC->pAddedClipCtxt->ShellAPI.m_pReader->m_pFctJump( 3050 pC->pAddedClipCtxt->pReaderContext, 3051 (M4_StreamHandler *)pC->pAddedClipCtxt-> 3052 pAudioStream, &time); 3053 3054 if( M4NO_ERROR != err ) 3055 { 3056 M4OSA_TRACE1_1( 3057 "M4VSS3GPP_intAudioMixingConvert():\ 3058 m_pReader->m_pFctJump(audio returns 0x%x", 3059 err); 3060 return err; 3061 } 3062 } 3063 else 3064 { 3065 /* Transition from encoding state to reading state */ 3066 err = M4VSS3GPP_intAudioMixingTransition(pC); 3067 3068 if( M4NO_ERROR != err ) 3069 { 3070 M4OSA_TRACE1_1( 3071 "M4VSS3GPP_intAudioMixingStepAudioMix(): pre-encode fails err = 0x%x", 3072 err); 3073 return err; 3074 } 3075 3076 /** 3077 * Second segment is over, state transition to third and return OK */ 3078 pC->State = M4VSS3GPP_kAudioMixingState_AUDIO_THIRD_SEGMENT; 3079 3080 /** 3081 * Return with no error so the step function will be called again */ 3082 M4OSA_TRACE2_0( 3083 "M4VSS3GPP_intAudioMixingConvert():\ 3084 returning M4VSS3GPP_WAR_END_OF_ADDED_AUDIO (2->3) a"); 3085 return M4VSS3GPP_WAR_END_OF_ADDED_AUDIO; 3086 } 3087 } 3088 else if( M4NO_ERROR != err ) 3089 { 3090 M4OSA_TRACE1_1( 3091 "M4VSS3GPP_intAudioMixingConvert(): m_pFctGetNextAu(audio) returns 0x%x", 3092 err); 3093 return err; 3094 } 3095 3096 err = M4VSS3GPP_intClipDecodeCurrentAudioFrame(pC->pAddedClipCtxt); 3097 3098 if( M4NO_ERROR != err ) 3099 { 3100 M4OSA_TRACE1_1( 3101 "M4VSS3GPP_intAudioMixingDoMixing:\ 3102 M4VSS3GPP_intClipDecodeCurrentAudioFrame(added) returns 0x%x", 3103 err); 3104 return M4VSS3GPP_ERR_INPUT_AUDIO_CORRUPTED_AU; 3105 } 3106 3107 /* Copy decoded data into SSRC buffer in */ 3108 M4OSA_memcpy(pC->pPosInSsrcBufferIn, 3109 pC->pAddedClipCtxt->AudioDecBufferOut.m_dataAddress, 3110 pC->pAddedClipCtxt->AudioDecBufferOut.m_bufferSize); 3111 /* Update position pointer into SSRC buffer In */ 3112 3113 pC->pPosInSsrcBufferIn += 3114 pC->pAddedClipCtxt->AudioDecBufferOut.m_bufferSize; 3115 } 3116 3117 /* Do the resampling / channel conversion if needed (=feed buffer out) */ 3118 if( pC->b_SSRCneeded == M4OSA_TRUE ) 3119 { 3120 pC->ChannelConversion = 0; 3121 if( pC->ChannelConversion > 0 ) 3122 { 3123 while( pC->pPosInTempBuffer - pC->pTempBuffer 3124 < (M4OSA_Int32)(pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize 3125 *pC->pAddedClipCtxt->pSettings->ClipProperties.uiNbChannels) 3126 / pC->ChannelConversion ) 3127 /* We use ChannelConversion variable because in case 2, we need twice less data */ 3128 { 3129 ssrcErr = 0; 3130 M4OSA_memset(pC->pPosInTempBuffer, 3131 (pC->iSsrcNbSamplOut * sizeof(short) * pC->ewc.uiNbChannels),0); 3132 3133 LVAudioresample_LowQuality((short*)pC->pPosInTempBuffer, 3134 (short*)pC->pSsrcBufferIn, 3135 pC->iSsrcNbSamplOut, 3136 pC->pLVAudioResampler); 3137 if( 0 != ssrcErr ) 3138 { 3139 M4OSA_TRACE1_1( 3140 "M4VSS3GPP_intAudioMixingConvert: SSRC_Process returns 0x%x, returning ", 3141 ssrcErr); 3142 return ssrcErr; 3143 } 3144 3145 pC->pPosInTempBuffer += pC->iSsrcNbSamplOut * sizeof(short) 3146 * pC->pAddedClipCtxt->pSettings-> 3147 ClipProperties.uiNbChannels; 3148 3149 /* Update SSRC bufferIn */ 3150 tempPosBuffer = 3151 pC->pSsrcBufferIn + (pC->iSsrcNbSamplIn * sizeof(short) 3152 * pC->pAddedClipCtxt->pSettings-> 3153 ClipProperties.uiNbChannels); 3154 M4OSA_memmove(pC->pSsrcBufferIn, tempPosBuffer, 3155 pC->pPosInSsrcBufferIn - tempPosBuffer); 3156 pC->pPosInSsrcBufferIn -= pC->iSsrcNbSamplIn * sizeof(short) 3157 * pC->pAddedClipCtxt->pSettings-> 3158 ClipProperties.uiNbChannels; 3159 } 3160 } 3161 else 3162 { 3163 while( pC->pPosInSsrcBufferOut - pC->pSsrcBufferOut 3164 < (M4OSA_Int32)pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize ) 3165 { 3166 ssrcErr = 0; 3167 M4OSA_memset(pC->pPosInSsrcBufferOut, 3168 (pC->iSsrcNbSamplOut * sizeof(short) * pC->ewc.uiNbChannels),0); 3169 3170 LVAudioresample_LowQuality((short*)pC->pPosInSsrcBufferOut, 3171 (short*)pC->pSsrcBufferIn, 3172 pC->iSsrcNbSamplOut, 3173 pC->pLVAudioResampler); 3174 if( 0 != ssrcErr ) 3175 { 3176 M4OSA_TRACE1_1( 3177 "M4VSS3GPP_intAudioMixingConvert: SSRC_Process returns 0x%x, returning ", 3178 ssrcErr); 3179 return ssrcErr; 3180 } 3181 pC->pPosInSsrcBufferOut += 3182 pC->iSsrcNbSamplOut * sizeof(short) * pC->ewc.uiNbChannels; 3183 3184 /* Update SSRC bufferIn */ 3185 tempPosBuffer = 3186 pC->pSsrcBufferIn + (pC->iSsrcNbSamplIn * sizeof(short) 3187 * pC->pAddedClipCtxt->pSettings-> 3188 ClipProperties.uiNbChannels); 3189 M4OSA_memmove(pC->pSsrcBufferIn, tempPosBuffer, 3190 pC->pPosInSsrcBufferIn - tempPosBuffer); 3191 pC->pPosInSsrcBufferIn -= pC->iSsrcNbSamplIn * sizeof(short) 3192 * pC->pAddedClipCtxt->pSettings-> 3193 ClipProperties.uiNbChannels; 3194 } 3195 } 3196 3197 /* Convert Stereo<->Mono */ 3198 switch( pC->ChannelConversion ) 3199 { 3200 case 0: /* No channel conversion */ 3201 break; 3202 3203 case 1: /* stereo to mono */ 3204 if( pC->pPosInSsrcBufferOut - pC->pSsrcBufferOut 3205 < (M4OSA_Int32)pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize ) 3206 { 3207 From2iToMono_16((short *)pC->pTempBuffer, 3208 (short *)pC->pSsrcBufferOut, 3209 (short)(uiChannelConvertorNbSamples)); 3210 /* Update pTempBuffer */ 3211 tempPosBuffer = pC->pTempBuffer 3212 + (uiChannelConvertorNbSamples * sizeof(short) 3213 * pC->pAddedClipCtxt->pSettings-> 3214 ClipProperties. 3215 uiNbChannels); /* Buffer is in bytes */ 3216 M4OSA_memmove(pC->pTempBuffer, tempPosBuffer, 3217 pC->pPosInTempBuffer - tempPosBuffer); 3218 pC->pPosInTempBuffer -= 3219 (uiChannelConvertorNbSamples * sizeof(short) 3220 * pC->pAddedClipCtxt->pSettings-> 3221 ClipProperties.uiNbChannels); 3222 pC->pPosInSsrcBufferOut += 3223 pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize; 3224 } 3225 break; 3226 3227 case 2: /* mono to stereo */ 3228 if( pC->pPosInSsrcBufferOut - pC->pSsrcBufferOut 3229 < (M4OSA_Int32)pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize ) 3230 { 3231 MonoTo2I_16((short *)pC->pTempBuffer, 3232 (short *)pC->pSsrcBufferOut, 3233 (short)uiChannelConvertorNbSamples); 3234 tempPosBuffer = pC->pTempBuffer 3235 + (uiChannelConvertorNbSamples * sizeof(short) 3236 * pC->pAddedClipCtxt->pSettings-> 3237 ClipProperties.uiNbChannels); 3238 M4OSA_memmove(pC->pTempBuffer, tempPosBuffer, 3239 pC->pPosInTempBuffer - tempPosBuffer); 3240 pC->pPosInTempBuffer -= 3241 (uiChannelConvertorNbSamples * sizeof(short) 3242 * pC->pAddedClipCtxt->pSettings-> 3243 ClipProperties.uiNbChannels); 3244 pC->pPosInSsrcBufferOut += 3245 pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize; 3246 } 3247 break; 3248 } 3249 } 3250 else if( pC->ChannelConversion > 0 ) 3251 { 3252 //M4OSA_UInt32 uiChannelConvertorNbSamples = 3253 // pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize / sizeof(short) / 3254 // pC->pInputClipCtxt->pSettings->ClipProperties.uiNbChannels; 3255 /* Convert Stereo<->Mono */ 3256 switch( pC->ChannelConversion ) 3257 { 3258 case 0: /* No channel conversion */ 3259 break; 3260 3261 case 1: /* stereo to mono */ 3262 if( pC->pPosInSsrcBufferOut - pC->pSsrcBufferOut 3263 < (M4OSA_Int32)pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize ) 3264 { 3265 From2iToMono_16((short *)pC->pSsrcBufferIn, 3266 (short *)pC->pSsrcBufferOut, 3267 (short)(uiChannelConvertorNbSamples)); 3268 /* Update pTempBuffer */ 3269 tempPosBuffer = pC->pSsrcBufferIn 3270 + (uiChannelConvertorNbSamples * sizeof(short) 3271 * pC->pAddedClipCtxt->pSettings-> 3272 ClipProperties. 3273 uiNbChannels); /* Buffer is in bytes */ 3274 M4OSA_memmove(pC->pSsrcBufferIn, tempPosBuffer, 3275 pC->pPosInSsrcBufferIn - tempPosBuffer); 3276 pC->pPosInSsrcBufferIn -= 3277 (uiChannelConvertorNbSamples * sizeof(short) 3278 * pC->pAddedClipCtxt->pSettings-> 3279 ClipProperties.uiNbChannels); 3280 pC->pPosInSsrcBufferOut += 3281 pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize; 3282 } 3283 break; 3284 3285 case 2: /* mono to stereo */ 3286 if( pC->pPosInSsrcBufferOut - pC->pSsrcBufferOut 3287 < (M4OSA_Int32)pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize ) 3288 { 3289 MonoTo2I_16((short *)pC->pSsrcBufferIn, 3290 (short *)pC->pSsrcBufferOut, 3291 (short)uiChannelConvertorNbSamples); 3292 tempPosBuffer = pC->pSsrcBufferIn 3293 + (uiChannelConvertorNbSamples * sizeof(short) 3294 * pC->pAddedClipCtxt->pSettings-> 3295 ClipProperties.uiNbChannels); 3296 M4OSA_memmove(pC->pSsrcBufferIn, tempPosBuffer, 3297 pC->pPosInSsrcBufferIn - tempPosBuffer); 3298 pC->pPosInSsrcBufferIn -= 3299 (uiChannelConvertorNbSamples * sizeof(short) 3300 * pC->pAddedClipCtxt->pSettings-> 3301 ClipProperties.uiNbChannels); 3302 pC->pPosInSsrcBufferOut += 3303 pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize; 3304 } 3305 break; 3306 } 3307 } 3308 else 3309 { 3310 /* No channel conversion nor sampl. freq. conversion needed, just buffer management */ 3311 pC->pPosInSsrcBufferOut = pC->pPosInSsrcBufferIn; 3312 } 3313 3314 return M4NO_ERROR; 3315} 3316 3317M4OSA_Int32 M4VSS3GPP_getDecibelSound( M4OSA_UInt32 value ) 3318 { 3319 int dbSound = 1; 3320 3321 if( value == 0 ) 3322 return 0; 3323 3324 if( value > 0x4000 && value <= 0x8000 ) // 32768 3325 dbSound = 90; 3326 3327 else if( value > 0x2000 && value <= 0x4000 ) // 16384 3328 dbSound = 84; 3329 3330 else if( value > 0x1000 && value <= 0x2000 ) // 8192 3331 dbSound = 78; 3332 3333 else if( value > 0x0800 && value <= 0x1000 ) // 4028 3334 dbSound = 72; 3335 3336 else if( value > 0x0400 && value <= 0x0800 ) // 2048 3337 dbSound = 66; 3338 3339 else if( value > 0x0200 && value <= 0x0400 ) // 1024 3340 dbSound = 60; 3341 3342 else if( value > 0x0100 && value <= 0x0200 ) // 512 3343 dbSound = 54; 3344 3345 else if( value > 0x0080 && value <= 0x0100 ) // 256 3346 dbSound = 48; 3347 3348 else if( value > 0x0040 && value <= 0x0080 ) // 128 3349 dbSound = 42; 3350 3351 else if( value > 0x0020 && value <= 0x0040 ) // 64 3352 dbSound = 36; 3353 3354 else if( value > 0x0010 && value <= 0x0020 ) // 32 3355 dbSound = 30; 3356 3357 else if( value > 0x0008 && value <= 0x0010 ) //16 3358 dbSound = 24; 3359 3360 else if( value > 0x0007 && value <= 0x0008 ) //8 3361 dbSound = 24; 3362 3363 else if( value > 0x0003 && value <= 0x0007 ) // 4 3364 dbSound = 18; 3365 3366 else if( value > 0x0001 && value <= 0x0003 ) //2 3367 dbSound = 12; 3368 3369 else if( value > 0x000 && value <= 0x0001 ) // 1 3370 dbSound = 6; 3371 3372 else 3373 dbSound = 0; 3374 3375 return dbSound; 3376 } 3377/** 3378 ****************************************************************************** 3379 * M4OSA_ERR M4VSS3GPP_intAudioMixingDoMixing(M4VSS3GPP_InternalAudioMixingContext *pC) 3380 * @brief Mix the current audio AUs (decoder, mix, encode) 3381 * @note 3382 * @param pC (IN) VSS audio mixing internal context 3383 * @return M4NO_ERROR: No error 3384 ****************************************************************************** 3385 */ 3386static M4OSA_ERR M4VSS3GPP_intAudioMixingDoMixing( 3387 M4VSS3GPP_InternalAudioMixingContext *pC ) 3388{ 3389 M4OSA_ERR err; 3390 M4OSA_Int16 *pPCMdata1; 3391 M4OSA_Int16 *pPCMdata2; 3392 M4OSA_UInt32 uiPCMsize; 3393 3394 M4ENCODER_AudioBuffer pEncInBuffer; /**< Encoder input buffer for api */ 3395 M4ENCODER_AudioBuffer pEncOutBuffer; /**< Encoder output buffer for api */ 3396 M4OSA_Time 3397 frameTimeDelta; /**< Duration of the encoded (then written) data */ 3398 M4OSA_MemAddr8 tempPosBuffer; 3399 /* ducking variable */ 3400 M4OSA_UInt16 loopIndex = 0; 3401 M4OSA_Int16 *pPCM16Sample = M4OSA_NULL; 3402 M4OSA_Int32 peakDbValue = 0; 3403 M4OSA_Int32 previousDbValue = 0; 3404 M4OSA_UInt32 i; 3405 3406 /** 3407 * Decode original audio track AU */ 3408 3409 err = M4VSS3GPP_intClipDecodeCurrentAudioFrame(pC->pInputClipCtxt); 3410 3411 if( M4NO_ERROR != err ) 3412 { 3413 M4OSA_TRACE1_1( 3414 "M4VSS3GPP_intAudioMixingDoMixing:\ 3415 M4VSS3GPP_intClipDecodeCurrentAudioFrame(orig) returns 0x%x", 3416 err); 3417 return M4VSS3GPP_ERR_INPUT_AUDIO_CORRUPTED_AU; 3418 } 3419 3420 if( M4OSA_TRUE == pC->b_SSRCneeded || pC->ChannelConversion > 0 3421 || pC->pAddedClipCtxt->pSettings->ClipProperties.AudioStreamType 3422 == M4VIDEOEDITING_kMP3 ) 3423 { 3424 err = M4VSS3GPP_intAudioMixingConvert(pC); 3425 3426 if( err == M4VSS3GPP_WAR_END_OF_ADDED_AUDIO ) 3427 { 3428 return err; 3429 } 3430 3431 if( err != M4NO_ERROR ) 3432 { 3433 M4OSA_TRACE1_1( 3434 "M4VSS3GPP_intAudioMixingDoMixing: M4VSS3GPP_intAudioMixingConvert returned 0x%x", 3435 err); 3436 return M4VSS3GPP_ERR_AUDIO_DECODED_PCM_SIZE_ISSUE; 3437 } 3438 3439 /** 3440 * Get the output AU to write into */ 3441 err = pC->ShellAPI.pWriterDataFcts->pStartAU(pC->ewc.p3gpWriterContext, 3442 M4VSS3GPP_WRITER_AUDIO_STREAM_ID, &pC->ewc.WriterAudioAU); 3443 3444 if( M4NO_ERROR != err ) 3445 { 3446 M4OSA_TRACE1_1( 3447 "M4VSS3GPP_intAudioMixingStepAudioMix:\ 3448 pWriterDataFcts->pStartAU(audio) returns 0x%x!", 3449 err); 3450 return err; 3451 } 3452 3453 pPCMdata2 = (M4OSA_Int16 *)pC->pSsrcBufferOut; 3454 } 3455 else 3456 { 3457 /** 3458 * Decode added audio track AU */ 3459 err = M4VSS3GPP_intClipDecodeCurrentAudioFrame(pC->pAddedClipCtxt); 3460 3461 if( M4NO_ERROR != err ) 3462 { 3463 M4OSA_TRACE1_1( 3464 "M4VSS3GPP_intAudioMixingDoMixing:\ 3465 M4VSS3GPP_intClipDecodeCurrentAudioFrame(added) returns 0x%x", 3466 err); 3467 return M4VSS3GPP_ERR_INPUT_AUDIO_CORRUPTED_AU; 3468 } 3469 3470 /** 3471 * Check both clips decoded the same amount of PCM samples */ 3472 if( pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize 3473 != pC->pAddedClipCtxt->AudioDecBufferOut.m_bufferSize ) 3474 { 3475 M4OSA_TRACE1_0( 3476 "M4VSS3GPP_intAudioMixingDoMixing:\ 3477 both clips AU must have the same decoded PCM size!"); 3478 return M4VSS3GPP_ERR_AUDIO_DECODED_PCM_SIZE_ISSUE; 3479 } 3480 pPCMdata2 = (M4OSA_Int16 *)pC->pAddedClipCtxt->AudioDecBufferOut.m_dataAddress; 3481 } 3482 3483 /** 3484 * Mix the two decoded PCM audios */ 3485 pPCMdata1 = 3486 (M4OSA_Int16 *)pC->pInputClipCtxt->AudioDecBufferOut.m_dataAddress; 3487 uiPCMsize = pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize 3488 / 2; /*buffer size (bytes) to number of sample (int16)*/ 3489 3490 if( pC->b_DuckingNeedeed ) 3491 { 3492 loopIndex = 0; 3493 peakDbValue = 0; 3494 previousDbValue = peakDbValue; 3495 3496 pPCM16Sample = (M4OSA_Int16 *)pC->pInputClipCtxt-> 3497 AudioDecBufferOut.m_dataAddress; 3498 3499 //Calculate the peak value 3500 while( loopIndex 3501 < pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize 3502 / sizeof(M4OSA_Int16) ) 3503 { 3504 if( pPCM16Sample[loopIndex] >= 0 ) 3505 { 3506 peakDbValue = previousDbValue > pPCM16Sample[loopIndex] 3507 ? previousDbValue : pPCM16Sample[loopIndex]; 3508 previousDbValue = peakDbValue; 3509 } 3510 else 3511 { 3512 peakDbValue = previousDbValue > -pPCM16Sample[loopIndex] 3513 ? previousDbValue : -pPCM16Sample[loopIndex]; 3514 previousDbValue = peakDbValue; 3515 } 3516 loopIndex++; 3517 } 3518 3519 pC->audioVolumeArray[pC->audVolArrIndex] = 3520 M4VSS3GPP_getDecibelSound(peakDbValue); 3521 3522 /* WINDOW_SIZE is 10 by default and check for threshold is done after 10 cycles */ 3523 if( pC->audVolArrIndex >= WINDOW_SIZE - 1 ) 3524 { 3525 pC->bDoDucking = 3526 M4VSS3GPP_isThresholdBreached((M4OSA_Int32 *)&(pC->audioVolumeArray), 3527 pC->audVolArrIndex, pC->InDucking_threshold); 3528 3529 pC->audVolArrIndex = 0; 3530 } 3531 else 3532 { 3533 pC->audVolArrIndex++; 3534 } 3535 3536 /* 3537 *Below logic controls the mixing weightage for Background Track and Primary Track 3538 *for the duration of window under analysis to give fade-out for Background and fade-in 3539 *for primary 3540 * 3541 *Current fading factor is distributed in equal range over the defined window size. 3542 * 3543 *For a window size = 25 (500 ms (window under analysis) / 20 ms (sample duration)) 3544 * 3545 */ 3546 3547 if( pC->bDoDucking ) 3548 { 3549 if( pC->duckingFactor 3550 > pC->InDucking_lowVolume ) // FADE OUT BG Track 3551 { 3552 // decrement ducking factor in total steps in factor of low volume steps to reach 3553 // low volume level 3554 pC->duckingFactor -= (pC->InDucking_lowVolume); 3555 } 3556 else 3557 { 3558 pC->duckingFactor = pC->InDucking_lowVolume; 3559 } 3560 } 3561 else 3562 { 3563 if( pC->duckingFactor < 1.0 ) // FADE IN BG Track 3564 { 3565 // increment ducking factor in total steps of low volume factor to reach 3566 // orig.volume level 3567 pC->duckingFactor += (pC->InDucking_lowVolume); 3568 } 3569 else 3570 { 3571 pC->duckingFactor = 1.0; 3572 } 3573 } 3574 /* endif - ducking_enable */ 3575 3576 /* Mixing Logic */ 3577 3578 while( uiPCMsize-- > 0 ) 3579 { 3580 M4OSA_Int32 temp; 3581 3582 /* set vol factor for BT and PT */ 3583 *pPCMdata2 = (M4OSA_Int16)(*pPCMdata2 * pC->fBTVolLevel); 3584 3585 *pPCMdata1 = (M4OSA_Int16)(*pPCMdata1 * pC->fPTVolLevel); 3586 3587 /* mix the two samples */ 3588 3589 *pPCMdata2 = (M4OSA_Int16)(( *pPCMdata2) * (pC->duckingFactor)); 3590 *pPCMdata1 = (M4OSA_Int16)(*pPCMdata2 / 2 + *pPCMdata1 / 2); 3591 3592 3593 if( *pPCMdata1 < 0 ) 3594 { 3595 temp = -( *pPCMdata1) 3596 * 2; // bring to same Amplitude level as it was original 3597 3598 if( temp > 32767 ) 3599 { 3600 *pPCMdata1 = -32766; // less then max allowed value 3601 } 3602 else 3603 { 3604 *pPCMdata1 = (M4OSA_Int16)(-temp); 3605 } 3606 } 3607 else 3608 { 3609 temp = ( *pPCMdata1) 3610 * 2; // bring to same Amplitude level as it was original 3611 3612 if( temp > 32768 ) 3613 { 3614 *pPCMdata1 = 32767; // less than max allowed value 3615 } 3616 else 3617 { 3618 *pPCMdata1 = (M4OSA_Int16)temp; 3619 } 3620 } 3621 3622 pPCMdata2++; 3623 pPCMdata1++; 3624 } 3625 } 3626 else 3627 { 3628 while( uiPCMsize-- > 0 ) 3629 { 3630 /* mix the two samples */ 3631 *pPCMdata1 = (M4OSA_Int16)(*pPCMdata1 * pC->fOrigFactor * pC->fPTVolLevel 3632 + *pPCMdata2 * pC->fAddedFactor * pC->fBTVolLevel ); 3633 3634 pPCMdata1++; 3635 pPCMdata2++; 3636 } 3637 } 3638 3639 /* Update pC->pSsrcBufferOut buffer */ 3640 3641 if( M4OSA_TRUE == pC->b_SSRCneeded || pC->ChannelConversion > 0 ) 3642 { 3643 tempPosBuffer = pC->pSsrcBufferOut 3644 + pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize; 3645 M4OSA_memmove(pC->pSsrcBufferOut, tempPosBuffer, 3646 pC->pPosInSsrcBufferOut - tempPosBuffer); 3647 pC->pPosInSsrcBufferOut -= 3648 pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize; 3649 } 3650 else if( pC->pAddedClipCtxt->pSettings->ClipProperties.AudioStreamType 3651 == M4VIDEOEDITING_kMP3 ) 3652 { 3653 tempPosBuffer = pC->pSsrcBufferIn 3654 + pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize; 3655 M4OSA_memmove(pC->pSsrcBufferIn, tempPosBuffer, 3656 pC->pPosInSsrcBufferIn - tempPosBuffer); 3657 pC->pPosInSsrcBufferIn -= 3658 pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize; 3659 } 3660 3661 /* [Mono] or [Stereo interleaved] : all is in one buffer */ 3662 pEncInBuffer.pTableBuffer[0] = 3663 pC->pInputClipCtxt->AudioDecBufferOut.m_dataAddress; 3664 pEncInBuffer.pTableBufferSize[0] = 3665 pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize; 3666 pEncInBuffer.pTableBuffer[1] = M4OSA_NULL; 3667 pEncInBuffer.pTableBufferSize[1] = 0; 3668 3669 /* Time in ms from data size, because it is PCM16 samples */ 3670 frameTimeDelta = 3671 pEncInBuffer.pTableBufferSize[0] / sizeof(short) / pC->ewc.uiNbChannels; 3672 3673 /** 3674 * Prepare output buffer */ 3675 pEncOutBuffer.pTableBuffer[0] = 3676 (M4OSA_MemAddr8)pC->ewc.WriterAudioAU.dataAddress; 3677 pEncOutBuffer.pTableBufferSize[0] = 0; 3678 3679 M4OSA_TRACE2_0("K **** blend AUs"); 3680 3681 /** 3682 * Encode the PCM audio */ 3683 err = pC->ShellAPI.pAudioEncoderGlobalFcts->pFctStep(pC->ewc.pAudioEncCtxt, 3684 &pEncInBuffer, &pEncOutBuffer); 3685 3686 if( M4NO_ERROR != err ) 3687 { 3688 M4OSA_TRACE1_1( 3689 "M4VSS3GPP_intAudioMixingDoMixing(): pAudioEncoderGlobalFcts->pFctStep returns 0x%x", 3690 err); 3691 return err; 3692 } 3693 3694 /** 3695 * Set AU cts and size */ 3696 pC->ewc.WriterAudioAU.size = 3697 pEncOutBuffer.pTableBufferSize[0]; /**< Get the size of encoded data */ 3698 pC->ewc.WriterAudioAU.CTS += frameTimeDelta; 3699 3700 /** 3701 * Write the AU */ 3702 M4OSA_TRACE2_2("L ---- write : cts = %ld [ 0x%x ]", 3703 (M4OSA_Int32)(pC->ewc.WriterAudioAU.CTS / pC->ewc.scale_audio), 3704 pC->ewc.WriterAudioAU.size); 3705 3706 err = pC->ShellAPI.pWriterDataFcts->pProcessAU(pC->ewc.p3gpWriterContext, 3707 M4VSS3GPP_WRITER_AUDIO_STREAM_ID, &pC->ewc.WriterAudioAU); 3708 3709 if( M4NO_ERROR != err ) 3710 { 3711 M4OSA_TRACE1_1( 3712 "M4VSS3GPP_intAudioMixingDoMixing: pWriterDataFcts->pProcessAU returns 0x%x!", 3713 err); 3714 return err; 3715 } 3716 3717 /** 3718 * Increment the audio CTS for the next step */ 3719 pC->ewc.dATo += frameTimeDelta / pC->ewc.scale_audio; 3720 3721 /** 3722 * Return with no error */ 3723 M4OSA_TRACE3_0("M4VSS3GPP_intAudioMixingDoMixing(): returning M4NO_ERROR"); 3724 return M4NO_ERROR; 3725} 3726 3727/** 3728 ****************************************************************************** 3729 * M4OSA_ERR M4VSS3GPP_intAudioMixingTransition(M4VSS3GPP_InternalAudioMixingContext *pC) 3730 * @brief Decode/encode a few AU backward to initiate the encoder for later Mix segment. 3731 * @note 3732 * @param pC (IN) VSS audio mixing internal context 3733 * @return M4NO_ERROR: No error 3734 ****************************************************************************** 3735 */ 3736static M4OSA_ERR M4VSS3GPP_intAudioMixingTransition( 3737 M4VSS3GPP_InternalAudioMixingContext *pC ) 3738{ 3739 M4OSA_ERR err; 3740 3741 M4ENCODER_AudioBuffer pEncInBuffer; /**< Encoder input buffer for api */ 3742 M4ENCODER_AudioBuffer pEncOutBuffer; /**< Encoder output buffer for api */ 3743 M4OSA_Time 3744 frameTimeDelta = 0; /**< Duration of the encoded (then written) data */ 3745 3746 M4OSA_Int32 iTargetCts, iCurrentCts; 3747 3748 /** 3749 * 'BZZZ' bug fix: 3750 * add a silence frame */ 3751 err = M4VSS3GPP_intAudioMixingWriteSilence(pC); 3752 3753 if( M4NO_ERROR != err ) 3754 { 3755 M4OSA_TRACE1_1( 3756 "M4VSS3GPP_intAudioMixingTransition():\ 3757 M4VSS3GPP_intAudioMixingWriteSilence returns 0x%x", 3758 err); 3759 return err; 3760 } 3761 3762 iCurrentCts = (M4OSA_Int32)(pC->ewc.dATo * pC->ewc.scale_audio + 0.5); 3763 3764 /* Do not do pre-encode step if there is no mixing (remove, 100 %, or not editable) */ 3765 if( M4OSA_FALSE == pC->bAudioMixingIsNeeded ) 3766 { 3767 /** 3768 * Advance in the original audio stream to reach the current time 3769 * (We don't want iAudioCTS to be modified by the jump function, 3770 * so we have to use a local variable). */ 3771 err = M4VSS3GPP_intClipJumpAudioAt(pC->pInputClipCtxt, &iCurrentCts); 3772 3773 if( M4NO_ERROR != err ) 3774 { 3775 M4OSA_TRACE1_1("M4VSS3GPP_intAudioMixingTransition:\ 3776 M4VSS3GPP_intClipJumpAudioAt() returns 0x%x!", err); 3777 return err; 3778 } 3779 } 3780 else 3781 { 3782 /**< don't try to pre-decode if clip is at its beginning... */ 3783 if( iCurrentCts > 0 ) 3784 { 3785 /** 3786 * Get the output AU to write into */ 3787 err = pC->ShellAPI.pWriterDataFcts->pStartAU( 3788 pC->ewc.p3gpWriterContext, M4VSS3GPP_WRITER_AUDIO_STREAM_ID, 3789 &pC->ewc.WriterAudioAU); 3790 3791 if( M4NO_ERROR != err ) 3792 { 3793 M4OSA_TRACE1_1( 3794 "M4VSS3GPP_intAudioMixingTransition:\ 3795 pWriterDataFcts->pStartAU(audio) returns 0x%x!", 3796 err); 3797 return err; 3798 } 3799 3800 /** 3801 * Jump a few AUs backward */ 3802 iTargetCts = iCurrentCts - M4VSS3GPP_NB_AU_PREFETCH 3803 * pC->ewc.iSilenceFrameDuration; 3804 3805 if( iTargetCts < 0 ) 3806 { 3807 iTargetCts = 0; /**< Sanity check */ 3808 } 3809 3810 err = M4VSS3GPP_intClipJumpAudioAt(pC->pInputClipCtxt, &iTargetCts); 3811 3812 if( M4NO_ERROR != err ) 3813 { 3814 M4OSA_TRACE1_1( 3815 "M4VSS3GPP_intAudioMixingTransition: DECODE_ENCODE-prefetch:\ 3816 M4VSS3GPP_intClipJumpAudioAt returns 0x%x!", 3817 err); 3818 return err; 3819 } 3820 3821 /** 3822 * Decode/encode up to the wanted position */ 3823 while( pC->pInputClipCtxt->iAudioFrameCts < iCurrentCts ) 3824 { 3825 err = M4VSS3GPP_intClipReadNextAudioFrame(pC->pInputClipCtxt); 3826 3827 M4OSA_TRACE2_3("M .... read : cts = %.0f + %.0f [ 0x%x ]", 3828 pC->pInputClipCtxt->iAudioFrameCts 3829 / pC->pInputClipCtxt->scale_audio, 3830 pC->pInputClipCtxt->iAoffset 3831 / pC->pInputClipCtxt->scale_audio, 3832 pC->pInputClipCtxt->uiAudioFrameSize); 3833 3834 if( M4OSA_ERR_IS_ERROR(err) ) 3835 { 3836 M4OSA_TRACE1_1( 3837 "M4VSS3GPP_intAudioMixingTransition: DECODE_ENCODE-prefetch:\ 3838 M4VSS3GPP_intClipReadNextAudioFrame(b) returns 0x%x!", 3839 err); 3840 return err; 3841 } 3842 3843 err = M4VSS3GPP_intClipDecodeCurrentAudioFrame( 3844 pC->pInputClipCtxt); 3845 3846 if( M4NO_ERROR != err ) 3847 { 3848 M4OSA_TRACE1_1( 3849 "M4VSS3GPP_intAudioMixingTransition: DECODE_ENCODE-prefetch:\ 3850 M4VSS3GPP_intClipDecodeCurrentAudioFrame returns 0x%x!", 3851 err); 3852 return err; 3853 } 3854 3855 /* [Mono] or [Stereo interleaved] : all is in one buffer */ 3856 pEncInBuffer.pTableBuffer[0] = 3857 pC->pInputClipCtxt->AudioDecBufferOut.m_dataAddress; 3858 pEncInBuffer.pTableBufferSize[0] = 3859 pC->pInputClipCtxt->AudioDecBufferOut.m_bufferSize; 3860 pEncInBuffer.pTableBuffer[1] = M4OSA_NULL; 3861 pEncInBuffer.pTableBufferSize[1] = 0; 3862 3863 /* Time in ms from data size, because it is PCM16 samples */ 3864 frameTimeDelta = 3865 pEncInBuffer.pTableBufferSize[0] / sizeof(short) 3866 / pC->ewc.uiNbChannels; 3867 3868 /** 3869 * Prepare output buffer */ 3870 pEncOutBuffer.pTableBuffer[0] = 3871 (M4OSA_MemAddr8)pC->ewc.WriterAudioAU.dataAddress; 3872 pEncOutBuffer.pTableBufferSize[0] = 0; 3873 3874 M4OSA_TRACE2_0("N **** pre-encode"); 3875 3876 /** 3877 * Encode the PCM audio */ 3878 err = pC->ShellAPI.pAudioEncoderGlobalFcts->pFctStep( 3879 pC->ewc.pAudioEncCtxt, &pEncInBuffer, &pEncOutBuffer); 3880 3881 if( M4NO_ERROR != err ) 3882 { 3883 M4OSA_TRACE1_1( 3884 "M4VSS3GPP_intAudioMixingTransition():\ 3885 pAudioEncoderGlobalFcts->pFctStep returns 0x%x", 3886 err); 3887 return err; 3888 } 3889 } 3890 3891 /** 3892 * Set AU cts and size */ 3893 pC->ewc.WriterAudioAU.size = pEncOutBuffer.pTableBufferSize[ 3894 0]; /**< Get the size of encoded data */ 3895 pC->ewc.WriterAudioAU.CTS += frameTimeDelta; 3896 3897 /** 3898 * Write the AU */ 3899 M4OSA_TRACE2_2("O ---- write : cts = %ld [ 0x%x ]", 3900 (M4OSA_Int32)(pC->ewc.WriterAudioAU.CTS / pC->ewc.scale_audio), 3901 pC->ewc.WriterAudioAU.size); 3902 3903 err = pC->ShellAPI.pWriterDataFcts->pProcessAU( 3904 pC->ewc.p3gpWriterContext, M4VSS3GPP_WRITER_AUDIO_STREAM_ID, 3905 &pC->ewc.WriterAudioAU); 3906 3907 if( M4NO_ERROR != err ) 3908 { 3909 M4OSA_TRACE1_1( 3910 "M4VSS3GPP_intAudioMixingTransition:\ 3911 pWriterDataFcts->pProcessAU returns 0x%x!", err); 3912 return err; 3913 } 3914 3915 /** 3916 * Increment the audio CTS for the next step */ 3917 pC->ewc.dATo += pC->ewc.iSilenceFrameDuration / pC->ewc.scale_audio; 3918 } 3919 } 3920 3921 return M4NO_ERROR; 3922} 3923 3924/** 3925 ****************************************************************************** 3926 * M4OSA_ERR M4VSS3GPP_intAudioMixingCreateVideoEncoder() 3927 * @brief Creates the video encoder 3928 * @note 3929 ****************************************************************************** 3930 */ 3931static M4OSA_ERR M4VSS3GPP_intAudioMixingCreateVideoEncoder( 3932 M4VSS3GPP_InternalAudioMixingContext *pC ) 3933{ 3934 M4OSA_ERR err; 3935 M4ENCODER_AdvancedParams EncParams; 3936 3937 /** 3938 * Simulate a writer interface with our specific function */ 3939 pC->ewc.OurWriterDataInterface.pProcessAU = 3940 M4VSS3GPP_intProcessAU; /**< This function is VSS 3GPP specific, 3941 but it follow the writer interface */ 3942 pC->ewc.OurWriterDataInterface.pStartAU = 3943 M4VSS3GPP_intStartAU; /**< This function is VSS 3GPP specific, 3944 but it follow the writer interface */ 3945 pC->ewc.OurWriterDataInterface.pWriterContext = 3946 (M4WRITER_Context) 3947 pC; /**< We give the internal context as writer context */ 3948 3949 /** 3950 * Get the encoder interface, if not already done */ 3951 if( M4OSA_NULL == pC->ShellAPI.pVideoEncoderGlobalFcts ) 3952 { 3953 err = M4VSS3GPP_setCurrentVideoEncoder(&pC->ShellAPI, 3954 pC->ewc.VideoStreamType); 3955 M4OSA_TRACE1_1( 3956 "M4VSS3GPP_intAudioMixingCreateVideoEncoder: setCurrentEncoder returns 0x%x", 3957 err); 3958 M4ERR_CHECK_RETURN(err); 3959 } 3960 3961 /** 3962 * Set encoder shell parameters according to VSS settings */ 3963 3964 /* Common parameters */ 3965 EncParams.InputFormat = M4ENCODER_kIYUV420; 3966 EncParams.FrameWidth = pC->ewc.uiVideoWidth; 3967 EncParams.FrameHeight = pC->ewc.uiVideoHeight; 3968 EncParams.uiTimeScale = pC->ewc.uiVideoTimeScale; 3969 3970 /* No strict regulation in video editor */ 3971 /* Because of the effects and transitions we should allow more flexibility */ 3972 /* Also it prevents to drop important frames 3973 (with a bad result on sheduling and block effetcs) */ 3974 EncParams.bInternalRegulation = M4OSA_FALSE; 3975 EncParams.FrameRate = M4ENCODER_kVARIABLE_FPS; 3976 3977 /** 3978 * Other encoder settings (defaults) */ 3979 EncParams.uiHorizontalSearchRange = 0; /* use default */ 3980 EncParams.uiVerticalSearchRange = 0; /* use default */ 3981 EncParams.bErrorResilience = M4OSA_FALSE; /* no error resilience */ 3982 EncParams.uiIVopPeriod = 0; /* use default */ 3983 EncParams.uiMotionEstimationTools = 0; /* M4V_MOTION_EST_TOOLS_ALL */ 3984 EncParams.bAcPrediction = M4OSA_TRUE; /* use AC prediction */ 3985 EncParams.uiStartingQuantizerValue = 10; /* initial QP = 10 */ 3986 EncParams.bDataPartitioning = M4OSA_FALSE; /* no data partitioning */ 3987 3988 switch( pC->ewc.VideoStreamType ) 3989 { 3990 case M4SYS_kH263: 3991 3992 EncParams.Format = M4ENCODER_kH263; 3993 3994 EncParams.uiStartingQuantizerValue = 10; 3995 EncParams.uiRateFactor = 1; /* default */ 3996 3997 EncParams.bErrorResilience = M4OSA_FALSE; 3998 EncParams.bDataPartitioning = M4OSA_FALSE; 3999 break; 4000 4001 case M4SYS_kMPEG_4: 4002 4003 EncParams.Format = M4ENCODER_kMPEG4; 4004 4005 EncParams.uiStartingQuantizerValue = 8; 4006 EncParams.uiRateFactor = 1; 4007 4008 if( M4OSA_FALSE == pC->ewc.bVideoDataPartitioning ) 4009 { 4010 EncParams.bErrorResilience = M4OSA_FALSE; 4011 EncParams.bDataPartitioning = M4OSA_FALSE; 4012 } 4013 else 4014 { 4015 EncParams.bErrorResilience = M4OSA_TRUE; 4016 EncParams.bDataPartitioning = M4OSA_TRUE; 4017 } 4018 break; 4019 4020 case M4SYS_kH264: 4021 M4OSA_TRACE1_0( 4022 "M4VSS3GPP_intAudioMixingCreateVideoEncoder: M4SYS_H264"); 4023 4024 EncParams.Format = M4ENCODER_kH264; 4025 4026 EncParams.uiStartingQuantizerValue = 10; 4027 EncParams.uiRateFactor = 1; /* default */ 4028 4029 EncParams.bErrorResilience = M4OSA_FALSE; 4030 EncParams.bDataPartitioning = M4OSA_FALSE; 4031 break; 4032 4033 default: 4034 M4OSA_TRACE1_1( 4035 "M4VSS3GPP_intAudioMixingCreateVideoEncoder: Unknown videoStreamType 0x%x", 4036 pC->ewc.VideoStreamType); 4037 return M4VSS3GPP_ERR_EDITING_UNSUPPORTED_VIDEO_FORMAT; 4038 } 4039 4040 /* In case of EMP we overwrite certain parameters */ 4041 if( M4OSA_TRUE == pC->ewc.bActivateEmp ) 4042 { 4043 EncParams.uiHorizontalSearchRange = 15; /* set value */ 4044 EncParams.uiVerticalSearchRange = 15; /* set value */ 4045 EncParams.bErrorResilience = M4OSA_FALSE; /* no error resilience */ 4046 EncParams.uiIVopPeriod = 15; /* one I frame every 15 frames */ 4047 EncParams.uiMotionEstimationTools = 1; /* M4V_MOTION_EST_TOOLS_NO_4MV */ 4048 EncParams.bAcPrediction = M4OSA_FALSE; /* no AC prediction */ 4049 EncParams.uiStartingQuantizerValue = 10; /* initial QP = 10 */ 4050 EncParams.bDataPartitioning = M4OSA_FALSE; /* no data partitioning */ 4051 } 4052 4053 EncParams.Bitrate = 4054 pC->pInputClipCtxt->pSettings->ClipProperties.uiVideoBitrate; 4055 4056 M4OSA_TRACE1_0( 4057 "M4VSS3GPP_intAudioMixingCreateVideoEncoder: calling encoder pFctInit"); 4058 /** 4059 * Init the video encoder (advanced settings version of the encoder Open function) */ 4060 err = pC->ShellAPI.pVideoEncoderGlobalFcts->pFctInit(&pC->ewc.pEncContext, 4061 &pC->ewc.OurWriterDataInterface, M4VSS3GPP_intVPP, pC, 4062 pC->ShellAPI.pCurrentVideoEncoderExternalAPI, 4063 pC->ShellAPI.pCurrentVideoEncoderUserData); 4064 4065 if( M4NO_ERROR != err ) 4066 { 4067 M4OSA_TRACE1_1( 4068 "M4VSS3GPP_intAudioMixingCreateVideoEncoder:\ 4069 pVideoEncoderGlobalFcts->pFctInit returns 0x%x", 4070 err); 4071 return err; 4072 } 4073 4074 pC->ewc.encoderState = M4VSS3GPP_kEncoderClosed; 4075 M4OSA_TRACE1_0( 4076 "M4VSS3GPP_intAudioMixingCreateVideoEncoder: calling encoder pFctOpen"); 4077 4078 err = pC->ShellAPI.pVideoEncoderGlobalFcts->pFctOpen(pC->ewc.pEncContext, 4079 &pC->ewc.WriterVideoAU, &EncParams); 4080 4081 if( M4NO_ERROR != err ) 4082 { 4083 M4OSA_TRACE1_1( 4084 "M4VSS3GPP_intAudioMixingCreateVideoEncoder:\ 4085 pVideoEncoderGlobalFcts->pFctOpen returns 0x%x", 4086 err); 4087 return err; 4088 } 4089 4090 pC->ewc.encoderState = M4VSS3GPP_kEncoderStopped; 4091 M4OSA_TRACE1_0( 4092 "M4VSS3GPP_intAudioMixingCreateVideoEncoder: calling encoder pFctStart"); 4093 4094 if( M4OSA_NULL != pC->ShellAPI.pVideoEncoderGlobalFcts->pFctStart ) 4095 { 4096 err = pC->ShellAPI.pVideoEncoderGlobalFcts->pFctStart( 4097 pC->ewc.pEncContext); 4098 4099 if( M4NO_ERROR != err ) 4100 { 4101 M4OSA_TRACE1_1( 4102 "M4VSS3GPP_intAudioMixingCreateVideoEncoder:\ 4103 pVideoEncoderGlobalFcts->pFctStart returns 0x%x", 4104 err); 4105 return err; 4106 } 4107 } 4108 4109 pC->ewc.encoderState = M4VSS3GPP_kEncoderRunning; 4110 4111 /** 4112 * Return */ 4113 M4OSA_TRACE3_0( 4114 "M4VSS3GPP_intAudioMixingCreateVideoEncoder: returning M4NO_ERROR"); 4115 return M4NO_ERROR; 4116} 4117 4118/** 4119 ****************************************************************************** 4120 * M4OSA_ERR M4VSS3GPP_intAudioMixingDestroyVideoEncoder() 4121 * @brief Destroy the video encoder 4122 * @note 4123 ****************************************************************************** 4124 */ 4125static M4OSA_ERR M4VSS3GPP_intAudioMixingDestroyVideoEncoder( 4126 M4VSS3GPP_InternalAudioMixingContext *pC ) 4127{ 4128 M4OSA_ERR err = M4NO_ERROR; 4129 4130 if( M4OSA_NULL != pC->ewc.pEncContext ) 4131 { 4132 if( M4VSS3GPP_kEncoderRunning == pC->ewc.encoderState ) 4133 { 4134 if( pC->ShellAPI.pVideoEncoderGlobalFcts->pFctStop != M4OSA_NULL ) 4135 { 4136 err = pC->ShellAPI.pVideoEncoderGlobalFcts->pFctStop( 4137 pC->ewc.pEncContext); 4138 4139 if( M4NO_ERROR != err ) 4140 { 4141 M4OSA_TRACE1_1( 4142 "M4VSS3GPP_intAudioMixingDestroyVideoEncoder:\ 4143 pVideoEncoderGlobalFcts->pFctStop returns 0x%x", 4144 err); 4145 } 4146 } 4147 4148 pC->ewc.encoderState = M4VSS3GPP_kEncoderStopped; 4149 } 4150 4151 /* Has the encoder actually been opened? Don't close it if that's not the case. */ 4152 if( M4VSS3GPP_kEncoderStopped == pC->ewc.encoderState ) 4153 { 4154 err = pC->ShellAPI.pVideoEncoderGlobalFcts->pFctClose( 4155 pC->ewc.pEncContext); 4156 4157 if( M4NO_ERROR != err ) 4158 { 4159 M4OSA_TRACE1_1( 4160 "M4VSS3GPP_intAudioMixingDestroyVideoEncoder:\ 4161 pVideoEncoderGlobalFcts->pFctClose returns 0x%x", 4162 err); 4163 } 4164 4165 pC->ewc.encoderState = M4VSS3GPP_kEncoderClosed; 4166 } 4167 4168 err = pC->ShellAPI.pVideoEncoderGlobalFcts->pFctCleanup( 4169 pC->ewc.pEncContext); 4170 4171 if( M4NO_ERROR != err ) 4172 { 4173 M4OSA_TRACE1_1( 4174 "M4VSS3GPP_intAudioMixingDestroyVideoEncoder:\ 4175 pVideoEncoderGlobalFcts->pFctCleanup returns 0x%x!", 4176 err); 4177 /**< We do not return the error here because we still have stuff to free */ 4178 } 4179 4180 pC->ewc.encoderState = M4VSS3GPP_kNoEncoder; 4181 /** 4182 * Reset variable */ 4183 pC->ewc.pEncContext = M4OSA_NULL; 4184 } 4185 4186 M4OSA_TRACE3_1( 4187 "M4VSS3GPP_intAudioMixingDestroyVideoEncoder: returning 0x%x", err); 4188 return err; 4189} 4190 4191M4OSA_Bool M4VSS3GPP_isThresholdBreached( M4OSA_Int32 *averageValue, 4192 M4OSA_Int32 storeCount, M4OSA_Int32 thresholdValue ) 4193{ 4194 M4OSA_Bool result = 0; 4195 int i; 4196 int finalValue = 0; 4197 4198 for ( i = 0; i < storeCount; i++ ) 4199 finalValue += averageValue[i]; 4200 4201 finalValue = finalValue / storeCount; 4202 4203 4204 if( finalValue > thresholdValue ) 4205 result = M4OSA_TRUE; 4206 else 4207 result = M4OSA_FALSE; 4208 4209 return result; 4210} 4211