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