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