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