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