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