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