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