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