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