Home | History | Annotate | Download | only in src
      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  */
     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  */
    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
    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
    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  */
    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  */
    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  */
   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  */
   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  */
   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 
   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 
   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  */
   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  */
   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
   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
   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
   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  */
   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  */
   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  */
   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  */
   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  */
   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