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