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