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