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