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