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 */
M4VSS3GPP_GetVersion(M4_VersionInfo * pVersionInfo)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 */
M4VSS3GPP_editInit(M4VSS3GPP_EditContext * pContext,M4OSA_FileReadPointer * pFileReadPtrFct,M4OSA_FileWriterPointer * pFileWritePtrFct)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
M4VSS3GPP_editCreateClipSettings(M4VSS3GPP_ClipSettings * pClipSettings,M4OSA_Void * pFile,M4OSA_UInt32 filePathSize,M4OSA_UInt8 nbEffects)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
M4VSS3GPP_editDuplicateClipSettings(M4VSS3GPP_ClipSettings * pClipSettingsDest,M4VSS3GPP_ClipSettings * pClipSettingsOrig,M4OSA_Bool bCopyEffects)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 */
M4VSS3GPP_editFreeClipSettings(M4VSS3GPP_ClipSettings * pClipSettings)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 */
M4VSS3GPP_editOpen(M4VSS3GPP_EditContext pContext,M4VSS3GPP_EditSettings * pSettings)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 */
M4VSS3GPP_editStep(M4VSS3GPP_EditContext pContext,M4OSA_UInt8 * pProgress)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 */
M4VSS3GPP_editClose(M4VSS3GPP_EditContext pContext)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 */
M4VSS3GPP_editCleanUp(M4VSS3GPP_EditContext pContext)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
M4VSS3GPP_GetErrorMessage(M4OSA_ERR err,M4OSA_Char * sMessage)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
M4VSS3GPP_intClipSettingsSanityCheck(M4VSS3GPP_ClipSettings * pClip)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 */
M4VSS3GPP_intTransitionSettingsSanityCheck(M4VSS3GPP_TransitionSettings * pTransition)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 */
M4VSS3GPP_intFreeSettingsList(M4VSS3GPP_InternalEditContext * pC)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
M4VSS3GPP_intCreateMP3OutputFile(M4VSS3GPP_InternalEditContext * pC,M4OSA_Void * pOutputFile)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
M4VSS3GPP_intCreate3GPPOutputFile(M4VSS3GPP_EncodeWriteContext * pC_ewc,M4VSS3GPP_MediaAndCodecCtxt * pC_ShellAPI,M4OSA_FileWriterPointer * pOsaFileWritPtr,M4OSA_Void * pOutputFile,M4OSA_FileReadPointer * pOsaFileReadPtr,M4OSA_Void * pTempFile,M4OSA_UInt32 maxOutputFileSize)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
M4VSS3GPP_intComputeOutputVideoAndAudioDsi(M4VSS3GPP_InternalEditContext * pC,M4OSA_UInt8 uiMasterClip)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 */
M4VSS3GPP_intSwitchToNextClip(M4VSS3GPP_InternalEditContext * pC)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 */
M4VSS3GPP_intReachedEndOfVideo(M4VSS3GPP_InternalEditContext * pC)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 */
M4VSS3GPP_intReachedEndOfAudio(M4VSS3GPP_InternalEditContext * pC)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 */
M4VSS3GPP_intOpenClip(M4VSS3GPP_InternalEditContext * pC,M4VSS3GPP_ClipContext ** hClip,M4VSS3GPP_ClipSettings * pClipSettings)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 */
M4VSS3GPP_intComputeOutputAverageVideoBitrate(M4VSS3GPP_InternalEditContext * pC)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