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