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