M4VSS3GPP_Edit.c revision 0a389ab70db304fb840e33f33781ecc0503eae3c
1/* 2 * Copyright (C) 2004-2011 NXP Software 3 * Copyright (C) 2011 The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17/** 18 ****************************************************************************** 19 * @file M4VSS3GPP_Edit.c 20 * @brief Video Studio Service 3GPP edit API implementation. 21 * @note 22 ****************************************************************************** 23 */ 24 25/****************/ 26/*** Includes ***/ 27/****************/ 28 29#include "NXPSW_CompilerSwitches.h" 30/** 31 * Our headers */ 32#include "M4VSS3GPP_API.h" 33#include "M4VSS3GPP_InternalTypes.h" 34#include "M4VSS3GPP_InternalFunctions.h" 35#include "M4VSS3GPP_InternalConfig.h" 36#include "M4VSS3GPP_ErrorCodes.h" 37 38 39/** 40 * OSAL headers */ 41#include "M4OSA_Memory.h" /**< OSAL memory management */ 42#include "M4OSA_Debug.h" /**< OSAL debug management */ 43#include "M4OSA_CharStar.h" /**< OSAL string management */ 44 45#ifdef WIN32 46#include "string.h" /**< for strcpy (Don't want to get dependencies 47 with M4OSA_String...) */ 48 49#endif /* WIN32 */ 50 51/************************************************************************/ 52/* Static local functions */ 53/************************************************************************/ 54static M4OSA_ERR M4VSS3GPP_intClipSettingsSanityCheck( 55 M4VSS3GPP_ClipSettings *pClip ); 56static M4OSA_ERR M4VSS3GPP_intTransitionSettingsSanityCheck( 57 M4VSS3GPP_TransitionSettings *pTransition ); 58static M4OSA_Void M4VSS3GPP_intFreeSettingsList( 59 M4VSS3GPP_InternalEditContext *pC ); 60static M4OSA_ERR 61M4VSS3GPP_intCreateMP3OutputFile( M4VSS3GPP_InternalEditContext *pC, 62 M4OSA_Void *pOutputFile ); 63static M4OSA_ERR M4VSS3GPP_intSwitchToNextClip( 64 M4VSS3GPP_InternalEditContext *pC ); 65static M4OSA_ERR 66M4VSS3GPP_intComputeOutputVideoAndAudioDsi( M4VSS3GPP_InternalEditContext *pC, 67 M4OSA_UInt8 uiMasterClip ); 68static M4OSA_Void M4VSS3GPP_intComputeOutputAverageVideoBitrate( 69 M4VSS3GPP_InternalEditContext *pC ); 70 71/** 72 ****************************************************************************** 73 * M4OSA_ERR M4VSS3GPP_GetVersion() 74 * @brief Get the VSS 3GPP version. 75 * @note Can be called anytime. Do not need any context. 76 * @param pVersionInfo (OUT) Pointer to a version info structure 77 * @return M4NO_ERROR: No error 78 * @return M4ERR_PARAMETER: pVersionInfo is M4OSA_NULL (If Debug Level >= 2) 79 ****************************************************************************** 80 */ 81M4OSA_ERR M4VSS3GPP_GetVersion( M4_VersionInfo *pVersionInfo ) 82{ 83 M4OSA_TRACE3_1("M4VSS3GPP_GetVersion called with pVersionInfo=0x%x", 84 pVersionInfo); 85 86 /** 87 * Check input parameters */ 88 M4OSA_DEBUG_IF2((M4OSA_NULL == pVersionInfo), M4ERR_PARAMETER, 89 "M4VSS3GPP_GetVersion: pVersionInfo is M4OSA_NULL"); 90 91 pVersionInfo->m_major = M4VSS_VERSION_MAJOR; 92 pVersionInfo->m_minor = M4VSS_VERSION_MINOR; 93 pVersionInfo->m_revision = M4VSS_VERSION_REVISION; 94 95 return M4NO_ERROR; 96} 97 98/** 99 ****************************************************************************** 100 * M4OSA_ERR M4VSS3GPP_editInit() 101 * @brief Initializes the VSS 3GPP edit operation (allocates an execution context). 102 * @note 103 * @param pContext (OUT) Pointer on the VSS 3GPP edit context to allocate 104 * @param pFileReadPtrFct (IN) Pointer to OSAL file reader functions 105 * @param pFileWritePtrFct (IN) Pointer to OSAL file writer functions 106 * @return M4NO_ERROR: No error 107 * @return M4ERR_PARAMETER: At least one parameter is M4OSA_NULL 108 * @return M4ERR_ALLOC: There is no more available memory 109 ****************************************************************************** 110 */ 111M4OSA_ERR M4VSS3GPP_editInit( M4VSS3GPP_EditContext *pContext, 112 M4OSA_FileReadPointer *pFileReadPtrFct, 113 M4OSA_FileWriterPointer *pFileWritePtrFct ) 114{ 115 M4VSS3GPP_InternalEditContext *pC; 116 M4OSA_ERR err; 117 M4OSA_UInt32 i; 118 119 M4OSA_TRACE3_3( 120 "M4VSS3GPP_editInit called with pContext=0x%x, \ 121 pFileReadPtrFct=0x%x, pFileWritePtrFct=0x%x", 122 pContext, pFileReadPtrFct, pFileWritePtrFct); 123 124 /** 125 * Check input parameters */ 126 M4OSA_DEBUG_IF2((M4OSA_NULL == pContext), M4ERR_PARAMETER, 127 "M4VSS3GPP_editInit: pContext is M4OSA_NULL"); 128 M4OSA_DEBUG_IF2((M4OSA_NULL == pFileReadPtrFct), M4ERR_PARAMETER, 129 "M4VSS3GPP_editInit: pFileReadPtrFct is M4OSA_NULL"); 130 M4OSA_DEBUG_IF2((M4OSA_NULL == pFileWritePtrFct), M4ERR_PARAMETER, 131 "M4VSS3GPP_editInit: pFileWritePtrFct is M4OSA_NULL"); 132 133 /** 134 * Allocate the VSS context and return it to the user */ 135 pC = (M4VSS3GPP_InternalEditContext 136 *)M4OSA_32bitAlignedMalloc(sizeof(M4VSS3GPP_InternalEditContext), 137 M4VSS3GPP, (M4OSA_Char *)"M4VSS3GPP_InternalContext"); 138 *pContext = pC; 139 /* Inialization of context Variables */ 140 memset((void *)pC, 0,sizeof(M4VSS3GPP_InternalEditContext)); 141 142 if( M4OSA_NULL == pC ) 143 { 144 M4OSA_TRACE1_0( 145 "M4VSS3GPP_editInit(): unable to allocate M4VSS3GPP_InternalContext,\ 146 returning M4ERR_ALLOC"); 147 return M4ERR_ALLOC; 148 } 149 150 151 /* Init the context. */ 152 pC->pClipList = M4OSA_NULL; 153 pC->pTransitionList = M4OSA_NULL; 154 pC->pEffectsList = M4OSA_NULL; 155 pC->pActiveEffectsList = M4OSA_NULL; 156 pC->pActiveEffectsList1 = M4OSA_NULL; 157 pC->pC1 = M4OSA_NULL; 158 pC->pC2 = M4OSA_NULL; 159 pC->yuv1[0].pac_data = pC->yuv1[1].pac_data = pC-> 160 yuv1[2].pac_data = M4OSA_NULL; 161 pC->yuv2[0].pac_data = pC->yuv2[1].pac_data = pC-> 162 yuv2[2].pac_data = M4OSA_NULL; 163 pC->yuv3[0].pac_data = pC->yuv3[1].pac_data = pC-> 164 yuv3[2].pac_data = M4OSA_NULL; 165 pC->yuv4[0].pac_data = pC->yuv4[1].pac_data = pC-> 166 yuv4[2].pac_data = M4OSA_NULL; 167 pC->bClip1AtBeginCut = M4OSA_FALSE; 168 pC->bTransitionEffect = M4OSA_FALSE; 169 pC->bSupportSilence = M4OSA_FALSE; 170 171 /** 172 * Init PC->ewc members */ 173 // Decorrelate input and output encoding timestamp to handle encoder prefetch 174 pC->ewc.VideoStreamType = M4SYS_kVideoUnknown; 175 pC->ewc.bVideoDataPartitioning = M4OSA_FALSE; 176 pC->ewc.pVideoOutputDsi = M4OSA_NULL; 177 pC->ewc.bActivateEmp = M4OSA_FALSE; 178 pC->ewc.AudioStreamType = M4SYS_kAudioUnknown; 179 pC->ewc.uiNbChannels = 1; 180 pC->ewc.pAudioOutputDsi = M4OSA_NULL; 181 pC->ewc.pAudioEncCtxt = M4OSA_NULL; 182 pC->ewc.pAudioEncDSI.pInfo = M4OSA_NULL; 183 pC->ewc.pSilenceFrameData = M4OSA_NULL; 184 pC->ewc.pEncContext = M4OSA_NULL; 185 pC->ewc.pDummyAuBuffer = M4OSA_NULL; 186 pC->ewc.encoderState = M4VSS3GPP_kNoEncoder; 187 pC->ewc.p3gpWriterContext = M4OSA_NULL; 188 /** 189 * Keep the OSAL file functions pointer set in our context */ 190 pC->pOsaFileReadPtr = pFileReadPtrFct; 191 pC->pOsaFileWritPtr = pFileWritePtrFct; 192 193 /* 194 * Reset pointers for media and codecs interfaces */ 195 196 err = M4VSS3GPP_clearInterfaceTables(&pC->ShellAPI); 197 M4ERR_CHECK_RETURN(err); 198 199 /* 200 * Call the media and codecs subscription module */ 201 err = M4VSS3GPP_subscribeMediaAndCodec(&pC->ShellAPI); 202 M4ERR_CHECK_RETURN(err); 203 204 /** 205 * Update main state automaton */ 206 pC->State = M4VSS3GPP_kEditState_CREATED; 207 pC->Vstate = M4VSS3GPP_kEditVideoState_READ_WRITE; 208 pC->Astate = M4VSS3GPP_kEditAudioState_READ_WRITE; 209 /* The flag is set to false at the beginning of every clip */ 210 pC->m_bClipExternalHasStarted = M4OSA_FALSE; 211 212 pC->bIsMMS = M4OSA_FALSE; 213 214 pC->iInOutTimeOffset = 0; 215 pC->bEncodeTillEoF = M4OSA_FALSE; 216 217 /** 218 * Return with no error */ 219 M4OSA_TRACE3_0("M4VSS3GPP_editInit(): returning M4NO_ERROR"); 220 return M4NO_ERROR; 221} 222 223/** 224 ****************************************************************************** 225 * M4OSA_ERR M4VSS3GPP_editCreateClipSettings() 226 * @brief Allows filling a clip settings structure with default values 227 * 228 * @note WARNING: pClipSettings->Effects[ ] will be allocated in this function. 229 * pClipSettings->pFile will be allocated in this function. 230 * 231 * @param pClipSettings (IN) Pointer to a valid M4VSS3GPP_ClipSettings structure 232 * @param pFile (IN) Clip file name 233 * @param filePathSize (IN) Clip path size (needed for UTF 16 conversion) 234 * @param nbEffects (IN) Nb of effect settings to allocate 235 * @return M4NO_ERROR: No error 236 * @return M4ERR_PARAMETER: pClipSettings is M4OSA_NULL (debug only) 237 ****************************************************************************** 238 */ 239M4OSA_ERR 240M4VSS3GPP_editCreateClipSettings( M4VSS3GPP_ClipSettings *pClipSettings, 241 M4OSA_Void *pFile, M4OSA_UInt32 filePathSize, 242 M4OSA_UInt8 nbEffects ) 243{ 244 M4OSA_UInt8 uiFx; 245 246 M4OSA_TRACE3_1( 247 "M4VSS3GPP_editCreateClipSettings called with pClipSettings=0x%p", 248 pClipSettings); 249 250 /** 251 * Check input parameter */ 252 M4OSA_DEBUG_IF2((M4OSA_NULL == pClipSettings), M4ERR_PARAMETER, 253 "M4VSS3GPP_editCreateClipSettings: pClipSettings is NULL"); 254 255 /** 256 * Set the clip settings to default */ 257 pClipSettings->pFile = M4OSA_NULL; /**< no file */ 258 pClipSettings->FileType = 259 M4VIDEOEDITING_kFileType_Unsupported; /**< undefined */ 260 261 if( M4OSA_NULL != pFile ) 262 { 263 //pClipSettings->pFile = (M4OSA_Char*) M4OSA_32bitAlignedMalloc(strlen(pFile)+1, M4VSS3GPP, 264 // "pClipSettings->pFile"); 265 /*FB: add clip path size because of utf 16 conversion*/ 266 pClipSettings->pFile = 267 (M4OSA_Void *)M4OSA_32bitAlignedMalloc(filePathSize + 1, M4VSS3GPP, 268 (M4OSA_Char *)"pClipSettings->pFile"); 269 270 if( M4OSA_NULL == pClipSettings->pFile ) 271 { 272 M4OSA_TRACE1_0( 273 "M4VSS3GPP_editCreateClipSettings : ERROR allocating filename"); 274 return M4ERR_ALLOC; 275 } 276 //memcpy(pClipSettings->pFile, pFile, strlen(pFile)+1); 277 /*FB: add clip path size because of utf 16 conversion*/ 278 memcpy((void *)pClipSettings->pFile, (void *)pFile, filePathSize + 1); 279 } 280 281 /*FB: add file path size to support UTF16 conversion*/ 282 pClipSettings->filePathSize = filePathSize + 1; 283 /**/ 284 pClipSettings->ClipProperties.bAnalysed = M4OSA_FALSE; 285 pClipSettings->ClipProperties.FileType = 0; 286 pClipSettings->ClipProperties.Version[0] = 0; 287 pClipSettings->ClipProperties.Version[1] = 0; 288 pClipSettings->ClipProperties.Version[2] = 0; 289 pClipSettings->ClipProperties.uiClipDuration = 0; 290 291 pClipSettings->uiBeginCutTime = 0; /**< no begin cut */ 292 pClipSettings->uiEndCutTime = 0; /**< no end cut */ 293 294 /** 295 * Reset video characteristics */ 296 pClipSettings->ClipProperties.VideoStreamType = M4VIDEOEDITING_kNoneVideo; 297 pClipSettings->ClipProperties.uiClipVideoDuration = 0; 298 pClipSettings->ClipProperties.uiVideoBitrate = 0; 299 pClipSettings->ClipProperties.uiVideoMaxAuSize = 0; 300 pClipSettings->ClipProperties.uiVideoWidth = 0; 301 pClipSettings->ClipProperties.uiVideoHeight = 0; 302 pClipSettings->ClipProperties.uiVideoTimeScale = 0; 303 pClipSettings->ClipProperties.fAverageFrameRate = 0.0; 304 pClipSettings->ClipProperties.ProfileAndLevel = 305 M4VIDEOEDITING_kProfile_and_Level_Out_Of_Range; 306 pClipSettings->ClipProperties.uiH263level = 0; 307 pClipSettings->ClipProperties.uiVideoProfile = 0; 308 pClipSettings->ClipProperties.bMPEG4dataPartition = M4OSA_FALSE; 309 pClipSettings->ClipProperties.bMPEG4rvlc = M4OSA_FALSE; 310 pClipSettings->ClipProperties.bMPEG4resynchMarker = M4OSA_FALSE; 311 312 /** 313 * Reset audio characteristics */ 314 pClipSettings->ClipProperties.AudioStreamType = M4VIDEOEDITING_kNoneAudio; 315 pClipSettings->ClipProperties.uiClipAudioDuration = 0; 316 pClipSettings->ClipProperties.uiAudioBitrate = 0; 317 pClipSettings->ClipProperties.uiAudioMaxAuSize = 0; 318 pClipSettings->ClipProperties.uiNbChannels = 0; 319 pClipSettings->ClipProperties.uiSamplingFrequency = 0; 320 pClipSettings->ClipProperties.uiExtendedSamplingFrequency = 0; 321 pClipSettings->ClipProperties.uiDecodedPcmSize = 0; 322 323 /** 324 * Return with no error */ 325 M4OSA_TRACE3_0("M4VSS3GPP_editSetDefaultSettings(): returning M4NO_ERROR"); 326 327 return M4NO_ERROR; 328} 329 330/** 331 ****************************************************************************** 332 * M4OSA_ERR M4VSS3GPP_editDuplicateClipSettings() 333 * @brief Duplicates a clip settings structure, performing allocations if required 334 * 335 * @param pClipSettingsDest (IN) Pointer to a valid M4VSS3GPP_ClipSettings structure 336 * @param pClipSettingsOrig (IN) Pointer to a valid M4VSS3GPP_ClipSettings structure 337 * @param bCopyEffects (IN) Flag to know if we have to duplicate effects 338 * @return M4NO_ERROR: No error 339 * @return M4ERR_PARAMETER: pClipSettings is M4OSA_NULL (debug only) 340 ****************************************************************************** 341 */ 342M4OSA_ERR 343M4VSS3GPP_editDuplicateClipSettings( M4VSS3GPP_ClipSettings *pClipSettingsDest, 344 M4VSS3GPP_ClipSettings *pClipSettingsOrig, 345 M4OSA_Bool bCopyEffects ) 346{ 347 M4OSA_UInt8 uiFx; 348 349 M4OSA_TRACE3_2( 350 "M4VSS3GPP_editDuplicateClipSettings called with dest=0x%p src=0x%p", 351 pClipSettingsDest, pClipSettingsOrig); 352 353 /* Check input parameter */ 354 M4OSA_DEBUG_IF2((M4OSA_NULL == pClipSettingsDest), M4ERR_PARAMETER, 355 "M4VSS3GPP_editDuplicateClipSettings: pClipSettingsDest is NULL"); 356 M4OSA_DEBUG_IF2((M4OSA_NULL == pClipSettingsOrig), M4ERR_PARAMETER, 357 "M4VSS3GPP_editDuplicateClipSettings: pClipSettingsOrig is NULL"); 358 359 /* Copy plain structure */ 360 memcpy((void *)pClipSettingsDest, 361 (void *)pClipSettingsOrig, sizeof(M4VSS3GPP_ClipSettings)); 362 363 /* Duplicate filename */ 364 if( M4OSA_NULL != pClipSettingsOrig->pFile ) 365 { 366 //pClipSettingsDest->pFile = 367 // (M4OSA_Char*) M4OSA_32bitAlignedMalloc(strlen(pClipSettingsOrig->pFile)+1, M4VSS3GPP, 368 // "pClipSettingsDest->pFile"); 369 /*FB: clip path size is needed for utf 16 conversion*/ 370 /*FB 2008/10/16: bad allocation size which raises a crash*/ 371 pClipSettingsDest->pFile = 372 (M4OSA_Char *)M4OSA_32bitAlignedMalloc(pClipSettingsOrig->filePathSize + 1, 373 M4VSS3GPP, (M4OSA_Char *)"pClipSettingsDest->pFile"); 374 375 if( M4OSA_NULL == pClipSettingsDest->pFile ) 376 { 377 M4OSA_TRACE1_0( 378 "M4VSS3GPP_editDuplicateClipSettings : ERROR allocating filename"); 379 return M4ERR_ALLOC; 380 } 381 /*FB: clip path size is needed for utf 16 conversion*/ 382 //memcpy(pClipSettingsDest->pFile, pClipSettingsOrig->pFile, 383 // strlen(pClipSettingsOrig->pFile)+1); 384 /*FB 2008/10/16: bad allocation size which raises a crash*/ 385 memcpy((void *)pClipSettingsDest->pFile, (void *)pClipSettingsOrig->pFile, 386 pClipSettingsOrig->filePathSize/*+1*/); 387 ( (M4OSA_Char 388 *)pClipSettingsDest->pFile)[pClipSettingsOrig->filePathSize] = '\0'; 389 } 390 391 /* Duplicate effects */ 392 /* Return with no error */ 393 394 M4OSA_TRACE3_0( 395 "M4VSS3GPP_editDuplicateClipSettings(): returning M4NO_ERROR"); 396 397 return M4NO_ERROR; 398} 399 400/** 401 ****************************************************************************** 402 * M4OSA_ERR M4VSS3GPP_editFreeClipSettings() 403 * @brief Free the pointers allocated in the ClipSetting structure (pFile, Effects). 404 * 405 * @param pClipSettings (IN) Pointer to a valid M4VSS3GPP_ClipSettings structure 406 * @return M4NO_ERROR: No error 407 * @return M4ERR_PARAMETER: pClipSettings is M4OSA_NULL (debug only) 408 ****************************************************************************** 409 */ 410M4OSA_ERR M4VSS3GPP_editFreeClipSettings( 411 M4VSS3GPP_ClipSettings *pClipSettings ) 412{ 413 /** 414 * Check input parameter */ 415 M4OSA_DEBUG_IF2((M4OSA_NULL == pClipSettings), M4ERR_PARAMETER, 416 "M4VSS3GPP_editFreeClipSettings: pClipSettings is NULL"); 417 418 /* free filename */ 419 if( M4OSA_NULL != pClipSettings->pFile ) 420 { 421 free(pClipSettings->pFile); 422 pClipSettings->pFile = M4OSA_NULL; 423 } 424 425 /* free effects settings */ 426 /* if(M4OSA_NULL != pClipSettings->Effects) 427 { 428 free(pClipSettings->Effects); 429 pClipSettings->Effects = M4OSA_NULL; 430 pClipSettings->nbEffects = 0; 431 } RC */ 432 433 return M4NO_ERROR; 434} 435 436/** 437 ****************************************************************************** 438 * M4OSA_ERR M4VSS3GPP_editOpen() 439 * @brief Set the VSS input and output files. 440 * @note It opens the input file, but the output file may not be created yet. 441 * @param pContext (IN) VSS edit context 442 * @param pSettings (IN) Edit settings 443 * @return M4NO_ERROR: No error 444 * @return M4ERR_PARAMETER: At least one parameter is M4OSA_NULL (debug only) 445 * @return M4ERR_STATE: VSS is not in an appropriate state for this function to be called 446 * @return M4ERR_ALLOC: There is no more available memory 447 ****************************************************************************** 448 */ 449M4OSA_ERR M4VSS3GPP_editOpen( M4VSS3GPP_EditContext pContext, 450 M4VSS3GPP_EditSettings *pSettings ) 451{ 452 M4VSS3GPP_InternalEditContext *pC = 453 (M4VSS3GPP_InternalEditContext *)pContext; 454 455 M4OSA_ERR err; 456 M4OSA_Int32 i; 457 M4VIDEOEDITING_FileType outputFileType = 458 M4VIDEOEDITING_kFileType_Unsupported; /**< 3GPP or MP3 (we don't do AMR output) */ 459 M4OSA_UInt32 uiC1duration, uiC2duration; 460 461 M4OSA_TRACE3_2( 462 "M4VSS3GPP_editOpen called with pContext=0x%x, pSettings=0x%x", 463 pContext, pSettings); 464 465 /** 466 * Check input parameters */ 467 M4OSA_DEBUG_IF2((M4OSA_NULL == pContext), M4ERR_PARAMETER, 468 "M4VSS3GPP_editOpen: pContext is M4OSA_NULL"); 469 M4OSA_DEBUG_IF2((M4OSA_NULL == pSettings), M4ERR_PARAMETER, 470 "M4VSS3GPP_editOpen: pSettings is M4OSA_NULL"); 471 M4OSA_DEBUG_IF2((M4OSA_NULL == pSettings->pClipList), M4ERR_PARAMETER, 472 "M4VSS3GPP_editOpen: pSettings->pClipList is M4OSA_NULL"); 473 M4OSA_DEBUG_IF2(( pSettings->uiClipNumber > 1) 474 && (M4OSA_NULL == pSettings->pTransitionList), M4ERR_PARAMETER, 475 "M4VSS3GPP_editOpen: pSettings->pTransitionList is M4OSA_NULL"); 476 477 /** 478 * Check state automaton */ 479 if( ( pC->State != M4VSS3GPP_kEditState_CREATED) 480 && (pC->State != M4VSS3GPP_kEditState_CLOSED) ) 481 { 482 M4OSA_TRACE1_1( 483 "M4VSS3GPP_editOpen: State error (0x%x)! Returning M4ERR_STATE", 484 pC->State); 485 return M4ERR_STATE; 486 } 487 488 /** 489 * Free any previously allocated internal settings list */ 490 M4VSS3GPP_intFreeSettingsList(pC); 491 492 /** 493 * Copy the user settings in our context */ 494 pC->uiClipNumber = pSettings->uiClipNumber; 495 496 /** 497 * Copy the clip list */ 498 pC->pClipList = 499 (M4VSS3GPP_ClipSettings *)M4OSA_32bitAlignedMalloc(sizeof(M4VSS3GPP_ClipSettings) 500 * pC->uiClipNumber, M4VSS3GPP, (M4OSA_Char *)"pC->pClipList"); 501 502 if( M4OSA_NULL == pC->pClipList ) 503 { 504 M4OSA_TRACE1_0( 505 "M4VSS3GPP_editOpen: unable to allocate pC->Settings.pClipList,\ 506 returning M4ERR_ALLOC"); 507 return M4ERR_ALLOC; 508 } 509 510 for ( i = 0; i < pSettings->uiClipNumber; i++ ) 511 { 512 M4VSS3GPP_editDuplicateClipSettings(&(pC->pClipList[i]), 513 pSettings->pClipList[i], M4OSA_TRUE); 514 } 515 516 /** 517 * Copy effects list RC */ 518 519 /*FB bug fix 19.03.2008 if the number of effects is 0 -> crash*/ 520 if( pSettings->nbEffects > 0 ) 521 { 522 pC->nbEffects = pSettings->nbEffects; 523 pC->pEffectsList = (M4VSS3GPP_EffectSettings 524 *)M4OSA_32bitAlignedMalloc(sizeof(M4VSS3GPP_EffectSettings) * pC->nbEffects, 525 M4VSS3GPP, (M4OSA_Char *)"pC->pEffectsList"); 526 527 if( M4OSA_NULL == pC->pEffectsList ) 528 { 529 M4OSA_TRACE1_0( 530 "M4VSS3GPP_editOpen: unable to allocate pC->pEffectsList, returning M4ERR_ALLOC"); 531 return M4ERR_ALLOC; 532 } 533 534 for ( i = 0; i < pC->nbEffects; i++ ) 535 { 536 memcpy((void *) &(pC->pEffectsList[i]), 537 (void *) &(pSettings->Effects[i]), 538 sizeof(M4VSS3GPP_EffectSettings)); 539 } 540 541 /** 542 * Allocate active effects list RC */ 543 pC->pActiveEffectsList = 544 (M4OSA_UInt8 *)M4OSA_32bitAlignedMalloc(sizeof(M4OSA_UInt8) * pC->nbEffects, 545 M4VSS3GPP, (M4OSA_Char *)"pC->pActiveEffectsList"); 546 547 if( M4OSA_NULL == pC->pActiveEffectsList ) 548 { 549 M4OSA_TRACE1_0( 550 "M4VSS3GPP_editOpen: unable to allocate pC->pActiveEffectsList,\ 551 returning M4ERR_ALLOC"); 552 return M4ERR_ALLOC; 553 } 554 /** 555 * Allocate active effects list */ 556 pC->pActiveEffectsList1 = 557 (M4OSA_UInt8 *)M4OSA_32bitAlignedMalloc(sizeof(M4OSA_UInt8) * pC->nbEffects, 558 M4VSS3GPP, (M4OSA_Char *)"pC->pActiveEffectsList"); 559 if (M4OSA_NULL == pC->pActiveEffectsList1) 560 { 561 M4OSA_TRACE1_0("M4VSS3GPP_editOpen: unable to allocate pC->pActiveEffectsList, \ 562 returning M4ERR_ALLOC"); 563 return M4ERR_ALLOC; 564 } 565 566 } 567 else 568 { 569 pC->nbEffects = 0; 570 pC->nbActiveEffects = 0; 571 pC->nbActiveEffects1 = 0; 572 pC->pEffectsList = M4OSA_NULL; 573 pC->pActiveEffectsList = M4OSA_NULL; 574 pC->pActiveEffectsList1 = M4OSA_NULL; 575 } 576 577 /** 578 * Test the clip analysis data, if it is not provided, analyse the clips by ourselves. */ 579 for ( i = 0; i < pC->uiClipNumber; i++ ) 580 { 581 if( M4OSA_FALSE == pC->pClipList[i].ClipProperties.bAnalysed ) 582 { 583 /**< Analysis not provided by the integrator */ 584 err = M4VSS3GPP_editAnalyseClip(pC->pClipList[i].pFile, 585 pC->pClipList[i].FileType, &pC->pClipList[i].ClipProperties, 586 pC->pOsaFileReadPtr); 587 588 if( M4NO_ERROR != err ) 589 { 590 M4OSA_TRACE1_1( 591 "M4VSS3GPP_editOpen: M4VSS3GPP_editAnalyseClip returns 0x%x!", 592 err); 593 return err; 594 } 595 } 596 } 597 598 /** 599 * Check clip compatibility */ 600 for ( i = 0; i < pC->uiClipNumber; i++ ) 601 { 602 /** 603 * Check all the clips are compatible with VSS 3GPP */ 604 err = M4VSS3GPP_intCheckClipCompatibleWithVssEditing( 605 &pC->pClipList[i].ClipProperties); 606 607 if( M4NO_ERROR != err ) 608 { 609 M4OSA_TRACE1_2( 610 "M4VSS3GPP_editOpen:\ 611 M4VSS3GPP_intCheckClipCompatibleWithVssEditing(%d) returns 0x%x!", 612 i, err); 613 return err; 614 } 615 616 /** 617 * Check the master clip versus all the other ones. 618 (including master clip with itself, else variables for master clip 619 are not properly setted) */ 620 err = M4VSS3GPP_editCheckClipCompatibility( 621 &pC->pClipList[pSettings->uiMasterClip].ClipProperties, 622 &pC->pClipList[i].ClipProperties); 623 /* in case of warning regarding audio incompatibility, editing continues */ 624 if( M4OSA_ERR_IS_ERROR(err) ) 625 { 626 M4OSA_TRACE1_2( 627 "M4VSS3GPP_editOpen: M4VSS3GPP_editCheckClipCompatibility(%d) returns 0x%x!", 628 i, err); 629 return err; 630 } 631 } 632 633 /* Search audio tracks that cannot be edited : 634 * - delete all audio effects for the clip 635 * - if master clip is editable let the transition 636 (bad track will be replaced later with silence) 637 * - if master clip is not editable switch to a dummy transition (only copy/paste) */ 638 for ( i = 0; i < pC->uiClipNumber; i++ ) 639 { 640 if( M4OSA_FALSE == pC->pClipList[i].ClipProperties.bAudioIsEditable ) 641 { 642 M4OSA_UInt8 uiFx; 643 644 for ( uiFx = 0; uiFx < pC->nbEffects; uiFx++ ) 645 { 646 pC->pEffectsList[uiFx].AudioEffectType 647 = M4VSS3GPP_kAudioEffectType_None; 648 } 649 650 if( ( i < (pC->uiClipNumber - 1)) 651 && (M4OSA_NULL != pSettings->pTransitionList[i]) 652 && (M4OSA_FALSE == pC->pClipList[pSettings-> 653 uiMasterClip].ClipProperties.bAudioIsEditable) ) 654 { 655 pSettings->pTransitionList[i]->AudioTransitionType 656 = M4VSS3GPP_kAudioTransitionType_None; 657 } 658 } 659 } 660 661 /** 662 * We add a transition of duration 0 at the end of the last clip. 663 * It will suppress a whole bunch a test latter in the processing... */ 664 pC->pTransitionList = (M4VSS3GPP_TransitionSettings 665 *)M4OSA_32bitAlignedMalloc(sizeof(M4VSS3GPP_TransitionSettings) 666 * (pC->uiClipNumber), M4VSS3GPP, (M4OSA_Char *)"pC->pTransitionList"); 667 668 if( M4OSA_NULL == pC->pTransitionList ) 669 { 670 M4OSA_TRACE1_0( 671 "M4VSS3GPP_editOpen: unable to allocate pC->Settings.pTransitionList,\ 672 returning M4ERR_ALLOC"); 673 return M4ERR_ALLOC; 674 } 675 676 /**< copy transition settings */ 677 for ( i = 0; i < (pSettings->uiClipNumber - 1); i++ ) 678 { 679 memcpy((void *) &(pC->pTransitionList[i]), 680 (void *)pSettings->pTransitionList[i], 681 sizeof(M4VSS3GPP_TransitionSettings)); 682 } 683 684 /**< We fill the last "dummy" transition */ 685 pC->pTransitionList[pC->uiClipNumber - 1].uiTransitionDuration = 0; 686 pC->pTransitionList[pC->uiClipNumber 687 - 1].VideoTransitionType = M4VSS3GPP_kVideoTransitionType_None; 688 pC->pTransitionList[pC->uiClipNumber 689 - 1].AudioTransitionType = M4VSS3GPP_kAudioTransitionType_None; 690 691 /** 692 * Avoid weird clip settings */ 693 for ( i = 0; i < pSettings->uiClipNumber; i++ ) 694 { 695 err = M4VSS3GPP_intClipSettingsSanityCheck(&pC->pClipList[i]); 696 697 if( M4NO_ERROR != err ) 698 { 699 M4OSA_TRACE1_1( 700 "M4VSS3GPP_editOpen: M4VSS3GPP_intClipSettingsSanityCheck returns 0x%x!", 701 err); 702 return err; 703 } 704 } 705 706 for ( i = 0; i < (pSettings->uiClipNumber - 1); i++ ) 707 { 708 /** 709 * Maximum transition duration between clip n and clip n+1 is the duration 710 * of the shortest clip */ 711 if( 0 == pC->pClipList[i].uiEndCutTime ) 712 { 713 uiC1duration = pC->pClipList[i].ClipProperties.uiClipVideoDuration; 714 } 715 else 716 { 717 /**< duration of clip n is the end cut time */ 718 uiC1duration = pC->pClipList[i].uiEndCutTime; 719 } 720 721 /**< Substract begin cut */ 722 uiC1duration -= pC->pClipList[i].uiBeginCutTime; 723 724 /**< Check that the transition is shorter than clip n */ 725 if( pC->pTransitionList[i].uiTransitionDuration > uiC1duration ) 726 { 727 pC->pTransitionList[i].uiTransitionDuration = uiC1duration - 1; 728 } 729 730 if( 0 == pC->pClipList[i + 1].uiEndCutTime ) 731 { 732 uiC2duration = 733 pC->pClipList[i + 1].ClipProperties.uiClipVideoDuration; 734 } 735 else 736 { 737 /**< duration of clip n+1 is the end cut time */ 738 uiC2duration = pC->pClipList[i + 1].uiEndCutTime; 739 } 740 741 /**< Substract begin cut */ 742 uiC2duration -= pC->pClipList[i + 1].uiBeginCutTime; 743 744 /**< Check that the transition is shorter than clip n+1 */ 745 if( pC->pTransitionList[i].uiTransitionDuration > uiC2duration ) 746 { 747 pC->pTransitionList[i].uiTransitionDuration = uiC2duration - 1; 748 } 749 750 /** 751 * Avoid weird transition settings */ 752 err = 753 M4VSS3GPP_intTransitionSettingsSanityCheck(&pC->pTransitionList[i]); 754 755 if( M4NO_ERROR != err ) 756 { 757 M4OSA_TRACE1_1( 758 "M4VSS3GPP_editOpen: M4VSS3GPP_intClipSettingsSanityCheck returns 0x%x!", 759 err); 760 return err; 761 } 762 763 /** 764 * Check that two transitions are not overlapping 765 (no overlapping possible for first clip) */ 766 if( i > 0 ) 767 { 768 /** 769 * There is a transition overlap if the sum of the duration of 770 two consecutive transitions 771 * is higher than the duration of the clip in-between. */ 772 if( ( pC->pTransitionList[i - 1].uiTransitionDuration 773 + pC->pTransitionList[i].uiTransitionDuration) >= uiC1duration ) 774 { 775 M4OSA_TRACE1_1( 776 "M4VSS3GPP_editOpen: Overlapping transitions on clip %d,\ 777 returning M4VSS3GPP_ERR_OVERLAPPING_TRANSITIONS", 778 i); 779 return M4VSS3GPP_ERR_OVERLAPPING_TRANSITIONS; 780 } 781 } 782 } 783 784 /** 785 * Output clip duration */ 786 for ( i = 0; i < pC->uiClipNumber; i++ ) 787 { 788 /** 789 * Compute the sum of the clip duration */ 790 if( 0 == pC->pClipList[i].uiEndCutTime ) 791 { 792 pC->ewc.iOutputDuration += 793 pC-> 794 pClipList[ 795 i].ClipProperties. 796 uiClipVideoDuration; /* Only video track duration is important to 797 avoid deviation if audio track is longer */ 798 } 799 else 800 { 801 pC->ewc.iOutputDuration += 802 pC->pClipList[i].uiEndCutTime; /**< Add end cut */ 803 } 804 805 pC->ewc.iOutputDuration -= 806 pC->pClipList[i].uiBeginCutTime; /**< Remove begin cut */ 807 808 /** 809 * Remove the duration of the transition (it is counted twice) */ 810 pC->ewc.iOutputDuration -= pC->pTransitionList[i].uiTransitionDuration; 811 } 812 813 /** 814 * Copy the video properties of the master clip to the output properties */ 815 pC->ewc.uiVideoWidth = 816 pC->pClipList[pSettings->uiMasterClip].ClipProperties.uiVideoWidth; 817 pC->ewc.uiVideoHeight = 818 pC->pClipList[pSettings->uiMasterClip].ClipProperties.uiVideoHeight; 819 pC->ewc.uiVideoTimeScale = 820 pC->pClipList[pSettings->uiMasterClip].ClipProperties.uiVideoTimeScale; 821 pC->ewc.bVideoDataPartitioning = pC->pClipList[pSettings-> 822 uiMasterClip].ClipProperties.bMPEG4dataPartition; 823 824 switch( pC->pClipList[pSettings->uiMasterClip].ClipProperties.VideoStreamType ) 825 { 826 case M4VIDEOEDITING_kH263: 827 pC->ewc.VideoStreamType = M4SYS_kH263; 828 break; 829 830 case M4VIDEOEDITING_kMPEG4_EMP: 831 pC->ewc.bActivateEmp = M4OSA_TRUE; /* no break */ 832 833 case M4VIDEOEDITING_kMPEG4: 834 pC->ewc.VideoStreamType = M4SYS_kMPEG_4; 835 break; 836 837 case M4VIDEOEDITING_kH264: 838 pC->ewc.VideoStreamType = M4SYS_kH264; 839 break; 840 841 default: 842 pC->ewc.VideoStreamType = M4SYS_kVideoUnknown; 843 break; 844 } 845 846 /** 847 * Copy the audio properties of the master clip to the output properties */ 848 pC->ewc.uiNbChannels = 849 pC->pClipList[pSettings->uiMasterClip].ClipProperties.uiNbChannels; 850 pC->ewc.uiAudioBitrate = 851 pC->pClipList[pSettings->uiMasterClip].ClipProperties.uiAudioBitrate; 852 pC->ewc.uiSamplingFrequency = pC->pClipList[pSettings-> 853 uiMasterClip].ClipProperties.uiSamplingFrequency; 854 pC->ewc.uiSilencePcmSize = 855 pC->pClipList[pSettings->uiMasterClip].ClipProperties.uiDecodedPcmSize; 856 pC->ewc.scale_audio = pC->ewc.uiSamplingFrequency / 1000.0; 857 858 switch( pC->pClipList[pSettings->uiMasterClip].ClipProperties.AudioStreamType ) 859 { 860 case M4VIDEOEDITING_kAMR_NB: 861 pC->ewc.AudioStreamType = M4SYS_kAMR; 862 pC->ewc.pSilenceFrameData = 863 (M4OSA_UInt8 *)M4VSS3GPP_AMR_AU_SILENCE_FRAME_048; 864 pC->ewc.uiSilenceFrameSize = 865 M4VSS3GPP_AMR_AU_SILENCE_FRAME_048_SIZE; 866 pC->ewc.iSilenceFrameDuration = 867 M4VSS3GPP_AMR_AU_SILENCE_FRAME_048_DURATION; 868 pC->bSupportSilence = M4OSA_TRUE; 869 break; 870 871 case M4VIDEOEDITING_kAAC: 872 case M4VIDEOEDITING_kAACplus: 873 case M4VIDEOEDITING_keAACplus: 874 pC->ewc.AudioStreamType = M4SYS_kAAC; 875 876 if( pC->ewc.uiNbChannels == 1 ) 877 { 878 pC->ewc.pSilenceFrameData = 879 (M4OSA_UInt8 *)M4VSS3GPP_AAC_AU_SILENCE_MONO; 880 pC->ewc.uiSilenceFrameSize = M4VSS3GPP_AAC_AU_SILENCE_MONO_SIZE; 881 pC->bSupportSilence = M4OSA_TRUE; 882 } 883 else 884 { 885 pC->ewc.pSilenceFrameData = 886 (M4OSA_UInt8 *)M4VSS3GPP_AAC_AU_SILENCE_STEREO; 887 pC->ewc.uiSilenceFrameSize = 888 M4VSS3GPP_AAC_AU_SILENCE_STEREO_SIZE; 889 pC->bSupportSilence = M4OSA_TRUE; 890 } 891 pC->ewc.iSilenceFrameDuration = 892 1024; /* AAC is always 1024/Freq sample duration */ 893 break; 894 895 case M4VIDEOEDITING_kMP3: 896 pC->ewc.AudioStreamType = M4SYS_kMP3; 897 pC->ewc.pSilenceFrameData = M4OSA_NULL; 898 pC->ewc.uiSilenceFrameSize = 0; 899 pC->ewc.iSilenceFrameDuration = 0; 900 /* Special case, mp3 core reader return a time in ms */ 901 pC->ewc.scale_audio = 1.0; 902 break; 903 904 case M4VIDEOEDITING_kEVRC: 905 pC->ewc.AudioStreamType = M4SYS_kEVRC; 906 pC->ewc.pSilenceFrameData = M4OSA_NULL; 907 pC->ewc.uiSilenceFrameSize = 0; 908 pC->ewc.iSilenceFrameDuration = 160; /* EVRC frames are 20 ms at 8000 Hz 909 (makes it easier to factorize amr and evrc code) */ 910 break; 911 912 default: 913 pC->ewc.AudioStreamType = M4SYS_kAudioUnknown; 914 break; 915 } 916 917 /** 918 * We produce a 3gpp file, unless it is mp3 */ 919 if( M4VIDEOEDITING_kMP3 == pC-> 920 pClipList[pSettings->uiMasterClip].ClipProperties.AudioStreamType ) 921 outputFileType = M4VIDEOEDITING_kFileType_MP3; 922 else 923 outputFileType = M4VIDEOEDITING_kFileType_3GPP; 924 925 /** 926 * Beware, a null duration would lead to a divide by zero error (better safe than sorry...) */ 927 if( 0 == pC->ewc.iOutputDuration ) 928 { 929 pC->ewc.iOutputDuration = 1; 930 } 931 932 /** 933 * Open first clip */ 934 pC->uiCurrentClip = 0; 935 936 // Decorrelate input and output encoding timestamp to handle encoder prefetch 937 pC->ewc.dInputVidCts = 0.0; 938 pC->ewc.dOutputVidCts = 0.0; 939 pC->ewc.dATo = 0.0; 940 941 err = M4VSS3GPP_intSwitchToNextClip(pC); 942 /* RC: to know when a file has been processed */ 943 if( M4NO_ERROR != err && err != M4VSS3GPP_WAR_SWITCH_CLIP ) 944 { 945 M4OSA_TRACE1_1( 946 "M4VSS3GPP_editOpen: M4VSS3GPP_intSwitchToNextClip() returns 0x%x!", 947 err); 948 return err; 949 } 950 951 /** 952 * Do the video stuff in 3GPP Audio/Video case */ 953 if( M4VIDEOEDITING_kFileType_3GPP == outputFileType ) 954 { 955 /** 956 * Compute the Decoder Specific Info for the output video and audio streams */ 957 err = M4VSS3GPP_intComputeOutputVideoAndAudioDsi(pC, 958 pSettings->uiMasterClip); 959 960 if( M4NO_ERROR != err ) 961 { 962 M4OSA_TRACE1_1( 963 "M4VSS3GPP_editOpen: M4VSS3GPP_intComputeOutputVideoAndAudioDsi() returns 0x%x!", 964 err); 965 return err; 966 } 967 968 /** 969 * Compute the time increment for the transition file */ 970 switch( pSettings->videoFrameRate ) 971 { 972 case M4VIDEOEDITING_k5_FPS: 973 pC->dOutputFrameDuration = 1000.0 / 5.0; 974 break; 975 976 case M4VIDEOEDITING_k7_5_FPS: 977 pC->dOutputFrameDuration = 1000.0 / 7.5; 978 break; 979 980 case M4VIDEOEDITING_k10_FPS: 981 pC->dOutputFrameDuration = 1000.0 / 10.0; 982 break; 983 984 case M4VIDEOEDITING_k12_5_FPS: 985 pC->dOutputFrameDuration = 1000.0 / 12.5; 986 break; 987 988 case M4VIDEOEDITING_k15_FPS: 989 pC->dOutputFrameDuration = 1000.0 / 15.0; 990 break; 991 992 case M4VIDEOEDITING_k20_FPS: 993 pC->dOutputFrameDuration = 1000.0 / 20.0; 994 break; 995 996 case M4VIDEOEDITING_k25_FPS: 997 pC->dOutputFrameDuration = 1000.0 / 25.0; 998 break; 999 1000 case M4VIDEOEDITING_k30_FPS: 1001 pC->dOutputFrameDuration = 1000.0 / 30.0; 1002 break; 1003 1004 default: 1005 M4OSA_TRACE1_1( 1006 "M4VSS3GPP_editOpen(): invalid videoFrameRate (0x%x),\ 1007 returning M4VSS3GPP_ERR_INVALID_VIDEO_ENCODING_FRAME_RATE", 1008 pSettings->videoFrameRate); 1009 return M4VSS3GPP_ERR_INVALID_VIDEO_ENCODING_FRAME_RATE; 1010 } 1011 1012 if( M4SYS_kMPEG_4 == pC->ewc.VideoStreamType ) 1013 { 1014 M4OSA_UInt32 uiAlpha; 1015 /** 1016 * MPEG-4 case. 1017 * Time scale of the transition encoder must be the same than the 1018 * timescale of the input files. 1019 * So the frame duration must be compatible with this time scale, 1020 * but without beeing too short. 1021 * For that, we must compute alpha (integer) so that: 1022 * (alpha x 1000)/EncoderTimeScale > MinFrameDuration 1023 **/ 1024 1025 uiAlpha = (M4OSA_UInt32)(( pC->dOutputFrameDuration 1026 * pC->ewc.uiVideoTimeScale) / 1000.0 + 0.5); 1027 1028 if( uiAlpha > 0 ) 1029 { 1030 pC->dOutputFrameDuration = 1031 ( uiAlpha * 1000.0) / pC->ewc.uiVideoTimeScale; 1032 } 1033 } 1034 else if( M4SYS_kH263 == pC->ewc.VideoStreamType ) 1035 { 1036 switch( pSettings->videoFrameRate ) 1037 { 1038 case M4VIDEOEDITING_k12_5_FPS: 1039 case M4VIDEOEDITING_k20_FPS: 1040 case M4VIDEOEDITING_k25_FPS: 1041 M4OSA_TRACE1_0( 1042 "M4VSS3GPP_editOpen(): invalid videoFrameRate for H263,\ 1043 returning M4VSS3GPP_ERR_INVALID_VIDEO_ENCODING_FRAME_RATE"); 1044 return M4VSS3GPP_ERR_INVALID_VIDEO_ENCODING_FRAME_RATE; 1045 default: 1046 break; 1047 } 1048 } 1049 } 1050 1051 /** 1052 * Create the MP3 output file */ 1053 if( M4VIDEOEDITING_kFileType_MP3 == outputFileType ) 1054 { 1055 M4READER_Buffer mp3tagBuffer; 1056 err = M4VSS3GPP_intCreateMP3OutputFile(pC, pSettings->pOutputFile); 1057 1058 if( M4NO_ERROR != err ) 1059 { 1060 M4OSA_TRACE1_1( 1061 "M4VSS3GPP_editOpen: M4VSS3GPP_intCreateMP3OutputFile returns 0x%x", 1062 err); 1063 return err; 1064 } 1065 1066 /* The ID3v2 tag could be at any place in the mp3 file */ 1067 /* The mp3 reader only checks few bytes in the beginning of 1068 stream to look for a ID3v2 tag */ 1069 /* It means that if the ID3v2 tag is not at the beginning of the file the reader do 1070 as there is no these metadata */ 1071 1072 /* Retrieve the data of the ID3v2 Tag */ 1073 err = pC->pC1->ShellAPI.m_pReader->m_pFctGetOption( 1074 pC->pC1->pReaderContext, M4READER_kOptionID_Mp3Id3v2Tag, 1075 (M4OSA_DataOption) &mp3tagBuffer); 1076 1077 if( M4NO_ERROR != err ) 1078 { 1079 M4OSA_TRACE1_1("M4VSS3GPP_editOpen: M4MP3R_getOption returns 0x%x", 1080 err); 1081 return err; 1082 } 1083 1084 /* Write the data of the ID3v2 Tag in the output file */ 1085 if( 0 != mp3tagBuffer.m_uiBufferSize ) 1086 { 1087 err = pC->pOsaFileWritPtr->writeData(pC->ewc.p3gpWriterContext, 1088 (M4OSA_MemAddr8)mp3tagBuffer.m_pData, mp3tagBuffer.m_uiBufferSize); 1089 1090 /** 1091 * Free before the error checking anyway */ 1092 free(mp3tagBuffer.m_pData); 1093 1094 /** 1095 * Error checking */ 1096 if( M4NO_ERROR != err ) 1097 { 1098 M4OSA_TRACE1_1( 1099 "M4VSS3GPP_editOpen: WriteData(ID3v2Tag) returns 0x%x", 1100 err); 1101 return err; 1102 } 1103 1104 mp3tagBuffer.m_uiBufferSize = 0; 1105 mp3tagBuffer.m_pData = M4OSA_NULL; 1106 } 1107 } 1108 /** 1109 * Create the 3GPP output file */ 1110 else if( M4VIDEOEDITING_kFileType_3GPP == outputFileType ) 1111 { 1112 /* Compute an average bitrate from mixed bitrates of the input clips */ 1113 M4VSS3GPP_intComputeOutputAverageVideoBitrate(pC); 1114 pC->ewc.uiVideoBitrate = pSettings->xVSS.outputVideoBitrate; 1115 1116 /** 1117 * 11/12/2008 CR3283 MMS use case in VideoArtist: Set max output file size if needed */ 1118 if( pC->bIsMMS == M4OSA_TRUE ) 1119 { 1120 err = M4VSS3GPP_intCreate3GPPOutputFile(&pC->ewc, &pC->ShellAPI, 1121 pC->pOsaFileWritPtr, pSettings->pOutputFile, 1122 pC->pOsaFileReadPtr, pSettings->pTemporaryFile, 1123 pSettings->xVSS.outputFileSize); 1124 } 1125 else 1126 { 1127 err = M4VSS3GPP_intCreate3GPPOutputFile(&pC->ewc, &pC->ShellAPI, 1128 pC->pOsaFileWritPtr, pSettings->pOutputFile, 1129 pC->pOsaFileReadPtr, pSettings->pTemporaryFile, 0); 1130 } 1131 1132 if( M4NO_ERROR != err ) 1133 { 1134 M4OSA_TRACE1_1( 1135 "M4VSS3GPP_editOpen: M4VSS3GPP_intCreate3GPPOutputFile returns 0x%x", 1136 err); 1137 return err; 1138 } 1139 } 1140 /** 1141 * Default error case */ 1142 else 1143 { 1144 M4OSA_TRACE1_1( 1145 "M4VSS3GPP_editOpen: invalid outputFileType = 0x%x,\ 1146 returning M4VSS3GPP_ERR_OUTPUT_FILE_TYPE_ERROR", 1147 outputFileType); 1148 return 1149 M4VSS3GPP_ERR_OUTPUT_FILE_TYPE_ERROR; /**< this is an internal error code 1150 unknown to the user */ 1151 } 1152 1153 /** 1154 * Initialize state */ 1155 if( M4SYS_kMP3 == pC->ewc.AudioStreamType ) 1156 { 1157 /** 1158 * In the MP3 case we use a special audio state */ 1159 pC->State = M4VSS3GPP_kEditState_MP3_JUMP; 1160 } 1161 else 1162 { 1163 /** 1164 * We start with the video processing */ 1165 pC->State = M4VSS3GPP_kEditState_VIDEO; 1166 } 1167 1168 /** 1169 * Initialize state. 1170 * The first clip is independant to the "virtual previous clips", 1171 * so it's like if we where in Read/Write mode before it. */ 1172 pC->Vstate = M4VSS3GPP_kEditVideoState_READ_WRITE; 1173 pC->Astate = M4VSS3GPP_kEditAudioState_READ_WRITE; 1174 1175 /** 1176 * Return with no error */ 1177 M4OSA_TRACE3_0("M4VSS3GPP_editOpen(): returning M4NO_ERROR"); 1178 return M4NO_ERROR; 1179} 1180 1181/** 1182 ****************************************************************************** 1183 * M4OSA_ERR M4VSS3GPP_editStep() 1184 * @brief Perform one step of editing. 1185 * @note 1186 * @param pContext (IN) VSS 3GPP edit context 1187 * @param pProgress (OUT) Progress percentage (0 to 100) of the editing operation 1188 * @return M4NO_ERROR: No error 1189 * @return M4ERR_PARAMETER: pContext is M4OSA_NULL (debug only) 1190 * @return M4ERR_STATE: VSS 3GPP is not in an appropriate state for this 1191 * function to be called 1192 * @return M4VSS3GPP_WAR_EDITING_DONE: Edition is done, user should now call 1193 * M4VSS3GPP_editClose() 1194 ****************************************************************************** 1195 */ 1196M4OSA_ERR M4VSS3GPP_editStep( M4VSS3GPP_EditContext pContext, 1197 M4OSA_UInt8 *pProgress ) 1198{ 1199 M4VSS3GPP_InternalEditContext *pC = 1200 (M4VSS3GPP_InternalEditContext *)pContext; 1201 M4OSA_UInt32 uiProgressAudio, uiProgressVideo, uiProgress; 1202 M4OSA_ERR err; 1203 1204 M4OSA_TRACE3_1("M4VSS3GPP_editStep called with pContext=0x%x", pContext); 1205 1206 /** 1207 * Check input parameter */ 1208 M4OSA_DEBUG_IF2((M4OSA_NULL == pContext), M4ERR_PARAMETER, 1209 "M4VSS3GPP_editStep: pContext is M4OSA_NULL"); 1210 M4OSA_DEBUG_IF2((M4OSA_NULL == pProgress), M4ERR_PARAMETER, 1211 "M4VSS3GPP_editStep: pProgress is M4OSA_NULL"); 1212 1213 /** 1214 * Check state automaton and select correct processing */ 1215 switch( pC->State ) 1216 { 1217 case M4VSS3GPP_kEditState_VIDEO: 1218 err = M4VSS3GPP_intEditStepVideo(pC); 1219 break; 1220 1221 case M4VSS3GPP_kEditState_AUDIO: 1222 err = M4VSS3GPP_intEditStepAudio(pC); 1223 break; 1224 1225 case M4VSS3GPP_kEditState_MP3: 1226 err = M4VSS3GPP_intEditStepMP3(pC); 1227 break; 1228 1229 case M4VSS3GPP_kEditState_MP3_JUMP: 1230 err = M4VSS3GPP_intEditJumpMP3(pC); 1231 break; 1232 1233 default: 1234 M4OSA_TRACE1_0( 1235 "M4VSS3GPP_editStep(): invalid internal state (0x%x), returning M4ERR_STATE"); 1236 return M4ERR_STATE; 1237 } 1238 1239 /** 1240 * Compute progress. 1241 * We do the computing with 32bits precision because in some (very) extreme case, we may get 1242 * values higher than 256 (...) */ 1243 uiProgressAudio = 1244 ( (M4OSA_UInt32)(pC->ewc.dATo * 100)) / pC->ewc.iOutputDuration; 1245 // Decorrelate input and output encoding timestamp to handle encoder prefetch 1246 uiProgressVideo = ((M4OSA_UInt32)(pC->ewc.dInputVidCts * 100)) / pC->ewc.iOutputDuration; 1247 1248 uiProgress = uiProgressAudio + uiProgressVideo; 1249 1250 if( ( pC->ewc.AudioStreamType != M4SYS_kAudioUnknown) 1251 && (pC->ewc.VideoStreamType != M4SYS_kVideoUnknown) ) 1252 uiProgress /= 2; 1253 1254 /** 1255 * Sanity check */ 1256 if( uiProgress > 100 ) 1257 { 1258 *pProgress = 100; 1259 } 1260 else 1261 { 1262 *pProgress = (M4OSA_UInt8)uiProgress; 1263 } 1264 1265 /** 1266 * Return the error */ 1267 M4OSA_TRACE3_1("M4VSS3GPP_editStep(): returning 0x%x", err); 1268 return err; 1269} 1270 1271/** 1272 ****************************************************************************** 1273 * M4OSA_ERR M4VSS3GPP_editClose() 1274 * @brief Finish the VSS edit operation. 1275 * @note The output 3GPP file is ready to be played after this call 1276 * @param pContext (IN) VSS edit context 1277 * @return M4NO_ERROR: No error 1278 * @return M4ERR_PARAMETER: pContext is M4OSA_NULL (debug only) 1279 * @return M4ERR_STATE: VSS is not in an appropriate state for this function to be called 1280 ****************************************************************************** 1281 */ 1282M4OSA_ERR M4VSS3GPP_editClose( M4VSS3GPP_EditContext pContext ) 1283{ 1284 M4VSS3GPP_InternalEditContext *pC = 1285 (M4VSS3GPP_InternalEditContext *)pContext; 1286 M4OSA_ERR err; 1287 M4OSA_ERR returnedError = M4NO_ERROR; 1288 M4OSA_UInt32 lastCTS; 1289 1290 M4OSA_TRACE3_1("M4VSS3GPP_editClose called with pContext=0x%x", pContext); 1291 1292 /** 1293 * Check input parameter */ 1294 M4OSA_DEBUG_IF2((M4OSA_NULL == pContext), M4ERR_PARAMETER, 1295 "M4VSS3GPP_editClose: pContext is M4OSA_NULL"); 1296 1297 /** 1298 * Check state automaton. 1299 * In "theory", we should not authorize closing if we are in CREATED state. 1300 * But in practice, in case the opening failed, it may have been partially done. 1301 * In that case we have to free some opened ressources by calling Close. */ 1302 if( M4VSS3GPP_kEditState_CLOSED == pC->State ) 1303 { 1304 M4OSA_TRACE1_1( 1305 "M4VSS3GPP_editClose: Wrong state (0x%x), returning M4ERR_STATE", 1306 pC->State); 1307 return M4ERR_STATE; 1308 } 1309 1310 /** 1311 * There may be an encoder to destroy */ 1312 err = M4VSS3GPP_intDestroyVideoEncoder(pC); 1313 1314 if( M4NO_ERROR != err ) 1315 { 1316 M4OSA_TRACE1_1( 1317 "M4VSS3GPP_editClose: M4VSS3GPP_editDestroyVideoEncoder() returns 0x%x!", 1318 err); 1319 /**< We do not return the error here because we still have stuff to free */ 1320 returnedError = err; 1321 } 1322 1323 /** 1324 * Close the output file */ 1325 if( M4SYS_kMP3 == pC->ewc.AudioStreamType ) 1326 { 1327 /** 1328 * MP3 case */ 1329 if( M4OSA_NULL != pC->ewc.p3gpWriterContext ) 1330 { 1331 err = pC->pOsaFileWritPtr->closeWrite(pC->ewc.p3gpWriterContext); 1332 pC->ewc.p3gpWriterContext = M4OSA_NULL; 1333 } 1334 } 1335 else 1336 { 1337 /** 1338 * Close the output 3GPP clip, if it has been opened */ 1339 if( M4OSA_NULL != pC->ewc.p3gpWriterContext ) 1340 { 1341 /* Update last Video CTS */ 1342 lastCTS = pC->ewc.iOutputDuration; 1343 1344 err = pC->ShellAPI.pWriterGlobalFcts->pFctSetOption( 1345 pC->ewc.p3gpWriterContext, 1346 (M4OSA_UInt32)M4WRITER_kMaxFileDuration, &lastCTS); 1347 1348 if( M4NO_ERROR != err ) 1349 { 1350 M4OSA_TRACE1_1( 1351 "M4VSS3GPP_editClose: SetOption(M4WRITER_kMaxFileDuration) returns 0x%x", 1352 err); 1353 } 1354 1355 err = pC->ShellAPI.pWriterGlobalFcts->pFctCloseWrite( 1356 pC->ewc.p3gpWriterContext); 1357 1358 if( M4NO_ERROR != err ) 1359 { 1360 M4OSA_TRACE1_1( 1361 "M4VSS3GPP_editClose: pFctCloseWrite(OUT) returns 0x%x!", 1362 err); 1363 /**< We do not return the error here because we still have stuff to free */ 1364 if( M4NO_ERROR 1365 == returnedError ) /**< we return the first error that happened */ 1366 { 1367 returnedError = err; 1368 } 1369 } 1370 pC->ewc.p3gpWriterContext = M4OSA_NULL; 1371 } 1372 } 1373 1374 /** 1375 * Free the output video DSI, if it has been created */ 1376 if( M4OSA_NULL != pC->ewc.pVideoOutputDsi ) 1377 { 1378 free(pC->ewc.pVideoOutputDsi); 1379 pC->ewc.pVideoOutputDsi = M4OSA_NULL; 1380 } 1381 1382 /** 1383 * Free the output audio DSI, if it has been created */ 1384 if( M4OSA_NULL != pC->ewc.pAudioOutputDsi ) 1385 { 1386 free(pC->ewc.pAudioOutputDsi); 1387 pC->ewc.pAudioOutputDsi = M4OSA_NULL; 1388 } 1389 1390 /** 1391 * Close clip1, if needed */ 1392 if( M4OSA_NULL != pC->pC1 ) 1393 { 1394 err = M4VSS3GPP_intClipCleanUp(pC->pC1); 1395 1396 if( M4NO_ERROR != err ) 1397 { 1398 M4OSA_TRACE1_1( 1399 "M4VSS3GPP_editClose: M4VSS3GPP_intClipCleanUp(C1) returns 0x%x!", 1400 err); 1401 /**< We do not return the error here because we still have stuff to free */ 1402 if( M4NO_ERROR 1403 == returnedError ) /**< we return the first error that happened */ 1404 { 1405 returnedError = err; 1406 } 1407 } 1408 pC->pC1 = M4OSA_NULL; 1409 } 1410 1411 /** 1412 * Close clip2, if needed */ 1413 if( M4OSA_NULL != pC->pC2 ) 1414 { 1415 err = M4VSS3GPP_intClipCleanUp(pC->pC2); 1416 1417 if( M4NO_ERROR != err ) 1418 { 1419 M4OSA_TRACE1_1( 1420 "M4VSS3GPP_editClose: M4VSS3GPP_intClipCleanUp(C2) returns 0x%x!", 1421 err); 1422 /**< We do not return the error here because we still have stuff to free */ 1423 if( M4NO_ERROR 1424 == returnedError ) /**< we return the first error that happened */ 1425 { 1426 returnedError = err; 1427 } 1428 } 1429 pC->pC2 = M4OSA_NULL; 1430 } 1431 1432 /** 1433 * Free the temporary YUV planes */ 1434 if( M4OSA_NULL != pC->yuv1[0].pac_data ) 1435 { 1436 free(pC->yuv1[0].pac_data); 1437 pC->yuv1[0].pac_data = M4OSA_NULL; 1438 } 1439 1440 if( M4OSA_NULL != pC->yuv1[1].pac_data ) 1441 { 1442 free(pC->yuv1[1].pac_data); 1443 pC->yuv1[1].pac_data = M4OSA_NULL; 1444 } 1445 1446 if( M4OSA_NULL != pC->yuv1[2].pac_data ) 1447 { 1448 free(pC->yuv1[2].pac_data); 1449 pC->yuv1[2].pac_data = M4OSA_NULL; 1450 } 1451 1452 if( M4OSA_NULL != pC->yuv2[0].pac_data ) 1453 { 1454 free(pC->yuv2[0].pac_data); 1455 pC->yuv2[0].pac_data = M4OSA_NULL; 1456 } 1457 1458 if( M4OSA_NULL != pC->yuv2[1].pac_data ) 1459 { 1460 free(pC->yuv2[1].pac_data); 1461 pC->yuv2[1].pac_data = M4OSA_NULL; 1462 } 1463 1464 if( M4OSA_NULL != pC->yuv2[2].pac_data ) 1465 { 1466 free(pC->yuv2[2].pac_data); 1467 pC->yuv2[2].pac_data = M4OSA_NULL; 1468 } 1469 1470 /* RC */ 1471 if( M4OSA_NULL != pC->yuv3[0].pac_data ) 1472 { 1473 free(pC->yuv3[0].pac_data); 1474 pC->yuv3[0].pac_data = M4OSA_NULL; 1475 } 1476 1477 if( M4OSA_NULL != pC->yuv3[1].pac_data ) 1478 { 1479 free(pC->yuv3[1].pac_data); 1480 pC->yuv3[1].pac_data = M4OSA_NULL; 1481 } 1482 1483 if( M4OSA_NULL != pC->yuv3[2].pac_data ) 1484 { 1485 free(pC->yuv3[2].pac_data); 1486 pC->yuv3[2].pac_data = M4OSA_NULL; 1487 } 1488 1489 /* RC */ 1490 if( M4OSA_NULL != pC->yuv4[0].pac_data ) 1491 { 1492 free(pC->yuv4[0].pac_data); 1493 pC->yuv4[0].pac_data = M4OSA_NULL; 1494 } 1495 1496 if( M4OSA_NULL != pC->yuv4[1].pac_data ) 1497 { 1498 free(pC->yuv4[1].pac_data); 1499 pC->yuv4[1].pac_data = M4OSA_NULL; 1500 } 1501 1502 if( M4OSA_NULL != pC->yuv4[2].pac_data ) 1503 { 1504 free(pC->yuv4[2].pac_data); 1505 pC->yuv4[2].pac_data = M4OSA_NULL; 1506 } 1507 1508 /** 1509 * RC Free effects list */ 1510 if( pC->pEffectsList != M4OSA_NULL ) 1511 { 1512 free(pC->pEffectsList); 1513 pC->pEffectsList = M4OSA_NULL; 1514 } 1515 1516 /** 1517 * RC Free active effects list */ 1518 if( pC->pActiveEffectsList != M4OSA_NULL ) 1519 { 1520 free(pC->pActiveEffectsList); 1521 pC->pActiveEffectsList = M4OSA_NULL; 1522 } 1523 /** 1524 * Free active effects list */ 1525 if(pC->pActiveEffectsList1 != M4OSA_NULL) 1526 { 1527 free(pC->pActiveEffectsList1); 1528 pC->pActiveEffectsList1 = M4OSA_NULL; 1529 } 1530 /** 1531 * Update state automaton */ 1532 pC->State = M4VSS3GPP_kEditState_CLOSED; 1533 1534 /** 1535 * Return with no error */ 1536 M4OSA_TRACE3_1("M4VSS3GPP_editClose(): returning 0x%x", returnedError); 1537 return returnedError; 1538} 1539 1540/** 1541 ****************************************************************************** 1542 * M4OSA_ERR M4VSS3GPP_editCleanUp() 1543 * @brief Free all resources used by the VSS edit operation. 1544 * @note The context is no more valid after this call 1545 * @param pContext (IN) VSS edit context 1546 * @return M4NO_ERROR: No error 1547 * @return M4ERR_PARAMETER: pContext is M4OSA_NULL (debug only) 1548 ****************************************************************************** 1549 */ 1550M4OSA_ERR M4VSS3GPP_editCleanUp( M4VSS3GPP_EditContext pContext ) 1551{ 1552 M4OSA_ERR err; 1553 M4VSS3GPP_InternalEditContext *pC = 1554 (M4VSS3GPP_InternalEditContext *)pContext; 1555 1556 M4OSA_TRACE3_1("M4VSS3GPP_editCleanUp called with pContext=0x%x", pContext); 1557 1558 /** 1559 * Check input parameter */ 1560 if( M4OSA_NULL == pContext ) 1561 { 1562 M4OSA_TRACE1_0( 1563 "M4VSS3GPP_editCleanUp(): pContext is M4OSA_NULL, returning M4ERR_PARAMETER"); 1564 return M4ERR_PARAMETER; 1565 } 1566 1567 /** 1568 * Close, if needed. 1569 * In "theory", we should not close if we are in CREATED state. 1570 * But in practice, in case the opening failed, it may have been partially done. 1571 * In that case we have to free some opened ressources by calling Close. */ 1572 if( M4VSS3GPP_kEditState_CLOSED != pC->State ) 1573 { 1574 M4OSA_TRACE3_0("M4VSS3GPP_editCleanUp(): calling M4VSS3GPP_editClose"); 1575 err = M4VSS3GPP_editClose(pC); 1576 1577 if( M4NO_ERROR != err ) 1578 { 1579 M4OSA_TRACE1_1( 1580 "M4VSS3GPP_editCleanUp(): M4VSS3GPP_editClose returns 0x%x", 1581 err); 1582 } 1583 } 1584 1585 /** 1586 * Free the video encoder dummy AU */ 1587 if( M4OSA_NULL != pC->ewc.pDummyAuBuffer ) 1588 { 1589 free(pC->ewc.pDummyAuBuffer); 1590 pC->ewc.pDummyAuBuffer = M4OSA_NULL; 1591 } 1592 1593 /** 1594 * Free the Audio encoder context */ 1595 if( M4OSA_NULL != pC->ewc.pAudioEncCtxt ) 1596 { 1597 err = pC->ShellAPI.pAudioEncoderGlobalFcts->pFctClose( 1598 pC->ewc.pAudioEncCtxt); 1599 1600 if( M4NO_ERROR != err ) 1601 { 1602 M4OSA_TRACE1_1( 1603 "M4VSS3GPP_editCleanUp: pAudioEncoderGlobalFcts->pFctClose returns 0x%x", 1604 err); 1605 /**< don't return, we still have stuff to free */ 1606 } 1607 1608 err = pC->ShellAPI.pAudioEncoderGlobalFcts->pFctCleanUp( 1609 pC->ewc.pAudioEncCtxt); 1610 1611 if( M4NO_ERROR != err ) 1612 { 1613 M4OSA_TRACE1_1( 1614 "M4VSS3GPP_editCleanUp: pAudioEncoderGlobalFcts->pFctCleanUp returns 0x%x", 1615 err); 1616 /**< don't return, we still have stuff to free */ 1617 } 1618 1619 pC->ewc.pAudioEncCtxt = M4OSA_NULL; 1620 } 1621 1622 /** 1623 * Free the shells interfaces */ 1624 M4VSS3GPP_unRegisterAllWriters(&pC->ShellAPI); 1625 M4VSS3GPP_unRegisterAllEncoders(&pC->ShellAPI); 1626 M4VSS3GPP_unRegisterAllReaders(&pC->ShellAPI); 1627 M4VSS3GPP_unRegisterAllDecoders(&pC->ShellAPI); 1628 1629 /** 1630 * Free the settings copied in the internal context */ 1631 M4VSS3GPP_intFreeSettingsList(pC); 1632 1633 /** 1634 * Finally, Free context */ 1635 free(pC); 1636 pC = M4OSA_NULL; 1637 1638 /** 1639 * Return with no error */ 1640 M4OSA_TRACE3_0("M4VSS3GPP_editCleanUp(): returning M4NO_ERROR"); 1641 return M4NO_ERROR; 1642} 1643 1644#ifdef WIN32 1645/** 1646 ****************************************************************************** 1647 * M4OSA_ERR M4VSS3GPP_GetErrorMessage() 1648 * @brief Return a string describing the given error code 1649 * @note The input string must be already allocated (and long enough!) 1650 * @param err (IN) Error code to get the description from 1651 * @param sMessage (IN/OUT) Allocated string in which the description will be copied 1652 * @return M4NO_ERROR: Input error is from the VSS3GPP module 1653 * @return M4ERR_PARAMETER:Input error is not from the VSS3GPP module 1654 ****************************************************************************** 1655 */ 1656 1657M4OSA_ERR M4VSS3GPP_GetErrorMessage( M4OSA_ERR err, M4OSA_Char *sMessage ) 1658{ 1659 switch( err ) 1660 { 1661 case M4VSS3GPP_WAR_EDITING_DONE: 1662 strcpy(sMessage, "M4VSS3GPP_WAR_EDITING_DONE"); 1663 break; 1664 1665 case M4VSS3GPP_WAR_END_OF_AUDIO_MIXING: 1666 strcpy(sMessage, "M4VSS3GPP_WAR_END_OF_AUDIO_MIXING"); 1667 break; 1668 1669 case M4VSS3GPP_WAR_END_OF_EXTRACT_PICTURE: 1670 strcpy(sMessage, "M4VSS3GPP_WAR_END_OF_EXTRACT_PICTURE"); 1671 break; 1672 1673 case M4VSS3GPP_ERR_INVALID_FILE_TYPE: 1674 strcpy(sMessage, "M4VSS3GPP_ERR_INVALID_FILE_TYPE"); 1675 break; 1676 1677 case M4VSS3GPP_ERR_INVALID_EFFECT_KIND: 1678 strcpy(sMessage, "M4VSS3GPP_ERR_INVALID_EFFECT_KIND"); 1679 break; 1680 1681 case M4VSS3GPP_ERR_INVALID_VIDEO_EFFECT_TYPE: 1682 strcpy(sMessage, "M4VSS3GPP_ERR_INVALID_VIDEO_EFFECT_TYPE"); 1683 break; 1684 1685 case M4VSS3GPP_ERR_INVALID_AUDIO_EFFECT_TYPE: 1686 strcpy(sMessage, "M4VSS3GPP_ERR_INVALID_AUDIO_EFFECT_TYPE"); 1687 break; 1688 1689 case M4VSS3GPP_ERR_INVALID_VIDEO_TRANSITION_TYPE: 1690 strcpy(sMessage, "M4VSS3GPP_ERR_INVALID_VIDEO_TRANSITION_TYPE"); 1691 break; 1692 1693 case M4VSS3GPP_ERR_INVALID_AUDIO_TRANSITION_TYPE: 1694 strcpy(sMessage, "M4VSS3GPP_ERR_INVALID_AUDIO_TRANSITION_TYPE"); 1695 break; 1696 1697 case M4VSS3GPP_ERR_INVALID_VIDEO_ENCODING_FRAME_RATE: 1698 strcpy(sMessage, "M4VSS3GPP_ERR_INVALID_VIDEO_ENCODING_FRAME_RATE"); 1699 break; 1700 1701 case M4VSS3GPP_ERR_EXTERNAL_EFFECT_NULL: 1702 strcpy(sMessage, "M4VSS3GPP_ERR_EXTERNAL_EFFECT_NULL"); 1703 break; 1704 1705 case M4VSS3GPP_ERR_EXTERNAL_TRANSITION_NULL: 1706 strcpy(sMessage, "M4VSS3GPP_ERR_EXTERNAL_TRANSITION_NULL"); 1707 break; 1708 1709 case M4VSS3GPP_ERR_BEGIN_CUT_LARGER_THAN_DURATION: 1710 strcpy(sMessage, "M4VSS3GPP_ERR_BEGIN_CUT_LARGER_THAN_DURATION"); 1711 break; 1712 1713 case M4VSS3GPP_ERR_BEGIN_CUT_LARGER_THAN_END_CUT: 1714 strcpy(sMessage, "M4VSS3GPP_ERR_BEGIN_CUT_LARGER_THAN_END_CUT"); 1715 break; 1716 1717 case M4VSS3GPP_ERR_OVERLAPPING_TRANSITIONS: 1718 strcpy(sMessage, "M4VSS3GPP_ERR_OVERLAPPING_TRANSITIONS"); 1719 break; 1720 1721 case M4VSS3GPP_ERR_INVALID_3GPP_FILE: 1722 strcpy(sMessage, "M4VSS3GPP_ERR_INVALID_3GPP_FILE"); 1723 break; 1724 1725 case M4VSS3GPP_ERR_UNSUPPORTED_INPUT_VIDEO_FORMAT: 1726 strcpy(sMessage, "M4VSS3GPP_ERR_UNSUPPORTED_INPUT_VIDEO_FORMAT"); 1727 break; 1728 1729 case M4VSS3GPP_ERR_UNSUPPORTED_INPUT_AUDIO_FORMAT: 1730 strcpy(sMessage, "M4VSS3GPP_ERR_UNSUPPORTED_INPUT_AUDIO_FORMAT"); 1731 break; 1732 1733 case M4VSS3GPP_ERR_AMR_EDITING_UNSUPPORTED: 1734 strcpy(sMessage, "M4VSS3GPP_ERR_AMR_EDITING_UNSUPPORTED"); 1735 break; 1736 1737 case M4VSS3GPP_ERR_INPUT_VIDEO_AU_TOO_LARGE: 1738 strcpy(sMessage, "M4VSS3GPP_ERR_INPUT_VIDEO_AU_TOO_LARGE"); 1739 break; 1740 1741 case M4VSS3GPP_ERR_INPUT_AUDIO_AU_TOO_LARGE: 1742 strcpy(sMessage, "M4VSS3GPP_ERR_INPUT_AUDIO_AU_TOO_LARGE"); 1743 break; 1744 1745 case M4VSS3GPP_ERR_INPUT_AUDIO_CORRUPTED_AU: 1746 strcpy(sMessage, "M4VSS3GPP_ERR_INPUT_AUDIO_CORRUPTED_AU"); 1747 break; 1748 1749 case M4VSS3GPP_ERR_ENCODER_ACCES_UNIT_ERROR: 1750 strcpy(sMessage, "M4VSS3GPP_ERR_ENCODER_ACCES_UNIT_ERROR"); 1751 break; 1752 1753 case M4VSS3GPP_ERR_EDITING_UNSUPPORTED_VIDEO_FORMAT: 1754 strcpy(sMessage, "M4VSS3GPP_ERR_EDITING_UNSUPPORTED_VIDEO_FORMAT"); 1755 break; 1756 1757 case M4VSS3GPP_ERR_EDITING_UNSUPPORTED_H263_PROFILE: 1758 strcpy(sMessage, "M4VSS3GPP_ERR_EDITING_UNSUPPORTED_H263_PROFILE"); 1759 break; 1760 1761 case M4VSS3GPP_ERR_EDITING_UNSUPPORTED_MPEG4_PROFILE: 1762 strcpy(sMessage, "M4VSS3GPP_ERR_EDITING_UNSUPPORTED_MPEG4_PROFILE"); 1763 break; 1764 1765 case M4VSS3GPP_ERR_EDITING_UNSUPPORTED_MPEG4_RVLC: 1766 strcpy(sMessage, "M4VSS3GPP_ERR_EDITING_UNSUPPORTED_MPEG4_RVLC"); 1767 break; 1768 1769 case M4VSS3GPP_ERR_EDITING_UNSUPPORTED_AUDIO_FORMAT: 1770 strcpy(sMessage, "M4VSS3GPP_ERR_EDITING_UNSUPPORTED_AUDIO_FORMAT"); 1771 break; 1772 1773 case M4VSS3GPP_ERR_EDITING_NO_SUPPORTED_STREAM_IN_FILE: 1774 strcpy(sMessage, 1775 "M4VSS3GPP_ERR_EDITING_NO_SUPPORTED_STREAM_IN_FILE"); 1776 break; 1777 1778 case M4VSS3GPP_ERR_EDITING_NO_SUPPORTED_VIDEO_STREAM_IN_FILE: 1779 strcpy(sMessage, 1780 "M4VSS3GPP_ERR_EDITING_NO_SUPPORTED_VIDEO_STREAM_IN_FILE"); 1781 break; 1782 1783 case M4VSS3GPP_ERR_INVALID_CLIP_ANALYSIS_VERSION: 1784 strcpy(sMessage, "M4VSS3GPP_ERR_INVALID_CLIP_ANALYSIS_VERSION"); 1785 break; 1786 1787 case M4VSS3GPP_ERR_INCOMPATIBLE_VIDEO_FORMAT: 1788 strcpy(sMessage, "M4VSS3GPP_ERR_INCOMPATIBLE_VIDEO_FORMAT"); 1789 break; 1790 1791 case M4VSS3GPP_ERR_INCOMPATIBLE_VIDEO_FRAME_SIZE: 1792 strcpy(sMessage, "M4VSS3GPP_ERR_INCOMPATIBLE_VIDEO_FRAME_SIZE"); 1793 break; 1794 1795 case M4VSS3GPP_ERR_INCOMPATIBLE_VIDEO_TIME_SCALE: 1796 strcpy(sMessage, "M4VSS3GPP_ERR_INCOMPATIBLE_VIDEO_TIME_SCALE"); 1797 break; 1798 1799 case M4VSS3GPP_ERR_INCOMPATIBLE_VIDEO_DATA_PARTITIONING: 1800 strcpy(sMessage, 1801 "M4VSS3GPP_ERR_INCOMPATIBLE_VIDEO_DATA_PARTITIONING"); 1802 break; 1803 1804 case M4VSS3GPP_ERR_UNSUPPORTED_MP3_ASSEMBLY: 1805 strcpy(sMessage, "M4VSS3GPP_ERR_UNSUPPORTED_MP3_ASSEMBLY"); 1806 break; 1807 1808 case M4VSS3GPP_WAR_INCOMPATIBLE_AUDIO_STREAM_TYPE: 1809 strcpy(sMessage, "M4VSS3GPP_WAR_INCOMPATIBLE_AUDIO_STREAM_TYPE"); 1810 break; 1811 1812 case M4VSS3GPP_WAR_INCOMPATIBLE_AUDIO_NB_OF_CHANNELS: 1813 strcpy(sMessage, "M4VSS3GPP_WAR_INCOMPATIBLE_AUDIO_NB_OF_CHANNELS"); 1814 break; 1815 1816 case M4VSS3GPP_WAR_INCOMPATIBLE_AUDIO_SAMPLING_FREQUENCY: 1817 strcpy(sMessage, 1818 "M4VSS3GPP_WAR_INCOMPATIBLE_AUDIO_SAMPLING_FREQUENCY"); 1819 break; 1820 1821 case M4VSS3GPP_ERR_NO_SUPPORTED_STREAM_IN_FILE: 1822 strcpy(sMessage, "M4VSS3GPP_ERR_NO_SUPPORTED_STREAM_IN_FILE"); 1823 break; 1824 1825 case M4VSS3GPP_ERR_ADDVOLUME_EQUALS_ZERO: 1826 strcpy(sMessage, "M4VSS3GPP_ERR_ADDVOLUME_EQUALS_ZERO"); 1827 break; 1828 1829 case M4VSS3GPP_ERR_ADDCTS_HIGHER_THAN_VIDEO_DURATION: 1830 strcpy(sMessage, "M4VSS3GPP_ERR_ADDCTS_HIGHER_THAN_VIDEO_DURATION"); 1831 break; 1832 1833 case M4VSS3GPP_ERR_UNDEFINED_AUDIO_TRACK_FILE_FORMAT: 1834 strcpy(sMessage, "M4VSS3GPP_ERR_UNDEFINED_AUDIO_TRACK_FILE_FORMAT"); 1835 break; 1836 1837 case M4VSS3GPP_ERR_UNSUPPORTED_ADDED_AUDIO_STREAM: 1838 strcpy(sMessage, "M4VSS3GPP_ERR_UNSUPPORTED_ADDED_AUDIO_STREAM"); 1839 break; 1840 1841 case M4VSS3GPP_ERR_AUDIO_MIXING_UNSUPPORTED: 1842 strcpy(sMessage, "M4VSS3GPP_ERR_AUDIO_MIXING_UNSUPPORTED"); 1843 break; 1844 1845 case M4VSS3GPP_ERR_FEATURE_UNSUPPORTED_WITH_AUDIO_TRACK: 1846 strcpy(sMessage, 1847 "M4VSS3GPP_ERR_FEATURE_UNSUPPORTED_WITH_AUDIO_TRACK"); 1848 break; 1849 1850 case M4VSS3GPP_ERR_AUDIO_CANNOT_BE_MIXED: 1851 strcpy(sMessage, "M4VSS3GPP_ERR_AUDIO_CANNOT_BE_MIXED"); 1852 break; 1853 1854 case M4VSS3GPP_ERR_INPUT_CLIP_IS_NOT_A_3GPP: 1855 strcpy(sMessage, "M4VSS3GPP_ERR_INPUT_CLIP_IS_NOT_A_3GPP"); 1856 break; 1857 1858 case M4VSS3GPP_ERR_BEGINLOOP_HIGHER_ENDLOOP: 1859 strcpy(sMessage, "M4VSS3GPP_ERR_BEGINLOOP_HIGHER_ENDLOOP"); 1860 break; 1861 1862 case M4VSS3GPP_ERR_H263_PROFILE_NOT_SUPPORTED: 1863 strcpy(sMessage, "M4VSS3GPP_ERR_H263_PROFILE_NOT_SUPPORTED"); 1864 break; 1865 1866 case M4VSS3GPP_ERR_NO_SUPPORTED_VIDEO_STREAM_IN_FILE: 1867 strcpy(sMessage, "M4VSS3GPP_ERR_NO_SUPPORTED_VIDEO_STREAM_IN_FILE"); 1868 break; 1869 1870 default: /**< Not a VSS3GPP error */ 1871 strcpy(sMessage, ""); 1872 return M4ERR_PARAMETER; 1873 } 1874 return M4NO_ERROR; 1875} 1876 1877#endif /* WIN32 */ 1878 1879/********************************************************/ 1880/********************************************************/ 1881/********************************************************/ 1882/**************** STATIC FUNCTIONS ******************/ 1883/********************************************************/ 1884/********************************************************/ 1885/********************************************************/ 1886 1887/** 1888 ****************************************************************************** 1889 * M4OSA_ERR M4VSS3GPP_intClipSettingsSanityCheck() 1890 * @brief Simplify the given clip settings 1891 * @note This function may modify the given structure 1892 * @param pClip (IN/OUT) Clip settings 1893 * @return M4NO_ERROR: No error 1894 * @return M4VSS3GPP_ERR_EXTERNAL_EFFECT_NULL: 1895 ****************************************************************************** 1896 */ 1897 1898static M4OSA_ERR M4VSS3GPP_intClipSettingsSanityCheck( 1899 M4VSS3GPP_ClipSettings *pClip ) 1900{ 1901 M4OSA_UInt8 uiFx; 1902 M4OSA_UInt32 1903 uiClipActualDuration; /**< the clip duration once the cuts are done */ 1904 M4OSA_UInt32 uiDuration; 1905 M4VSS3GPP_EffectSettings *pFx; 1906 1907 /** 1908 * If begin cut is too far, return an error */ 1909 uiDuration = pClip->ClipProperties.uiClipDuration; 1910 1911 if( pClip->uiBeginCutTime > uiDuration ) 1912 { 1913 M4OSA_TRACE1_2( 1914 "M4VSS3GPP_intClipSettingsSanityCheck: %d > %d,\ 1915 returning M4VSS3GPP_ERR_BEGIN_CUT_LARGER_THAN_DURATION", 1916 pClip->uiBeginCutTime, uiDuration); 1917 return M4VSS3GPP_ERR_BEGIN_CUT_LARGER_THAN_DURATION; 1918 } 1919 1920 /** 1921 * If end cut is too far, set to zero (it means no end cut) */ 1922 if( pClip->uiEndCutTime > uiDuration ) 1923 { 1924 pClip->uiEndCutTime = 0; 1925 } 1926 1927 /** 1928 * Compute actual clip duration (once cuts are done) */ 1929 if( 0 == pClip->uiEndCutTime ) 1930 { 1931 /** 1932 * No end cut */ 1933 uiClipActualDuration = uiDuration - pClip->uiBeginCutTime; 1934 } 1935 else 1936 { 1937 if( pClip->uiBeginCutTime >= pClip->uiEndCutTime ) 1938 { 1939 M4OSA_TRACE1_2( 1940 "M4VSS3GPP_intClipSettingsSanityCheck: %d > %d,\ 1941 returning M4VSS3GPP_ERR_BEGIN_CUT_LARGER_THAN_END_CUT", 1942 pClip->uiBeginCutTime, pClip->uiEndCutTime); 1943 return M4VSS3GPP_ERR_BEGIN_CUT_LARGER_THAN_END_CUT; 1944 } 1945 uiClipActualDuration = pClip->uiEndCutTime - pClip->uiBeginCutTime; 1946 } 1947 1948 return M4NO_ERROR; 1949} 1950 1951/** 1952 ****************************************************************************** 1953 * M4OSA_ERR M4VSS3GPP_intTransitionSettingsSanityCheck() 1954 * @brief Simplify the given transition settings 1955 * @note This function may modify the given structure 1956 * @param pTransition (IN/OUT) Transition settings 1957 * @return M4NO_ERROR: No error 1958 * @return M4VSS3GPP_ERR_EXTERNAL_TRANSITION_NULL: 1959 ****************************************************************************** 1960 */ 1961static M4OSA_ERR M4VSS3GPP_intTransitionSettingsSanityCheck( 1962 M4VSS3GPP_TransitionSettings *pTransition ) 1963{ 1964 /** 1965 * No transition */ 1966 if( 0 == pTransition->uiTransitionDuration ) 1967 { 1968 pTransition->VideoTransitionType = M4VSS3GPP_kVideoTransitionType_None; 1969 pTransition->AudioTransitionType = M4VSS3GPP_kAudioTransitionType_None; 1970 } 1971 else if( ( M4VSS3GPP_kVideoTransitionType_None 1972 == pTransition->VideoTransitionType) 1973 && (M4VSS3GPP_kAudioTransitionType_None 1974 == pTransition->AudioTransitionType) ) 1975 { 1976 pTransition->uiTransitionDuration = 0; 1977 } 1978 1979 /** 1980 * Check external transition function is set */ 1981 if( ( pTransition->VideoTransitionType 1982 >= M4VSS3GPP_kVideoTransitionType_External) 1983 && (M4OSA_NULL == pTransition->ExtVideoTransitionFct) ) 1984 { 1985 return M4VSS3GPP_ERR_EXTERNAL_TRANSITION_NULL; 1986 } 1987 1988 /** 1989 * Set minimal transition duration */ 1990 if( ( pTransition->uiTransitionDuration > 0) 1991 && (pTransition->uiTransitionDuration 1992 < M4VSS3GPP_MINIMAL_TRANSITION_DURATION) ) 1993 { 1994 pTransition->uiTransitionDuration = 1995 M4VSS3GPP_MINIMAL_TRANSITION_DURATION; 1996 } 1997 return M4NO_ERROR; 1998} 1999 2000/** 2001 ****************************************************************************** 2002 * M4OSA_ERR M4VSS3GPP_intFreeSettingsList() 2003 * @brief Free the settings copied in the internal context 2004 * @param pC (IN/OUT) Internal edit context 2005 ****************************************************************************** 2006 */ 2007static M4OSA_Void M4VSS3GPP_intFreeSettingsList( 2008 M4VSS3GPP_InternalEditContext *pC ) 2009{ 2010 M4OSA_UInt32 i; 2011 2012 /** 2013 * Free the settings list */ 2014 if( M4OSA_NULL != pC->pClipList ) 2015 { 2016 for ( i = 0; i < pC->uiClipNumber; i++ ) 2017 { 2018 M4VSS3GPP_editFreeClipSettings(&(pC->pClipList[i])); 2019 } 2020 2021 free(pC->pClipList); 2022 pC->pClipList = M4OSA_NULL; 2023 } 2024 2025 /** 2026 * Free the transition list */ 2027 if( M4OSA_NULL != pC->pTransitionList ) 2028 { 2029 free(pC->pTransitionList); 2030 pC->pTransitionList = M4OSA_NULL; 2031 } 2032} 2033/** 2034 ****************************************************************************** 2035 * M4OSA_ERR M4VSS3GPP_intCreateMP3OutputFile() 2036 * @brief Creates and prepare the output MP file 2037 * @param pC (IN/OUT) Internal edit context 2038 ****************************************************************************** 2039 */ 2040static M4OSA_ERR 2041M4VSS3GPP_intCreateMP3OutputFile( M4VSS3GPP_InternalEditContext *pC, 2042 M4OSA_Void *pOutputFile ) 2043{ 2044 M4OSA_ERR err; 2045 2046 err = 2047 pC->pOsaFileWritPtr->openWrite(&pC->ewc.p3gpWriterContext, pOutputFile, 2048 M4OSA_kFileWrite); 2049 2050 if( M4NO_ERROR != err ) 2051 { 2052 M4OSA_TRACE1_1( 2053 "M4VSS3GPP_intCreateMP3OutputFile: WriteOpen returns 0x%x!", err); 2054 return err; 2055 } 2056 2057 return M4NO_ERROR; 2058} 2059/** 2060 ****************************************************************************** 2061 * M4OSA_ERR M4VSS3GPP_intCreate3GPPOutputFile() 2062 * @brief Creates and prepare the output MP3 file 2063 * @note Creates the writer, Creates the output file, Adds the streams, 2064 Readies the writing process 2065 * @param pC (IN/OUT) Internal edit context 2066 ****************************************************************************** 2067 */ 2068M4OSA_ERR 2069M4VSS3GPP_intCreate3GPPOutputFile( M4VSS3GPP_EncodeWriteContext *pC_ewc, 2070 M4VSS3GPP_MediaAndCodecCtxt *pC_ShellAPI, 2071 M4OSA_FileWriterPointer *pOsaFileWritPtr, 2072 M4OSA_Void *pOutputFile, 2073 M4OSA_FileReadPointer *pOsaFileReadPtr, 2074 M4OSA_Void *pTempFile, 2075 M4OSA_UInt32 maxOutputFileSize ) 2076{ 2077 M4OSA_ERR err; 2078 M4OSA_UInt32 uiVersion; 2079 M4SYS_StreamIDValue temp; 2080 2081 M4OSA_TRACE3_2( 2082 "M4VSS3GPP_intCreate3GPPOutputFile called with pC_ewc=0x%x, pOutputFile=0x%x", 2083 pC_ewc, pOutputFile); 2084 2085 /** 2086 * Check input parameter */ 2087 M4OSA_DEBUG_IF2((M4OSA_NULL == pC_ewc), M4ERR_PARAMETER, 2088 "M4VSS3GPP_intCreate3GPPOutputFile: pC_ewc is M4OSA_NULL"); 2089 M4OSA_DEBUG_IF2((M4OSA_NULL == pOutputFile), M4ERR_PARAMETER, 2090 "M4VSS3GPP_intCreate3GPPOutputFile: pOutputFile is M4OSA_NULL"); 2091 2092 /* Set writer */ 2093 err = 2094 M4VSS3GPP_setCurrentWriter(pC_ShellAPI, M4VIDEOEDITING_kFileType_3GPP); 2095 M4ERR_CHECK_RETURN(err); 2096 2097 /** 2098 * Create the output file */ 2099 err = pC_ShellAPI->pWriterGlobalFcts->pFctOpen(&pC_ewc->p3gpWriterContext, 2100 pOutputFile, pOsaFileWritPtr, pTempFile, pOsaFileReadPtr); 2101 2102 if( M4NO_ERROR != err ) 2103 { 2104 M4OSA_TRACE1_1( 2105 "M4VSS3GPP_intCreate3GPPOutputFile: pWriterGlobalFcts->pFctOpen returns 0x%x!", 2106 err); 2107 return err; 2108 } 2109 2110 /** 2111 * Set the signature option of the writer */ 2112 err = 2113 pC_ShellAPI->pWriterGlobalFcts->pFctSetOption(pC_ewc->p3gpWriterContext, 2114 M4WRITER_kEmbeddedString, (M4OSA_DataOption)"NXP-SW : VSS "); 2115 2116 if( ( M4NO_ERROR != err) && (((M4OSA_UInt32)M4ERR_BAD_OPTION_ID) 2117 != err) ) /* this option may not be implemented by some writers */ 2118 { 2119 M4OSA_TRACE1_1( 2120 "M4VSS3GPP_intCreate3GPPOutputFile:\ 2121 pWriterGlobalFcts->pFctSetOption(M4WRITER_kEmbeddedString) returns 0x%x!", 2122 err); 2123 return err; 2124 } 2125 2126 /*11/12/2008 CR3283 MMS use case for VideoArtist: 2127 Set the max output file size option in the writer so that the output file will be 2128 smaller than the given file size limitation*/ 2129 if( maxOutputFileSize > 0 ) 2130 { 2131 err = pC_ShellAPI->pWriterGlobalFcts->pFctSetOption( 2132 pC_ewc->p3gpWriterContext, 2133 M4WRITER_kMaxFileSize, &maxOutputFileSize); 2134 2135 if( M4NO_ERROR != err ) 2136 { 2137 M4OSA_TRACE1_1( 2138 "M4VSS3GPP_intCreate3GPPOutputFile:\ 2139 writer set option M4WRITER_kMaxFileSize returns 0x%x", 2140 err); 2141 return err; 2142 } 2143 } 2144 2145 /** 2146 * Set the version option of the writer */ 2147 uiVersion = 2148 (M4VIDEOEDITING_VERSION_MAJOR * 100 + M4VIDEOEDITING_VERSION_MINOR * 10 2149 + M4VIDEOEDITING_VERSION_REVISION); 2150 err = 2151 pC_ShellAPI->pWriterGlobalFcts->pFctSetOption(pC_ewc->p3gpWriterContext, 2152 M4WRITER_kEmbeddedVersion, (M4OSA_DataOption) &uiVersion); 2153 2154 if( ( M4NO_ERROR != err) && (((M4OSA_UInt32)M4ERR_BAD_OPTION_ID) 2155 != err) ) /* this option may not be implemented by some writers */ 2156 { 2157 M4OSA_TRACE1_1( 2158 "M4VSS3GPP_intCreate3GPPOutputFile:\ 2159 pWriterGlobalFcts->pFctSetOption(M4WRITER_kEmbeddedVersion) returns 0x%x!", 2160 err); 2161 return err; 2162 } 2163 2164 /** 2165 * In case of EMP, we have to explicitely give an emp ftyp to the writer */ 2166 if( M4OSA_TRUE == pC_ewc->bActivateEmp ) 2167 { 2168 M4VIDEOEDITING_FtypBox ftyp; 2169 2170 ftyp.major_brand = M4VIDEOEDITING_BRAND_3GP4; 2171 ftyp.minor_version = M4VIDEOEDITING_BRAND_0000; 2172 ftyp.nbCompatibleBrands = 2; 2173 ftyp.compatible_brands[0] = M4VIDEOEDITING_BRAND_3GP4; 2174 ftyp.compatible_brands[1] = M4VIDEOEDITING_BRAND_EMP; 2175 2176 err = pC_ShellAPI->pWriterGlobalFcts->pFctSetOption( 2177 pC_ewc->p3gpWriterContext, 2178 M4WRITER_kSetFtypBox, (M4OSA_DataOption) &ftyp); 2179 2180 if( M4NO_ERROR != err ) 2181 { 2182 M4OSA_TRACE1_1( 2183 "M4VSS3GPP_intCreate3GPPOutputFile:\ 2184 pWriterGlobalFcts->pFctSetOption(M4WRITER_kSetFtypBox) returns 0x%x!", 2185 err); 2186 return err; 2187 } 2188 } 2189 2190 if( M4SYS_kVideoUnknown != pC_ewc->VideoStreamType ) 2191 { 2192 /** 2193 * Set the video stream properties */ 2194 pC_ewc->WriterVideoStreamInfo.height = pC_ewc->uiVideoHeight; 2195 pC_ewc->WriterVideoStreamInfo.width = pC_ewc->uiVideoWidth; 2196 pC_ewc->WriterVideoStreamInfo.fps = 2197 0.0; /**< Not used by the shell/core writer */ 2198 pC_ewc->WriterVideoStreamInfo.Header.pBuf = 2199 pC_ewc->pVideoOutputDsi; /**< Previously computed output DSI */ 2200 pC_ewc->WriterVideoStreamInfo.Header.Size = pC_ewc-> 2201 uiVideoOutputDsiSize; /**< Previously computed output DSI size */ 2202 2203 pC_ewc->WriterVideoStream.streamType = pC_ewc->VideoStreamType; 2204 2205 switch( pC_ewc->VideoStreamType ) 2206 { 2207 case M4SYS_kMPEG_4: 2208 case M4SYS_kH263: 2209 case M4SYS_kH264: 2210 /**< We HAVE to put a value here... */ 2211 pC_ewc->WriterVideoStream.averageBitrate = 2212 pC_ewc->uiVideoBitrate; 2213 pC_ewc->WriterVideoStream.maxBitrate = pC_ewc->uiVideoBitrate; 2214 break; 2215 2216 default: 2217 M4OSA_TRACE1_1( 2218 "M4VSS3GPP_intCreate3GPPOutputFile: unknown input video format (0x%x),\ 2219 returning M4VSS3GPP_ERR_UNSUPPORTED_INPUT_VIDEO_FORMAT!", 2220 pC_ewc->VideoStreamType); 2221 return M4VSS3GPP_ERR_UNSUPPORTED_INPUT_VIDEO_FORMAT; 2222 } 2223 2224 pC_ewc->WriterVideoStream.streamID = M4VSS3GPP_WRITER_VIDEO_STREAM_ID; 2225 pC_ewc->WriterVideoStream.timeScale = 2226 0; /**< Not used by the shell/core writer */ 2227 pC_ewc->WriterVideoStream.profileLevel = 2228 0; /**< Not used by the shell/core writer */ 2229 pC_ewc->WriterVideoStream.duration = 2230 0; /**< Not used by the shell/core writer */ 2231 2232 pC_ewc->WriterVideoStream.decoderSpecificInfoSize = 2233 sizeof(M4WRITER_StreamVideoInfos); 2234 pC_ewc->WriterVideoStream.decoderSpecificInfo = 2235 (M4OSA_MemAddr32) &(pC_ewc->WriterVideoStreamInfo); 2236 2237 /** 2238 * Add the video stream */ 2239 err = pC_ShellAPI->pWriterGlobalFcts->pFctAddStream( 2240 pC_ewc->p3gpWriterContext, &pC_ewc->WriterVideoStream); 2241 2242 if( M4NO_ERROR != err ) 2243 { 2244 M4OSA_TRACE1_1( 2245 "M4VSS3GPP_intCreate3GPPOutputFile:\ 2246 pWriterGlobalFcts->pFctAddStream(video) returns 0x%x!", 2247 err); 2248 return err; 2249 } 2250 2251 /** 2252 * Update AU properties for video stream */ 2253 pC_ewc->WriterVideoAU.attribute = AU_RAP; 2254 pC_ewc->WriterVideoAU.CTS = 0; 2255 pC_ewc->WriterVideoAU.DTS = 0; /** Reset time */ 2256 pC_ewc->WriterVideoAU.frag = M4OSA_NULL; 2257 pC_ewc->WriterVideoAU.nbFrag = 0; /** No fragment */ 2258 pC_ewc->WriterVideoAU.size = 0; 2259 pC_ewc->WriterVideoAU.dataAddress = M4OSA_NULL; 2260 pC_ewc->WriterVideoAU.stream = &(pC_ewc->WriterVideoStream); 2261 2262 /** 2263 * Set the writer max video AU size */ 2264 pC_ewc->uiVideoMaxAuSize = (M4OSA_UInt32)(1.5F 2265 *(M4OSA_Float)(pC_ewc->WriterVideoStreamInfo.width 2266 * pC_ewc->WriterVideoStreamInfo.height) 2267 * M4VSS3GPP_VIDEO_MIN_COMPRESSION_RATIO); 2268 temp.streamID = M4VSS3GPP_WRITER_VIDEO_STREAM_ID; 2269 temp.value = pC_ewc->uiVideoMaxAuSize; 2270 err = pC_ShellAPI->pWriterGlobalFcts->pFctSetOption( 2271 pC_ewc->p3gpWriterContext, (M4OSA_UInt32)M4WRITER_kMaxAUSize, 2272 (M4OSA_DataOption) &temp); 2273 2274 if( M4NO_ERROR != err ) 2275 { 2276 M4OSA_TRACE1_1( 2277 "M4VSS3GPP_intCreate3GPPOutputFile:\ 2278 pWriterGlobalFcts->pFctSetOption(M4WRITER_kMaxAUSize, video) returns 0x%x!", 2279 err); 2280 return err; 2281 } 2282 2283 /** 2284 * Set the writer max video chunk size */ 2285 temp.streamID = M4VSS3GPP_WRITER_VIDEO_STREAM_ID; 2286 temp.value = (M4OSA_UInt32)(pC_ewc->uiVideoMaxAuSize \ 2287 * M4VSS3GPP_VIDEO_AU_SIZE_TO_CHUNCK_SIZE_RATIO); /**< from max AU size to 2288 max Chunck size */ 2289 err = pC_ShellAPI->pWriterGlobalFcts->pFctSetOption( 2290 pC_ewc->p3gpWriterContext, 2291 (M4OSA_UInt32)M4WRITER_kMaxChunckSize, 2292 (M4OSA_DataOption) &temp); 2293 2294 if( M4NO_ERROR != err ) 2295 { 2296 M4OSA_TRACE1_1( 2297 "M4VSS3GPP_intCreate3GPPOutputFile:\ 2298 pWriterGlobalFcts->pFctSetOption(M4WRITER_kMaxAUSize, video) returns 0x%x!", 2299 err); 2300 return err; 2301 } 2302 } 2303 2304 if( M4SYS_kAudioUnknown != pC_ewc->AudioStreamType ) 2305 { 2306 M4WRITER_StreamAudioInfos streamAudioInfo; 2307 2308 streamAudioInfo.nbSamplesPerSec = 0; /**< unused by our shell writer */ 2309 streamAudioInfo.nbBitsPerSample = 0; /**< unused by our shell writer */ 2310 streamAudioInfo.nbChannels = 1; /**< unused by our shell writer */ 2311 2312 if( pC_ewc->pAudioOutputDsi != M4OSA_NULL ) 2313 { 2314 /* If we copy the stream from the input, we copy its DSI */ 2315 streamAudioInfo.Header.Size = pC_ewc->uiAudioOutputDsiSize; 2316 streamAudioInfo.Header.pBuf = pC_ewc->pAudioOutputDsi; 2317 } 2318 else 2319 { 2320 /* Writer will put a default DSI */ 2321 streamAudioInfo.Header.Size = 0; 2322 streamAudioInfo.Header.pBuf = M4OSA_NULL; 2323 } 2324 2325 pC_ewc->WriterAudioStream.streamID = M4VSS3GPP_WRITER_AUDIO_STREAM_ID; 2326 pC_ewc->WriterAudioStream.streamType = pC_ewc->AudioStreamType; 2327 pC_ewc->WriterAudioStream.duration = 2328 0; /**< Not used by the shell/core writer */ 2329 pC_ewc->WriterAudioStream.profileLevel = 2330 0; /**< Not used by the shell/core writer */ 2331 pC_ewc->WriterAudioStreamInfo.nbSamplesPerSec = 2332 pC_ewc->uiSamplingFrequency; 2333 pC_ewc->WriterAudioStream.timeScale = pC_ewc->uiSamplingFrequency; 2334 pC_ewc->WriterAudioStreamInfo.nbChannels = 2335 (M4OSA_UInt16)pC_ewc->uiNbChannels; 2336 pC_ewc->WriterAudioStreamInfo.nbBitsPerSample = 2337 0; /**< Not used by the shell/core writer */ 2338 2339 /** 2340 * Add the audio stream */ 2341 switch( pC_ewc->AudioStreamType ) 2342 { 2343 case M4SYS_kAMR: 2344 pC_ewc->WriterAudioStream.averageBitrate = 2345 0; /**< It is not used by the shell, the DSI is taken into account instead */ 2346 pC_ewc->WriterAudioStream.maxBitrate = 2347 0; /**< Not used by the shell/core writer */ 2348 break; 2349 2350 case M4SYS_kAAC: 2351 pC_ewc->WriterAudioStream.averageBitrate = 2352 pC_ewc->uiAudioBitrate; 2353 pC_ewc->WriterAudioStream.maxBitrate = pC_ewc->uiAudioBitrate; 2354 break; 2355 2356 case M4SYS_kEVRC: 2357 pC_ewc->WriterAudioStream.averageBitrate = 2358 0; /**< It is not used by the shell, the DSI is taken into account instead */ 2359 pC_ewc->WriterAudioStream.maxBitrate = 2360 0; /**< Not used by the shell/core writer */ 2361 break; 2362 2363 case M4SYS_kMP3: /**< there can't be MP3 track in 3GPP file -> error */ 2364 default: 2365 M4OSA_TRACE1_1( 2366 "M4VSS3GPP_intCreate3GPPOutputFile: unknown output audio format (0x%x),\ 2367 returning M4VSS3GPP_ERR_UNSUPPORTED_INPUT_AUDIO_FORMAT!", 2368 pC_ewc->AudioStreamType); 2369 return M4VSS3GPP_ERR_UNSUPPORTED_INPUT_AUDIO_FORMAT; 2370 } 2371 2372 /** 2373 * Our writer shell interface is a little tricky: we put M4WRITER_StreamAudioInfos 2374 in the DSI pointer... */ 2375 pC_ewc->WriterAudioStream.decoderSpecificInfo = 2376 (M4OSA_MemAddr32) &streamAudioInfo; 2377 2378 /** 2379 * Link the AU and the stream */ 2380 pC_ewc->WriterAudioAU.stream = &(pC_ewc->WriterAudioStream); 2381 pC_ewc->WriterAudioAU.dataAddress = M4OSA_NULL; 2382 pC_ewc->WriterAudioAU.size = 0; 2383 pC_ewc->WriterAudioAU.CTS = 2384 -pC_ewc->iSilenceFrameDuration; /** Reset time */ 2385 pC_ewc->WriterAudioAU.DTS = 0; 2386 pC_ewc->WriterAudioAU.attribute = 0; 2387 pC_ewc->WriterAudioAU.nbFrag = 0; /** No fragment */ 2388 pC_ewc->WriterAudioAU.frag = M4OSA_NULL; 2389 2390 err = pC_ShellAPI->pWriterGlobalFcts->pFctAddStream( 2391 pC_ewc->p3gpWriterContext, &pC_ewc->WriterAudioStream); 2392 2393 if( M4NO_ERROR != err ) 2394 { 2395 M4OSA_TRACE1_1( 2396 "M4VSS3GPP_intCreate3GPPOutputFile:\ 2397 pWriterGlobalFcts->pFctAddStream(audio) returns 0x%x!", 2398 err); 2399 return err; 2400 } 2401 2402 /** 2403 * Set the writer max audio AU size */ 2404 pC_ewc->uiAudioMaxAuSize = M4VSS3GPP_AUDIO_MAX_AU_SIZE; 2405 temp.streamID = M4VSS3GPP_WRITER_AUDIO_STREAM_ID; 2406 temp.value = pC_ewc->uiAudioMaxAuSize; 2407 err = pC_ShellAPI->pWriterGlobalFcts->pFctSetOption( 2408 pC_ewc->p3gpWriterContext, (M4OSA_UInt32)M4WRITER_kMaxAUSize, 2409 (M4OSA_DataOption) &temp); 2410 2411 if( M4NO_ERROR != err ) 2412 { 2413 M4OSA_TRACE1_1( 2414 "M4VSS3GPP_intCreate3GPPOutputFile:\ 2415 pWriterGlobalFcts->pFctSetOption(M4WRITER_kMaxAUSize, audio) returns 0x%x!", 2416 err); 2417 return err; 2418 } 2419 2420 /** 2421 * Set the writer max audio chunck size */ 2422 temp.streamID = M4VSS3GPP_WRITER_AUDIO_STREAM_ID; 2423 temp.value = M4VSS3GPP_AUDIO_MAX_CHUNCK_SIZE; 2424 err = pC_ShellAPI->pWriterGlobalFcts->pFctSetOption( 2425 pC_ewc->p3gpWriterContext, 2426 (M4OSA_UInt32)M4WRITER_kMaxChunckSize, 2427 (M4OSA_DataOption) &temp); 2428 2429 if( M4NO_ERROR != err ) 2430 { 2431 M4OSA_TRACE1_1( 2432 "M4VSS3GPP_intCreate3GPPOutputFile:\ 2433 pWriterGlobalFcts->pFctSetOption(M4WRITER_kMaxAUSize, audio) returns 0x%x!", 2434 err); 2435 return err; 2436 } 2437 } 2438 2439 /** 2440 * All streams added, we're now ready to write */ 2441 err = pC_ShellAPI->pWriterGlobalFcts->pFctStartWriting( 2442 pC_ewc->p3gpWriterContext); 2443 2444 if( M4NO_ERROR != err ) 2445 { 2446 M4OSA_TRACE1_1( 2447 "M4VSS3GPP_intCreate3GPPOutputFile:\ 2448 pWriterGlobalFcts->pFctStartWriting() returns 0x%x!", 2449 err); 2450 return err; 2451 } 2452 2453 /** 2454 * Return with no error */ 2455 M4OSA_TRACE3_0("M4VSS3GPP_intCreate3GPPOutputFile(): returning M4NO_ERROR"); 2456 return M4NO_ERROR; 2457} 2458 2459/** 2460 ****************************************************************************** 2461 * M4OSA_ERR M4VSS3GPP_intComputeOutputVideoAndAudioDsi() 2462 * @brief Generate a H263 or MPEG-4 decoder specific info compatible with all input video 2463 * tracks. Copy audio dsi from master clip. 2464 * @param pC (IN/OUT) Internal edit context 2465 ****************************************************************************** 2466 */ 2467static M4OSA_ERR 2468M4VSS3GPP_intComputeOutputVideoAndAudioDsi( M4VSS3GPP_InternalEditContext *pC, 2469 M4OSA_UInt8 uiMasterClip ) 2470{ 2471 M4OSA_UInt8 uiCurrentLevel, uiNewLevel; 2472 M4OSA_UInt8 uiCurrentProf, uiNewProf; 2473 M4OSA_Int32 iResynchMarkerDsiIndex; 2474 M4_StreamHandler *pStreamForDsi; 2475 M4VSS3GPP_ClipContext *pClip; 2476 M4OSA_ERR err; 2477 M4OSA_UInt32 i; 2478 2479 M4ENCODER_Header *encHeader; 2480 M4SYS_StreamIDmemAddr streamHeader; 2481 2482 pStreamForDsi = M4OSA_NULL; 2483 pClip = M4OSA_NULL; 2484 2485 /** 2486 * H263 case */ 2487 if( M4SYS_kH263 == pC->ewc.VideoStreamType ) 2488 { 2489 /** 2490 * H263 output DSI is always 7 bytes */ 2491 pC->ewc.uiVideoOutputDsiSize = 7; 2492 pC->ewc.pVideoOutputDsi = 2493 (M4OSA_MemAddr8)M4OSA_32bitAlignedMalloc(pC->ewc.uiVideoOutputDsiSize, 2494 M4VSS3GPP, (M4OSA_Char *)"pC->ewc.pVideoOutputDsi (H263)"); 2495 2496 if( M4OSA_NULL == pC->ewc.pVideoOutputDsi ) 2497 { 2498 M4OSA_TRACE1_0( 2499 "M4VSS3GPP_intComputeOutputVideoAndAudioDsi():\ 2500 unable to allocate pVideoOutputDsi (H263), returning M4ERR_ALLOC"); 2501 return M4ERR_ALLOC; 2502 } 2503 2504 /** 2505 * (We override the input vendor info. 2506 * At least we know that nothing special will be tried with PHLP-stamped 2507 edited streams...) */ 2508 pC->ewc.pVideoOutputDsi[0] = 'P'; 2509 pC->ewc.pVideoOutputDsi[1] = 'H'; 2510 pC->ewc.pVideoOutputDsi[2] = 'L'; 2511 pC->ewc.pVideoOutputDsi[3] = 'P'; 2512 2513 /** 2514 * Decoder version is 0 */ 2515 pC->ewc.pVideoOutputDsi[4] = 0; 2516 2517 /** 2518 * We take the max level of all input streams, but 10 is the minimum */ 2519 uiCurrentLevel = 10; 2520 2521 for ( i = 0; i < pC->uiClipNumber; i++ ) 2522 { 2523 uiNewLevel = pC->pClipList[i].ClipProperties.uiH263level; 2524 2525 if( uiNewLevel > uiCurrentLevel ) 2526 { 2527 uiCurrentLevel = uiNewLevel; 2528 } 2529 } 2530 2531 /** 2532 * Level is the sixth byte i the DSI */ 2533 pC->ewc.pVideoOutputDsi[5] = uiCurrentLevel; 2534 2535 /** 2536 * Profile is always 0, and it's the seventh byte in the DSI */ 2537 pC->ewc.pVideoOutputDsi[6] = 0; 2538 } 2539 2540 /** 2541 * MPEG-4 case */ 2542 else if( M4SYS_kMPEG_4 == pC->ewc.VideoStreamType ) 2543 { 2544 /** 2545 * Profile combination rules: 2546 * 8 and x -> x 2547 * 1, 2 or 3 -> max 2548 * 9 and 1 -> 2 2549 * 9 and 2 -> 2 2550 * 9 and 3 -> 3 2551 */ 2552 2553 /** 2554 * Note: 2555 * The part of the output video encoded by the VSS3GPP 2556 * have a profile of 8. 2557 * Since 8 is the less "strong" profile (8 and x --> x), 2558 * we can check only the input clips to compute the 2559 * profile of the output combined clip. 2560 */ 2561 2562 /** 2563 * Start with profile of the first clip */ 2564 uiCurrentProf = pC->pClipList[0].ClipProperties.uiVideoProfile; 2565 2566 /** 2567 * Combine current profile with the one of the next clip */ 2568 for ( i = 1; i < pC->uiClipNumber; i++ ) 2569 { 2570 uiNewProf = pC->pClipList[i].ClipProperties.uiVideoProfile; 2571 2572 switch( uiNewProf ) 2573 { 2574 case 8: 2575 /**< 8 + x --> x */ 2576 /**< uiCurrentProf is not updated */ 2577 break; 2578 2579 case 1: 2580 case 2: 2581 case 3: 2582 switch( uiCurrentProf ) 2583 { 2584 case 1: 2585 case 2: 2586 case 3: 2587 case 4: 2588 case 5: 2589 /**< 1, 2, 3, 4 or 5 -> max */ 2590 uiCurrentProf = (uiCurrentProf > uiNewProf) 2591 ? uiCurrentProf : uiNewProf; 2592 break; 2593 2594 case 8: /**< 8 + x -> x */ 2595 uiCurrentProf = uiNewProf; 2596 break; 2597 2598 case 9: 2599 /**< 9 and 1 -> 2 */ 2600 /**< 9 and 2 -> 2 */ 2601 /**< 9 and 3 -> 3 */ 2602 /**< 9 and 4 -> 4 */ 2603 /**< 9 and 5 -> 5 */ 2604 uiCurrentProf = (uiNewProf > 2) ? uiNewProf : 2; 2605 break; 2606 } 2607 break; 2608 2609 case 9: 2610 switch( uiCurrentProf ) 2611 { 2612 case 1: 2613 case 2: 2614 case 3: 2615 /**< 9 and 1 -> 2 */ 2616 /**< 9 and 2 -> 2 */ 2617 /**< 9 and 3 -> 3 */ 2618 uiCurrentProf = 2619 (uiCurrentProf > 2) ? uiCurrentProf : 2; 2620 break; 2621 2622 case 9: /**< 9 + x -> x */ 2623 case 8: /**< 8 + x -> x */ 2624 uiCurrentProf = uiNewProf; 2625 break; 2626 } 2627 } 2628 } 2629 2630 /** 2631 * Look for the DSI of an input video stream which would use the Resynch. Marker tool */ 2632 i = 0; 2633 iResynchMarkerDsiIndex = 2634 0; /**< By default we take the first DSI (if we find no Resynch Marker DSI) */ 2635 2636 while( i < pC->uiClipNumber ) 2637 { 2638 if( M4OSA_TRUE 2639 == pC->pClipList[i].ClipProperties.bMPEG4resynchMarker ) 2640 { 2641 iResynchMarkerDsiIndex = i; 2642 break; /**< we found it, get out the while loop */ 2643 } 2644 i++; 2645 } 2646 2647 /** 2648 * Get the DSI of the clip found. If it is the first clip, it is already opened. 2649 * Else we must open it (and later close it...) */ 2650 if( 0 == iResynchMarkerDsiIndex ) 2651 { 2652 pStreamForDsi = &(pC->pC1->pVideoStream->m_basicProperties); 2653 } 2654 else 2655 { 2656 /** 2657 * We can use the fast open mode and the skip audio mode to get the DSI */ 2658 err = M4VSS3GPP_intClipInit(&pClip, pC->pOsaFileReadPtr); 2659 2660 if( M4NO_ERROR != err ) 2661 { 2662 M4OSA_TRACE1_1( 2663 "M4VSS3GPP_intComputeOutputVideoAndAudioDsi:\ 2664 M4VSS3GPP_intClipInit() returns 0x%x!", 2665 err); 2666 2667 if( M4OSA_NULL != pClip ) 2668 { 2669 M4VSS3GPP_intClipCleanUp(pClip); 2670 } 2671 return err; 2672 } 2673 2674 err = M4VSS3GPP_intClipOpen(pClip, 2675 &pC->pClipList[iResynchMarkerDsiIndex], M4OSA_TRUE, 2676 M4OSA_TRUE, M4OSA_TRUE); 2677 2678 if( M4NO_ERROR != err ) 2679 { 2680 M4OSA_TRACE1_1( 2681 "M4VSS3GPP_intComputeOutputVideoAndAudioDsi:\ 2682 M4VSS3GPP_intClipOpen() returns 0x%x!", 2683 err); 2684 M4VSS3GPP_intClipCleanUp(pClip); 2685 return err; 2686 } 2687 2688 pStreamForDsi = &(pClip->pVideoStream->m_basicProperties); 2689 } 2690 2691 /** 2692 * Allocate and copy the new DSI */ 2693 pC->ewc.pVideoOutputDsi = (M4OSA_MemAddr8)M4OSA_32bitAlignedMalloc( 2694 pStreamForDsi->m_decoderSpecificInfoSize, 2695 M4VSS3GPP, (M4OSA_Char *)"pC->ewc.pVideoOutputDsi (MPEG4)"); 2696 2697 if( M4OSA_NULL == pC->ewc.pVideoOutputDsi ) 2698 { 2699 M4OSA_TRACE1_0( 2700 "M4VSS3GPP_intComputeOutputVideoAndAudioDsi():\ 2701 unable to allocate pVideoOutputDsi (MPEG4), returning M4ERR_ALLOC"); 2702 return M4ERR_ALLOC; 2703 } 2704 pC->ewc.uiVideoOutputDsiSize = 2705 (M4OSA_UInt16)pStreamForDsi->m_decoderSpecificInfoSize; 2706 memcpy((void *)pC->ewc.pVideoOutputDsi, 2707 (void *)pStreamForDsi->m_pDecoderSpecificInfo, 2708 pC->ewc.uiVideoOutputDsiSize); 2709 2710 /** 2711 * We rewrite the profile in the output DSI because it may not be the good one 2712 * The profile and level is always at byte number 4 */ 2713 (pC->ewc.pVideoOutputDsi)[4] = uiCurrentProf; 2714 2715 /** 2716 * If a clip has been temporarily opened to get its DSI, close it */ 2717 if( M4OSA_NULL != pClip ) 2718 { 2719 err = M4VSS3GPP_intClipCleanUp(pClip); 2720 2721 if( M4NO_ERROR != err ) 2722 { 2723 M4OSA_TRACE1_1( 2724 "M4VSS3GPP_intComputeOutputVideoAndAudioDsi:\ 2725 M4VSS3GPP_intClipCleanUp() returns 0x%x!", 2726 err); 2727 return err; 2728 } 2729 } 2730 } 2731 else if( M4SYS_kH264 == pC->ewc.VideoStreamType ) 2732 { 2733 2734 /* For H.264 encoder case 2735 * Fetch the DSI from the shell video encoder, and feed it to the writer before 2736 closing it. */ 2737 2738 M4OSA_TRACE1_0( 2739 "M4VSS3GPP_intComputeOutputVideoAndAudioDsi: get DSI for H264 stream"); 2740 2741 if( M4OSA_NULL == pC->ewc.pEncContext ) 2742 { 2743 M4OSA_TRACE1_0( 2744 "M4VSS3GPP_intComputeOutputVideoAndAudioDsi: pC->ewc.pEncContext is NULL"); 2745 err = M4VSS3GPP_intCreateVideoEncoder(pC); 2746 2747 if( M4NO_ERROR != err ) 2748 { 2749 M4OSA_TRACE1_1( 2750 "M4VSS3GPP_intComputeOutputVideoAndAudioDsi:\ 2751 M4VSS3GPP_intCreateVideoEncoder returned error 0x%x", 2752 err); 2753 } 2754 } 2755 2756 if( M4OSA_NULL != pC->ewc.pEncContext ) 2757 { 2758 err = pC->ShellAPI.pVideoEncoderGlobalFcts->pFctGetOption( 2759 pC->ewc.pEncContext, M4ENCODER_kOptionID_EncoderHeader, 2760 (M4OSA_DataOption) &encHeader); 2761 2762 if( ( M4NO_ERROR != err) || (M4OSA_NULL == encHeader->pBuf) ) 2763 { 2764 M4OSA_TRACE1_1( 2765 "M4VSS3GPP_intComputeOutputVideoAndAudioDsi:\ 2766 failed to get the encoder header (err 0x%x)", 2767 err); 2768 M4OSA_TRACE1_2( 2769 "M4VSS3GPP_intComputeOutputVideoAndAudioDsi: encHeader->pBuf=0x%x, size=0x%x", 2770 encHeader->pBuf, encHeader->Size); 2771 } 2772 else 2773 { 2774 M4OSA_TRACE1_0( 2775 "M4VSS3GPP_intComputeOutputVideoAndAudioDsi:\ 2776 send DSI for H264 stream to 3GP writer"); 2777 2778 /** 2779 * Allocate and copy the new DSI */ 2780 pC->ewc.pVideoOutputDsi = 2781 (M4OSA_MemAddr8)M4OSA_32bitAlignedMalloc(encHeader->Size, M4VSS3GPP, 2782 (M4OSA_Char *)"pC->ewc.pVideoOutputDsi (H264)"); 2783 2784 if( M4OSA_NULL == pC->ewc.pVideoOutputDsi ) 2785 { 2786 M4OSA_TRACE1_0( 2787 "M4VSS3GPP_intComputeOutputVideoAndAudioDsi():\ 2788 unable to allocate pVideoOutputDsi (H264), returning M4ERR_ALLOC"); 2789 return M4ERR_ALLOC; 2790 } 2791 pC->ewc.uiVideoOutputDsiSize = (M4OSA_UInt16)encHeader->Size; 2792 memcpy((void *)pC->ewc.pVideoOutputDsi, (void *)encHeader->pBuf, 2793 encHeader->Size); 2794 } 2795 2796 err = M4VSS3GPP_intDestroyVideoEncoder(pC); 2797 2798 if( M4NO_ERROR != err ) 2799 { 2800 M4OSA_TRACE1_1( 2801 "M4VSS3GPP_intComputeOutputVideoAndAudioDsi:\ 2802 M4VSS3GPP_intDestroyVideoEncoder returned error 0x%x", 2803 err); 2804 } 2805 } 2806 else 2807 { 2808 M4OSA_TRACE1_0( 2809 "M4VSS3GPP_intComputeOutputVideoAndAudioDsi:\ 2810 pC->ewc.pEncContext is NULL, cannot get the DSI"); 2811 } 2812 } 2813 2814 pStreamForDsi = M4OSA_NULL; 2815 pClip = M4OSA_NULL; 2816 2817 /* Compute Audio DSI */ 2818 if( M4SYS_kAudioUnknown != pC->ewc.AudioStreamType ) 2819 { 2820 if( uiMasterClip == 0 ) 2821 { 2822 /* Clip is already opened */ 2823 pStreamForDsi = &(pC->pC1->pAudioStream->m_basicProperties); 2824 } 2825 else 2826 { 2827 /** 2828 * We can use the fast open mode to get the DSI */ 2829 err = M4VSS3GPP_intClipInit(&pClip, pC->pOsaFileReadPtr); 2830 2831 if( M4NO_ERROR != err ) 2832 { 2833 M4OSA_TRACE1_1( 2834 "M4VSS3GPP_intComputeOutputVideoAndAudioDsi:\ 2835 M4VSS3GPP_intClipInit() returns 0x%x!", 2836 err); 2837 2838 if( pClip != M4OSA_NULL ) 2839 { 2840 M4VSS3GPP_intClipCleanUp(pClip); 2841 } 2842 return err; 2843 } 2844 2845 err = M4VSS3GPP_intClipOpen(pClip, &pC->pClipList[uiMasterClip], 2846 M4OSA_FALSE, M4OSA_TRUE, M4OSA_TRUE); 2847 2848 if( M4NO_ERROR != err ) 2849 { 2850 M4OSA_TRACE1_1( 2851 "M4VSS3GPP_intComputeOutputVideoAndAudioDsi:\ 2852 M4VSS3GPP_intClipOpen() returns 0x%x!", 2853 err); 2854 M4VSS3GPP_intClipCleanUp(pClip); 2855 return err; 2856 } 2857 2858 pStreamForDsi = &(pClip->pAudioStream->m_basicProperties); 2859 } 2860 2861 /** 2862 * Allocate and copy the new DSI */ 2863 pC->ewc.pAudioOutputDsi = (M4OSA_MemAddr8)M4OSA_32bitAlignedMalloc( 2864 pStreamForDsi->m_decoderSpecificInfoSize, 2865 M4VSS3GPP, (M4OSA_Char *)"pC->ewc.pAudioOutputDsi"); 2866 2867 if( M4OSA_NULL == pC->ewc.pAudioOutputDsi ) 2868 { 2869 M4OSA_TRACE1_0( 2870 "M4VSS3GPP_intComputeOutputVideoAndAudioDsi():\ 2871 unable to allocate pAudioOutputDsi, returning M4ERR_ALLOC"); 2872 return M4ERR_ALLOC; 2873 } 2874 pC->ewc.uiAudioOutputDsiSize = 2875 (M4OSA_UInt16)pStreamForDsi->m_decoderSpecificInfoSize; 2876 memcpy((void *)pC->ewc.pAudioOutputDsi, 2877 (void *)pStreamForDsi->m_pDecoderSpecificInfo, 2878 pC->ewc.uiAudioOutputDsiSize); 2879 2880 /** 2881 * If a clip has been temporarily opened to get its DSI, close it */ 2882 if( M4OSA_NULL != pClip ) 2883 { 2884 err = M4VSS3GPP_intClipCleanUp(pClip); 2885 2886 if( M4NO_ERROR != err ) 2887 { 2888 M4OSA_TRACE1_1( 2889 "M4VSS3GPP_intComputeOutputVideoAndAudioDsi:\ 2890 M4VSS3GPP_intClipCleanUp() returns 0x%x!", 2891 err); 2892 return err; 2893 } 2894 } 2895 } 2896 2897 /** 2898 * Return with no error */ 2899 M4OSA_TRACE3_0( 2900 "M4VSS3GPP_intComputeOutputVideoAndAudioDsi(): returning M4NO_ERROR"); 2901 return M4NO_ERROR; 2902} 2903 2904/** 2905 ****************************************************************************** 2906 * M4OSA_ERR M4VSS3GPP_intSwitchToNextClip() 2907 * @brief Switch from the current clip to the next one 2908 * @param pC (IN/OUT) Internal edit context 2909 ****************************************************************************** 2910 */ 2911static M4OSA_ERR M4VSS3GPP_intSwitchToNextClip( 2912 M4VSS3GPP_InternalEditContext *pC ) 2913{ 2914 M4OSA_ERR err; 2915 2916 if( M4OSA_NULL != pC->pC1 ) 2917 { 2918 /** 2919 * Close the current first clip */ 2920 err = M4VSS3GPP_intClipCleanUp(pC->pC1); 2921 2922 if( M4NO_ERROR != err ) 2923 { 2924 M4OSA_TRACE1_1( 2925 "M4VSS3GPP_intSwitchToNextClip: M4VSS3GPP_intClipCleanUp(C1) returns 0x%x!", 2926 err); 2927 return err; 2928 } 2929 2930 /** 2931 * increment clip counter */ 2932 pC->uiCurrentClip++; 2933 } 2934 2935 /** 2936 * Check if we reached the last clip */ 2937 if( pC->uiCurrentClip >= pC->uiClipNumber ) 2938 { 2939 pC->pC1 = M4OSA_NULL; 2940 pC->State = M4VSS3GPP_kEditState_FINISHED; 2941 2942 M4OSA_TRACE1_0( 2943 "M4VSS3GPP_intSwitchToNextClip:\ 2944 M4VSS3GPP_intClipClose(C1) returns M4VSS3GPP_WAR_EDITING_DONE"); 2945 return M4VSS3GPP_WAR_EDITING_DONE; 2946 } 2947 2948 /** 2949 * If the next clip has already be opened, set it as first clip */ 2950 if( M4OSA_NULL != pC->pC2 ) 2951 { 2952 pC->pC1 = pC->pC2; 2953 pC->pC2 = M4OSA_NULL; 2954 } 2955 /** 2956 * else open it */ 2957 else 2958 { 2959 err = M4VSS3GPP_intOpenClip(pC, &pC->pC1, 2960 &pC->pClipList[pC->uiCurrentClip]); 2961 2962 if( M4NO_ERROR != err ) 2963 { 2964 M4OSA_TRACE1_1( 2965 "M4VSS3GPP_intSwitchToNextClip: M4VSS3GPP_intOpenClip() returns 0x%x!", 2966 err); 2967 return err; 2968 } 2969 2970 /** 2971 * If the second clip has not been opened yet, 2972 that means that there has been no transition. 2973 * So both output video and audio times are OK. 2974 * So we can set both video2 and audio offsets */ 2975 2976 /** 2977 * Add current video output CTS to the clip video offset */ 2978 2979 // Decorrelate input and output encoding timestamp to handle encoder prefetch 2980 pC->pC1->iVoffset += (M4OSA_UInt32)pC->ewc.dInputVidCts; 2981 /** 2982 * Add current audio output CTS to the clip audio offset */ 2983 pC->pC1->iAoffset += 2984 (M4OSA_UInt32)(pC->ewc.dATo * pC->ewc.scale_audio + 0.5); 2985 2986 /** 2987 * 2005-03-24: BugFix for audio-video synchro: 2988 * There may be a portion of the duration of an audio AU of desynchro at each assembly. 2989 * It leads to an audible desynchro when there are a lot of clips assembled. 2990 * This bug fix allows to resynch the audio track when the delta is higher 2991 * than one audio AU duration. 2992 * We Step one AU in the second clip and we change the audio offset accordingly. */ 2993 if( ( pC->pC1->iAoffset 2994 - (M4OSA_Int32)(pC->pC1->iVoffset *pC->pC1->scale_audio + 0.5)) 2995 > pC->ewc.iSilenceFrameDuration ) 2996 { 2997 /** 2998 * Advance one AMR frame */ 2999 err = M4VSS3GPP_intClipReadNextAudioFrame(pC->pC1); 3000 3001 if( M4OSA_ERR_IS_ERROR(err) ) 3002 { 3003 M4OSA_TRACE1_1( 3004 "M4VSS3GPP_intSwitchToNextClip:\ 3005 M4VSS3GPP_intClipReadNextAudioFrame returns 0x%x!", 3006 err); 3007 return err; 3008 } 3009 /** 3010 * Update audio offset accordingly*/ 3011 pC->pC1->iAoffset -= pC->ewc.iSilenceFrameDuration; 3012 } 3013 } 3014 3015 /** 3016 * Init starting state for this clip processing */ 3017 if( M4SYS_kMP3 == pC->ewc.AudioStreamType ) 3018 { 3019 /** 3020 * In the MP3 case we use a special audio state */ 3021 pC->State = M4VSS3GPP_kEditState_MP3_JUMP; 3022 } 3023 else 3024 { 3025 /** 3026 * We start with the video processing */ 3027 pC->State = M4VSS3GPP_kEditState_VIDEO; 3028 3029 if( pC->Vstate != M4VSS3GPP_kEditVideoState_TRANSITION ) 3030 { 3031 /* if not a transition then reset previous video state */ 3032 pC->Vstate = M4VSS3GPP_kEditVideoState_READ_WRITE; 3033 3034 if( pC->bIsMMS == M4OSA_FALSE ) /* RC */ 3035 { 3036 /* There may be an encoder to destroy */ 3037 err = M4VSS3GPP_intDestroyVideoEncoder(pC); 3038 3039 if( M4NO_ERROR != err ) 3040 { 3041 M4OSA_TRACE1_1( 3042 "M4VSS3GPP_intSwitchToNextClip:\ 3043 M4VSS3GPP_editDestroyVideoEncoder() returns 0x%x!", 3044 err); 3045 return err; 3046 } 3047 } 3048 } 3049 } 3050 /* The flags are set to false at the beginning of every clip */ 3051 pC->m_bClipExternalHasStarted = M4OSA_FALSE; 3052 pC->bEncodeTillEoF = M4OSA_FALSE; 3053 3054 /** 3055 * Return with no error */ 3056 M4OSA_TRACE3_0("M4VSS3GPP_intSwitchToNextClip(): returning M4NO_ERROR"); 3057 /* RC: to know when a file has been processed */ 3058 return M4VSS3GPP_WAR_SWITCH_CLIP; 3059} 3060 3061/** 3062 ****************************************************************************** 3063 * M4OSA_ERR M4VSS3GPP_intReachedEndOfVideo() 3064 * @brief Do what to do when the end of a clip video track is reached 3065 * @note If there is audio on the current clip, process it, else switch to the next clip 3066 * @param pC (IN/OUT) Internal edit context 3067 ****************************************************************************** 3068 */ 3069M4OSA_ERR M4VSS3GPP_intReachedEndOfVideo( M4VSS3GPP_InternalEditContext *pC ) 3070{ 3071 M4OSA_ERR err; 3072 3073 /** 3074 * Video is done for this clip, now we do the audio */ 3075 if( M4SYS_kAudioUnknown != pC->ewc.AudioStreamType ) 3076 { 3077 pC->State = M4VSS3GPP_kEditState_AUDIO; 3078 } 3079 else 3080 { 3081 /** 3082 * Clip done, do the next one */ 3083 err = M4VSS3GPP_intSwitchToNextClip(pC); 3084 3085 if( M4NO_ERROR != err ) 3086 { 3087 M4OSA_TRACE1_1( 3088 "M4VSS3GPP_intReachedEndOfVideo: M4VSS3GPP_intSwitchToNextClip() returns 0x%x", 3089 err); 3090 return err; 3091 } 3092 } 3093 3094 /** 3095 * Return with no error */ 3096 M4OSA_TRACE3_0("M4VSS3GPP_intReachedEndOfVideo(): returning M4NO_ERROR"); 3097 return M4NO_ERROR; 3098} 3099 3100/** 3101 ****************************************************************************** 3102 * M4OSA_ERR M4VSS3GPP_intReachedEndOfAudio() 3103 * @brief Do what to do when the end of a clip audio track is reached 3104 * @param pC (IN/OUT) Internal edit context 3105 ****************************************************************************** 3106 */ 3107M4OSA_ERR M4VSS3GPP_intReachedEndOfAudio( M4VSS3GPP_InternalEditContext *pC ) 3108{ 3109 M4OSA_ERR err; 3110 3111 /** 3112 * Clip done, do the next one */ 3113 err = M4VSS3GPP_intSwitchToNextClip(pC); 3114 3115 if( M4NO_ERROR != err ) 3116 { 3117 M4OSA_TRACE1_1( 3118 "M4VSS3GPP_intReachedEndOfAudio: M4VSS3GPP_intSwitchToNextClip() returns 0x%x", 3119 err); 3120 return err; 3121 } 3122 3123 /** 3124 * Start with the video */ 3125 if( M4SYS_kVideoUnknown != pC->ewc.VideoStreamType ) 3126 { 3127 pC->State = M4VSS3GPP_kEditState_VIDEO; 3128 } 3129 3130 /** 3131 * Return with no error */ 3132 M4OSA_TRACE3_0("M4VSS3GPP_intReachedEndOfAudio(): returning M4NO_ERROR"); 3133 return M4NO_ERROR; 3134} 3135 3136/** 3137 ****************************************************************************** 3138 * M4OSA_ERR M4VSS3GPP_intOpenClip() 3139 * @brief Open next clip 3140 * @param pC (IN/OUT) Internal edit context 3141 ****************************************************************************** 3142 */ 3143M4OSA_ERR M4VSS3GPP_intOpenClip( M4VSS3GPP_InternalEditContext *pC, 3144 M4VSS3GPP_ClipContext ** hClip, 3145 M4VSS3GPP_ClipSettings *pClipSettings ) 3146{ 3147 M4OSA_ERR err; 3148 M4VSS3GPP_ClipContext *pClip; /**< shortcut */ 3149 M4VIDEOEDITING_ClipProperties *pClipProperties; 3150 M4OSA_Int32 iCts; 3151 M4OSA_UInt32 i; 3152 3153 M4OSA_TRACE2_1("M4VSS3GPP_intOpenClip: \"%s\"", 3154 (M4OSA_Char *)pClipSettings->pFile); 3155 3156 err = M4VSS3GPP_intClipInit(hClip, pC->pOsaFileReadPtr); 3157 3158 if( M4NO_ERROR != err ) 3159 { 3160 M4OSA_TRACE1_1( 3161 "M4VSS3GPP_intOpenClip: M4VSS3GPP_intClipInit() returns 0x%x!", 3162 err); 3163 3164 if( *hClip != M4OSA_NULL ) 3165 { 3166 M4VSS3GPP_intClipCleanUp(*hClip); 3167 } 3168 return err; 3169 } 3170 3171 /** 3172 * Set shortcut */ 3173 pClip = *hClip; 3174 3175 err = M4VSS3GPP_intClipOpen(pClip, pClipSettings, M4OSA_FALSE, M4OSA_FALSE, 3176 M4OSA_FALSE); 3177 3178 if( M4NO_ERROR != err ) 3179 { 3180 M4OSA_TRACE1_1( 3181 "M4VSS3GPP_intOpenClip: M4VSS3GPP_intClipOpen() returns 0x%x!", 3182 err); 3183 M4VSS3GPP_intClipCleanUp(pClip); 3184 *hClip = M4OSA_NULL; 3185 return err; 3186 } 3187 3188 pClipProperties = &pClip->pSettings->ClipProperties; 3189 3190 /** 3191 * Copy common 'silence frame stuff' to ClipContext */ 3192 pClip->uiSilencePcmSize = pC->ewc.uiSilencePcmSize; 3193 pClip->pSilenceFrameData = pC->ewc.pSilenceFrameData; 3194 pClip->uiSilenceFrameSize = pC->ewc.uiSilenceFrameSize; 3195 pClip->iSilenceFrameDuration = pC->ewc.iSilenceFrameDuration; 3196 pClip->scale_audio = pC->ewc.scale_audio; 3197 3198 pClip->iAudioFrameCts = -pClip->iSilenceFrameDuration; /* Reset time */ 3199 3200 /** 3201 * If the audio track is not compatible with the output audio format, 3202 * we remove it. So it will be replaced by silence */ 3203 if( M4OSA_FALSE == pClipProperties->bAudioIsCompatibleWithMasterClip ) 3204 { 3205 M4VSS3GPP_intClipDeleteAudioTrack(pClip); 3206 } 3207 3208 /** 3209 * Actual begin cut */ 3210 if( 0 == pClipSettings->uiBeginCutTime ) 3211 { 3212 pClip->iVoffset = 0; 3213 pClip->iAoffset = 0; 3214 pClip->iActualVideoBeginCut = 0; 3215 pClip->iActualAudioBeginCut = 0; 3216 } 3217 else 3218 { 3219 if( M4SYS_kVideoUnknown != pC->ewc.VideoStreamType ) 3220 { 3221 /** 3222 * Jump the video to the target begin cut to get the actual begin cut value */ 3223 pClip->iActualVideoBeginCut = 3224 (M4OSA_Int32)pClipSettings->uiBeginCutTime; 3225 iCts = pClip->iActualVideoBeginCut; 3226 3227 err = pClip->ShellAPI.m_pReader->m_pFctJump(pClip->pReaderContext, 3228 (M4_StreamHandler *)pClip->pVideoStream, &iCts); 3229 3230 if( M4NO_ERROR != err ) 3231 { 3232 M4OSA_TRACE1_1( 3233 "M4VSS3GPP_intOpenClip: m_pFctJump(V) returns 0x%x!", err); 3234 return err; 3235 } 3236 3237 /** 3238 * Update clip offset with the video begin cut */ 3239 pClip->iVoffset = -pClip->iActualVideoBeginCut; 3240 } 3241 3242 if( M4SYS_kAudioUnknown != pC->ewc.AudioStreamType ) 3243 { 3244 /** 3245 * Jump the audio to the video actual begin cut */ 3246 if( M4VIDEOEDITING_kMP3 != pClipProperties->AudioStreamType ) 3247 { 3248 pClip->iActualAudioBeginCut = pClip->iActualVideoBeginCut; 3249 iCts = (M4OSA_Int32)(pClip->iActualAudioBeginCut 3250 * pClip->scale_audio + 0.5); 3251 3252 err = M4VSS3GPP_intClipJumpAudioAt(pClip, &iCts); 3253 3254 if( M4NO_ERROR != err ) 3255 { 3256 M4OSA_TRACE1_1( 3257 "M4VSS3GPP_intOpenClip: M4VSS3GPP_intClipJumpAudioAt(A) returns 0x%x!", 3258 err); 3259 return err; 3260 } 3261 /** 3262 * Update clip offset with the audio begin cut */ 3263 pClip->iAoffset = -iCts; 3264 } 3265 else 3266 { 3267 /** 3268 * For the MP3, the jump is not done because of the VBR, 3269 it could be not enough accurate */ 3270 pClip->iActualAudioBeginCut = 3271 (M4OSA_Int32)pClipSettings->uiBeginCutTime; 3272 } 3273 } 3274 } 3275 3276 if( M4SYS_kVideoUnknown != pC->ewc.VideoStreamType ) 3277 { 3278 /** 3279 * Read the first Video AU of the clip */ 3280 err = pClip->ShellAPI.m_pReaderDataIt->m_pFctGetNextAu( 3281 pClip->pReaderContext, 3282 (M4_StreamHandler *)pClip->pVideoStream, &pClip->VideoAU); 3283 3284 if( M4WAR_NO_MORE_AU == err ) 3285 { 3286 /** 3287 * If we (already!) reach the end of the clip, we filter the error. 3288 * It will be correctly managed at the first step. */ 3289 err = M4NO_ERROR; 3290 } 3291 else if( M4NO_ERROR != err ) 3292 { 3293 M4OSA_TRACE1_1( 3294 "M4VSS3GPP_intOpenClip: m_pReaderDataIt->m_pFctGetNextAu() returns 0x%x!", 3295 err); 3296 return err; 3297 } 3298 3299 /** 3300 * The video is currently in reading mode */ 3301 pClip->Vstatus = M4VSS3GPP_kClipStatus_READ; 3302 } 3303 3304 if( ( M4SYS_kAudioUnknown != pC->ewc.AudioStreamType) 3305 && (M4VIDEOEDITING_kMP3 != pClipProperties->AudioStreamType) ) 3306 { 3307 /** 3308 * Read the first Audio AU of the clip */ 3309 err = M4VSS3GPP_intClipReadNextAudioFrame(pClip); 3310 3311 if( M4OSA_ERR_IS_ERROR(err) ) 3312 { 3313 M4OSA_TRACE1_1( 3314 "M4VSS3GPP_intOpenClip: M4VSS3GPP_intClipReadNextAudioFrame returns 0x%x!", 3315 err); 3316 return err; 3317 } 3318 3319 /** 3320 * The audio is currently in reading mode */ 3321 pClip->Astatus = M4VSS3GPP_kClipStatus_READ; 3322 } 3323 3324 /** 3325 * Return with no error */ 3326 M4OSA_TRACE3_0("M4VSS3GPP_intOpenClip(): returning M4NO_ERROR"); 3327 return M4NO_ERROR; 3328} 3329 3330/** 3331 ****************************************************************************** 3332 * M4OSA_ERR M4VSS3GPP_intComputeOutputAverageVideoBitrate() 3333 * @brief Average bitrate of the output file, computed from input bitrates, 3334 * durations, transitions and cuts. 3335 * @param pC (IN/OUT) Internal edit context 3336 ****************************************************************************** 3337 */ 3338static M4OSA_Void M4VSS3GPP_intComputeOutputAverageVideoBitrate( 3339 M4VSS3GPP_InternalEditContext *pC ) 3340{ 3341 M4VSS3GPP_ClipSettings *pCS_0, *pCS_1, *pCS_2; 3342 M4VSS3GPP_TransitionSettings *pT0, *pT2; 3343 M4OSA_Int32 i; 3344 3345 M4OSA_UInt32 t0_duration, t2_duration; 3346 M4OSA_UInt32 t0_bitrate, t2_bitrate; 3347 M4OSA_UInt32 c1_duration; 3348 3349 M4OSA_UInt32 total_duration; 3350 M4OSA_UInt32 total_bitsum; 3351 3352 total_duration = 0; 3353 total_bitsum = 0; 3354 3355 /* Loop on the number of clips */ 3356 for ( i = 0; i < pC->uiClipNumber; i++ ) 3357 { 3358 pCS_1 = &pC->pClipList[i]; 3359 3360 t0_duration = 0; 3361 t0_bitrate = pCS_1->ClipProperties.uiVideoBitrate; 3362 t2_duration = 0; 3363 t2_bitrate = pCS_1->ClipProperties.uiVideoBitrate; 3364 3365 /* Transition with the previous clip */ 3366 if( i > 0 ) 3367 { 3368 pCS_0 = &pC->pClipList[i - 1]; 3369 pT0 = &pC->pTransitionList[i - 1]; 3370 3371 if( pT0->VideoTransitionType 3372 != M4VSS3GPP_kVideoTransitionType_None ) 3373 { 3374 t0_duration = pT0->uiTransitionDuration; 3375 3376 if( pCS_0->ClipProperties.uiVideoBitrate > t0_bitrate ) 3377 { 3378 t0_bitrate = pCS_0->ClipProperties.uiVideoBitrate; 3379 } 3380 } 3381 } 3382 3383 /* Transition with the next clip */ 3384 if( i < pC->uiClipNumber - 1 ) 3385 { 3386 pCS_2 = &pC->pClipList[i + 1]; 3387 pT2 = &pC->pTransitionList[i]; 3388 3389 if( pT2->VideoTransitionType 3390 != M4VSS3GPP_kVideoTransitionType_None ) 3391 { 3392 t2_duration = pT2->uiTransitionDuration; 3393 3394 if( pCS_2->ClipProperties.uiVideoBitrate > t2_bitrate ) 3395 { 3396 t2_bitrate = pCS_2->ClipProperties.uiVideoBitrate; 3397 } 3398 } 3399 } 3400 3401 /* Check for cut times */ 3402 if( pCS_1->uiEndCutTime > 0 ) 3403 c1_duration = pCS_1->uiEndCutTime; 3404 else 3405 c1_duration = pCS_1->ClipProperties.uiClipVideoDuration; 3406 3407 if( pCS_1->uiBeginCutTime > 0 ) 3408 c1_duration -= pCS_1->uiBeginCutTime; 3409 3410 c1_duration -= t0_duration + t2_duration; 3411 3412 /* Compute bitsum and duration */ 3413 total_duration += c1_duration + t0_duration / 2 + t2_duration / 2; 3414 3415 total_bitsum += 3416 c1_duration * (pCS_1->ClipProperties.uiVideoBitrate / 1000) 3417 + (t0_bitrate / 1000) * t0_duration / 2 3418 + (t2_bitrate / 1000) * t2_duration / 2; 3419 } 3420 3421 pC->ewc.uiVideoBitrate = ( total_bitsum / total_duration) * 1000; 3422} 3423 3424