/* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** ****************************************************************************** * @file M4xVSS_API.c * @brief API of eXtended Video Studio Service (Video Studio 2.1) * @note ****************************************************************************** */ /** * OSAL main types and errors ***/ #include "M4OSA_Types.h" #include "M4OSA_Error.h" #include "M4OSA_Memory.h" #include "M4OSA_Debug.h" #include "M4OSA_FileReader.h" #include "M4OSA_FileWriter.h" #include "M4OSA_CoreID.h" #include "M4OSA_CharStar.h" // StageFright encoders require %16 resolution #include "M4ENCODER_common.h" #include "M4DECODER_Common.h" #include "VideoEditorVideoDecoder.h" /** * VSS 3GPP API definition */ #include "M4VSS3GPP_ErrorCodes.h" /************************* Begin of xVSS API **************************/ #include "M4xVSS_API.h" #include "M4xVSS_Internal.h" /* RC: to delete unecessary temp files on the fly */ #include "M4VSS3GPP_InternalTypes.h" #include <utils/Log.h> /** ****************************************************************************** * prototype M4OSA_ERR M4xVSS_Init(M4OSA_Context* pContext, M4xVSS_InitParams* pParams) * @brief This function initializes the xVSS * @note Initializes the xVSS edit operation (allocates an execution context). * * @param pContext (OUT) Pointer on the xVSS edit context to allocate * @param params (IN) Parameters mandatory for xVSS * @return M4NO_ERROR: No error * @return M4ERR_PARAMETER: At least one parameter is M4OSA_NULL * @return M4ERR_ALLOC: Memory allocation has failed ****************************************************************************** */ M4OSA_ERR M4xVSS_Init( M4OSA_Context *pContext, M4xVSS_InitParams *pParams ) { M4xVSS_Context *xVSS_context; M4OSA_UInt32 length = 0, i; if( pParams == M4OSA_NULL ) { M4OSA_TRACE1_0("Parameter structure for M4xVSS_Init function is NULL"); return M4ERR_PARAMETER; } if( pParams->pFileReadPtr == M4OSA_NULL || pParams->pFileWritePtr == M4OSA_NULL ) { M4OSA_TRACE1_0( "pFileReadPtr or pFileWritePtr in M4xVSS_InitParams structure is NULL"); return M4ERR_PARAMETER; } xVSS_context = (M4xVSS_Context *)M4OSA_32bitAlignedMalloc(sizeof(M4xVSS_Context), M4VS, (M4OSA_Char *)"Context of the xVSS layer"); if( xVSS_context == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_Init"); return M4ERR_ALLOC; } /* Initialize file read/write functions pointers */ xVSS_context->pFileReadPtr = pParams->pFileReadPtr; xVSS_context->pFileWritePtr = pParams->pFileWritePtr; /*UTF Conversion support: copy conversion functions pointers and allocate the temporary buffer*/ if( pParams->pConvFromUTF8Fct != M4OSA_NULL ) { if( pParams->pConvToUTF8Fct != M4OSA_NULL ) { xVSS_context->UTFConversionContext.pConvFromUTF8Fct = pParams->pConvFromUTF8Fct; xVSS_context->UTFConversionContext.pConvToUTF8Fct = pParams->pConvToUTF8Fct; xVSS_context->UTFConversionContext.m_TempOutConversionSize = UTF_CONVERSION_BUFFER_SIZE; xVSS_context->UTFConversionContext.pTempOutConversionBuffer = (M4OSA_Void *)M4OSA_32bitAlignedMalloc(UTF_CONVERSION_BUFFER_SIZE * sizeof(M4OSA_UInt8), M4VA, (M4OSA_Char *)"M4xVSS_Init: UTF conversion buffer"); if( M4OSA_NULL == xVSS_context->UTFConversionContext.pTempOutConversionBuffer ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_Init"); free(xVSS_context->pTempPath); xVSS_context->pTempPath = M4OSA_NULL; free(xVSS_context); xVSS_context = M4OSA_NULL; return M4ERR_ALLOC; } } else { M4OSA_TRACE1_0("M4xVSS_Init: one UTF conversion pointer is null and the other\ is not null"); free(xVSS_context->pTempPath); xVSS_context->pTempPath = M4OSA_NULL; free(xVSS_context); xVSS_context = M4OSA_NULL; return M4ERR_PARAMETER; } } else { xVSS_context->UTFConversionContext.pConvFromUTF8Fct = M4OSA_NULL; xVSS_context->UTFConversionContext.pConvToUTF8Fct = M4OSA_NULL; xVSS_context->UTFConversionContext.m_TempOutConversionSize = 0; xVSS_context->UTFConversionContext.pTempOutConversionBuffer = M4OSA_NULL; } if( pParams->pTempPath != M4OSA_NULL ) { /*No need to convert into UTF8 as all input of xVSS are in UTF8 (the conversion customer format into UTF8 is done in VA/VAL)*/ xVSS_context->pTempPath = (M4OSA_Void *)M4OSA_32bitAlignedMalloc(strlen(pParams->pTempPath) + 1, M4VS, (M4OSA_Char *)"xVSS Path for temporary files"); if( xVSS_context->pTempPath == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_Init"); return M4ERR_ALLOC; } memcpy((void *)xVSS_context->pTempPath, (void *)pParams->pTempPath, strlen(pParams->pTempPath) + 1); /* TODO: Check that no previous xVSS temporary files are present ? */ } else { M4OSA_TRACE1_0("Path for temporary files is NULL"); free(xVSS_context); xVSS_context = M4OSA_NULL; return M4ERR_PARAMETER; } xVSS_context->pSettings = (M4VSS3GPP_EditSettings *)M4OSA_32bitAlignedMalloc(sizeof(M4VSS3GPP_EditSettings), M4VS, (M4OSA_Char *)"Copy of VSS structure"); if( xVSS_context->pSettings == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_Init"); free(xVSS_context->pTempPath); xVSS_context->pTempPath = M4OSA_NULL; free(xVSS_context); xVSS_context = M4OSA_NULL; return M4ERR_ALLOC; } /* Initialize pointers in pSettings */ xVSS_context->pSettings->pClipList = M4OSA_NULL; xVSS_context->pSettings->pTransitionList = M4OSA_NULL; xVSS_context->pSettings->Effects = M4OSA_NULL; /* RC */ xVSS_context->pSettings->xVSS.pBGMtrack = M4OSA_NULL; /* This is used to know if the user has added or removed some medias */ xVSS_context->previousClipNumber = 0; /* "State machine" */ xVSS_context->editingStep = 0; xVSS_context->analyseStep = 0; xVSS_context->pcmPreviewFile = M4OSA_NULL; /* Initialize Pto3GPP and MCS lists */ xVSS_context->pMCSparamsList = M4OSA_NULL; xVSS_context->pPTo3GPPparamsList = M4OSA_NULL; xVSS_context->pPTo3GPPcurrentParams = M4OSA_NULL; xVSS_context->pMCScurrentParams = M4OSA_NULL; xVSS_context->tempFileIndex = 0; xVSS_context->targetedBitrate = 0; xVSS_context->targetedTimescale = 0; xVSS_context->pAudioMixContext = M4OSA_NULL; xVSS_context->pAudioMixSettings = M4OSA_NULL; /*FB: initialize to avoid crash when error during the editing*/ xVSS_context->pCurrentEditSettings = M4OSA_NULL; /* Initialize state if all initializations are corrects */ xVSS_context->m_state = M4xVSS_kStateInitialized; /* initialize MCS context*/ xVSS_context->pMCS_Ctxt = M4OSA_NULL; *pContext = xVSS_context; return M4NO_ERROR; } /** ****************************************************************************** * prototype M4xVSS_ReduceTranscode * @brief This function changes the given editing structure in order to * minimize the transcoding time. * @note The xVSS analyses this structure, and if needed, changes the * output parameters (Video codec, video size, audio codec, * audio nb of channels) to minimize the transcoding time. * * @param pContext (OUT) Pointer on the xVSS edit context to allocate * @param pSettings (IN) Edition settings (allocated by the user) * @return M4NO_ERROR: No error * @return M4ERR_PARAMETER: At least one parameter is M4OSA_NULL * @return M4ERR_ALLOC: Memory allocation has failed * @return M4ERR_STATE: This function cannot not be called at this time ****************************************************************************** */ M4OSA_ERR M4xVSS_ReduceTranscode( M4OSA_Context pContext, M4VSS3GPP_EditSettings *pSettings ) { M4xVSS_Context *xVSS_context = (M4xVSS_Context *)pContext; M4OSA_ERR err = M4NO_ERROR; M4VIDEOEDITING_ClipProperties fileProperties; M4OSA_UInt8 i, j; M4OSA_Bool bAudioTransition = M4OSA_FALSE; M4OSA_Bool bIsBGMReplace = M4OSA_FALSE; M4OSA_Bool bFound; M4OSA_UInt32 videoConfig[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /** Index <-> Video config **/ /* 0: H263 SQCIF */ /* 1: H263 QCIF */ /* 2: H263 CIF */ /* 3: MPEG4 SQCIF */ /* 4: MPEG4 QQVGA */ /* 5: MPEG4 QCIF */ /* 6: MPEG4 QVGA */ /* 7: MPEG4 CIF */ /* 8: MPEG4 VGA */ /****************************/ M4OSA_UInt32 audioConfig[3] = { 0, 0, 0 }; /** Index <-> Audio config **/ /* 0: AMR */ /* 1: AAC 16kHz mono */ /* 2: AAC 16kHz stereo */ /****************************/ /* Check state */ if( xVSS_context->m_state != M4xVSS_kStateInitialized \ && xVSS_context->m_state != M4xVSS_kStateOpened ) { M4OSA_TRACE1_1( "Bad state when calling M4xVSS_ReduceTranscode function! State is %d", xVSS_context->m_state); return M4ERR_STATE; } /* Check number of clips */ if( pSettings->uiClipNumber == 0 ) { M4OSA_TRACE1_0("The number of input clip must be greater than 0 !"); return M4ERR_PARAMETER; } /* Check if there is a background music, and if its audio will replace input clip audio */ if( pSettings->xVSS.pBGMtrack != M4OSA_NULL ) { if( pSettings->xVSS.pBGMtrack->uiAddVolume == 100 ) { bIsBGMReplace = M4OSA_TRUE; } } /* Parse all clips, and give occurences of each combination */ for ( i = 0; i < pSettings->uiClipNumber; i++ ) { /* We ignore JPG input files as they are always transcoded */ if( pSettings->pClipList[i]->FileType == M4VIDEOEDITING_kFileType_3GPP ) { /** * UTF conversion: convert into the customer format*/ M4OSA_Void *pDecodedPath = pSettings->pClipList[i]->pFile; M4OSA_UInt32 ConvertedSize = 0; if( xVSS_context->UTFConversionContext.pConvFromUTF8Fct != M4OSA_NULL && xVSS_context-> UTFConversionContext.pTempOutConversionBuffer != M4OSA_NULL ) { err = M4xVSS_internalConvertFromUTF8(xVSS_context, (M4OSA_Void *)pSettings->pClipList[i]->pFile, (M4OSA_Void *)xVSS_context-> UTFConversionContext.pTempOutConversionBuffer, &ConvertedSize); if( err != M4NO_ERROR ) { M4OSA_TRACE1_1("M4xVSS_ReduceTranscode:\ M4xVSS_internalConvertFromUTF8 returns err: 0x%x", err); return err; } pDecodedPath = xVSS_context->UTFConversionContext.pTempOutConversionBuffer; } /** * End of the utf conversion, now use the converted path*/ err = M4xVSS_internalGetProperties(xVSS_context, pDecodedPath, &fileProperties); //err = M4xVSS_internalGetProperties(xVSS_context, pSettings->pClipList[i]->pFile, // &fileProperties); if( err != M4NO_ERROR ) { M4OSA_TRACE1_1( "M4xVSS_sendCommand: M4xVSS_internalGetProperties returned 0x%x", err); /* TODO: Translate error code of MCS to an xVSS error code ? */ return err; } /* Check best video settings */ if( fileProperties.uiVideoWidth == 128 && fileProperties.uiVideoHeight == 96 ) { if( fileProperties.VideoStreamType == M4VIDEOEDITING_kH263 ) { videoConfig[0] += fileProperties.uiClipVideoDuration; } else if( ( fileProperties.VideoStreamType == M4VIDEOEDITING_kMPEG4) \ || (fileProperties.VideoStreamType == M4VIDEOEDITING_kH264) ) { videoConfig[3] += fileProperties.uiClipVideoDuration; } } else if( fileProperties.uiVideoWidth == 160 && fileProperties.uiVideoHeight == 120 ) { if( ( fileProperties.VideoStreamType == M4VIDEOEDITING_kMPEG4) \ || (fileProperties.VideoStreamType == M4VIDEOEDITING_kH264) ) { videoConfig[4] += fileProperties.uiClipVideoDuration; } } else if( fileProperties.uiVideoWidth == 176 && fileProperties.uiVideoHeight == 144 ) { if( fileProperties.VideoStreamType == M4VIDEOEDITING_kH263 ) { videoConfig[1] += fileProperties.uiClipVideoDuration; } else if( ( fileProperties.VideoStreamType == M4VIDEOEDITING_kMPEG4) \ || (fileProperties.VideoStreamType == M4VIDEOEDITING_kH264) ) { videoConfig[5] += fileProperties.uiClipVideoDuration; } } else if( fileProperties.uiVideoWidth == 320 && fileProperties.uiVideoHeight == 240 ) { if( ( fileProperties.VideoStreamType == M4VIDEOEDITING_kMPEG4) \ || (fileProperties.VideoStreamType == M4VIDEOEDITING_kH264) ) { videoConfig[6] += fileProperties.uiClipVideoDuration; } } else if( fileProperties.uiVideoWidth == 352 && fileProperties.uiVideoHeight == 288 ) { if( fileProperties.VideoStreamType == M4VIDEOEDITING_kH263 ) { videoConfig[2] += fileProperties.uiClipVideoDuration; } else if( ( fileProperties.VideoStreamType == M4VIDEOEDITING_kMPEG4) \ || (fileProperties.VideoStreamType == M4VIDEOEDITING_kH264) ) { videoConfig[7] += fileProperties.uiClipVideoDuration; } } else if( fileProperties.uiVideoWidth == 640 && fileProperties.uiVideoHeight == 480 ) { if( ( fileProperties.VideoStreamType == M4VIDEOEDITING_kMPEG4) \ || (fileProperties.VideoStreamType == M4VIDEOEDITING_kH264) ) { videoConfig[8] += fileProperties.uiClipVideoDuration; } } /* If there is a BGM that replaces existing audio track, we do not care about audio track as it will be replaced */ /* If not, we try to minimize audio reencoding */ if( bIsBGMReplace == M4OSA_FALSE ) { if( fileProperties.AudioStreamType == M4VIDEOEDITING_kAAC ) { if( fileProperties.uiSamplingFrequency == 16000 && \ fileProperties.uiNbChannels == 1 ) { audioConfig[1] += fileProperties.uiClipAudioDuration; } else if( fileProperties.uiSamplingFrequency == 16000 && \ fileProperties.uiNbChannels == 2 ) { audioConfig[2] += fileProperties.uiClipAudioDuration; } } else if( fileProperties.AudioStreamType == M4VIDEOEDITING_kAMR_NB ) { audioConfig[0] += fileProperties.uiClipAudioDuration; } } } } /* Find best output video format (the most occuring combination) */ j = 0; bFound = M4OSA_FALSE; for ( i = 0; i < 9; i++ ) { if( videoConfig[i] >= videoConfig[j] ) { j = i; bFound = M4OSA_TRUE; } } if( bFound ) { switch( j ) { case 0: pSettings->xVSS.outputVideoFormat = M4VIDEOEDITING_kH263; pSettings->xVSS.outputVideoSize = M4VIDEOEDITING_kSQCIF; break; case 1: pSettings->xVSS.outputVideoFormat = M4VIDEOEDITING_kH263; pSettings->xVSS.outputVideoSize = M4VIDEOEDITING_kQCIF; break; case 2: pSettings->xVSS.outputVideoFormat = M4VIDEOEDITING_kH263; pSettings->xVSS.outputVideoSize = M4VIDEOEDITING_kCIF; break; case 3: pSettings->xVSS.outputVideoFormat = (fileProperties.VideoStreamType == M4VIDEOEDITING_kMPEG4) ? M4VIDEOEDITING_kMPEG4 : M4VIDEOEDITING_kH264; pSettings->xVSS.outputVideoSize = M4VIDEOEDITING_kSQCIF; break; case 4: pSettings->xVSS.outputVideoFormat = (fileProperties.VideoStreamType == M4VIDEOEDITING_kMPEG4) ? M4VIDEOEDITING_kMPEG4 : M4VIDEOEDITING_kH264; pSettings->xVSS.outputVideoSize = M4VIDEOEDITING_kQQVGA; break; case 5: pSettings->xVSS.outputVideoFormat = (fileProperties.VideoStreamType == M4VIDEOEDITING_kMPEG4) ? M4VIDEOEDITING_kMPEG4 : M4VIDEOEDITING_kH264; pSettings->xVSS.outputVideoSize = M4VIDEOEDITING_kQCIF; break; case 6: pSettings->xVSS.outputVideoFormat = (fileProperties.VideoStreamType == M4VIDEOEDITING_kMPEG4) ? M4VIDEOEDITING_kMPEG4 : M4VIDEOEDITING_kH264; pSettings->xVSS.outputVideoSize = M4VIDEOEDITING_kQVGA; break; case 7: pSettings->xVSS.outputVideoFormat = (fileProperties.VideoStreamType == M4VIDEOEDITING_kMPEG4) ? M4VIDEOEDITING_kMPEG4 : M4VIDEOEDITING_kH264; pSettings->xVSS.outputVideoSize = M4VIDEOEDITING_kCIF; break; case 8: pSettings->xVSS.outputVideoFormat = (fileProperties.VideoStreamType == M4VIDEOEDITING_kMPEG4) ? M4VIDEOEDITING_kMPEG4 : M4VIDEOEDITING_kH264; pSettings->xVSS.outputVideoSize = M4VIDEOEDITING_kVGA; break; } } /* Find best output audio format (the most occuring combination) */ j = 0; bFound = M4OSA_FALSE; for ( i = 0; i < 3; i++ ) { if( audioConfig[i] >= audioConfig[j] ) { j = i; bFound = M4OSA_TRUE; } } if( bFound ) { switch( j ) { case 0: pSettings->xVSS.outputAudioFormat = M4VIDEOEDITING_kAMR_NB; pSettings->xVSS.bAudioMono = M4OSA_TRUE; break; case 1: pSettings->xVSS.outputAudioFormat = M4VIDEOEDITING_kAAC; pSettings->xVSS.bAudioMono = M4OSA_TRUE; break; case 2: pSettings->xVSS.outputAudioFormat = M4VIDEOEDITING_kAAC; pSettings->xVSS.bAudioMono = M4OSA_FALSE; break; } } return M4NO_ERROR; } /** ****************************************************************************** * prototype M4OSA_ERR M4xVSS_SendCommand(M4OSA_Context pContext, * M4VSS3GPP_EditSettings* pSettings) * @brief This function gives to the xVSS an editing structure * @note The xVSS analyses this structure, and prepare edition * This function must be called after M4xVSS_Init, after * M4xVSS_CloseCommand, or after M4xVSS_PreviewStop. * After this function, the user must call M4xVSS_Step until * it returns another error than M4NO_ERROR. * * @param pContext (IN) Pointer on the xVSS edit context * @param pSettings (IN) Edition settings (allocated by the user) * @return M4NO_ERROR: No error * @return M4ERR_PARAMETER: At least one parameter is M4OSA_NULL * @return M4ERR_ALLOC: Memory allocation has failed * @return M4ERR_STATE: This function cannot not be called at this time ****************************************************************************** */ M4OSA_ERR M4xVSS_SendCommand( M4OSA_Context pContext, M4VSS3GPP_EditSettings *pSettings ) { M4xVSS_Context *xVSS_context = (M4xVSS_Context *)pContext; M4OSA_UInt8 i, j; M4OSA_UInt8 nbOfSameClip = 0; M4OSA_ERR err; M4OSA_Bool isNewBGM = M4OSA_TRUE; M4xVSS_Pto3GPP_params *pPto3GPP_last = M4OSA_NULL; M4xVSS_MCS_params *pMCS_last = M4OSA_NULL; M4OSA_UInt32 width, height, samplingFreq; M4OSA_Bool bIsTranscoding = M4OSA_FALSE; M4OSA_Int32 totalDuration; M4OSA_UInt32 outputSamplingFrequency = 0; M4OSA_UInt32 length = 0; M4OSA_Int8 masterClip = -1; i = 0; /* Check state */ if( xVSS_context->m_state != M4xVSS_kStateInitialized \ && xVSS_context->m_state != M4xVSS_kStateOpened ) { M4OSA_TRACE1_1( "Bad state when calling M4xVSS_SendCommand function! State is %d", xVSS_context->m_state); return M4ERR_STATE; } /* State is back to initialized to allow call of cleanup function in case of error */ xVSS_context->m_state = M4xVSS_kStateInitialized; /* Check if a previous sendCommand has been called */ if( xVSS_context->previousClipNumber != 0 ) { M4OSA_UInt32 pCmpResult = 0; /* Compare BGM input */ if( xVSS_context->pSettings->xVSS.pBGMtrack != M4OSA_NULL \ && pSettings->xVSS.pBGMtrack != M4OSA_NULL ) { pCmpResult = strcmp((const char *)xVSS_context->pSettings->xVSS.pBGMtrack->pFile, (const char *)pSettings->xVSS.pBGMtrack->pFile); if( pCmpResult == 0 ) { /* Check if audio output parameters have changed */ if( xVSS_context->pSettings->xVSS.outputAudioFormat == pSettings->xVSS.outputAudioFormat && xVSS_context->pSettings->xVSS.bAudioMono == pSettings->xVSS.bAudioMono ) { /* It means that BGM is the same as before, so, no need to redecode it */ M4OSA_TRACE2_0( "BGM is the same as before, nothing to decode"); isNewBGM = M4OSA_FALSE; } else { /* We need to unallocate PCM preview file path in internal context */ if( xVSS_context->pcmPreviewFile != M4OSA_NULL ) { free(xVSS_context->pcmPreviewFile); xVSS_context->pcmPreviewFile = M4OSA_NULL; } } } else { /* We need to unallocate PCM preview file path in internal context */ if( xVSS_context->pcmPreviewFile != M4OSA_NULL ) { free(xVSS_context->pcmPreviewFile); xVSS_context->pcmPreviewFile = M4OSA_NULL; } } } /* Check if output settings have changed */ if( xVSS_context->pSettings->xVSS.outputVideoSize != pSettings->xVSS.outputVideoSize || xVSS_context->pSettings->xVSS.outputVideoFormat != pSettings->xVSS.outputVideoFormat || xVSS_context->pSettings->xVSS.outputVideoProfile != pSettings->xVSS.outputVideoProfile || xVSS_context->pSettings->xVSS.outputVideoLevel != pSettings->xVSS.outputVideoLevel || xVSS_context->pSettings->xVSS.outputAudioFormat != pSettings->xVSS.outputAudioFormat || xVSS_context->pSettings->xVSS.bAudioMono != pSettings->xVSS.bAudioMono || xVSS_context->pSettings->xVSS.outputAudioSamplFreq != pSettings->xVSS.outputAudioSamplFreq ) { /* If it is the case, we can't reuse already transcoded/converted files */ /* so, we delete these files and remove them from chained list */ if( xVSS_context->pPTo3GPPparamsList != M4OSA_NULL ) { M4xVSS_Pto3GPP_params *pParams = xVSS_context->pPTo3GPPparamsList; M4xVSS_Pto3GPP_params *pParams_sauv; while( pParams != M4OSA_NULL ) { if( pParams->pFileIn != M4OSA_NULL ) { free(pParams->pFileIn); pParams->pFileIn = M4OSA_NULL; } if( pParams->pFileOut != M4OSA_NULL ) { /* Delete temporary file */ remove((const char *)pParams->pFileOut); free(pParams->pFileOut); pParams->pFileOut = M4OSA_NULL; } if( pParams->pFileTemp != M4OSA_NULL ) { /* Delete temporary file */ #ifdef M4xVSS_RESERVED_MOOV_DISK_SPACE remove((const char *)pParams->pFileTemp); free(pParams->pFileTemp); #endif /*M4xVSS_RESERVED_MOOV_DISK_SPACE*/ pParams->pFileTemp = M4OSA_NULL; } pParams_sauv = pParams; pParams = pParams->pNext; free(pParams_sauv); pParams_sauv = M4OSA_NULL; } xVSS_context->pPTo3GPPparamsList = M4OSA_NULL; } if( xVSS_context->pMCSparamsList != M4OSA_NULL ) { M4xVSS_MCS_params *pParams = xVSS_context->pMCSparamsList; M4xVSS_MCS_params *pParams_sauv; M4xVSS_MCS_params *pParams_bgm = M4OSA_NULL; while( pParams != M4OSA_NULL ) { /* Here, we do not delete BGM */ if( pParams->isBGM != M4OSA_TRUE ) { if( pParams->pFileIn != M4OSA_NULL ) { free(pParams->pFileIn); pParams->pFileIn = M4OSA_NULL; } if( pParams->pFileOut != M4OSA_NULL ) { /* Delete temporary file */ remove((const char *)pParams->pFileOut); free(pParams->pFileOut); pParams->pFileOut = M4OSA_NULL; } if( pParams->pFileTemp != M4OSA_NULL ) { /* Delete temporary file */ #ifdef M4xVSS_RESERVED_MOOV_DISK_SPACE remove((const char *)pParams->pFileTemp); free(pParams->pFileTemp); #endif /*M4xVSS_RESERVED_MOOV_DISK_SPACE*/ pParams->pFileTemp = M4OSA_NULL; } pParams_sauv = pParams; pParams = pParams->pNext; free(pParams_sauv); pParams_sauv = M4OSA_NULL; } else { pParams_bgm = pParams; pParams = pParams->pNext; /*PR P4ME00003182 initialize this pointer because the following params element will be deallocated*/ if( pParams != M4OSA_NULL && pParams->isBGM != M4OSA_TRUE ) { pParams_bgm->pNext = M4OSA_NULL; } } } xVSS_context->pMCSparamsList = pParams_bgm; } /* Maybe need to implement framerate changing */ //xVSS_context->pSettings->videoFrameRate; } /* Unallocate previous xVSS_context->pSettings structure */ M4xVSS_freeSettings(xVSS_context->pSettings); /*Unallocate output file path*/ if( xVSS_context->pSettings->pOutputFile != M4OSA_NULL ) { free(xVSS_context->pSettings->pOutputFile); xVSS_context->pSettings->pOutputFile = M4OSA_NULL; } xVSS_context->pSettings->uiOutputPathSize = 0; xVSS_context->pOutputFile = M4OSA_NULL; } /********************************** Clips registering **********************************/ /* Copy settings from user given structure to our "local" structure */ xVSS_context->pSettings->xVSS.outputVideoFormat = pSettings->xVSS.outputVideoFormat; xVSS_context->pSettings->xVSS.outputVideoProfile = pSettings->xVSS.outputVideoProfile; xVSS_context->pSettings->xVSS.outputVideoLevel = pSettings->xVSS.outputVideoLevel; xVSS_context->pSettings->xVSS.outputVideoSize = pSettings->xVSS.outputVideoSize; xVSS_context->pSettings->xVSS.outputAudioFormat = pSettings->xVSS.outputAudioFormat; xVSS_context->pSettings->xVSS.bAudioMono = pSettings->xVSS.bAudioMono; xVSS_context->pSettings->xVSS.outputAudioSamplFreq = pSettings->xVSS.outputAudioSamplFreq; /*xVSS_context->pSettings->pOutputFile = pSettings->pOutputFile;*/ /*FB: VAL CR P4ME00003076 The output video and audio bitrate are given by the user in the edition settings structure*/ xVSS_context->pSettings->xVSS.outputVideoBitrate = pSettings->xVSS.outputVideoBitrate; xVSS_context->pSettings->xVSS.outputAudioBitrate = pSettings->xVSS.outputAudioBitrate; xVSS_context->pSettings->PTVolLevel = pSettings->PTVolLevel; /*FB: bug fix if the output path is given in M4xVSS_sendCommand*/ if( pSettings->pOutputFile != M4OSA_NULL && pSettings->uiOutputPathSize > 0 ) { M4OSA_Void *pDecodedPath = pSettings->pOutputFile; /*As all inputs of the xVSS are in UTF8, convert the output file path into the customer format*/ if( xVSS_context->UTFConversionContext.pConvFromUTF8Fct != M4OSA_NULL && xVSS_context->UTFConversionContext.pTempOutConversionBuffer != M4OSA_NULL ) { err = M4xVSS_internalConvertFromUTF8(xVSS_context, (M4OSA_Void *)pSettings->pOutputFile, (M4OSA_Void *)xVSS_context-> UTFConversionContext.pTempOutConversionBuffer, &length); if( err != M4NO_ERROR ) { M4OSA_TRACE1_1("M4xVSS_SendCommand:\ M4xVSS_internalConvertFromUTF8 returns err: 0x%x", err); return err; } pDecodedPath = xVSS_context->UTFConversionContext.pTempOutConversionBuffer; pSettings->uiOutputPathSize = length; } xVSS_context->pSettings->pOutputFile = (M4OSA_Void *)M4OSA_32bitAlignedMalloc \ (pSettings->uiOutputPathSize + 1, M4VS, (M4OSA_Char *)"output file path"); if( xVSS_context->pSettings->pOutputFile == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SendCommand"); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_ALLOC; } memcpy((void *)xVSS_context->pSettings->pOutputFile, (void *)pDecodedPath, pSettings->uiOutputPathSize + 1); xVSS_context->pSettings->uiOutputPathSize = pSettings->uiOutputPathSize; xVSS_context->pOutputFile = xVSS_context->pSettings->pOutputFile; } else { xVSS_context->pSettings->pOutputFile = M4OSA_NULL; xVSS_context->pSettings->uiOutputPathSize = 0; xVSS_context->pOutputFile = M4OSA_NULL; } xVSS_context->pSettings->pTemporaryFile = pSettings->pTemporaryFile; xVSS_context->pSettings->uiClipNumber = pSettings->uiClipNumber; xVSS_context->pSettings->videoFrameRate = pSettings->videoFrameRate; xVSS_context->pSettings->uiMasterClip = 0; /* With VSS 2.0, this new param is mandatory */ xVSS_context->pSettings->xVSS.pTextRenderingFct = pSettings->xVSS.pTextRenderingFct; /* CR text handling */ xVSS_context->pSettings->xVSS.outputFileSize = pSettings->xVSS.outputFileSize; if( pSettings->xVSS.outputFileSize != 0 \ && pSettings->xVSS.outputAudioFormat != M4VIDEOEDITING_kAMR_NB ) { M4OSA_TRACE1_0("M4xVSS_SendCommand: Impossible to limit file\ size with other audio output than AAC"); return M4ERR_PARAMETER; } xVSS_context->nbStepTotal = 0; xVSS_context->currentStep = 0; if( xVSS_context->pSettings->xVSS.outputVideoFormat != M4VIDEOEDITING_kMPEG4 && xVSS_context->pSettings->xVSS.outputVideoFormat != M4VIDEOEDITING_kH263 && xVSS_context->pSettings->xVSS.outputVideoFormat != M4VIDEOEDITING_kH264 ) { xVSS_context->pSettings->xVSS.outputVideoFormat = M4VIDEOEDITING_kNoneVideo; } /* Get output width/height */ switch( xVSS_context->pSettings->xVSS.outputVideoSize ) { case M4VIDEOEDITING_kSQCIF: width = 128; height = 96; break; case M4VIDEOEDITING_kQQVGA: width = 160; height = 120; break; case M4VIDEOEDITING_kQCIF: width = 176; height = 144; break; case M4VIDEOEDITING_kQVGA: width = 320; height = 240; break; case M4VIDEOEDITING_kCIF: width = 352; height = 288; break; case M4VIDEOEDITING_kVGA: width = 640; height = 480; break; /* +PR LV5807 */ case M4VIDEOEDITING_kWVGA: width = 800; height = 480; break; case M4VIDEOEDITING_kNTSC: width = 720; height = 480; break; /* -PR LV5807 */ /* +CR Google */ case M4VIDEOEDITING_k640_360: width = 640; height = 360; break; case M4VIDEOEDITING_k854_480: // StageFright encoders require %16 resolution width = M4ENCODER_854_480_Width; height = 480; break; case M4VIDEOEDITING_k1280_720: width = 1280; height = 720; break; case M4VIDEOEDITING_k1080_720: // StageFright encoders require %16 resolution width = M4ENCODER_1080_720_Width; height = 720; break; case M4VIDEOEDITING_k960_720: width = 960; height = 720; break; case M4VIDEOEDITING_k1920_1080: width = 1920; height = M4ENCODER_1920_1080_Height; break; /* -CR Google */ default: /* If output video size is not given, we take QCIF size */ width = 176; height = 144; xVSS_context->pSettings->xVSS.outputVideoSize = M4VIDEOEDITING_kQCIF; break; } /* Get output Sampling frequency */ switch( xVSS_context->pSettings->xVSS.outputAudioSamplFreq ) { case M4VIDEOEDITING_k8000_ASF: samplingFreq = 8000; break; case M4VIDEOEDITING_k16000_ASF: samplingFreq = 16000; break; case M4VIDEOEDITING_k22050_ASF: samplingFreq = 22050; break; case M4VIDEOEDITING_k24000_ASF: samplingFreq = 24000; break; case M4VIDEOEDITING_k32000_ASF: samplingFreq = 32000; break; case M4VIDEOEDITING_k44100_ASF: samplingFreq = 44100; break; case M4VIDEOEDITING_k48000_ASF: samplingFreq = 48000; break; case M4VIDEOEDITING_kDefault_ASF: default: if( xVSS_context->pSettings->xVSS.outputAudioFormat == M4VIDEOEDITING_kAMR_NB ) { samplingFreq = 8000; } else if( xVSS_context->pSettings->xVSS.outputAudioFormat == M4VIDEOEDITING_kAAC ) { samplingFreq = 16000; } else { samplingFreq = 0; } break; } /* Allocate clip/transitions if clip number is not null ... */ if( 0 < xVSS_context->pSettings->uiClipNumber ) { if( xVSS_context->pSettings->pClipList != M4OSA_NULL ) { free((xVSS_context->pSettings->pClipList)); xVSS_context->pSettings->pClipList = M4OSA_NULL; } if( xVSS_context->pSettings->pTransitionList != M4OSA_NULL ) { free(xVSS_context->pSettings->pTransitionList); xVSS_context->pSettings->pTransitionList = M4OSA_NULL; } xVSS_context->pSettings->pClipList = (M4VSS3GPP_ClipSettings ** )M4OSA_32bitAlignedMalloc \ (sizeof(M4VSS3GPP_ClipSettings *)*xVSS_context->pSettings->uiClipNumber, M4VS, (M4OSA_Char *)"xVSS, copy of pClipList"); if( xVSS_context->pSettings->pClipList == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SendCommand"); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_ALLOC; } /* Set clip list to NULL */ memset((void *)xVSS_context->pSettings->pClipList,0, sizeof(M4VSS3GPP_ClipSettings *) *xVSS_context->pSettings->uiClipNumber); if( xVSS_context->pSettings->uiClipNumber > 1 ) { xVSS_context->pSettings->pTransitionList = (M4VSS3GPP_TransitionSettings ** ) \ M4OSA_32bitAlignedMalloc(sizeof(M4VSS3GPP_TransitionSettings *) \ *(xVSS_context->pSettings->uiClipNumber - 1), M4VS, (M4OSA_Char *) \ "xVSS, copy of pTransitionList"); if( xVSS_context->pSettings->pTransitionList == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SendCommand"); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_ALLOC; } /* Set transition list to NULL */ memset( (void *)xVSS_context->pSettings->pTransitionList,0, sizeof(M4VSS3GPP_TransitionSettings *) *(xVSS_context->pSettings->uiClipNumber - 1)); } else { xVSS_context->pSettings->pTransitionList = M4OSA_NULL; } } /* else, there is a pb in the input settings structure */ else { M4OSA_TRACE1_0("No clip in this settings list !!"); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_PARAMETER; } /* RC Allocate effects settings */ xVSS_context->pSettings->nbEffects = pSettings->nbEffects; if( 0 < xVSS_context->pSettings->nbEffects ) { xVSS_context->pSettings->Effects = (M4VSS3GPP_EffectSettings *)M4OSA_32bitAlignedMalloc \ (xVSS_context->pSettings->nbEffects * sizeof(M4VSS3GPP_EffectSettings), M4VS, (M4OSA_Char *)"effects settings"); if( xVSS_context->pSettings->Effects == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SendCommand"); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_ALLOC; } /*FB bug fix 19.03.2008: these pointers were not initialized -> crash when free*/ for ( i = 0; i < xVSS_context->pSettings->nbEffects; i++ ) { xVSS_context->pSettings->Effects[i].xVSS.pFramingFilePath = M4OSA_NULL; xVSS_context->pSettings->Effects[i].xVSS.pFramingBuffer = M4OSA_NULL; xVSS_context->pSettings->Effects[i].xVSS.pTextBuffer = M4OSA_NULL; } /**/ } if( xVSS_context->targetedTimescale == 0 ) { M4OSA_UInt32 pTargetedTimeScale = 0; err = M4xVSS_internalGetTargetedTimeScale(xVSS_context, pSettings, &pTargetedTimeScale); if( M4NO_ERROR != err || pTargetedTimeScale == 0 ) { M4OSA_TRACE1_1("M4xVSS_SendCommand: M4xVSS_internalGetTargetedTimeScale\ returned 0x%x", err); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return err; } xVSS_context->targetedTimescale = pTargetedTimeScale; } /* Initialize total duration variable */ totalDuration = 0; /* Parsing list of clips given by application, and prepare analyzing */ for ( i = 0; i < xVSS_context->pSettings->uiClipNumber; i++ ) { /* Allocate current clip */ xVSS_context->pSettings->pClipList[i] = (M4VSS3GPP_ClipSettings *)M4OSA_32bitAlignedMalloc \ (sizeof(M4VSS3GPP_ClipSettings), M4VS, (M4OSA_Char *)"clip settings"); if( xVSS_context->pSettings->pClipList[i] == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SendCommand"); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_ALLOC; } /* Copy clip settings from given structure to our xVSS_context structure */ err = M4xVSS_DuplicateClipSettings(xVSS_context->pSettings->pClipList[i], pSettings->pClipList[i], M4OSA_TRUE); if( err != M4NO_ERROR ) { M4OSA_TRACE1_1( "M4xVSS_SendCommand: M4xVSS_DuplicateClipSettings return error 0x%x", err); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return err; } xVSS_context->pSettings->pClipList[i]->bTranscodingRequired = M4OSA_FALSE; /* Because there is 1 less transition than clip number */ if( i < xVSS_context->pSettings->uiClipNumber - 1 ) { xVSS_context->pSettings->pTransitionList[i] = (M4VSS3GPP_TransitionSettings *)M4OSA_32bitAlignedMalloc(sizeof(M4VSS3GPP_TransitionSettings), M4VS, (M4OSA_Char *)"transition settings"); if( xVSS_context->pSettings->pTransitionList[i] == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SendCommand"); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_ALLOC; } memcpy( (void *)xVSS_context->pSettings->pTransitionList[i], (void *)pSettings->pTransitionList[i], sizeof(M4VSS3GPP_TransitionSettings)); /* Initialize external effect context to NULL, to know if input jpg has already been decoded or not */ xVSS_context->pSettings->pTransitionList[i]-> pExtVideoTransitionFctCtxt = M4OSA_NULL; switch( xVSS_context->pSettings-> pTransitionList[i]->VideoTransitionType ) { /* If transition type is alpha magic, we need to decode input file */ case M4xVSS_kVideoTransitionType_AlphaMagic: /* Allocate our alpha magic settings structure to have a copy of the provided one */ xVSS_context->pSettings->pTransitionList[i]-> \ xVSS.transitionSpecific.pAlphaMagicSettings = (M4xVSS_AlphaMagicSettings *)M4OSA_32bitAlignedMalloc \ (sizeof(M4xVSS_AlphaMagicSettings), M4VS, (M4OSA_Char *)"Input Alpha magic settings structure"); if( xVSS_context->pSettings->pTransitionList[i]-> \ xVSS.transitionSpecific.pAlphaMagicSettings == M4OSA_NULL ) { M4OSA_TRACE1_0( "Allocation error in M4xVSS_SendCommand"); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_ALLOC; } /* Copy data from the provided alpha magic settings structure tou our structure */ memcpy((void *)xVSS_context->pSettings-> pTransitionList[i]-> \ xVSS.transitionSpecific.pAlphaMagicSettings, (void *)pSettings->pTransitionList[i]-> \ xVSS.transitionSpecific.pAlphaMagicSettings, sizeof(M4xVSS_AlphaMagicSettings)); /* Allocate our alpha magic input filename */ xVSS_context->pSettings->pTransitionList[i]-> \ xVSS.transitionSpecific.pAlphaMagicSettings-> pAlphaFilePath = M4OSA_32bitAlignedMalloc( (strlen(pSettings->pTransitionList[i]-> \ xVSS.transitionSpecific.pAlphaMagicSettings->pAlphaFilePath) + 1), M4VS, (M4OSA_Char *)"Alpha magic file path"); if( xVSS_context->pSettings->pTransitionList[i]-> \ xVSS.transitionSpecific.pAlphaMagicSettings->pAlphaFilePath == M4OSA_NULL ) { M4OSA_TRACE1_0( "Allocation error in M4xVSS_SendCommand"); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_ALLOC; } /* Copy data from the provided alpha magic filename to our */ M4OSA_chrNCopy( xVSS_context->pSettings->pTransitionList[i]->xVSS. transitionSpecific.pAlphaMagicSettings-> pAlphaFilePath, pSettings->pTransitionList[i]->xVSS. transitionSpecific.pAlphaMagicSettings-> pAlphaFilePath, strlen( pSettings->pTransitionList[i]->xVSS. transitionSpecific.pAlphaMagicSettings-> pAlphaFilePath) + 1); /* Parse all transition to know if the input jpg has already been decoded */ for ( j = 0; j < i; j++ ) { if( xVSS_context->pSettings-> pTransitionList[j]->VideoTransitionType == M4xVSS_kVideoTransitionType_AlphaMagic ) { M4OSA_UInt32 pCmpResult = 0; pCmpResult = strcmp((const char *)xVSS_context->pSettings-> pTransitionList[i]->xVSS. transitionSpecific.pAlphaMagicSettings-> pAlphaFilePath, (const char *)xVSS_context->pSettings-> pTransitionList[j]->xVSS. transitionSpecific. pAlphaMagicSettings->pAlphaFilePath); if( pCmpResult == 0 ) { M4xVSS_internal_AlphaMagicSettings *alphaSettings; alphaSettings = (M4xVSS_internal_AlphaMagicSettings *)M4OSA_32bitAlignedMalloc( sizeof( M4xVSS_internal_AlphaMagicSettings), M4VS, (M4OSA_Char *) "Alpha magic settings structure 1"); if( alphaSettings == M4OSA_NULL ) { M4OSA_TRACE1_0( "Allocation error in M4xVSS_SendCommand"); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_ALLOC; } alphaSettings->pPlane = ((M4xVSS_internal_AlphaMagicSettings *)( xVSS_context->pSettings-> pTransitionList[j]-> pExtVideoTransitionFctCtxt))-> pPlane; if( xVSS_context->pSettings-> pTransitionList[i]->xVSS.transitionSpecific. pAlphaMagicSettings->blendingPercent > 0 && xVSS_context->pSettings-> pTransitionList[i]->xVSS. transitionSpecific. pAlphaMagicSettings->blendingPercent <= 100 ) { alphaSettings->blendingthreshold = ( xVSS_context->pSettings-> pTransitionList[i]->xVSS. transitionSpecific. pAlphaMagicSettings-> blendingPercent) * 255 / 200; } else { alphaSettings->blendingthreshold = 0; } alphaSettings->isreverse = xVSS_context->pSettings-> pTransitionList[i]->xVSS. transitionSpecific. pAlphaMagicSettings->isreverse; /* It means that the input jpg file for alpha magic has already been decoded -> no nedd to decode it again */ if( alphaSettings->blendingthreshold == 0 ) { xVSS_context->pSettings-> pTransitionList[i]-> ExtVideoTransitionFct = M4xVSS_AlphaMagic; } else { xVSS_context->pSettings-> pTransitionList[i]-> ExtVideoTransitionFct = M4xVSS_AlphaMagicBlending; } xVSS_context->pSettings->pTransitionList[i]-> pExtVideoTransitionFctCtxt = alphaSettings; break; } } } /* If the jpg has not been decoded yet ... */ if( xVSS_context->pSettings-> pTransitionList[i]->pExtVideoTransitionFctCtxt == M4OSA_NULL ) { M4VIFI_ImagePlane *outputPlane; M4xVSS_internal_AlphaMagicSettings *alphaSettings; /*UTF conversion support*/ M4OSA_Void *pDecodedPath = M4OSA_NULL; /*To support ARGB8888 : get the width and height */ M4OSA_UInt32 width_ARGB888 = xVSS_context->pSettings->pTransitionList[i]->xVSS. transitionSpecific.pAlphaMagicSettings->width; M4OSA_UInt32 height_ARGB888 = xVSS_context->pSettings->pTransitionList[i]->xVSS. transitionSpecific.pAlphaMagicSettings->height; M4OSA_TRACE1_1( " TransitionListM4xVSS_SendCommand width State is %d", width_ARGB888); M4OSA_TRACE1_1( " TransitionListM4xVSS_SendCommand height! State is %d", height_ARGB888); /* Allocate output plane */ outputPlane = (M4VIFI_ImagePlane *)M4OSA_32bitAlignedMalloc(3 * sizeof(M4VIFI_ImagePlane), M4VS, (M4OSA_Char *) "Output plane for Alpha magic transition"); if( outputPlane == M4OSA_NULL ) { M4OSA_TRACE1_0( "Allocation error in M4xVSS_SendCommand"); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_ALLOC; } outputPlane[0].u_width = width; outputPlane[0].u_height = height; outputPlane[0].u_topleft = 0; outputPlane[0].u_stride = width; outputPlane[0].pac_data = (M4VIFI_UInt8 *)M4OSA_32bitAlignedMalloc(( width * height * 3) >> 1, M4VS, (M4OSA_Char *) "Alloc for the Alpha magic pac_data output YUV"); ; if( outputPlane[0].pac_data == M4OSA_NULL ) { free(outputPlane); outputPlane = M4OSA_NULL; M4OSA_TRACE1_0( "Allocation error in M4xVSS_SendCommand"); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_ALLOC; } outputPlane[1].u_width = width >> 1; outputPlane[1].u_height = height >> 1; outputPlane[1].u_topleft = 0; outputPlane[1].u_stride = width >> 1; outputPlane[1].pac_data = outputPlane[0].pac_data + outputPlane[0].u_width * outputPlane[0].u_height; outputPlane[2].u_width = width >> 1; outputPlane[2].u_height = height >> 1; outputPlane[2].u_topleft = 0; outputPlane[2].u_stride = width >> 1; outputPlane[2].pac_data = outputPlane[1].pac_data + outputPlane[1].u_width * outputPlane[1].u_height; pDecodedPath = xVSS_context->pSettings->pTransitionList[i]->xVSS. transitionSpecific.pAlphaMagicSettings-> pAlphaFilePath; /** * UTF conversion: convert into the customer format, before being used*/ if( xVSS_context->UTFConversionContext.pConvFromUTF8Fct != M4OSA_NULL && xVSS_context-> UTFConversionContext. pTempOutConversionBuffer != M4OSA_NULL ) { err = M4xVSS_internalConvertFromUTF8(xVSS_context, (M4OSA_Void *)xVSS_context->pSettings-> pTransitionList[i]->xVSS. transitionSpecific. pAlphaMagicSettings->pAlphaFilePath, (M4OSA_Void *)xVSS_context-> UTFConversionContext. pTempOutConversionBuffer, &length); if( err != M4NO_ERROR ) { M4OSA_TRACE1_1( "M4xVSS_SendCommand: pConvFromUTF8Fct returns err: 0x%x", err); /* Free Send command */ M4xVSS_freeCommand(xVSS_context); return err; } pDecodedPath = xVSS_context->UTFConversionContext. pTempOutConversionBuffer; } /** End of the conversion, use the decoded path*/ /*To support ARGB8888 : convert + resizing from ARGB8888 to yuv420 */ err = M4xVSS_internalConvertAndResizeARGB8888toYUV420( pDecodedPath, xVSS_context->pFileReadPtr, outputPlane, width_ARGB888, height_ARGB888); if( err != M4NO_ERROR ) { free(outputPlane[0].pac_data); outputPlane[0].pac_data = M4OSA_NULL; free(outputPlane); outputPlane = M4OSA_NULL; M4xVSS_freeCommand(xVSS_context); M4OSA_TRACE1_1( "M4xVSS_SendCommand: error when decoding alpha magic JPEG: 0x%x", err); return err; } /* Allocate alpha settings structure */ alphaSettings = (M4xVSS_internal_AlphaMagicSettings *)M4OSA_32bitAlignedMalloc( sizeof(M4xVSS_internal_AlphaMagicSettings), M4VS, (M4OSA_Char *)"Alpha magic settings structure 2"); if( alphaSettings == M4OSA_NULL ) { M4OSA_TRACE1_0( "Allocation error in M4xVSS_SendCommand"); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_ALLOC; } alphaSettings->pPlane = outputPlane; if( xVSS_context->pSettings->pTransitionList[i]->xVSS. transitionSpecific.pAlphaMagicSettings-> blendingPercent > 0 && xVSS_context->pSettings-> pTransitionList[i]->xVSS. transitionSpecific.pAlphaMagicSettings-> blendingPercent <= 100 ) { alphaSettings->blendingthreshold = ( xVSS_context->pSettings-> pTransitionList[i]->xVSS. transitionSpecific.pAlphaMagicSettings-> blendingPercent) * 255 / 200; } else { alphaSettings->blendingthreshold = 0; } alphaSettings->isreverse = xVSS_context->pSettings->pTransitionList[i]->xVSS. transitionSpecific.pAlphaMagicSettings-> isreverse; if( alphaSettings->blendingthreshold == 0 ) { xVSS_context->pSettings->pTransitionList[i]-> ExtVideoTransitionFct = M4xVSS_AlphaMagic; } else { xVSS_context->pSettings->pTransitionList[i]-> ExtVideoTransitionFct = M4xVSS_AlphaMagicBlending; } xVSS_context->pSettings->pTransitionList[i]-> pExtVideoTransitionFctCtxt = alphaSettings; } break; case M4xVSS_kVideoTransitionType_SlideTransition: { M4xVSS_internal_SlideTransitionSettings *slideSettings; slideSettings = (M4xVSS_internal_SlideTransitionSettings *)M4OSA_32bitAlignedMalloc( sizeof(M4xVSS_internal_SlideTransitionSettings), M4VS, (M4OSA_Char *)"Internal slide transition settings"); if( M4OSA_NULL == slideSettings ) { M4OSA_TRACE1_0( "Allocation error in M4xVSS_SendCommand"); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_ALLOC; } /* Just copy the lone parameter from the input settings to the internal context. */ slideSettings->direction = pSettings->pTransitionList[i]->xVSS.transitionSpecific. pSlideTransitionSettings->direction; /* No need to keep our copy of the settings. */ xVSS_context->pSettings->pTransitionList[i]-> xVSS.transitionSpecific.pSlideTransitionSettings = M4OSA_NULL; xVSS_context->pSettings->pTransitionList[i]-> ExtVideoTransitionFct = &M4xVSS_SlideTransition; xVSS_context->pSettings->pTransitionList[i]-> pExtVideoTransitionFctCtxt = slideSettings; } break; case M4xVSS_kVideoTransitionType_FadeBlack: { xVSS_context->pSettings->pTransitionList[i]-> ExtVideoTransitionFct = &M4xVSS_FadeBlackTransition; } break; case M4xVSS_kVideoTransitionType_External: { xVSS_context->pSettings->pTransitionList[i]-> ExtVideoTransitionFct = pSettings->pTransitionList[i]->ExtVideoTransitionFct; xVSS_context->pSettings->pTransitionList[i]-> pExtVideoTransitionFctCtxt = pSettings->pTransitionList[i]-> pExtVideoTransitionFctCtxt; xVSS_context->pSettings->pTransitionList[i]-> VideoTransitionType = M4VSS3GPP_kVideoTransitionType_External; } break; default: break; } // switch /* Update total_duration with transition duration */ totalDuration -= xVSS_context->pSettings-> pTransitionList[i]->uiTransitionDuration; } if( xVSS_context->pSettings->pClipList[i]->FileType == M4VIDEOEDITING_kFileType_ARGB8888 ) { if(M4OSA_TRUE == xVSS_context->pSettings->pClipList[i]->xVSS.isPanZoom) { M4OSA_Char out_img[M4XVSS_MAX_PATH_LEN]; M4OSA_Char out_img_tmp[M4XVSS_MAX_PATH_LEN]; M4xVSS_Pto3GPP_params *pParams = M4OSA_NULL; M4OSA_Context pARGBFileIn; /*UTF conversion support*/ M4OSA_Void *pDecodedPath = pSettings->pClipList[i]->pFile; /* Parse Pto3GPP params chained list to know if input file has already been converted */ if( xVSS_context->pPTo3GPPparamsList != M4OSA_NULL ) { M4OSA_UInt32 pCmpResult = 0; pParams = xVSS_context->pPTo3GPPparamsList; /* We parse all Pto3gpp Param chained list */ while( pParams != M4OSA_NULL ) { pCmpResult = strcmp((const char *)pSettings->pClipList[i]->pFile, (const char *)pParams->pFileIn); if( pCmpResult == 0 && (pSettings->pClipList[i]->uiEndCutTime == pParams->duration || pSettings->pClipList[i]->xVSS.uiDuration == pParams->duration) && pSettings->pClipList[i]->xVSS.MediaRendering == pParams->MediaRendering ) { /* Replace JPG filename with existing 3GP filename */ goto replaceARGB_3GP; } /* We need to update this variable, in case some pictures have been added between two */ /* calls to M4xVSS_sendCommand */ pPto3GPP_last = pParams; pParams = pParams->pNext; } } /* Construct output temporary 3GP filename */ err = M4OSA_chrSPrintf(out_img, M4XVSS_MAX_PATH_LEN - 1, (M4OSA_Char *)"%simg%d.3gp", xVSS_context->pTempPath, xVSS_context->tempFileIndex); if( err != M4NO_ERROR ) { M4OSA_TRACE1_1("Error in M4OSA_chrSPrintf: 0x%x", err); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return err; } #ifdef M4xVSS_RESERVED_MOOV_DISK_SPACE err = M4OSA_chrSPrintf(out_img_tmp, M4XVSS_MAX_PATH_LEN - 1, "%simg%d.tmp", xVSS_context->pTempPath, xVSS_context->tempFileIndex); if( err != M4NO_ERROR ) { M4OSA_TRACE1_1("Error in M4OSA_chrSPrintf: 0x%x", err); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return err; } #endif /*M4xVSS_RESERVED_MOOV_DISK_SPACE*/ xVSS_context->tempFileIndex++; /* Allocate last element Pto3GPP params structure */ pParams = (M4xVSS_Pto3GPP_params *)M4OSA_32bitAlignedMalloc(sizeof(M4xVSS_Pto3GPP_params), M4VS, (M4OSA_Char *)"Element of Pto3GPP Params"); if( pParams == M4OSA_NULL ) { M4OSA_TRACE1_0( "M4xVSS_sendCommand: Problem when allocating one element Pto3GPP Params"); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_ALLOC; } /* Initializes pfilexxx members of pParams to be able to free them correctly */ pParams->pFileIn = M4OSA_NULL; pParams->pFileOut = M4OSA_NULL; pParams->pFileTemp = M4OSA_NULL; pParams->pNext = M4OSA_NULL; pParams->MediaRendering = M4xVSS_kResizing; /*To support ARGB8888 :get the width and height */ pParams->height = pSettings->pClipList[ i]->ClipProperties.uiStillPicHeight; //ARGB_Height; pParams->width = pSettings->pClipList[ i]->ClipProperties.uiStillPicWidth; //ARGB_Width; M4OSA_TRACE3_1("CLIP M4xVSS_SendCommand ARGB8888 H = %d", pParams->height); M4OSA_TRACE3_1("CLIP M4xVSS_SendCommand ARGB8888 W = %d", pParams->width); if( xVSS_context->pPTo3GPPparamsList == M4OSA_NULL ) /* Means it is the first element of the list */ { /* Initialize the xVSS context with the first element of the list */ xVSS_context->pPTo3GPPparamsList = pParams; /* Save this element in case of other file to convert */ pPto3GPP_last = pParams; } else { /* Update next pointer of the previous last element of the chain */ pPto3GPP_last->pNext = pParams; /* Update save of last element of the chain */ pPto3GPP_last = pParams; } /* Fill the last M4xVSS_Pto3GPP_params element */ pParams->duration = xVSS_context->pSettings->pClipList[i]->uiEndCutTime; /* If duration is filled, let's use it instead of EndCutTime */ if( xVSS_context->pSettings->pClipList[i]->xVSS.uiDuration != 0 ) { pParams->duration = xVSS_context->pSettings->pClipList[i]->xVSS.uiDuration; } pParams->InputFileType = M4VIDEOEDITING_kFileType_ARGB8888; /** * UTF conversion: convert into the customer format, before being used*/ pDecodedPath = xVSS_context->pSettings->pClipList[i]->pFile; length = strlen(pDecodedPath); /** * UTF conversion: convert into the customer format, before being used*/ if( xVSS_context->UTFConversionContext.pConvFromUTF8Fct != M4OSA_NULL && xVSS_context-> UTFConversionContext.pTempOutConversionBuffer != M4OSA_NULL ) { err = M4xVSS_internalConvertFromUTF8(xVSS_context, (M4OSA_Void *)xVSS_context->pSettings->pClipList[i]->pFile, (M4OSA_Void *)xVSS_context-> UTFConversionContext.pTempOutConversionBuffer, &length); if( err != M4NO_ERROR ) { M4OSA_TRACE1_1( "M4xVSS_SendCommand: pConvFromUTF8Fct returns err: 0x%x", err); /* Free Send command */ M4xVSS_freeCommand(xVSS_context); return err; } pDecodedPath = xVSS_context->UTFConversionContext.pTempOutConversionBuffer; } /** * End of the UTF conversion, use the converted file path*/ pParams->pFileIn = (M4OSA_Void *)M4OSA_32bitAlignedMalloc(length + 1, M4VS, (M4OSA_Char *)"Pto3GPP Params: file in"); if( pParams->pFileIn == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SendCommand"); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_ALLOC; } memcpy((void *)pParams->pFileIn, (void *)pDecodedPath, (length + 1)); /* Copy input file path */ /* Check that JPG file is present on the FS (P4ME00002974) by just opening and closing it */ err = xVSS_context->pFileReadPtr->openRead(&pARGBFileIn, pDecodedPath, M4OSA_kFileRead); if( err != M4NO_ERROR ) { M4OSA_TRACE1_2("Can't open input jpg file %s, error: 0x%x\n", pDecodedPath, err); /* Free Send command */ M4xVSS_freeCommand(xVSS_context); return err; } err = xVSS_context->pFileReadPtr->closeRead(pARGBFileIn); if( err != M4NO_ERROR ) { M4OSA_TRACE1_2("Can't close input jpg file %s, error: 0x%x\n", pDecodedPath, err); /* Free Send command */ M4xVSS_freeCommand(xVSS_context); return err; } /** * UTF conversion: convert into the customer format, before being used*/ pDecodedPath = out_img; length = strlen(pDecodedPath); if( xVSS_context->UTFConversionContext.pConvFromUTF8Fct != M4OSA_NULL && xVSS_context-> UTFConversionContext.pTempOutConversionBuffer != M4OSA_NULL ) { err = M4xVSS_internalConvertFromUTF8(xVSS_context, (M4OSA_Void *)out_img, (M4OSA_Void *)xVSS_context-> UTFConversionContext.pTempOutConversionBuffer, &length); if( err != M4NO_ERROR ) { M4OSA_TRACE1_1( "M4xVSS_SendCommand: pConvFromUTF8Fct returns err: 0x%x", err); /* Free Send command */ M4xVSS_freeCommand(xVSS_context); return err; } pDecodedPath = xVSS_context->UTFConversionContext.pTempOutConversionBuffer; } /** * End of the UTF conversion, use the converted file path*/ pParams->pFileOut = (M4OSA_Void *)M4OSA_32bitAlignedMalloc((length + 1), M4VS, (M4OSA_Char *)"Pto3GPP Params: file out"); if( pParams->pFileOut == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SendCommand"); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_ALLOC; } memcpy((void *)pParams->pFileOut, (void *)pDecodedPath, (length + 1)); /* Copy output file path */ #ifdef M4xVSS_RESERVED_MOOV_DISK_SPACE /** * UTF conversion: convert into the customer format, before being used*/ pDecodedPath = out_img_tmp; length = strlen(pDecodedPath); if( xVSS_context->UTFConversionContext.pConvFromUTF8Fct != M4OSA_NULL && xVSS_context-> UTFConversionContext.pTempOutConversionBuffer != M4OSA_NULL ) { err = M4xVSS_internalConvertFromUTF8(xVSS_context, (M4OSA_Void *)out_img_tmp, (M4OSA_Void *)xVSS_context-> UTFConversionContext.pTempOutConversionBuffer, &length); if( err != M4NO_ERROR ) { M4OSA_TRACE1_1("M4xVSS_SendCommand: M4xVSS_internalConvertFromUTF8\ returns err: 0x%x", err); /* Free Send command */ M4xVSS_freeCommand(xVSS_context); return err; } pDecodedPath = xVSS_context->UTFConversionContext.pTempOutConversionBuffer; } /** * End of the UTF conversion, use the converted file path*/ pParams->pFileTemp = (M4OSA_Void *)M4OSA_32bitAlignedMalloc((length + 1), M4VS, (M4OSA_Char *)"Pto3GPP Params: file temp"); if( pParams->pFileTemp == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SendCommand"); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_ALLOC; } memcpy((void *)pParams->pFileTemp, (void *)pDecodedPath, (length + 1)); /* Copy temporary file path */ #endif /*M4xVSS_RESERVED_MOOV_DISK_SPACE*/ /* Fill PanAndZoom settings if needed */ if( M4OSA_TRUE == xVSS_context->pSettings->pClipList[i]->xVSS.isPanZoom ) { pParams->isPanZoom = xVSS_context->pSettings->pClipList[i]->xVSS.isPanZoom; /* Check that Pan & Zoom parameters are corrects */ if( xVSS_context->pSettings->pClipList[i]->xVSS.PanZoomXa > 1000 || xVSS_context->pSettings->pClipList[i]->xVSS.PanZoomXa <= 0 || xVSS_context->pSettings->pClipList[i]->xVSS. PanZoomTopleftXa > 1000 || xVSS_context->pSettings->pClipList[i]->xVSS. PanZoomTopleftYa > 1000 || xVSS_context->pSettings->pClipList[i]->xVSS.PanZoomXb > 1000 || xVSS_context->pSettings->pClipList[i]->xVSS.PanZoomXb <= 0 || xVSS_context->pSettings->pClipList[i]->xVSS. PanZoomTopleftXb > 1000 || xVSS_context->pSettings->pClipList[i]->xVSS. PanZoomTopleftYb > 1000) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SendCommand"); M4xVSS_freeCommand(xVSS_context); return M4ERR_PARAMETER; } pParams->PanZoomXa = xVSS_context->pSettings->pClipList[i]->xVSS.PanZoomXa; pParams->PanZoomTopleftXa = xVSS_context->pSettings-> pClipList[i]->xVSS.PanZoomTopleftXa; pParams->PanZoomTopleftYa = xVSS_context->pSettings-> pClipList[i]->xVSS.PanZoomTopleftYa; pParams->PanZoomXb = xVSS_context->pSettings->pClipList[i]->xVSS.PanZoomXb; pParams->PanZoomTopleftXb = xVSS_context->pSettings-> pClipList[i]->xVSS.PanZoomTopleftXb; pParams->PanZoomTopleftYb = xVSS_context->pSettings-> pClipList[i]->xVSS.PanZoomTopleftYb; } else { pParams->isPanZoom = M4OSA_FALSE; } /*+ PR No: blrnxpsw#223*/ /*Intializing the Video Frame Rate as it may not be intialized*/ /*Other changes made is @ M4xVSS_Internal.c @ line 1518 in M4xVSS_internalStartConvertPictureTo3gp*/ switch( xVSS_context->pSettings->videoFrameRate ) { case M4VIDEOEDITING_k30_FPS: pParams->framerate = 33; break; case M4VIDEOEDITING_k25_FPS: pParams->framerate = 40; break; case M4VIDEOEDITING_k20_FPS: pParams->framerate = 50; break; case M4VIDEOEDITING_k15_FPS: pParams->framerate = 66; break; case M4VIDEOEDITING_k12_5_FPS: pParams->framerate = 80; break; case M4VIDEOEDITING_k10_FPS: pParams->framerate = 100; break; case M4VIDEOEDITING_k7_5_FPS: pParams->framerate = 133; break; case M4VIDEOEDITING_k5_FPS: pParams->framerate = 200; break; default: /*Making Default Frame Rate @ 15 FPS*/ pParams->framerate = 66; break; } /*-PR No: blrnxpsw#223*/ if( xVSS_context->pSettings->pClipList[i]->xVSS.MediaRendering == M4xVSS_kCropping || xVSS_context->pSettings->pClipList[i]->xVSS. MediaRendering == M4xVSS_kBlackBorders || xVSS_context->pSettings->pClipList[i]->xVSS. MediaRendering == M4xVSS_kResizing ) { pParams->MediaRendering = xVSS_context->pSettings->pClipList[i]->xVSS.MediaRendering; } pParams->pNext = M4OSA_NULL; pParams->isCreated = M4OSA_FALSE; xVSS_context->nbStepTotal++; /* Set bTranscodingRequired to TRUE to indicate the kenburn video has * been generated in analysis phase, and does not need to be tanscoded again * in saving phase */ xVSS_context->pSettings->pClipList[i]->bTranscodingRequired = M4OSA_TRUE; replaceARGB_3GP: /* Update total duration */ totalDuration += pParams->duration; /* Replacing in VSS structure the JPG file by the 3gp file */ xVSS_context->pSettings->pClipList[i]->FileType = M4VIDEOEDITING_kFileType_3GPP; if( xVSS_context->pSettings->pClipList[i]->pFile != M4OSA_NULL ) { free(xVSS_context->pSettings->pClipList[i]->pFile); xVSS_context->pSettings->pClipList[i]->pFile = M4OSA_NULL; } /** * UTF conversion: convert into UTF8, before being used*/ pDecodedPath = pParams->pFileOut; if( xVSS_context->UTFConversionContext.pConvToUTF8Fct != M4OSA_NULL && xVSS_context->UTFConversionContext.pTempOutConversionBuffer != M4OSA_NULL ) { err = M4xVSS_internalConvertToUTF8(xVSS_context, (M4OSA_Void *)pParams->pFileOut, (M4OSA_Void *)xVSS_context-> UTFConversionContext.pTempOutConversionBuffer, &length); if( err != M4NO_ERROR ) { M4OSA_TRACE1_1( "M4xVSS_SendCommand: M4xVSS_internalConvertToUTF8 returns err: \ 0x%x",err); /* Free Send command */ M4xVSS_freeCommand(xVSS_context); return err; } pDecodedPath = xVSS_context->UTFConversionContext.pTempOutConversionBuffer; } else { length = strlen(pDecodedPath); } /** * End of the UTF conversion, use the converted file path*/ xVSS_context->pSettings->pClipList[i]->pFile = M4OSA_32bitAlignedMalloc((length + 1), M4VS, (M4OSA_Char *)"xVSS file path of ARGB to 3gp"); if( xVSS_context->pSettings->pClipList[i]->pFile == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SendCommand"); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_ALLOC; } memcpy((void *)xVSS_context->pSettings->pClipList[i]->pFile, (void *)pDecodedPath, (length + 1)); /*FB: add file path size because of UTF16 conversion*/ xVSS_context->pSettings->pClipList[i]->filePathSize = length+1; } } /************************ 3GP input file type case *************************/ else if( xVSS_context->pSettings->pClipList[i]->FileType == M4VIDEOEDITING_kFileType_3GPP || xVSS_context->pSettings->pClipList[i]->FileType == M4VIDEOEDITING_kFileType_MP4 || xVSS_context->pSettings->pClipList[i]->FileType == M4VIDEOEDITING_kFileType_M4V ) { /*UTF conversion support*/ M4OSA_Void *pDecodedPath = M4OSA_NULL; /* Need to call MCS in case 3GP video/audio types are not compatible (H263/MPEG4 or AMRNB/AAC) */ /* => Need to fill MCS_Params structure with the right parameters ! */ /* Need also to parse MCS params struct to check if file has already been transcoded */ M4VIDEOEDITING_ClipProperties fileProperties; M4xVSS_MCS_params *pParams; M4OSA_Bool audioIsDifferent = M4OSA_FALSE; M4OSA_Bool videoIsDifferent = M4OSA_FALSE; M4OSA_Bool bAudioMono; /* Initialize file properties structure */ memset((void *) &fileProperties,0, sizeof(M4VIDEOEDITING_ClipProperties)); //fileProperties.AudioStreamType = M4VIDEOEDITING_kNoneAudio; /* Prevent from bad initializing of percentage cut time */ if( xVSS_context->pSettings->pClipList[i]->xVSS.uiEndCutPercent > 100 || xVSS_context->pSettings->pClipList[i]->xVSS. uiBeginCutPercent > 100 ) { /* These percentage cut time have probably not been initialized */ /* Let's not use them by setting them to 0 */ xVSS_context->pSettings->pClipList[i]->xVSS.uiEndCutPercent = 0; xVSS_context->pSettings->pClipList[i]->xVSS.uiBeginCutPercent = 0; } /** * UTF conversion: convert into the customer format, before being used*/ pDecodedPath = xVSS_context->pSettings->pClipList[i]->pFile; if( xVSS_context->UTFConversionContext.pConvFromUTF8Fct != M4OSA_NULL && xVSS_context-> UTFConversionContext.pTempOutConversionBuffer != M4OSA_NULL ) { err = M4xVSS_internalConvertFromUTF8(xVSS_context, (M4OSA_Void *)xVSS_context->pSettings->pClipList[i]->pFile, (M4OSA_Void *)xVSS_context-> UTFConversionContext.pTempOutConversionBuffer, &length); if( err != M4NO_ERROR ) { M4OSA_TRACE1_1( "M4xVSS_SendCommand: M4xVSS_internalConvertFromUTF8 returns err: 0x%x", err); /* Free Send command */ M4xVSS_freeCommand(xVSS_context); return err; } pDecodedPath = xVSS_context->UTFConversionContext.pTempOutConversionBuffer; } /** * End of the UTF conversion, use the converted file path*/ err = M4xVSS_internalGetProperties(xVSS_context, pDecodedPath, &fileProperties); if( err != M4NO_ERROR ) { M4xVSS_freeCommand(xVSS_context); M4OSA_TRACE1_1( "M4xVSS_sendCommand: M4xVSS_internalGetProperties returned 0x%x", err); /* TODO: Translate error code of MCS to an xVSS error code */ return err; } /* Parse MCS params chained list to know if input file has already been converted */ if( xVSS_context->pMCSparamsList != M4OSA_NULL ) { M4OSA_UInt32 pCmpResult = 0; pParams = xVSS_context->pMCSparamsList; /* We parse all MCS Param chained list */ while( pParams != M4OSA_NULL ) { /** * UTF conversion: convert into UTF8, before being used*/ pDecodedPath = pParams->pFileIn; if( xVSS_context->UTFConversionContext.pConvToUTF8Fct != M4OSA_NULL && xVSS_context-> UTFConversionContext.pTempOutConversionBuffer != M4OSA_NULL ) { err = M4xVSS_internalConvertToUTF8(xVSS_context, (M4OSA_Void *)pParams->pFileIn, (M4OSA_Void *)xVSS_context-> UTFConversionContext. pTempOutConversionBuffer, &length); if( err != M4NO_ERROR ) { M4OSA_TRACE1_1( "M4xVSS_SendCommand: M4xVSS_internalConvertToUTF8 returns err:\ 0x%x", err); /* Free Send command */ M4xVSS_freeCommand(xVSS_context); return err; } pDecodedPath = xVSS_context-> UTFConversionContext.pTempOutConversionBuffer; } /** * End of the UTF conversion, use the converted file path*/ pCmpResult = strcmp((const char *)pSettings->pClipList[i]->pFile, (const char *)pDecodedPath); /* If input filenames are the same, and if this is not a BGM, we can reuse the transcoded file */ if( pCmpResult == 0 && pParams->isBGM == M4OSA_FALSE && pParams->BeginCutTime == pSettings->pClipList[i]->uiBeginCutTime && (pParams->EndCutTime == pSettings->pClipList[i]->uiEndCutTime || pParams->EndCutTime == pSettings->pClipList[i]->uiBeginCutTime + pSettings->pClipList[i]->xVSS.uiDuration) && pSettings->pClipList[i]->xVSS.MediaRendering == pParams->MediaRendering ) { if( pSettings->xVSS.pBGMtrack != M4OSA_NULL ) { if( pSettings->xVSS.pBGMtrack->uiAddVolume == 100 || (pParams->OutputAudioFormat == M4VIDEOEDITING_kNullAudio && fileProperties.AudioStreamType == pSettings->xVSS.outputAudioFormat) || pParams->OutputAudioFormat == pSettings->xVSS.outputAudioFormat || fileProperties.AudioStreamType == M4VIDEOEDITING_kNoneAudio ) { /* Replace 3GP filename with transcoded 3GP filename */ goto replace3GP_3GP; } } else if( ( pParams->OutputAudioFormat == M4VIDEOEDITING_kNullAudio && fileProperties.AudioStreamType == pSettings->xVSS.outputAudioFormat) || pParams->OutputAudioFormat == pSettings->xVSS.outputAudioFormat || fileProperties.AudioStreamType == M4VIDEOEDITING_kNoneAudio ) { /* Replace 3GP filename with transcoded 3GP filename */ goto replace3GP_3GP; } } /* We need to update this variable, in case some 3GP files have been added between two */ /* calls to M4xVSS_sendCommand */ pMCS_last = pParams; pParams = pParams->pNext; } } /* If we have percentage information let's use it... */ if( xVSS_context->pSettings->pClipList[i]->xVSS.uiEndCutPercent != 0 || xVSS_context->pSettings->pClipList[i]->xVSS.uiBeginCutPercent != 0 ) { /* If percentage information are not correct and if duration field is not filled */ if( ( xVSS_context->pSettings->pClipList[i]->xVSS. uiEndCutPercent <= xVSS_context->pSettings->pClipList[i]->xVSS. uiBeginCutPercent) && xVSS_context->pSettings->pClipList[i]->xVSS.uiDuration == 0 ) { M4OSA_TRACE1_0( "M4xVSS_sendCommand: Bad percentage for begin and end cut time !"); M4xVSS_freeCommand(xVSS_context); return M4ERR_PARAMETER; } /* We transform the percentage into absolute time */ xVSS_context->pSettings->pClipList[i]->uiBeginCutTime = (M4OSA_UInt32)( xVSS_context->pSettings->pClipList[i]->xVSS. uiBeginCutPercent * fileProperties.uiClipDuration / 100); xVSS_context->pSettings->pClipList[i]->uiEndCutTime = (M4OSA_UInt32)( xVSS_context->pSettings->pClipList[i]->xVSS. uiEndCutPercent * fileProperties.uiClipDuration / 100); } /* ...Otherwise, we use absolute time. */ else { /* If endCutTime == 0, it means all the file is taken. Let's change to the file duration, to accurate preview. */ if( xVSS_context->pSettings->pClipList[i]->uiEndCutTime == 0 || xVSS_context->pSettings->pClipList[i]->uiEndCutTime > fileProperties.uiClipDuration ) { xVSS_context->pSettings->pClipList[i]->uiEndCutTime = fileProperties.uiClipDuration; } } /* If duration field is filled, it has priority on other fields on EndCutTime, so let's use it */ if( xVSS_context->pSettings->pClipList[i]->xVSS.uiDuration != 0 ) { xVSS_context->pSettings->pClipList[i]->uiEndCutTime = xVSS_context->pSettings->pClipList[i]->uiBeginCutTime +xVSS_context->pSettings->pClipList[i]->xVSS.uiDuration; if( xVSS_context->pSettings->pClipList[i]->uiEndCutTime > fileProperties.uiClipDuration ) { xVSS_context->pSettings->pClipList[i]->uiEndCutTime = fileProperties.uiClipDuration; } } /* If output video format is not set, we take video format of the first 3GP video */ if( xVSS_context->pSettings->xVSS.outputVideoFormat == M4VIDEOEDITING_kNoneVideo ) { //xVSS_context->pSettings->xVSS.outputVideoFormat = fileProperties.VideoStreamType; //M4OSA_TRACE2_1("Output video format is not set, set it to current clip: %d", // xVSS_context->pSettings->xVSS.outputVideoFormat); M4OSA_TRACE1_0( "Output video format is not set, an error parameter is returned."); M4xVSS_freeCommand(xVSS_context); return M4ERR_PARAMETER; } if( xVSS_context->pSettings->xVSS.outputAudioFormat == M4VIDEOEDITING_kNoneAudio ) { //xVSS_context->pSettings->xVSS.outputAudioFormat = fileProperties.AudioStreamType; M4OSA_TRACE2_1( "Output audio format is not set -> remove audio track of clip: %d", i); } if( fileProperties.uiNbChannels == 1 ) { bAudioMono = M4OSA_TRUE; } else { bAudioMono = M4OSA_FALSE; } if( fileProperties.AudioStreamType != xVSS_context->pSettings->xVSS.outputAudioFormat || (fileProperties.AudioStreamType == M4VIDEOEDITING_kAAC && (fileProperties.uiSamplingFrequency != samplingFreq || bAudioMono != xVSS_context->pSettings->xVSS.bAudioMono)) ) { audioIsDifferent = M4OSA_TRUE; /* If we want to replace audio, there is no need to transcode audio */ if( pSettings->xVSS.pBGMtrack != M4OSA_NULL ) { /* temp fix :PT volume not herad in the second clip */ if( /*(pSettings->xVSS.pBGMtrack->uiAddVolume == 100 && xVSS_context->pSettings->xVSS.outputFileSize == 0) ||*/ fileProperties.AudioStreamType == M4VIDEOEDITING_kNoneAudio ) /*11/12/2008 CR 3283 VAL for the MMS use case, we need to transcode except the media without audio*/ { audioIsDifferent = M4OSA_FALSE; } } else if( fileProperties.AudioStreamType == M4VIDEOEDITING_kNoneAudio ) { audioIsDifferent = M4OSA_FALSE; } } /* Here check the clip video profile and level, if it exceeds * the profile and level of export file, then the file needs * to be transcoded(do not do compress domain trim). * Also for MPEG4 fomart, always do transcoding since HW encoder * may use different time scale value than the input clip*/ if ((fileProperties.uiVideoProfile > xVSS_context->pSettings->xVSS.outputVideoProfile) || (fileProperties.uiVideoLevel > xVSS_context->pSettings->xVSS.outputVideoLevel) || (fileProperties.VideoStreamType == M4VIDEOEDITING_kMPEG4)) { /* Set bTranscodingRequired to TRUE to indicate the video will be * transcoded in MCS. */ xVSS_context->pSettings->pClipList[i]->bTranscodingRequired = M4OSA_TRUE; videoIsDifferent = M4OSA_TRUE; } if( videoIsDifferent == M4OSA_TRUE || audioIsDifferent == M4OSA_TRUE) { M4OSA_Char out_3gp[M4XVSS_MAX_PATH_LEN]; M4OSA_Char out_3gp_tmp[M4XVSS_MAX_PATH_LEN]; /* Construct output temporary 3GP filename */ err = M4OSA_chrSPrintf(out_3gp, M4XVSS_MAX_PATH_LEN - 1, (M4OSA_Char *)"%svid%d.3gp", xVSS_context->pTempPath, xVSS_context->tempFileIndex); if( err != M4NO_ERROR ) { M4OSA_TRACE1_1("Error in M4OSA_chrSPrintf: 0x%x", err); return err; } #ifdef M4xVSS_RESERVED_MOOV_DISK_SPACE err = M4OSA_chrSPrintf(out_3gp_tmp, M4XVSS_MAX_PATH_LEN - 1, "%svid%d.tmp", xVSS_context->pTempPath, xVSS_context->tempFileIndex); if( err != M4NO_ERROR ) { M4OSA_TRACE1_1("Error in M4OSA_chrSPrintf: 0x%x", err); return err; } #endif /*M4xVSS_RESERVED_MOOV_DISK_SPACE*/ xVSS_context->tempFileIndex++; pParams = (M4xVSS_MCS_params *)M4OSA_32bitAlignedMalloc(sizeof(M4xVSS_MCS_params), M4VS, (M4OSA_Char *)"Element of MCS Params (for 3GP)"); if( pParams == M4OSA_NULL ) { M4OSA_TRACE1_0( "M4xVSS_sendCommand: Problem when allocating one element MCS Params"); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_ALLOC; } pParams->MediaRendering = M4xVSS_kResizing; pParams->videoclipnumber = i; // Indicates video clip index if( xVSS_context->pMCSparamsList == M4OSA_NULL ) /* Means it is the first element of the list */ { /* Initialize the xVSS context with the first element of the list */ xVSS_context->pMCSparamsList = pParams; } else { /* Update next pointer of the previous last element of the chain */ pMCS_last->pNext = pParams; } /* Save this element in case of other file to convert */ pMCS_last = pParams; /* Fill the last M4xVSS_MCS_params element */ pParams->InputFileType = M4VIDEOEDITING_kFileType_3GPP; pParams->OutputFileType = M4VIDEOEDITING_kFileType_3GPP; pParams->OutputVideoTimescale = xVSS_context->targetedTimescale; /* We do not need to reencode video if its parameters do not differ */ /* from output settings parameters */ if( videoIsDifferent == M4OSA_TRUE ) { pParams->OutputVideoFormat = xVSS_context->pSettings->xVSS.outputVideoFormat; pParams->outputVideoProfile = xVSS_context->pSettings->xVSS.outputVideoProfile; pParams->outputVideoLevel = xVSS_context->pSettings->xVSS.outputVideoLevel; pParams->OutputVideoFrameRate = xVSS_context->pSettings->videoFrameRate; pParams->OutputVideoFrameSize = xVSS_context->pSettings->xVSS.outputVideoSize; /*FB: VAL CR P4ME00003076 The output video bitrate is now directly given by the user in the edition settings structure If the bitrate given by the user is irrelevant (the MCS minimum and maximum video bitrate are used), the output video bitrate is hardcoded according to the output video size*/ if( xVSS_context->pSettings->xVSS.outputVideoBitrate >= M4VIDEOEDITING_k16_KBPS && xVSS_context->pSettings->xVSS.outputVideoBitrate <= M4VIDEOEDITING_k8_MBPS ) /*+ New Encoder bitrates */ { pParams->OutputVideoBitrate = xVSS_context->pSettings->xVSS.outputVideoBitrate; } else { switch( xVSS_context->pSettings->xVSS.outputVideoSize ) { case M4VIDEOEDITING_kSQCIF: pParams->OutputVideoBitrate = M4VIDEOEDITING_k48_KBPS; break; case M4VIDEOEDITING_kQQVGA: pParams->OutputVideoBitrate = M4VIDEOEDITING_k64_KBPS; break; case M4VIDEOEDITING_kQCIF: pParams->OutputVideoBitrate = M4VIDEOEDITING_k128_KBPS; break; case M4VIDEOEDITING_kQVGA: pParams->OutputVideoBitrate = M4VIDEOEDITING_k384_KBPS; break; case M4VIDEOEDITING_kCIF: pParams->OutputVideoBitrate = M4VIDEOEDITING_k384_KBPS; break; case M4VIDEOEDITING_kVGA: pParams->OutputVideoBitrate = M4VIDEOEDITING_k512_KBPS; break; default: /* Should not happen !! */ pParams->OutputVideoBitrate = M4VIDEOEDITING_k64_KBPS; break; } } } else { pParams->outputVideoProfile = xVSS_context->pSettings->xVSS.outputVideoProfile; pParams->outputVideoLevel = xVSS_context->pSettings->xVSS.outputVideoLevel; pParams->OutputVideoFormat = M4VIDEOEDITING_kNullVideo; pParams->OutputVideoFrameRate = M4VIDEOEDITING_k15_FPS; /* Must be set, otherwise, MCS returns an error */ } if( audioIsDifferent == M4OSA_TRUE ) { pParams->OutputAudioFormat = xVSS_context->pSettings->xVSS.outputAudioFormat; switch( xVSS_context->pSettings->xVSS.outputAudioFormat ) { case M4VIDEOEDITING_kNoneAudio: break; case M4VIDEOEDITING_kAMR_NB: pParams->OutputAudioBitrate = M4VIDEOEDITING_k12_2_KBPS; pParams->bAudioMono = M4OSA_TRUE; pParams->OutputAudioSamplingFrequency = M4VIDEOEDITING_kDefault_ASF; break; case M4VIDEOEDITING_kAAC: { /*FB: VAL CR P4ME00003076 The output audio bitrate in the AAC case is now directly given by the user in the edition settings structure If the bitrate given by the user is irrelevant or undefined (the MCS minimum and maximum audio bitrate are used), the output audio bitrate is hard coded according to the output audio sampling frequency*/ /*Check if the audio bitrate is correctly defined*/ /*Mono MCS values for AAC Mono are min: 16kbps and max: 192 kbps*/ if( xVSS_context->pSettings->xVSS.outputAudioBitrate >= M4VIDEOEDITING_k16_KBPS && xVSS_context->pSettings-> xVSS.outputAudioBitrate <= M4VIDEOEDITING_k192_KBPS && xVSS_context->pSettings->xVSS.bAudioMono == M4OSA_TRUE ) { pParams->OutputAudioBitrate = xVSS_context->pSettings-> xVSS.outputAudioBitrate; } /*Stereo MCS values for AAC Mono are min: 32kbps and max: 192 kbps*/ else if( xVSS_context->pSettings-> xVSS.outputAudioBitrate >= M4VIDEOEDITING_k32_KBPS && xVSS_context->pSettings-> xVSS.outputAudioBitrate <= M4VIDEOEDITING_k192_KBPS && xVSS_context->pSettings->xVSS.bAudioMono == M4OSA_FALSE ) { pParams->OutputAudioBitrate = xVSS_context->pSettings-> xVSS.outputAudioBitrate; } /*The audio bitrate is hard coded according to the output audio sampling frequency*/ else { switch( xVSS_context->pSettings-> xVSS.outputAudioSamplFreq ) { case M4VIDEOEDITING_k16000_ASF: pParams->OutputAudioBitrate = M4VIDEOEDITING_k24_KBPS; break; case M4VIDEOEDITING_k22050_ASF: case M4VIDEOEDITING_k24000_ASF: pParams->OutputAudioBitrate = M4VIDEOEDITING_k32_KBPS; break; case M4VIDEOEDITING_k32000_ASF: pParams->OutputAudioBitrate = M4VIDEOEDITING_k48_KBPS; break; case M4VIDEOEDITING_k44100_ASF: case M4VIDEOEDITING_k48000_ASF: pParams->OutputAudioBitrate = M4VIDEOEDITING_k64_KBPS; break; default: pParams->OutputAudioBitrate = M4VIDEOEDITING_k64_KBPS; break; } if( xVSS_context->pSettings->xVSS.bAudioMono == M4OSA_FALSE ) { /* Output bitrate have to be doubled */ pParams->OutputAudioBitrate += pParams->OutputAudioBitrate; } } pParams->bAudioMono = xVSS_context->pSettings->xVSS.bAudioMono; if( xVSS_context->pSettings-> xVSS.outputAudioSamplFreq == M4VIDEOEDITING_k8000_ASF ) { /* Prevent from unallowed sampling frequencies */ pParams->OutputAudioSamplingFrequency = M4VIDEOEDITING_kDefault_ASF; } else { pParams->OutputAudioSamplingFrequency = xVSS_context->pSettings-> xVSS.outputAudioSamplFreq; } break; } default: /* Should not happen !! */ pParams->OutputAudioFormat = M4VIDEOEDITING_kAMR_NB; pParams->OutputAudioBitrate = M4VIDEOEDITING_k12_2_KBPS; pParams->bAudioMono = M4OSA_TRUE; pParams->OutputAudioSamplingFrequency = M4VIDEOEDITING_kDefault_ASF; break; } } else { pParams->OutputAudioFormat = M4VIDEOEDITING_kNullAudio; } /** * UTF conversion: convert into the customer format, before being used*/ pDecodedPath = xVSS_context->pSettings->pClipList[i]->pFile; length = strlen(pDecodedPath); if( xVSS_context->UTFConversionContext.pConvFromUTF8Fct != M4OSA_NULL && xVSS_context-> UTFConversionContext.pTempOutConversionBuffer != M4OSA_NULL ) { err = M4xVSS_internalConvertFromUTF8(xVSS_context, (M4OSA_Void *)xVSS_context->pSettings-> pClipList[i]->pFile, (M4OSA_Void *)xVSS_context-> UTFConversionContext.pTempOutConversionBuffer, &length); if( err != M4NO_ERROR ) { M4OSA_TRACE1_1( "M4xVSS_SendCommand: M4xVSS_internalConvertFromUTF8 returns err: 0x%x", err); /* Free Send command */ M4xVSS_freeCommand(xVSS_context); return err; } pDecodedPath = xVSS_context-> UTFConversionContext.pTempOutConversionBuffer; } /** * End of the UTF conversion, use the converted file path*/ pParams->pFileIn = (M4OSA_Void *)M4OSA_32bitAlignedMalloc((length + 1), M4VS, (M4OSA_Char *)"MCS 3GP Params: file in"); if( pParams->pFileIn == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SendCommand"); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_ALLOC; } memcpy((void *)pParams->pFileIn, (void *)pDecodedPath, (length + 1)); /* Copy input file path */ /** * UTF conversion: convert into the customer format, before being used*/ pDecodedPath = out_3gp; length = strlen(pDecodedPath); if( xVSS_context->UTFConversionContext.pConvFromUTF8Fct != M4OSA_NULL && xVSS_context-> UTFConversionContext.pTempOutConversionBuffer != M4OSA_NULL ) { err = M4xVSS_internalConvertFromUTF8(xVSS_context, (M4OSA_Void *)out_3gp, (M4OSA_Void *)xVSS_context-> UTFConversionContext.pTempOutConversionBuffer, &length); if( err != M4NO_ERROR ) { M4OSA_TRACE1_1( "M4xVSS_SendCommand: M4xVSS_internalConvertFromUTF8 returns err: 0x%x", err); /* Free Send command */ M4xVSS_freeCommand(xVSS_context); return err; } pDecodedPath = xVSS_context-> UTFConversionContext.pTempOutConversionBuffer; } /** * End of the UTF conversion, use the converted file path*/ pParams->pFileOut = (M4OSA_Void *)M4OSA_32bitAlignedMalloc((length + 1), M4VS, (M4OSA_Char *)"MCS 3GP Params: file out"); if( pParams->pFileOut == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SendCommand"); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_ALLOC; } memcpy((void *)pParams->pFileOut, (void *)pDecodedPath, (length + 1)); /* Copy output file path */ #ifdef M4xVSS_RESERVED_MOOV_DISK_SPACE /** * UTF conversion: convert into the customer format, before being used*/ pDecodedPath = out_3gp_tmp; length = strlen(pDecodedPath); if( xVSS_context->UTFConversionContext.pConvFromUTF8Fct != M4OSA_NULL && xVSS_context-> UTFConversionContext.pTempOutConversionBuffer != M4OSA_NULL ) { err = M4xVSS_internalConvertFromUTF8(xVSS_context, (M4OSA_Void *)out_3gp_tmp, (M4OSA_Void *)xVSS_context-> UTFConversionContext.pTempOutConversionBuffer, &length); if( err != M4NO_ERROR ) { M4OSA_TRACE1_1( "M4xVSS_SendCommand: M4xVSS_internalConvertFromUTF8 returns err: 0x%x", err); /* Free Send command */ M4xVSS_freeCommand(xVSS_context); return err; } pDecodedPath = xVSS_context-> UTFConversionContext.pTempOutConversionBuffer; } /** * End of the UTF conversion, use the converted file path*/ pParams->pFileTemp = (M4OSA_Void *)M4OSA_32bitAlignedMalloc((length + 1), M4VS, (M4OSA_Char *)"MCS 3GP Params: file temp"); if( pParams->pFileTemp == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SendCommand"); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_ALLOC; } memcpy((void *)pParams->pFileTemp, (void *)pDecodedPath, (length + 1)); /* Copy temporary file path */ #else pParams->pFileTemp = M4OSA_NULL; #endif /*M4xVSS_RESERVED_MOOV_DISK_SPACE*/ /*FB 2008/10/20 keep media aspect ratio, add media rendering parameter*/ if( xVSS_context->pSettings->pClipList[i]->xVSS.MediaRendering == M4xVSS_kCropping || xVSS_context->pSettings->pClipList[i]->xVSS. MediaRendering == M4xVSS_kBlackBorders || xVSS_context->pSettings->pClipList[i]->xVSS. MediaRendering == M4xVSS_kResizing ) { pParams->MediaRendering = xVSS_context->pSettings->pClipList[i]->xVSS. MediaRendering; } /*FB: transcoding per parts*/ pParams->BeginCutTime = xVSS_context->pSettings->pClipList[i]->uiBeginCutTime; pParams->EndCutTime = xVSS_context->pSettings->pClipList[i]->uiEndCutTime; pParams->pNext = M4OSA_NULL; pParams->isBGM = M4OSA_FALSE; pParams->isCreated = M4OSA_FALSE; xVSS_context->nbStepTotal++; bIsTranscoding = M4OSA_TRUE; replace3GP_3GP: /* Update total duration */ totalDuration += xVSS_context->pSettings->pClipList[i]->uiEndCutTime - xVSS_context->pSettings->pClipList[i]->uiBeginCutTime; /* Replacing in VSS structure the original 3GP file by the transcoded 3GP file */ xVSS_context->pSettings->pClipList[i]->FileType = M4VIDEOEDITING_kFileType_3GPP; if( xVSS_context->pSettings->pClipList[i]->pFile != M4OSA_NULL ) { free(xVSS_context->pSettings->pClipList[i]->pFile); xVSS_context->pSettings->pClipList[i]->pFile = M4OSA_NULL; } /** * UTF conversion: convert into the customer format, before being used*/ pDecodedPath = pParams->pFileOut; if( xVSS_context->UTFConversionContext.pConvToUTF8Fct != M4OSA_NULL && xVSS_context-> UTFConversionContext.pTempOutConversionBuffer != M4OSA_NULL ) { err = M4xVSS_internalConvertToUTF8(xVSS_context, (M4OSA_Void *)pParams->pFileOut, (M4OSA_Void *)xVSS_context-> UTFConversionContext.pTempOutConversionBuffer, &length); if( err != M4NO_ERROR ) { M4OSA_TRACE1_1( "M4xVSS_SendCommand: M4xVSS_internalConvertToUTF8 returns err: 0x%x", err); /* Free Send command */ M4xVSS_freeCommand(xVSS_context); return err; } pDecodedPath = xVSS_context-> UTFConversionContext.pTempOutConversionBuffer; } else { length = strlen(pDecodedPath); } /** * End of the UTF conversion, use the converted file path*/ xVSS_context->pSettings->pClipList[i]->pFile = M4OSA_32bitAlignedMalloc( (length + 1), M4VS, (M4OSA_Char *)"xVSS file path of 3gp to 3gp"); if( xVSS_context->pSettings->pClipList[i]->pFile == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SendCommand"); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_ALLOC; } memcpy((void *)xVSS_context->pSettings->pClipList[i]->pFile, (void *)pDecodedPath, (length + 1)); /*FB: add file path size because of UTF 16 conversion*/ xVSS_context->pSettings->pClipList[i]->filePathSize = length+1; /* We define master clip as first 3GP input clip */ /*if(xVSS_context->pSettings->uiMasterClip == 0 && fileProperties. AudioStreamType != M4VIDEOEDITING_kNoneAudio) { xVSS_context->pSettings->uiMasterClip = i; }*/ } else { /* Update total duration */ totalDuration += xVSS_context->pSettings->pClipList[i]->uiEndCutTime - xVSS_context->pSettings->pClipList[i]->uiBeginCutTime; } /* We define master clip as first 3GP input clip */ if( masterClip == -1 && fileProperties.AudioStreamType != M4VIDEOEDITING_kNoneAudio ) { masterClip = i; xVSS_context->pSettings->uiMasterClip = i; } } /************************** Other input file type case ***************************/ else { M4OSA_TRACE1_0("Bad file type as input clip"); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_PARAMETER; } } /********************************************************* * Parse all effects to make some adjustment for framing, * * text and to transform relative time into absolute time * **********************************************************/ for ( j = 0; j < xVSS_context->pSettings->nbEffects; j++ ) { /* Copy effect to "local" structure */ memcpy((void *) &(xVSS_context->pSettings->Effects[j]), (void *) &(pSettings->Effects[j]), sizeof(M4VSS3GPP_EffectSettings)); /* Prevent from bad initializing of effect percentage time */ if( xVSS_context->pSettings->Effects[j].xVSS.uiDurationPercent > 100 || xVSS_context->pSettings->Effects[j].xVSS.uiStartPercent > 100 ) { /* These percentage time have probably not been initialized */ /* Let's not use them by setting them to 0 */ xVSS_context->pSettings->Effects[j].xVSS.uiDurationPercent = 0; xVSS_context->pSettings->Effects[j].xVSS.uiStartPercent = 0; } /* If we have percentage information let's use it... Otherwise, we use absolute time. */ if( xVSS_context->pSettings->Effects[j].xVSS.uiDurationPercent != 0 ) { xVSS_context->pSettings-> Effects[j].uiStartTime = (M4OSA_UInt32)(totalDuration * xVSS_context->pSettings->Effects[j].xVSS.uiStartPercent / 100); /* The percentage of effect duration is based on the duration of the clip - start time */ xVSS_context->pSettings-> Effects[j].uiDuration = (M4OSA_UInt32)(totalDuration * xVSS_context->pSettings->Effects[j].xVSS.uiDurationPercent / 100); } /* If there is a framing effect, we need to allocate framing effect structure */ if( xVSS_context->pSettings->Effects[j].VideoEffectType == M4xVSS_kVideoEffectType_Framing ) { #ifdef DECODE_GIF_ON_SAVING M4xVSS_FramingContext *framingCtx; /*UTF conversion support*/ M4OSA_Void *pDecodedPath = M4OSA_NULL; #else M4xVSS_FramingStruct *framingCtx; #endif /*DECODE_GIF_ON_SAVING*/ M4OSA_Char *pExt2 = M4OSA_NULL; M4VIFI_ImagePlane *pPlane = xVSS_context->pSettings->Effects[j].xVSS.pFramingBuffer; M4OSA_Int32 result1, result2; /* Copy framing file path */ if( pSettings->Effects[j].xVSS.pFramingFilePath != M4OSA_NULL ) { xVSS_context->pSettings-> Effects[j].xVSS.pFramingFilePath = M4OSA_32bitAlignedMalloc( strlen(pSettings->Effects[j].xVSS.pFramingFilePath) + 1, M4VS, (M4OSA_Char *)"Local Framing file path"); if( xVSS_context->pSettings->Effects[j].xVSS.pFramingFilePath == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SendCommand"); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_ALLOC; } memcpy((void *)xVSS_context->pSettings-> Effects[j].xVSS.pFramingFilePath, (void *)pSettings-> Effects[j].xVSS.pFramingFilePath, strlen( pSettings->Effects[j].xVSS.pFramingFilePath) + 1); pExt2 = xVSS_context->pSettings->Effects[j].xVSS.pFramingFilePath; } #ifdef DECODE_GIF_ON_SAVING framingCtx = (M4xVSS_FramingContext *)M4OSA_32bitAlignedMalloc(sizeof(M4xVSS_FramingContext), M4VS, (M4OSA_Char *)"Context of the framing effect"); if( framingCtx == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SendCommand"); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_ALLOC; } framingCtx->aFramingCtx = M4OSA_NULL; framingCtx->aFramingCtx_last = M4OSA_NULL; framingCtx->pSPSContext = M4OSA_NULL; framingCtx->outputVideoSize = xVSS_context->pSettings->xVSS.outputVideoSize; framingCtx->topleft_x = xVSS_context->pSettings->Effects[j].xVSS.topleft_x; framingCtx->topleft_y = xVSS_context->pSettings->Effects[j].xVSS.topleft_y; framingCtx->bEffectResize = xVSS_context->pSettings->Effects[j].xVSS.bResize; framingCtx->pEffectFilePath = xVSS_context->pSettings->Effects[j].xVSS.pFramingFilePath; framingCtx->pFileReadPtr = xVSS_context->pFileReadPtr; framingCtx->pFileWritePtr = xVSS_context->pFileWritePtr; framingCtx->effectDuration = xVSS_context->pSettings->Effects[j].uiDuration; framingCtx->b_IsFileGif = M4OSA_FALSE; framingCtx->alphaBlendingStruct = M4OSA_NULL; framingCtx->b_animated = M4OSA_FALSE; /* Output ratio for the effect is stored in uiFiftiesOutFrameRate parameters of the extended xVSS effects structure */ if( xVSS_context->pSettings->Effects[j].xVSS.uiFiftiesOutFrameRate != 0 ) { framingCtx->frameDurationRatio = (M4OSA_Float)(( xVSS_context->pSettings-> Effects[j].xVSS.uiFiftiesOutFrameRate) / 1000.0); } else { framingCtx->frameDurationRatio = 1.0; } /*Alpha blending*/ /*Check if the alpha blending parameters are corrects*/ if( pSettings->Effects[j].xVSS.uialphaBlendingFadeInTime > 100 ) { pSettings->Effects[j].xVSS.uialphaBlendingFadeInTime = 0; } if( pSettings->Effects[j].xVSS.uialphaBlendingFadeOutTime > 100 ) { pSettings->Effects[j].xVSS.uialphaBlendingFadeOutTime = 0; } if( pSettings->Effects[j].xVSS.uialphaBlendingEnd > 100 ) { pSettings->Effects[j].xVSS.uialphaBlendingEnd = 100; } if( pSettings->Effects[j].xVSS.uialphaBlendingMiddle > 100 ) { pSettings->Effects[j].xVSS.uialphaBlendingMiddle = 100; } if( pSettings->Effects[j].xVSS.uialphaBlendingStart > 100 ) { pSettings->Effects[j].xVSS.uialphaBlendingStart = 100; } if( pSettings->Effects[j].xVSS.uialphaBlendingFadeInTime > 0 || pSettings->Effects[j].xVSS.uialphaBlendingFadeOutTime > 0 ) { /*Allocate the alpha blending structure*/ framingCtx->alphaBlendingStruct = (M4xVSS_internalEffectsAlphaBlending *)M4OSA_32bitAlignedMalloc( sizeof(M4xVSS_internalEffectsAlphaBlending), M4VS, (M4OSA_Char *)"alpha blending structure"); if( framingCtx->alphaBlendingStruct == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SendCommand"); M4xVSS_freeCommand(xVSS_context); return M4ERR_ALLOC; } /*Fill the alpha blending structure*/ framingCtx->alphaBlendingStruct->m_fadeInTime = pSettings->Effects[j].xVSS.uialphaBlendingFadeInTime; framingCtx->alphaBlendingStruct->m_fadeOutTime = pSettings->Effects[j].xVSS.uialphaBlendingFadeOutTime; framingCtx->alphaBlendingStruct->m_end = pSettings->Effects[j].xVSS.uialphaBlendingEnd; framingCtx->alphaBlendingStruct->m_middle = pSettings->Effects[j].xVSS.uialphaBlendingMiddle; framingCtx->alphaBlendingStruct->m_start = pSettings->Effects[j].xVSS.uialphaBlendingStart; if( pSettings->Effects[j].xVSS.uialphaBlendingFadeInTime + pSettings->Effects[j].xVSS.uialphaBlendingFadeOutTime > 100 ) { framingCtx->alphaBlendingStruct->m_fadeOutTime = 100 - framingCtx->alphaBlendingStruct->m_fadeInTime; } } /** * UTF conversion: convert into the customer format, before being used*/ pDecodedPath = xVSS_context->pSettings->Effects[j].xVSS.pFramingFilePath; length = strlen(pDecodedPath); if( xVSS_context->UTFConversionContext.pConvFromUTF8Fct != M4OSA_NULL && xVSS_context-> UTFConversionContext.pTempOutConversionBuffer != M4OSA_NULL ) { err = M4xVSS_internalConvertFromUTF8(xVSS_context, (M4OSA_Void *)xVSS_context->pSettings-> Effects[j].xVSS.pFramingFilePath, (M4OSA_Void *)xVSS_context-> UTFConversionContext.pTempOutConversionBuffer, &length); if( err != M4NO_ERROR ) { M4OSA_TRACE1_1( "M4xVSS_SendCommand: M4xVSS_internalConvertFromUTF8 returns err: 0x%x", err); /* Free Send command */ M4xVSS_freeCommand(xVSS_context); return err; } pDecodedPath = xVSS_context->UTFConversionContext.pTempOutConversionBuffer; } /** * End of the UTF conversion, use the converted file path*/ framingCtx->pEffectFilePath = M4OSA_32bitAlignedMalloc(length + 1, M4VS, (M4OSA_Char *)"Local Framing file path"); if( framingCtx->pEffectFilePath == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SendCommand"); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_ALLOC; } memcpy((void *)framingCtx->pEffectFilePath, (void *)pDecodedPath, length + 1); /* Save framing structure associated with corresponding effect */ xVSS_context->pSettings->Effects[j].pExtVideoEffectFctCtxt = framingCtx; #else framingCtx = (M4xVSS_FramingStruct *)M4OSA_32bitAlignedMalloc(sizeof(M4xVSS_FramingStruct), M4VS, (M4OSA_Char *)"Context of the framing effect"); if( framingCtx == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SendCommand"); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_ALLOC; } framingCtx->topleft_x = xVSS_context->pSettings->Effects[j].xVSS.topleft_x; framingCtx->topleft_y = xVSS_context->pSettings->Effects[j].xVSS.topleft_y; /* BugFix 1.2.0: Leak when decoding error */ framingCtx->FramingRgb = M4OSA_NULL; framingCtx->FramingYuv = M4OSA_NULL; framingCtx->pNext = framingCtx; /* Save framing structure associated with corresponding effect */ xVSS_context->pSettings->Effects[j].pExtVideoEffectFctCtxt = framingCtx; #endif /*DECODE_GIF_ON_SAVING*/ if( pExt2 != M4OSA_NULL ) { /* Decode the image associated to the effect, and fill framing structure */ pExt2 += (strlen((const char *)pExt2) - 4); result1 = strcmp((const char *)pExt2,(const char *)".rgb"); result2 = strcmp((const char *)pExt2,(const char *)".RGB"); if( 0 == result1 || 0 == result2 ) { #ifdef DECODE_GIF_ON_SAVING framingCtx->aFramingCtx = (M4xVSS_FramingStruct *)M4OSA_32bitAlignedMalloc(sizeof(M4xVSS_FramingStruct), M4VS, (M4OSA_Char *) "M4xVSS_internalDecodeGIF: Context of the framing effect"); if( framingCtx->aFramingCtx == M4OSA_NULL ) { M4OSA_TRACE1_0( "Allocation error in M4xVSS_SendCommand"); /* TODO: Translate error code of SPS to an xVSS error code */ M4xVSS_freeCommand(xVSS_context); return M4ERR_ALLOC; } framingCtx->aFramingCtx->pCurrent = M4OSA_NULL; /* Only used by the first element of the chain */ framingCtx->aFramingCtx->previousClipTime = -1; framingCtx->aFramingCtx->FramingYuv = M4OSA_NULL; framingCtx->aFramingCtx->FramingRgb = M4OSA_NULL; framingCtx->aFramingCtx->topleft_x = xVSS_context->pSettings->Effects[j].xVSS.topleft_x; framingCtx->aFramingCtx->topleft_y = xVSS_context->pSettings->Effects[j].xVSS.topleft_y; /*To support ARGB8888 : get the width and height */ framingCtx->aFramingCtx->width = xVSS_context->pSettings->Effects[j].xVSS.width; framingCtx->aFramingCtx->height = xVSS_context->pSettings->Effects[j].xVSS.height; M4OSA_TRACE1_1("FRAMMING BEFORE M4xVSS_SendCommand %d", framingCtx->aFramingCtx->width); M4OSA_TRACE1_1("FRAMMING BEFORE M4xVSS_SendCommand %d", framingCtx->aFramingCtx->height); #endif err = M4xVSS_internalConvertARGB888toYUV420_FrammingEffect( xVSS_context, &(xVSS_context->pSettings->Effects[j]), framingCtx->aFramingCtx,xVSS_context->pSettings->xVSS.outputVideoSize); M4OSA_TRACE3_1("FRAMING WIDTH BEFORE M4xVSS_SendCommand %d", framingCtx->aFramingCtx->width); M4OSA_TRACE3_1("FRAMING HEIGHT BEFORE M4xVSS_SendCommand %d", framingCtx->aFramingCtx->height); if( err != M4NO_ERROR ) { M4OSA_TRACE1_1( "M4xVSS_SendCommand: M4xVSS_internalDecodePNG returned 0x%x", err); /* TODO: Translate error code of SPS to an xVSS error code */ M4xVSS_freeCommand(xVSS_context); return err; } } else { M4OSA_TRACE1_1( "M4xVSS_SendCommand: Not supported still picture format 0x%x", err); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_PARAMETER; } } else if( pPlane != M4OSA_NULL ) { #ifdef DECODE_GIF_ON_SAVING framingCtx->aFramingCtx = (M4xVSS_FramingStruct *)M4OSA_32bitAlignedMalloc(sizeof(M4xVSS_FramingStruct), M4VS, (M4OSA_Char *)"Context of the framing effect"); if( framingCtx->aFramingCtx == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SendCommand"); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_ALLOC; } framingCtx->aFramingCtx->topleft_x = xVSS_context->pSettings->Effects[j].xVSS.topleft_x; framingCtx->aFramingCtx->topleft_y = xVSS_context->pSettings->Effects[j].xVSS.topleft_y; /* BugFix 1.2.0: Leak when decoding error */ framingCtx->aFramingCtx->FramingRgb = M4OSA_NULL; framingCtx->aFramingCtx->FramingYuv = M4OSA_NULL; framingCtx->aFramingCtx->pNext = framingCtx->aFramingCtx; framingCtx->aFramingCtx->pCurrent = framingCtx->aFramingCtx; framingCtx->aFramingCtx->duration = 0; framingCtx->aFramingCtx->previousClipTime = -1; framingCtx->aFramingCtx->FramingRgb = xVSS_context->pSettings->Effects[j].xVSS.pFramingBuffer; /* Force input RGB buffer to even size to avoid errors in YUV conversion */ framingCtx->aFramingCtx->FramingRgb->u_width = framingCtx->aFramingCtx->FramingRgb->u_width & ~1; framingCtx->aFramingCtx->FramingRgb->u_height = framingCtx->aFramingCtx->FramingRgb->u_height & ~1; /* Input RGB plane is provided, let's convert it to YUV420, and update framing structure */ err = M4xVSS_internalConvertRGBtoYUV(framingCtx->aFramingCtx); #else framingCtx->FramingRgb = xVSS_context->pSettings->Effects[j].xVSS.pFramingBuffer; /* Force input RGB buffer to even size to avoid errors in YUV conversion */ framingCtx->FramingRgb.u_width = framingCtx->FramingRgb.u_width & ~1; framingCtx->FramingRgb.u_height = framingCtx->FramingRgb.u_height & ~1; /* Input RGB plane is provided, let's convert it to YUV420, and update framing structure */ err = M4xVSS_internalConvertRGBtoYUV(framingCtx); #endif if( err != M4NO_ERROR ) { M4OSA_TRACE1_1( "M4xVSS_sendCommand: error when converting RGB to YUV: 0w%x", err); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return err; } } else { M4OSA_TRACE1_0( "M4xVSS_sendCommand: No input image/plane provided for framing effect."); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_PARAMETER; } } /* CR: Add text handling with external text interface */ /* If effect type is text, we call external text function to get RGB 565 buffer */ if( xVSS_context->pSettings->Effects[j].VideoEffectType == M4xVSS_kVideoEffectType_Text ) { /* Call the font engine function pointer to get RGB565 buffer */ /* We transform text effect into framing effect from buffer */ if( xVSS_context->pSettings->xVSS.pTextRenderingFct != M4OSA_NULL ) { /*FB: add UTF convertion for text buffer*/ M4OSA_Void *pDecodedPath = M4OSA_NULL; #ifdef DECODE_GIF_ON_SAVING M4xVSS_FramingContext *framingCtx; #else M4xVSS_FramingStruct *framingCtx; #endif /*DECODE_GIF_ON_SAVING*/ #ifdef DECODE_GIF_ON_SAVING framingCtx = (M4xVSS_FramingContext *)M4OSA_32bitAlignedMalloc(sizeof(M4xVSS_FramingContext), M4VS, (M4OSA_Char *)"Context of the framing effect"); if( framingCtx == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SendCommand"); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_ALLOC; } framingCtx->aFramingCtx = M4OSA_NULL; framingCtx->aFramingCtx_last = M4OSA_NULL; framingCtx->pSPSContext = M4OSA_NULL; framingCtx->outputVideoSize = xVSS_context->pSettings->xVSS.outputVideoSize; framingCtx->topleft_x = xVSS_context->pSettings->Effects[j].xVSS.topleft_x; framingCtx->topleft_y = xVSS_context->pSettings->Effects[j].xVSS.topleft_y; framingCtx->bEffectResize = xVSS_context->pSettings->Effects[j].xVSS.bResize; framingCtx->pEffectFilePath = xVSS_context->pSettings->Effects[j].xVSS.pFramingFilePath; framingCtx->pFileReadPtr = xVSS_context->pFileReadPtr; framingCtx->pFileWritePtr = xVSS_context->pFileWritePtr; framingCtx->effectDuration = xVSS_context->pSettings->Effects[j].uiDuration; framingCtx->b_IsFileGif = M4OSA_FALSE; framingCtx->b_animated = M4OSA_FALSE; framingCtx->alphaBlendingStruct = M4OSA_NULL; /* Save framing structure associated with corresponding effect */ xVSS_context->pSettings->Effects[j].pExtVideoEffectFctCtxt = framingCtx; framingCtx->aFramingCtx = (M4xVSS_FramingStruct *)M4OSA_32bitAlignedMalloc(sizeof(M4xVSS_FramingStruct), M4VS, (M4OSA_Char *)"Context of the framing effect"); if( framingCtx->aFramingCtx == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SendCommand"); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_ALLOC; } framingCtx->aFramingCtx->topleft_x = xVSS_context->pSettings->Effects[j].xVSS.topleft_x; framingCtx->aFramingCtx->topleft_y = xVSS_context->pSettings->Effects[j].xVSS.topleft_y; /* BugFix 1.2.0: Leak when decoding error */ framingCtx->aFramingCtx->FramingRgb = M4OSA_NULL; framingCtx->aFramingCtx->FramingYuv = M4OSA_NULL; framingCtx->aFramingCtx->pNext = framingCtx->aFramingCtx; framingCtx->aFramingCtx->pCurrent = framingCtx->aFramingCtx; framingCtx->aFramingCtx->duration = 0; framingCtx->aFramingCtx->previousClipTime = -1; /*Alpha blending*/ /*Check if the alpha blending parameters are corrects*/ if( pSettings->Effects[j].xVSS.uialphaBlendingFadeInTime > 100 ) { pSettings->Effects[j].xVSS.uialphaBlendingFadeInTime = 0; } if( pSettings->Effects[j].xVSS.uialphaBlendingFadeOutTime > 100 ) { pSettings->Effects[j].xVSS.uialphaBlendingFadeOutTime = 0; } if( pSettings->Effects[j].xVSS.uialphaBlendingEnd > 100 ) { pSettings->Effects[j].xVSS.uialphaBlendingEnd = 100; } if( pSettings->Effects[j].xVSS.uialphaBlendingMiddle > 100 ) { pSettings->Effects[j].xVSS.uialphaBlendingMiddle = 100; } if( pSettings->Effects[j].xVSS.uialphaBlendingStart > 100 ) { pSettings->Effects[j].xVSS.uialphaBlendingStart = 100; } if( pSettings->Effects[j].xVSS.uialphaBlendingFadeInTime > 0 || pSettings->Effects[j].xVSS.uialphaBlendingFadeOutTime > 0 ) { /*Allocate the alpha blending structure*/ framingCtx->alphaBlendingStruct = (M4xVSS_internalEffectsAlphaBlending *)M4OSA_32bitAlignedMalloc( sizeof(M4xVSS_internalEffectsAlphaBlending), M4VS, (M4OSA_Char *)"alpha blending structure"); if( framingCtx->alphaBlendingStruct == M4OSA_NULL ) { M4OSA_TRACE1_0( "Allocation error in M4xVSS_SendCommand"); M4xVSS_freeCommand(xVSS_context); return M4ERR_ALLOC; } /*Fill the alpha blending structure*/ framingCtx->alphaBlendingStruct->m_fadeInTime = pSettings->Effects[j].xVSS.uialphaBlendingFadeInTime; framingCtx->alphaBlendingStruct->m_fadeOutTime = pSettings->Effects[j].xVSS.uialphaBlendingFadeOutTime; framingCtx->alphaBlendingStruct->m_end = pSettings->Effects[j].xVSS.uialphaBlendingEnd; framingCtx->alphaBlendingStruct->m_middle = pSettings->Effects[j].xVSS.uialphaBlendingMiddle; framingCtx->alphaBlendingStruct->m_start = pSettings->Effects[j].xVSS.uialphaBlendingStart; if( pSettings->Effects[j].xVSS.uialphaBlendingFadeInTime + pSettings->Effects[j].xVSS.uialphaBlendingFadeOutTime > 100 ) { framingCtx->alphaBlendingStruct->m_fadeOutTime = 100 - framingCtx->alphaBlendingStruct->m_fadeInTime; } } #else framingCtx = (M4xVSS_FramingStruct *)M4OSA_32bitAlignedMalloc(sizeof(M4xVSS_FramingStruct), M4VS, (M4OSA_Char *)"Context of the framing effect (for text)"); if( framingCtx == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SendCommand"); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_ALLOC; } framingCtx->topleft_x = xVSS_context->pSettings->Effects[j].xVSS.topleft_x; framingCtx->topleft_y = xVSS_context->pSettings->Effects[j].xVSS.topleft_y; framingCtx->FramingRgb = M4OSA_NULL; /* BugFix 1.2.0: Leak when decoding error */ framingCtx->FramingYuv = M4OSA_NULL; framingCtx->pNext = framingCtx; #endif /* Save framing structure associated with corresponding effect */ xVSS_context->pSettings->Effects[j].pExtVideoEffectFctCtxt = framingCtx; /* FB: changes for Video Artist: memcopy pTextBuffer so that it can be changed after a complete analysis*/ if( pSettings->Effects[j].xVSS.pTextBuffer == M4OSA_NULL ) { M4OSA_TRACE1_0("M4xVSS_SendCommand: pTextBuffer is null"); M4xVSS_freeCommand(xVSS_context); return M4ERR_PARAMETER; } /*Convert text buffer into customer format before being used*/ /** * UTF conversion: convert into the customer format, before being used*/ pDecodedPath = pSettings->Effects[j].xVSS.pTextBuffer; xVSS_context->pSettings->Effects[j].xVSS.textBufferSize = pSettings->Effects[j].xVSS.textBufferSize; if( xVSS_context->UTFConversionContext.pConvFromUTF8Fct != M4OSA_NULL && xVSS_context-> UTFConversionContext.pTempOutConversionBuffer != M4OSA_NULL ) { err = M4xVSS_internalConvertFromUTF8(xVSS_context, (M4OSA_Void *)pSettings-> Effects[j].xVSS.pTextBuffer, (M4OSA_Void *)xVSS_context-> UTFConversionContext.pTempOutConversionBuffer, &length); if( err != M4NO_ERROR ) { M4OSA_TRACE1_1( "M4xVSS_SendCommand: M4xVSS_internalConvertFromUTF8 returns err: 0x%x", err); /* Free Send command */ M4xVSS_freeCommand(xVSS_context); return err; } pDecodedPath = xVSS_context-> UTFConversionContext.pTempOutConversionBuffer; xVSS_context->pSettings->Effects[j].xVSS.textBufferSize = length; } /** * End of the UTF conversion, use the converted file path*/ xVSS_context->pSettings-> Effects[j].xVSS.pTextBuffer = M4OSA_32bitAlignedMalloc( xVSS_context->pSettings->Effects[j].xVSS.textBufferSize + 1, M4VS, (M4OSA_Char *)"Local text buffer effect"); //xVSS_context->pSettings->Effects[j].xVSS.pTextBuffer = // M4OSA_32bitAlignedMalloc(strlen(pSettings->Effects[j].xVSS.pTextBuffer)+1, // M4VS, "Local text buffer effect"); if( xVSS_context->pSettings->Effects[j].xVSS.pTextBuffer == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SendCommand"); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_ALLOC; } if( pSettings->Effects[j].xVSS.pTextBuffer != M4OSA_NULL ) { //memcpy((M4OSA_MemAddr8)xVSS_context->pSettings->Effects[j] //.xVSS.pTextBuffer, (M4OSA_MemAddr8)pSettings->Effects[j].xVSS.pTextBuffer, // strlen(pSettings->Effects[j].xVSS.pTextBuffer)+1); memcpy((void *)xVSS_context->pSettings-> Effects[j].xVSS.pTextBuffer, (void *)pDecodedPath, xVSS_context->pSettings-> Effects[j].xVSS.textBufferSize + 1); } /*Allocate the text RGB buffer*/ framingCtx->aFramingCtx->FramingRgb = (M4VIFI_ImagePlane *)M4OSA_32bitAlignedMalloc(sizeof(M4VIFI_ImagePlane), M4VS, (M4OSA_Char *)"RGB structure for the text effect"); if( framingCtx->aFramingCtx->FramingRgb == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SendCommand"); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_ALLOC; } if( xVSS_context->pSettings->Effects[j].xVSS.uiTextBufferWidth == 0 || xVSS_context->pSettings-> Effects[j].xVSS.uiTextBufferHeight == 0 ) { M4OSA_TRACE1_0( "M4xVSS_SendCommand: text plane width and height are not defined"); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_PARAMETER; } /* Allocate input RGB text buffer and force it to even size to avoid errors in YUV conversion */ framingCtx->aFramingCtx->FramingRgb->u_width = xVSS_context->pSettings-> Effects[j].xVSS.uiTextBufferWidth & ~1; framingCtx->aFramingCtx->FramingRgb->u_height = xVSS_context->pSettings-> Effects[j].xVSS.uiTextBufferHeight & ~1; framingCtx->aFramingCtx->FramingRgb->u_stride = 2 * framingCtx->aFramingCtx->FramingRgb->u_width; framingCtx->aFramingCtx->FramingRgb->u_topleft = 0; framingCtx->aFramingCtx->FramingRgb->pac_data = (M4VIFI_UInt8 *)M4OSA_32bitAlignedMalloc( framingCtx->aFramingCtx->FramingRgb->u_height * framingCtx->aFramingCtx->FramingRgb->u_stride, M4VS, (M4OSA_Char *)"Text RGB plane->pac_data"); if( framingCtx->aFramingCtx->FramingRgb->pac_data == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SendCommand"); /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_ALLOC; } #ifdef DECODE_GIF_ON_SAVING /**/ /* Call text rendering function */ err = xVSS_context->pSettings->xVSS.pTextRenderingFct( xVSS_context->pSettings->Effects[j].xVSS.pRenderingData, xVSS_context->pSettings-> Effects[j].xVSS.pTextBuffer, xVSS_context->pSettings-> Effects[j].xVSS.textBufferSize, &(framingCtx->aFramingCtx->FramingRgb)); if( err != M4NO_ERROR ) { M4OSA_TRACE1_0("Text rendering external function failed\n"); M4xVSS_freeCommand(xVSS_context); return err; } /* Check that RGB buffer is set */ if( framingCtx->aFramingCtx->FramingRgb == M4OSA_NULL ) { M4OSA_TRACE1_0( "Text rendering function did not set RGB buffer correctly !"); M4xVSS_freeCommand(xVSS_context); return M4ERR_PARAMETER; } /* Convert RGB plane to YUV420 and update framing structure */ err = M4xVSS_internalConvertRGBtoYUV(framingCtx->aFramingCtx); if( err != M4NO_ERROR ) { M4OSA_TRACE1_1( "M4xVSS_sendCommand: error when converting RGB to YUV: 0w%x", err); M4xVSS_freeCommand(xVSS_context); return err; } #else /**/ /* Call text rendering function */ err = xVSS_context->pSettings->xVSS.pTextRenderingFct( xVSS_context->pSettings->Effects[j].xVSS.pRenderingData, xVSS_context->pSettings-> Effects[j].xVSS.pTextBuffer, xVSS_context->pSettings-> Effects[j].xVSS.textBufferSize, &(framingCtx->FramingRgb)); if( err != M4NO_ERROR ) { M4OSA_TRACE1_0("Text rendering external function failed\n"); M4xVSS_freeCommand(xVSS_context); return err; } /* Check that RGB buffer is set */ if( framingCtx->FramingRgb == M4OSA_NULL ) { M4OSA_TRACE1_0( "Text rendering function did not set RGB buffer correctly !"); M4xVSS_freeCommand(xVSS_context); return M4ERR_PARAMETER; } /* Convert RGB plane to YUV420 and update framing structure */ err = M4xVSS_internalConvertRGBtoYUV(framingCtx); if( err != M4NO_ERROR ) { M4OSA_TRACE1_1( "M4xVSS_sendCommand: error when converting RGB to YUV: 0w%x", err); M4xVSS_freeCommand(xVSS_context); return err; } #endif /*DECODE_GIF_ON_SAVING*/ /* Change internally effect type from "text" to framing */ xVSS_context->pSettings->Effects[j].VideoEffectType = M4xVSS_kVideoEffectType_Framing; xVSS_context->pSettings->Effects[j].xVSS.bResize = M4OSA_FALSE; } else { M4OSA_TRACE1_0( "M4xVSS_sendCommand: No text rendering function set !!"); M4xVSS_freeCommand(xVSS_context); return M4ERR_PARAMETER; } } /* Allocate the structure to store the data needed by the Fifties effect */ else if( xVSS_context->pSettings->Effects[j].VideoEffectType == M4xVSS_kVideoEffectType_Fifties ) { M4xVSS_FiftiesStruct *fiftiesCtx; /* Check the expected frame rate for the fifties effect (must be above 0) */ if( 0 == xVSS_context->pSettings-> Effects[j].xVSS.uiFiftiesOutFrameRate ) { M4OSA_TRACE1_0( "The frame rate for the fifties effect must be greater than 0 !"); M4xVSS_freeCommand(xVSS_context); return M4ERR_PARAMETER; } fiftiesCtx = (M4xVSS_FiftiesStruct *)M4OSA_32bitAlignedMalloc(sizeof(M4xVSS_FiftiesStruct), M4VS, (M4OSA_Char *)"Context of the fifties effect"); if( fiftiesCtx == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SendCommand"); /* Free Send command */ M4xVSS_freeCommand(xVSS_context); return M4ERR_ALLOC; } fiftiesCtx->previousClipTime = -1; fiftiesCtx->fiftiesEffectDuration = 1000 / xVSS_context->pSettings-> Effects[j].xVSS.uiFiftiesOutFrameRate; fiftiesCtx->shiftRandomValue = 0; fiftiesCtx->stripeRandomValue = 0; /* Save the structure associated with corresponding effect */ xVSS_context->pSettings->Effects[j].pExtVideoEffectFctCtxt = fiftiesCtx; } /* Allocate the structure to store the data needed by the Color effect */ else if( xVSS_context->pSettings->Effects[j].VideoEffectType == M4xVSS_kVideoEffectType_ColorRGB16 || xVSS_context->pSettings->Effects[j].VideoEffectType == M4xVSS_kVideoEffectType_BlackAndWhite || xVSS_context->pSettings->Effects[j].VideoEffectType == M4xVSS_kVideoEffectType_Pink || xVSS_context->pSettings->Effects[j].VideoEffectType == M4xVSS_kVideoEffectType_Green || xVSS_context->pSettings->Effects[j].VideoEffectType == M4xVSS_kVideoEffectType_Sepia || xVSS_context->pSettings->Effects[j].VideoEffectType == M4xVSS_kVideoEffectType_Negative || xVSS_context->pSettings->Effects[j].VideoEffectType == M4xVSS_kVideoEffectType_Gradient ) { M4xVSS_ColorStruct *ColorCtx; ColorCtx = (M4xVSS_ColorStruct *)M4OSA_32bitAlignedMalloc(sizeof(M4xVSS_ColorStruct), M4VS, (M4OSA_Char *)"Context of the color effect"); if( ColorCtx == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SendCommand"); /* Free Send command */ M4xVSS_freeCommand(xVSS_context); return M4ERR_ALLOC; } ColorCtx->colorEffectType = xVSS_context->pSettings->Effects[j].VideoEffectType; if( xVSS_context->pSettings->Effects[j].VideoEffectType == M4xVSS_kVideoEffectType_ColorRGB16 || xVSS_context->pSettings->Effects[j].VideoEffectType == M4xVSS_kVideoEffectType_Gradient ) { ColorCtx->rgb16ColorData = xVSS_context->pSettings->Effects[j].xVSS.uiRgb16InputColor; } else { ColorCtx->rgb16ColorData = 0; } /* Save the structure associated with corresponding effect */ xVSS_context->pSettings->Effects[j].pExtVideoEffectFctCtxt = ColorCtx; } } /********************************** Background music registering **********************************/ if( pSettings->xVSS.pBGMtrack != M4OSA_NULL && isNewBGM == M4OSA_TRUE ) { #ifdef PREVIEW_ENABLED M4xVSS_MCS_params *pParams; M4OSA_Char *out_pcm; /*UTF conversion support*/ M4OSA_Void *pDecodedPath = M4OSA_NULL; #endif /* We save output file pointer, because we will need to use it when saving audio mixed file (last save step) */ xVSS_context->pOutputFile = xVSS_context->pSettings->pOutputFile; xVSS_context->pTemporaryFile = xVSS_context->pSettings->pTemporaryFile; /* If a previous BGM has already been registered, delete it */ /* Here can be implemented test to know if the same BGM is registered */ if( xVSS_context->pSettings->xVSS.pBGMtrack != M4OSA_NULL ) { if( xVSS_context->pSettings->xVSS.pBGMtrack->pFile != M4OSA_NULL ) { free(xVSS_context->pSettings->xVSS.pBGMtrack-> pFile); xVSS_context->pSettings->xVSS.pBGMtrack->pFile = M4OSA_NULL; } free(xVSS_context->pSettings->xVSS.pBGMtrack); xVSS_context->pSettings->xVSS.pBGMtrack = M4OSA_NULL; } /* Allocate BGM */ xVSS_context->pSettings->xVSS.pBGMtrack = (M4xVSS_BGMSettings *)M4OSA_32bitAlignedMalloc(sizeof(M4xVSS_BGMSettings), M4VS, (M4OSA_Char *)"xVSS_context->pSettings->xVSS.pBGMtrack"); if( xVSS_context->pSettings->xVSS.pBGMtrack == M4OSA_NULL ) { M4xVSS_freeCommand(xVSS_context); M4OSA_TRACE1_0("Allocation error in M4xVSS_SendCommand"); return M4ERR_ALLOC; } /* Copy input structure to our structure */ memcpy((void *)xVSS_context->pSettings->xVSS.pBGMtrack, (void *)pSettings->xVSS.pBGMtrack, sizeof(M4xVSS_BGMSettings)); /* Allocate file name, and copy file name buffer to our structure */ xVSS_context->pSettings->xVSS.pBGMtrack->pFile = M4OSA_32bitAlignedMalloc((strlen(pSettings->xVSS.pBGMtrack->pFile) + 1), M4VS, (M4OSA_Char *)"xVSS BGM file path"); if( xVSS_context->pSettings->xVSS.pBGMtrack->pFile == M4OSA_NULL ) { M4xVSS_freeCommand(xVSS_context); M4OSA_TRACE1_0("Allocation error in M4xVSS_SendCommand"); return M4ERR_ALLOC; } memcpy((void *)xVSS_context->pSettings->xVSS.pBGMtrack->pFile, (void *)pSettings->xVSS.pBGMtrack->pFile, strlen(pSettings->xVSS.pBGMtrack->pFile) + 1); #ifdef PREVIEW_ENABLED /* Decode BGM track to pcm output file */ pParams = (M4xVSS_MCS_params *)M4OSA_32bitAlignedMalloc(sizeof(M4xVSS_MCS_params), M4VS, (M4OSA_Char *)"Element of MCS Params (for BGM)"); if( pParams == M4OSA_NULL ) { M4xVSS_freeCommand(xVSS_context); M4OSA_TRACE1_0( "M4xVSS_sendCommand: Problem when allocating one element MCS Params"); return M4ERR_ALLOC; } /* Initialize the pointers in case of problem (PR 2273) */ pParams->pFileIn = M4OSA_NULL; pParams->pFileOut = M4OSA_NULL; pParams->pFileTemp = M4OSA_NULL; pParams->pNext = M4OSA_NULL; pParams->BeginCutTime = 0; pParams->EndCutTime = 0; if( xVSS_context->pMCSparamsList == M4OSA_NULL ) /* Means it is the first element of the list */ { /* Initialize the xVSS context with the first element of the list */ xVSS_context->pMCSparamsList = pParams; } else { M4xVSS_MCS_params *pParams_temp = xVSS_context->pMCSparamsList; M4xVSS_MCS_params *pParams_prev = M4OSA_NULL; /* Parse MCS params chained list to find and delete BGM element */ while( pParams_temp != M4OSA_NULL ) { if( pParams_temp->isBGM == M4OSA_TRUE ) { /* Remove this element */ if( pParams_temp->pFileIn != M4OSA_NULL ) { free(pParams_temp->pFileIn); pParams_temp->pFileIn = M4OSA_NULL; } if( pParams_temp->pFileOut != M4OSA_NULL ) { /* Remove PCM temporary file */ remove((const char *)pParams_temp->pFileOut); free(pParams_temp->pFileOut); pParams_temp->pFileOut = M4OSA_NULL; } /* Chain previous element with next element = remove BGM chained list element */ if( pParams_prev != M4OSA_NULL ) { pParams_prev->pNext = pParams_temp->pNext; } /* If current pointer is the first of the chained list and next pointer of the chained list is NULL */ /* it means that there was only one element in the list */ /* => we put the context variable to NULL to reaffect the first chained list element */ if( pParams_temp == xVSS_context->pMCSparamsList && pParams_temp->pNext == M4OSA_NULL ) { xVSS_context->pMCSparamsList = M4OSA_NULL; } /* In that case, BGM pointer is the first one, but there are others elements after it */ /* So, we need to change first chained list element */ else if( pParams_temp->pNext != M4OSA_NULL && pParams_prev == M4OSA_NULL ) { xVSS_context->pMCSparamsList = pParams_temp->pNext; } if( pParams_temp->pNext != M4OSA_NULL ) { pParams_prev = pParams_temp->pNext; free(pParams_temp); pParams_temp = M4OSA_NULL; pParams_temp = pParams_prev; } else { free(pParams_temp); pParams_temp = M4OSA_NULL; } } else { pParams_prev = pParams_temp; pParams_temp = pParams_temp->pNext; } } /* We need to initialize the last element of the chained list to be able to add new BGM element */ pMCS_last = pParams_prev; if( xVSS_context->pMCSparamsList == M4OSA_NULL ) { /* In that case, it means that there was only one element in the chained list */ /* So, we need to save the new params*/ xVSS_context->pMCSparamsList = pParams; } else { /* Update next pointer of the previous last element of the chain */ pMCS_last->pNext = pParams; } } /* Fill the last M4xVSS_MCS_params element */ pParams->InputFileType = xVSS_context->pSettings->xVSS.pBGMtrack->FileType; pParams->OutputFileType = M4VIDEOEDITING_kFileType_PCM; pParams->OutputVideoFormat = M4VIDEOEDITING_kNoneVideo; pParams->OutputVideoFrameSize = M4VIDEOEDITING_kQCIF; pParams->OutputVideoFrameRate = M4VIDEOEDITING_k15_FPS; if( xVSS_context->pSettings->xVSS.outputAudioFormat == M4VIDEOEDITING_kAAC ) { pParams->OutputAudioFormat = M4VIDEOEDITING_kAAC; pParams->OutputAudioSamplingFrequency = M4VIDEOEDITING_kDefault_ASF; /*FB: VAL CR P4ME00003076 The output audio bitrate in the AAC case is now directly given by the user*/ /*Check if the audio bitrate is correctly defined*/ /*Mono MCS values for AAC Mono are min: 16kbps and max: 192 kbps*/ if( xVSS_context->pSettings->xVSS.outputAudioBitrate >= M4VIDEOEDITING_k16_KBPS && xVSS_context->pSettings->xVSS.outputAudioBitrate <= M4VIDEOEDITING_k192_KBPS && xVSS_context->pSettings->xVSS.bAudioMono == M4OSA_TRUE ) { pParams->OutputAudioBitrate = xVSS_context->pSettings->xVSS.outputAudioBitrate; } /*Stereo MCS values for AAC Mono are min: 32kbps and max: 192 kbps*/ else if( xVSS_context->pSettings->xVSS.outputAudioBitrate >= M4VIDEOEDITING_k32_KBPS && xVSS_context->pSettings->xVSS.outputAudioBitrate <= M4VIDEOEDITING_k192_KBPS && xVSS_context->pSettings->xVSS.bAudioMono == M4OSA_FALSE ) { pParams->OutputAudioBitrate = xVSS_context->pSettings->xVSS.outputAudioBitrate; } else { pParams->OutputAudioBitrate = M4VIDEOEDITING_k32_KBPS; } pParams->bAudioMono = xVSS_context->pSettings->xVSS.bAudioMono; } else { pParams->OutputAudioFormat = M4VIDEOEDITING_kAMR_NB; pParams->OutputAudioSamplingFrequency = M4VIDEOEDITING_kDefault_ASF; pParams->OutputAudioBitrate = M4VIDEOEDITING_k12_2_KBPS; pParams->bAudioMono = M4OSA_TRUE; } pParams->OutputVideoBitrate = M4VIDEOEDITING_kUndefinedBitrate; /* Prepare output filename */ /* 21 is the size of "preview_16000_2.pcm" + \0 */ out_pcm = (M4OSA_Char *)M4OSA_32bitAlignedMalloc(strlen(xVSS_context->pTempPath) + 21, M4VS, (M4OSA_Char *)"Temp char* for pcmPreviewFile"); if( out_pcm == M4OSA_NULL ) { M4xVSS_freeCommand(xVSS_context); M4OSA_TRACE1_0("Allocation error in M4xVSS_Init"); return M4ERR_ALLOC; } /* Copy temporary path to final preview path string */ M4OSA_chrNCopy(out_pcm, xVSS_context->pTempPath, strlen(xVSS_context->pTempPath) + 1); /* Depending of the output sample frequency and nb of channels, we construct preview output filename */ if( xVSS_context->pSettings->xVSS.outputAudioFormat == M4VIDEOEDITING_kAAC ) { /* Construct output temporary PCM filename */ if( xVSS_context->pSettings->xVSS.bAudioMono == M4OSA_TRUE ) { strncat((char *)out_pcm, (const char *)"preview_16000_1.pcm\0", 20); } else { strncat((char *)out_pcm, (const char *)"preview_16000_2.pcm\0", 20); } } else if( xVSS_context->pSettings->xVSS.outputAudioFormat == M4VIDEOEDITING_kAMR_NB ) { /* Construct output temporary PCM filename */ strncat((char *)out_pcm, (const char *)"preview_08000_1.pcm\0", 20); } else { if( out_pcm != M4OSA_NULL ) { free(out_pcm); out_pcm = M4OSA_NULL; } M4xVSS_freeCommand(xVSS_context); M4OSA_TRACE1_0("Bad audio output format \n"); return M4ERR_PARAMETER; } xVSS_context->pcmPreviewFile = out_pcm; /** * UTF conversion: convert into the customer format, before being used*/ pDecodedPath = out_pcm; length = strlen(pDecodedPath); if( xVSS_context->UTFConversionContext.pConvFromUTF8Fct != M4OSA_NULL && xVSS_context->UTFConversionContext.pTempOutConversionBuffer != M4OSA_NULL ) { err = M4xVSS_internalConvertFromUTF8(xVSS_context, (M4OSA_Void *)out_pcm, (M4OSA_Void *)xVSS_context-> UTFConversionContext.pTempOutConversionBuffer, &length); if( err != M4NO_ERROR ) { M4OSA_TRACE1_1( "M4xVSS_SendCommand: M4xVSS_internalConvertFromUTF8 returns err: 0x%x", err); /* Free Send command */ M4xVSS_freeCommand(xVSS_context); return err; } pDecodedPath = xVSS_context->UTFConversionContext.pTempOutConversionBuffer; } /** * End of the UTF conversion, use the converted file path*/ xVSS_context->pcmPreviewFile = (M4OSA_Void *)M4OSA_32bitAlignedMalloc(length + 1, M4VS, (M4OSA_Char *)"pcmPreviewFile"); if( xVSS_context->pcmPreviewFile == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SendCommand"); free(out_pcm); out_pcm = M4OSA_NULL; /*FB: to avoid leaks when there is an error in the send command*/ /* Free Send command */ M4xVSS_freeCommand(xVSS_context); /**/ return M4ERR_ALLOC; } memcpy((void *)xVSS_context->pcmPreviewFile, (void *)pDecodedPath, length + 1); /* Free temporary output filename */ if( out_pcm != M4OSA_NULL ) { free(out_pcm); out_pcm = M4OSA_NULL; } pParams->pFileOut = M4OSA_32bitAlignedMalloc((length + 1), M4VS, (M4OSA_Char *)"MCS BGM Params: file out"); if( pParams->pFileOut == M4OSA_NULL ) { M4xVSS_freeCommand(xVSS_context); M4OSA_TRACE1_0("Allocation error in M4xVSS_SendCommand"); return M4ERR_ALLOC; } pParams->pFileTemp = M4OSA_NULL; memcpy((void *)pParams->pFileOut,(void *) xVSS_context->pcmPreviewFile, (length + 1)); /* Copy output file path */ /** * UTF conversion: convert into the customer format, before being used*/ pDecodedPath = xVSS_context->pSettings->xVSS.pBGMtrack->pFile; length = strlen(pDecodedPath); if( xVSS_context->UTFConversionContext.pConvFromUTF8Fct != M4OSA_NULL && xVSS_context->UTFConversionContext.pTempOutConversionBuffer != M4OSA_NULL ) { err = M4xVSS_internalConvertFromUTF8(xVSS_context, (M4OSA_Void *)xVSS_context->pSettings->xVSS.pBGMtrack-> pFile, (M4OSA_Void *)xVSS_context-> UTFConversionContext.pTempOutConversionBuffer, &length); if( err != M4NO_ERROR ) { M4OSA_TRACE1_1( "M4xVSS_SendCommand: M4xVSS_internalConvertFromUTF8 returns err: 0x%x", err); /* Free Send command */ M4xVSS_freeCommand(xVSS_context); return err; } pDecodedPath = xVSS_context->UTFConversionContext.pTempOutConversionBuffer; } /** * End of the UTF conversion, use the converted file path*/ pParams->pFileIn = (M4OSA_Void *)M4OSA_32bitAlignedMalloc((length + 1), M4VS, (M4OSA_Char *)"MCS BGM Params: file in"); if( pParams->pFileIn == M4OSA_NULL ) { M4xVSS_freeCommand(xVSS_context); M4OSA_TRACE1_0("Allocation error in M4xVSS_SendCommand"); return M4ERR_ALLOC; } memcpy((void *)pParams->pFileIn, (void *)pDecodedPath, (length + 1)); /* Copy input file path */ pParams->isBGM = M4OSA_TRUE; pParams->isCreated = M4OSA_FALSE; xVSS_context->nbStepTotal++; bIsTranscoding = M4OSA_TRUE; #endif /* PREVIEW_ENABLED */ } else if( pSettings->xVSS.pBGMtrack != M4OSA_NULL && isNewBGM == M4OSA_FALSE ) { #ifdef PREVIEW_ENABLED /* BGM is the same as previously, no need to redecode audio */ /* Need to update MCS params chained list, to signal M4xVSS_step function to skip BGM decoding */ M4xVSS_MCS_params *pParams_temp = xVSS_context->pMCSparamsList; M4xVSS_MCS_params *pParams_prev = M4OSA_NULL; #endif /* PREVIEW_ENABLED */ /* We save output file pointer, because we will need to use it when saving audio mixed file (last save step) */ xVSS_context->pOutputFile = xVSS_context->pSettings->pOutputFile; xVSS_context->pTemporaryFile = xVSS_context->pSettings->pTemporaryFile; /* Re-write BGM settings in case they have changed between two sendCommand */ xVSS_context->pSettings->xVSS.pBGMtrack->uiAddCts = pSettings->xVSS.pBGMtrack->uiAddCts; xVSS_context->pSettings->xVSS.pBGMtrack->uiAddVolume = pSettings->xVSS.pBGMtrack->uiAddVolume; xVSS_context->pSettings->xVSS.pBGMtrack->uiBeginLoop = pSettings->xVSS.pBGMtrack->uiBeginLoop; xVSS_context->pSettings->xVSS.pBGMtrack->uiEndLoop = pSettings->xVSS.pBGMtrack->uiEndLoop; #ifdef PREVIEW_ENABLED /* Parse MCS params chained list to find and delete BGM element */ while( pParams_temp != M4OSA_NULL ) { if( pParams_temp->isBGM == M4OSA_TRUE ) { pParams_temp->isCreated = M4OSA_TRUE; break; } pParams_prev = pParams_temp; pParams_temp = pParams_temp->pNext; } #endif /* PREVIEW_ENABLED */ M4OSA_TRACE2_0("M4xVSS_SendCommand has been recalled, BGM is the same"); } else { M4OSA_TRACE1_0("No BGM in this xVSS command"); if( xVSS_context->pSettings->xVSS.pBGMtrack != M4OSA_NULL ) { #ifdef PREVIEW_ENABLED /* Need to remove MCS previous params chained list */ M4xVSS_MCS_params *pParams_temp = xVSS_context->pMCSparamsList; M4xVSS_MCS_params *pParams_prev = M4OSA_NULL; /* Parse MCS params chained list to find and delete BGM element */ while( pParams_temp != M4OSA_NULL ) { if( pParams_temp->isBGM == M4OSA_TRUE ) { /* Remove this element */ if( pParams_temp->pFileIn != M4OSA_NULL ) { free(pParams_temp->pFileIn); pParams_temp->pFileIn = M4OSA_NULL; } if( pParams_temp->pFileOut != M4OSA_NULL ) { free(pParams_temp->pFileOut); pParams_temp->pFileOut = M4OSA_NULL; } /* Chain previous element with next element */ if( pParams_prev != M4OSA_NULL ) { pParams_prev->pNext = pParams_temp->pNext; } /* If current pointer is the first of the chained list and next pointer of the chained list is NULL */ /* it means that there was only one element in the list */ /* => we put the context variable to NULL */ if( pParams_temp == xVSS_context->pMCSparamsList && pParams_temp->pNext == M4OSA_NULL ) { free(pParams_temp); xVSS_context->pMCSparamsList = M4OSA_NULL; } /* In that case, BGM pointer is the first one, but there are others elements after it */ /* So, we need to change first chained list element */ else if( pParams_temp->pNext != M4OSA_NULL ) { xVSS_context->pMCSparamsList = pParams_temp->pNext; free(pParams_temp); pParams_temp = M4OSA_NULL; } /* In all other cases, nothing else to do except freeing the chained list element */ else { free(pParams_temp); pParams_temp = M4OSA_NULL; } break; } pParams_prev = pParams_temp; pParams_temp = pParams_temp->pNext; } #endif /* PREVIEW_ENABLED */ /* Here, we unallocate all BGM components and put xVSS_context->pSettings-> xVSS.pBGMtrack to NULL */ if( xVSS_context->pSettings->xVSS.pBGMtrack != M4OSA_NULL ) { if( xVSS_context->pSettings->xVSS.pBGMtrack->pFile != M4OSA_NULL ) { free(xVSS_context->pSettings->xVSS.pBGMtrack->pFile); xVSS_context->pSettings->xVSS.pBGMtrack->pFile = M4OSA_NULL; } free(xVSS_context->pSettings->xVSS.pBGMtrack); xVSS_context->pSettings->xVSS.pBGMtrack = M4OSA_NULL; } } } /* Changed to be able to mix with video only files -> in case no master clip is found (i.e only JPG input or video only input) */ /* and if there is a BGM, we force the added volume to 100 (i.e replace audio) */ if( masterClip == -1 && xVSS_context->pSettings->xVSS.pBGMtrack != M4OSA_NULL ) { /* In that case, it means that no input 3GP file has a video track. Therefore, if a mixing is asked, it will fail. Thus, we force replace audio. */ xVSS_context->pSettings->xVSS.pBGMtrack->uiAddVolume = 100; } /* Save clip number to know if a M4xVSS_sendCommand has already been called */ xVSS_context->previousClipNumber = xVSS_context->pSettings->uiClipNumber; /* Change state */ xVSS_context->m_state = M4xVSS_kStateAnalyzing; /* In case of MMS use case, we compute here the max video bitrate */ /* In case of too low bitrate, a specific warning is returned */ if( xVSS_context->pSettings->xVSS.outputFileSize != 0 && totalDuration > 0 ) { M4OSA_UInt32 targetedBitrate = 0; M4VIDEOEDITING_ClipProperties fileProperties; M4OSA_Double ratio; if( xVSS_context->pSettings->xVSS.pBGMtrack != M4OSA_NULL ) { if( xVSS_context->pSettings->xVSS.pBGMtrack->uiAddVolume == 100 ) /* We are in "replace audio mode, need to check the filetype */ { if( xVSS_context->pSettings->xVSS.pBGMtrack->FileType == M4VIDEOEDITING_kFileType_3GPP ) { M4OSA_Void *pDecodedPath; /** * UTF conversion: convert into the customer format, before being used*/ pDecodedPath = xVSS_context->pSettings->xVSS.pBGMtrack->pFile; length = strlen(pDecodedPath); if( xVSS_context->UTFConversionContext.pConvFromUTF8Fct != M4OSA_NULL && xVSS_context-> UTFConversionContext.pTempOutConversionBuffer != M4OSA_NULL ) { err = M4xVSS_internalConvertFromUTF8(xVSS_context, (M4OSA_Void *)xVSS_context->pSettings-> xVSS.pBGMtrack->pFile, (M4OSA_Void *)xVSS_context-> UTFConversionContext. pTempOutConversionBuffer, &length); if( err != M4NO_ERROR ) { M4OSA_TRACE1_1("M4xVSS_SendCommand: \ M4xVSS_internalConvertFromUTF8 returns err: 0x%x", err); /* Free Send command */ M4xVSS_freeCommand(xVSS_context); return err; } pDecodedPath = xVSS_context-> UTFConversionContext.pTempOutConversionBuffer; } /** * End of the UTF conversion, use the converted file path*/ err = M4xVSS_internalGetProperties(xVSS_context, pDecodedPath, &fileProperties); /* Get the properties of the BGM track */ /*err = M4xVSS_internalGetProperties(xVSS_context, xVSS_context->pSettings-> xVSS.pBGMtrack->pFile, &fileProperties);*/ if( err != M4NO_ERROR ) { M4OSA_TRACE1_1( "M4xVSS_sendCommand: M4xVSS_internalGetProperties returned an error:\ 0x%x", err); return err; } if( fileProperties.AudioStreamType != M4VIDEOEDITING_kAMR_NB ) { M4OSA_TRACE1_0( "M4xVSS_sendCommand: Impossible to use MMS mode with BGM != AMR-NB"); return M4ERR_PARAMETER; } } else if( xVSS_context->pSettings->xVSS.pBGMtrack->FileType != M4VIDEOEDITING_kFileType_AMR && xVSS_context->pSettings->xVSS.pBGMtrack->FileType != M4VIDEOEDITING_kFileType_MP3 ) { M4OSA_TRACE1_0("M4xVSS_sendCommand: Bad input BGM file"); return M4ERR_PARAMETER; } } } /* Compute targeted bitrate, with 8% margin (moov) */ if( totalDuration > 1000 ) { targetedBitrate = (M4OSA_UInt32)(( xVSS_context->pSettings->xVSS.outputFileSize * 8 * 0.84) / (totalDuration / 1000)); } else { targetedBitrate = 0; } /* Remove audio bitrate */ if( targetedBitrate >= 12200 ) { targetedBitrate -= 12200; /* Only AMR is supported in MMS case */ } else { targetedBitrate = 0; } /* Compute an indicator of "complexity" depending on nb of sequences and total duration */ /* The highest is the number of sequences, the more there are some I frames */ /* In that case, it is necessary to reduce the target bitrate */ ratio = (M4OSA_Double)((M4OSA_Double)(xVSS_context->pSettings->uiClipNumber * 100000) / (M4OSA_Double)(totalDuration)); M4OSA_TRACE2_3( "Ratio clip_nb/duration = %f\nTargeted bitrate = %d\nTotal duration: %d", (M4OSA_Double)((M4OSA_Double)(xVSS_context->pSettings->uiClipNumber * 100000) / (M4OSA_Double)(totalDuration)), targetedBitrate, totalDuration); if( ratio > 50 && ratio <= 75 ) { /* It means that there is a potential risk of having a higher file size than specified */ targetedBitrate -= (M4OSA_UInt32)(targetedBitrate * 0.1); M4OSA_TRACE2_2( "New bitrate1 !!\nRatio clip_nb/duration = %f\nTargeted bitrate = %d", ratio, targetedBitrate); } else if( ratio > 75 ) { targetedBitrate -= (M4OSA_UInt32)(targetedBitrate * 0.15); M4OSA_TRACE2_2( "New bitrate2 !!\nRatio clip_nb/duration = %f\nTargeted bitrate = %d", ratio, targetedBitrate); } /*CR 3283 MMS use case for VAL: Decrease the output file size to keep a margin of 5% The writer will stop when the targeted output file size will be reached*/ xVSS_context->pSettings->xVSS.outputFileSize -= (M4OSA_UInt32)(xVSS_context->pSettings->xVSS.outputFileSize * 0.05); switch( xVSS_context->pSettings->xVSS.outputVideoSize ) { case M4VIDEOEDITING_kSQCIF: if( targetedBitrate < 32000 ) { xVSS_context->targetedBitrate = 32000; return M4VSS3GPP_WAR_OUTPUTFILESIZE_EXCEED; } break; case M4VIDEOEDITING_kQQVGA: if( targetedBitrate < 32000 ) /*48000)*/ { xVSS_context->targetedBitrate = 32000; /*48000;*/ return M4VSS3GPP_WAR_OUTPUTFILESIZE_EXCEED; } break; case M4VIDEOEDITING_kQCIF: if( targetedBitrate < 48000 ) /*64000)*/ { xVSS_context->targetedBitrate = 48000; /*64000;*/ return M4VSS3GPP_WAR_OUTPUTFILESIZE_EXCEED; } break; case M4VIDEOEDITING_kQVGA: if( targetedBitrate < 64000 ) /*128000)*/ { xVSS_context->targetedBitrate = 64000; /*128000;*/ return M4VSS3GPP_WAR_OUTPUTFILESIZE_EXCEED; } break; case M4VIDEOEDITING_kCIF: if( targetedBitrate < 128000 ) { xVSS_context->targetedBitrate = 128000; return M4VSS3GPP_WAR_OUTPUTFILESIZE_EXCEED; } break; case M4VIDEOEDITING_kVGA: if( targetedBitrate < 192000 ) { xVSS_context->targetedBitrate = 192000; return M4VSS3GPP_WAR_OUTPUTFILESIZE_EXCEED; } break; default: /* Cannot happen */ M4OSA_TRACE1_0( "M4xVSS_sendCommand: Error in output fileSize !"); return M4ERR_PARAMETER; break; } xVSS_context->targetedBitrate = (M4OSA_UInt32)targetedBitrate; } if( bIsTranscoding ) { return M4VSS3GPP_WAR_TRANSCODING_NECESSARY; } else { return M4NO_ERROR; } } /** ****************************************************************************** * prototype M4OSA_ERR M4xVSS_SaveStart(M4OSA_Context pContext, M4OSA_Char* pFilePath) * @brief This function prepare the save * @note The xVSS create 3GP edited final file * This function must be called once M4xVSS_Step has returned * M4VSS3GPP_WAR_ANALYZING_DONE * After this function, the user must call M4xVSS_Step until * it returns another error than M4NO_ERROR. * * @param pContext (IN) Pointer on the xVSS edit context * @param pFilePath (IN) If the user wants to provide a different * output filename, else can be NULL (allocated by the user) * @return M4NO_ERROR: No error * @return M4ERR_PARAMETER: At least one parameter is M4OSA_NULL * @return M4ERR_ALLOC: Memory allocation has failed * @return M4ERR_STATE: This function cannot not be called at this time ****************************************************************************** */ M4OSA_ERR M4xVSS_SaveStart( M4OSA_Context pContext, M4OSA_Void *pFilePath, M4OSA_UInt32 filePathSize ) { M4xVSS_Context *xVSS_context = (M4xVSS_Context *)pContext; M4OSA_ERR err; /*Add for UTF conversion: copy the pSettings structure into a new pCurrentEditSettings*/ M4VSS3GPP_EditSettings *pEditSavingSettings = M4OSA_NULL; M4OSA_UInt8 i, j; M4OSA_UInt32 offset = 0; M4OSA_UInt8 nbEffects = 0; /*only for UTF conversion support*/ M4OSA_Void *pDecodedPath = M4OSA_NULL; M4OSA_UInt32 length = 0; /**/ /* Check state */ if( xVSS_context->m_state != M4xVSS_kStateOpened ) { M4OSA_TRACE1_1( "Bad state when calling M4xVSS_SaveStart function! State is %d", xVSS_context->m_state); return M4ERR_STATE; } /* RC: to temporary handle changing of output filepath */ /* TO BE CHANGED CLEANLY WITH A MALLOC/MEMCPY !!!! */ if( pFilePath != M4OSA_NULL ) { if( xVSS_context->pSettings->pOutputFile != M4OSA_NULL ) { /*it means that pOutputFile has been allocated in M4xVSS_sendCommand()*/ free(xVSS_context->pSettings->pOutputFile); xVSS_context->pSettings->pOutputFile = M4OSA_NULL; xVSS_context->pSettings->uiOutputPathSize = 0; } pDecodedPath = pFilePath; /*As all inputs of the xVSS are in UTF8, convert the output file path into the customer format*/ if( xVSS_context->UTFConversionContext.pConvFromUTF8Fct != M4OSA_NULL && xVSS_context->UTFConversionContext.pTempOutConversionBuffer != M4OSA_NULL ) { err = M4xVSS_internalConvertFromUTF8(xVSS_context, (M4OSA_Void *)pFilePath, (M4OSA_Void *)xVSS_context-> UTFConversionContext.pTempOutConversionBuffer, &length); if( err != M4NO_ERROR ) { M4OSA_TRACE1_1( "M4xVSS_SaveStart: M4xVSS_internalConvertFromUTF8 returns err: 0x%x", err); return err; } pDecodedPath = xVSS_context->UTFConversionContext.pTempOutConversionBuffer; filePathSize = length; } xVSS_context->pOutputFile = (M4OSA_Void *)M4OSA_32bitAlignedMalloc(filePathSize + 1, M4VS, (M4OSA_Char *)"M4xVSS_SaveStart: output file"); if( xVSS_context->pOutputFile == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SaveStart"); return M4ERR_ALLOC; } memcpy((void *)xVSS_context->pOutputFile, (void *)pDecodedPath, filePathSize + 1); xVSS_context->pOutputFile[filePathSize] = '\0'; xVSS_context->pSettings->pOutputFile = xVSS_context->pOutputFile; xVSS_context->pSettings->uiOutputPathSize = filePathSize; } /** ***/ /*FB: Add for UTF conversion: copy the pSettings structure into a new pCurrentEditSettings*/ /*It is the same principle as in the PreviewStart()*/ pEditSavingSettings = (M4VSS3GPP_EditSettings *)M4OSA_32bitAlignedMalloc(sizeof(M4VSS3GPP_EditSettings), M4VS, (M4OSA_Char *)"Saving, copy of VSS structure"); if( pEditSavingSettings == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SaveStart"); if( xVSS_context->pOutputFile != M4OSA_NULL ) { free(xVSS_context->pOutputFile); xVSS_context->pOutputFile = M4OSA_NULL; } return M4ERR_ALLOC; } /* Copy settings from input structure */ memcpy((void *) &(pEditSavingSettings->xVSS), (void *) &(xVSS_context->pSettings->xVSS), sizeof(M4xVSS_EditSettings)); /* Initialize pEditSavingSettings structure */ pEditSavingSettings->xVSS.pBGMtrack = M4OSA_NULL; pEditSavingSettings->videoFrameRate = xVSS_context->pSettings->videoFrameRate; pEditSavingSettings->uiClipNumber = xVSS_context->pSettings->uiClipNumber; pEditSavingSettings->uiMasterClip = xVSS_context->pSettings->uiMasterClip; /* VSS2.0 mandatory parameter */ /* Allocate savingSettings.pClipList/pTransitions structure */ pEditSavingSettings->pClipList = (M4VSS3GPP_ClipSettings * * )M4OSA_32bitAlignedMalloc(sizeof(M4VSS3GPP_ClipSettings *) *pEditSavingSettings->uiClipNumber, M4VS, (M4OSA_Char *)"xVSS, saving , copy of pClipList"); if( pEditSavingSettings->pClipList == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SaveStart"); if( xVSS_context->pOutputFile != M4OSA_NULL ) { free(xVSS_context->pOutputFile); xVSS_context->pOutputFile = M4OSA_NULL; } return M4ERR_ALLOC; } if( pEditSavingSettings->uiClipNumber > 1 ) { pEditSavingSettings->pTransitionList = (M4VSS3GPP_TransitionSettings * * )M4OSA_32bitAlignedMalloc(sizeof(M4VSS3GPP_TransitionSettings *) *(pEditSavingSettings->uiClipNumber - 1), M4VS, (M4OSA_Char *)"xVSS, saving, copy of pTransitionList"); if( pEditSavingSettings->pTransitionList == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SaveStart"); if( xVSS_context->pOutputFile != M4OSA_NULL ) { free(xVSS_context->pOutputFile); xVSS_context->pOutputFile = M4OSA_NULL; } return M4ERR_ALLOC; } } else { pEditSavingSettings->pTransitionList = M4OSA_NULL; } for ( i = 0; i < pEditSavingSettings->uiClipNumber; i++ ) { pEditSavingSettings->pClipList[i] = (M4VSS3GPP_ClipSettings *)M4OSA_32bitAlignedMalloc(sizeof(M4VSS3GPP_ClipSettings), M4VS, (M4OSA_Char *)"saving clip settings"); if( pEditSavingSettings->pClipList[i] == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SaveStart"); if( xVSS_context->pOutputFile != M4OSA_NULL ) { free(xVSS_context->pOutputFile); xVSS_context->pOutputFile = M4OSA_NULL; } return M4ERR_ALLOC; } if( i < pEditSavingSettings->uiClipNumber - 1 ) /* Because there is 1 less transition than clip number */ { pEditSavingSettings->pTransitionList[i] = (M4VSS3GPP_TransitionSettings *)M4OSA_32bitAlignedMalloc(sizeof(M4VSS3GPP_TransitionSettings), M4VS, (M4OSA_Char *)"saving transition settings"); if( pEditSavingSettings->pTransitionList[i] == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SaveStart"); if( xVSS_context->pOutputFile != M4OSA_NULL ) { free(xVSS_context->pOutputFile); xVSS_context->pOutputFile = M4OSA_NULL; } return M4ERR_ALLOC; } } } for ( i = 0; i < xVSS_context->pSettings->uiClipNumber; i++ ) { // Add MP4 file support if( ( xVSS_context->pSettings->pClipList[i]->FileType == M4VIDEOEDITING_kFileType_3GPP) || (xVSS_context->pSettings->pClipList[i]->FileType == M4VIDEOEDITING_kFileType_MP4) || (xVSS_context->pSettings->pClipList[i]->FileType == M4VIDEOEDITING_kFileType_M4V) || (xVSS_context->pSettings->pClipList[i]->FileType == M4VIDEOEDITING_kFileType_ARGB8888)) { /* Copy data from given structure to our saving structure */ M4xVSS_DuplicateClipSettings(pEditSavingSettings->pClipList[i], xVSS_context->pSettings->pClipList[i], M4OSA_FALSE /* remove effects */); /** * UTF conversion: convert into the customer format, before being used*/ pDecodedPath = pEditSavingSettings->pClipList[i]->pFile; length = strlen(pDecodedPath); if( xVSS_context->UTFConversionContext.pConvFromUTF8Fct != M4OSA_NULL && xVSS_context-> UTFConversionContext.pTempOutConversionBuffer != M4OSA_NULL ) { err = M4xVSS_internalConvertFromUTF8(xVSS_context, (M4OSA_Void *)pEditSavingSettings->pClipList[i]->pFile, (M4OSA_Void *)xVSS_context-> UTFConversionContext.pTempOutConversionBuffer, &length); if( err != M4NO_ERROR ) { M4OSA_TRACE1_1( "M4xVSS_SaveStart: M4xVSS_internalConvertFromUTF8 returns err: 0x%x", err); if( xVSS_context->pOutputFile != M4OSA_NULL ) { free(xVSS_context->pOutputFile); xVSS_context->pOutputFile = M4OSA_NULL; } return err; } pDecodedPath = xVSS_context-> UTFConversionContext.pTempOutConversionBuffer; /** * End of the UTF conversion, use the converted file path*/ free( pEditSavingSettings->pClipList[i]->pFile); pEditSavingSettings->pClipList[i]->pFile = (M4OSA_Void *)M4OSA_32bitAlignedMalloc((length + 1), M4VS, (M4OSA_Char *)"saving transition settings"); if( pEditSavingSettings->pClipList[i]->pFile == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SaveStart"); if( xVSS_context->pOutputFile != M4OSA_NULL ) { free(xVSS_context->pOutputFile); xVSS_context->pOutputFile = M4OSA_NULL; } return M4ERR_ALLOC; } memcpy((void *)pEditSavingSettings->pClipList[i]->pFile, (void *)pDecodedPath, length + 1); } /*FB: add file path size because of UTF 16 conversion*/ pEditSavingSettings->pClipList[i]->filePathSize = length+1; if( i < xVSS_context->pSettings->uiClipNumber - 1 ) /* Because there is 1 less transition than clip number */ { memcpy( (void *)pEditSavingSettings->pTransitionList[i], (void *)xVSS_context->pSettings-> pTransitionList[i], sizeof(M4VSS3GPP_TransitionSettings)); } } else { M4OSA_TRACE1_0( "M4xVSS_SaveStart: Error when parsing xVSS_context->pSettings->pClipList[i]:\ Bad file type"); if( xVSS_context->pOutputFile != M4OSA_NULL ) { free(xVSS_context->pOutputFile); xVSS_context->pOutputFile = M4OSA_NULL; } return M4ERR_PARAMETER; } } /* Count the number of video effects, used to know how much memory is needed to allocate*/ /* FB 2008/10/15: removed : not compatible with M4VSS3GPP_kVideoEffectType_None for(j=0;j<xVSS_context->pSettings->nbEffects;j++) { if(xVSS_context->pSettings->Effects[j].VideoEffectType != M4VSS3GPP_kVideoEffectType_None) { nbEffects++; } }*/ nbEffects = xVSS_context->pSettings->nbEffects; /* Allocate effects saving structure with correct number of effects */ if( nbEffects != 0 ) { pEditSavingSettings->Effects = (M4VSS3GPP_EffectSettings *)M4OSA_32bitAlignedMalloc(nbEffects * sizeof(M4VSS3GPP_EffectSettings), M4VS, (M4OSA_Char *)"Saving settings, effects table of structure settings"); if( pEditSavingSettings->Effects == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SaveStart"); if( xVSS_context->pOutputFile != M4OSA_NULL ) { free(xVSS_context->pOutputFile); xVSS_context->pOutputFile = M4OSA_NULL; } return M4ERR_ALLOC; } /* Just copy effect structure to saving structure, as effects time are now */ /* relative to output clip time*/ memcpy((void *)pEditSavingSettings->Effects, (void *)xVSS_context->pSettings->Effects, nbEffects * sizeof(M4VSS3GPP_EffectSettings)); } else { pEditSavingSettings->Effects = M4OSA_NULL; pEditSavingSettings->nbEffects = 0; } pEditSavingSettings->nbEffects = nbEffects; if( pFilePath != M4OSA_NULL ) { pEditSavingSettings->pOutputFile = pFilePath; } /* Save pointer of saving video editor to use in step function */ xVSS_context->pCurrentEditSettings = pEditSavingSettings; /* Change output file name to temporary output file name, because final file will be generated by audio mixer */ if( xVSS_context->pSettings->xVSS.pBGMtrack != M4OSA_NULL ) { M4OSA_Char out_3gp[M4XVSS_MAX_PATH_LEN]; M4OSA_Char out_3gp_tmp[M4XVSS_MAX_PATH_LEN]; /**/ pEditSavingSettings->xVSS.pBGMtrack = (M4xVSS_BGMSettings *)M4OSA_32bitAlignedMalloc(sizeof(M4xVSS_BGMSettings), M4VS, (M4OSA_Char *)"Saving settings, effects table of structure settings"); if( pEditSavingSettings->xVSS.pBGMtrack == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SaveStart"); if( xVSS_context->pOutputFile != M4OSA_NULL ) { free(xVSS_context->pOutputFile); xVSS_context->pOutputFile = M4OSA_NULL; } return M4ERR_ALLOC; } /* Just copy effect structure to saving structure, as effects time are now */ /* relative to output clip time*/ memcpy((void *)pEditSavingSettings->xVSS.pBGMtrack, (void *)xVSS_context->pSettings->xVSS.pBGMtrack, sizeof(M4xVSS_BGMSettings)); /* Allocate file name, and copy file name buffer to our structure */ pEditSavingSettings->xVSS.pBGMtrack->pFile = M4OSA_32bitAlignedMalloc( (strlen(xVSS_context->pSettings->xVSS.pBGMtrack->pFile) + 1), M4VS, (M4OSA_Char *)"Saving struct xVSS BGM file path"); if( pEditSavingSettings->xVSS.pBGMtrack->pFile == M4OSA_NULL ) { M4xVSS_freeCommand(xVSS_context); M4OSA_TRACE1_0("Allocation error in M4xVSS_SaveStart"); if( xVSS_context->pOutputFile != M4OSA_NULL ) { free(xVSS_context->pOutputFile); xVSS_context->pOutputFile = M4OSA_NULL; } return M4ERR_ALLOC; } memcpy((void *)pEditSavingSettings->xVSS.pBGMtrack->pFile, (void *)xVSS_context->pSettings->xVSS.pBGMtrack->pFile, strlen(xVSS_context->pSettings->xVSS.pBGMtrack->pFile) + 1); /*Copy BGM track file path*/ /** * UTF conversion*/ if( xVSS_context->UTFConversionContext.pConvFromUTF8Fct != M4OSA_NULL && xVSS_context->UTFConversionContext.pTempOutConversionBuffer != M4OSA_NULL ) { err = M4xVSS_internalConvertFromUTF8(xVSS_context, (M4OSA_Void *)pEditSavingSettings->xVSS.pBGMtrack->pFile, (M4OSA_Void *)xVSS_context-> UTFConversionContext.pTempOutConversionBuffer, &length); if( err != M4NO_ERROR ) { M4OSA_TRACE1_1( "M4xVSS_SaveStart: M4xVSS_internalConvertFromUTF8 returns err: 0x%x", err); if( xVSS_context->pOutputFile != M4OSA_NULL ) { free(xVSS_context->pOutputFile); xVSS_context->pOutputFile = M4OSA_NULL; } return err; } pDecodedPath = xVSS_context->UTFConversionContext.pTempOutConversionBuffer; free(pEditSavingSettings->xVSS.pBGMtrack->pFile); pEditSavingSettings->xVSS.pBGMtrack->pFile = (M4OSA_Void *)M4OSA_32bitAlignedMalloc(length + 1, M4VS, (M4OSA_Char *)"M4xVSS_SaveStart: Temp filename in case of BGM"); if( pEditSavingSettings->xVSS.pBGMtrack->pFile == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SaveStart"); if( xVSS_context->pOutputFile != M4OSA_NULL ) { free(xVSS_context->pOutputFile); xVSS_context->pOutputFile = M4OSA_NULL; } return M4ERR_ALLOC; } memcpy((void *)pEditSavingSettings->xVSS.pBGMtrack->pFile, (void *)pDecodedPath, length + 1); } /**/ M4OSA_chrNCopy(out_3gp, xVSS_context->pTempPath, M4XVSS_MAX_PATH_LEN - 1); M4OSA_chrNCopy(out_3gp_tmp, xVSS_context->pTempPath, M4XVSS_MAX_PATH_LEN - 1); /* Construct output temporary 3GP filename */ strncat((char *)out_3gp, (const char *)"savetemp.3gp\0", 13); strncat((char *)out_3gp_tmp, (const char *)"savetemp.tmp\0", 13); /** * UTF conversion: convert into the customer format, before being used*/ pDecodedPath = out_3gp; length = strlen(pDecodedPath); if( xVSS_context->UTFConversionContext.pConvFromUTF8Fct != M4OSA_NULL && xVSS_context->UTFConversionContext.pTempOutConversionBuffer != M4OSA_NULL ) { err = M4xVSS_internalConvertFromUTF8(xVSS_context, (M4OSA_Void *)out_3gp, (M4OSA_Void *)xVSS_context-> UTFConversionContext.pTempOutConversionBuffer, &length); if( err != M4NO_ERROR ) { M4OSA_TRACE1_1( "M4xVSS_SaveStart: M4xVSS_internalConvertFromUTF8 returns err: 0x%x", err); if( xVSS_context->pOutputFile != M4OSA_NULL ) { free(xVSS_context->pOutputFile); xVSS_context->pOutputFile = M4OSA_NULL; } return err; } pDecodedPath = xVSS_context->UTFConversionContext.pTempOutConversionBuffer; } /** * End of the UTF conversion, use the converted file path*/ xVSS_context->pCurrentEditSettings->pOutputFile = (M4OSA_Void *)M4OSA_32bitAlignedMalloc(length + 1, M4VS, (M4OSA_Char *)"M4xVSS_SaveStart: Temp filename in case of BGM"); if( xVSS_context->pCurrentEditSettings->pOutputFile == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SaveStart"); if( xVSS_context->pOutputFile != M4OSA_NULL ) { free(xVSS_context->pOutputFile); xVSS_context->pOutputFile = M4OSA_NULL; } return M4ERR_ALLOC; } memcpy((void *)xVSS_context->pCurrentEditSettings->pOutputFile, (void *)pDecodedPath, length + 1); xVSS_context->pCurrentEditSettings->uiOutputPathSize = length + 1; /** * UTF conversion: convert into the customer format, before being used*/ pDecodedPath = out_3gp_tmp; length = strlen(pDecodedPath); if( xVSS_context->UTFConversionContext.pConvFromUTF8Fct != M4OSA_NULL && xVSS_context->UTFConversionContext.pTempOutConversionBuffer != M4OSA_NULL ) { err = M4xVSS_internalConvertFromUTF8(xVSS_context, (M4OSA_Void *)out_3gp_tmp, (M4OSA_Void *)xVSS_context-> UTFConversionContext.pTempOutConversionBuffer, &length); if( err != M4NO_ERROR ) { M4OSA_TRACE1_1( "M4xVSS_SaveStart: M4xVSS_internalConvertFromUTF8 returns err: 0x%x", err); if( xVSS_context->pOutputFile != M4OSA_NULL ) { free(xVSS_context->pOutputFile); xVSS_context->pOutputFile = M4OSA_NULL; } return err; } pDecodedPath = xVSS_context->UTFConversionContext.pTempOutConversionBuffer; } /** * End of the UTF conversion, use the converted file path*/ xVSS_context->pCurrentEditSettings->pTemporaryFile = (M4OSA_Void *)M4OSA_32bitAlignedMalloc(length + 1, M4VS, (M4OSA_Char *)"M4xVSS_SaveStart: Temporary file"); if( xVSS_context->pCurrentEditSettings->pTemporaryFile == M4OSA_NULL ) { M4OSA_TRACE1_0("Allocation error in M4xVSS_SaveStart"); if( xVSS_context->pOutputFile != M4OSA_NULL ) { free(xVSS_context->pOutputFile); xVSS_context->pOutputFile = M4OSA_NULL; } return M4ERR_ALLOC; } memcpy((void *)xVSS_context->pCurrentEditSettings->pTemporaryFile, (void *)pDecodedPath, length + 1); /* Put nb of step for progression monitoring to 2, because audio mixing is needed */ xVSS_context->nbStepTotal = 2; } else { xVSS_context->pCurrentEditSettings->pOutputFile = xVSS_context->pOutputFile; xVSS_context->pCurrentEditSettings->pTemporaryFile = M4OSA_NULL; /* Put nb of step for progression monitoring to 1, because no audio mixing is needed */ xVSS_context->nbStepTotal = 1; } /** ***/ err = M4xVSS_internalGenerateEditedFile(xVSS_context); if( err != M4NO_ERROR ) { M4OSA_TRACE1_1( "M4xVSS_SaveStart: M4xVSS_internalGenerateEditedFile returned an error: 0x%x", err); /**/ if( xVSS_context->pCurrentEditSettings->pOutputFile != M4OSA_NULL && xVSS_context->pSettings->xVSS.pBGMtrack == M4OSA_NULL ) { free(xVSS_context->pCurrentEditSettings-> pOutputFile); xVSS_context->pCurrentEditSettings->pOutputFile = M4OSA_NULL; xVSS_context->pOutputFile = M4OSA_NULL; } if( xVSS_context->pCurrentEditSettings->pTemporaryFile != M4OSA_NULL && xVSS_context->pSettings->xVSS.pBGMtrack != M4OSA_NULL ) { free(xVSS_context->pCurrentEditSettings-> pTemporaryFile); xVSS_context->pCurrentEditSettings->pTemporaryFile = M4OSA_NULL; } if( xVSS_context->pOutputFile != M4OSA_NULL ) { free(xVSS_context->pOutputFile); xVSS_context->pOutputFile = M4OSA_NULL; } /* TODO: Translate error code of VSS to an xVSS error code */ return err; } /* Reinitialize current step number for progression monitoring */ xVSS_context->currentStep = 0; /* Change xVSS state */ xVSS_context->m_state = M4xVSS_kStateSaving; return M4NO_ERROR; } /** ****************************************************************************** * prototype M4OSA_ERR M4xVSS_SaveStop(M4OSA_Context pContext) * @brief This function unallocate save ressources and change xVSS * internal state. * @note This function must be called once M4xVSS_Step has returned * M4VSS3GPP_WAR_SAVING_DONE * * @param pContext (IN) Pointer on the xVSS edit context * @return M4NO_ERROR: No error * @return M4ERR_PARAMETER: At least one parameter is M4OSA_NULL * @return M4ERR_STATE: This function cannot not be called at this time ****************************************************************************** */ M4OSA_ERR M4xVSS_SaveStop( M4OSA_Context pContext ) { M4xVSS_Context *xVSS_context = (M4xVSS_Context *)pContext; M4OSA_ERR err = M4NO_ERROR; /* Check state */ if( xVSS_context->m_state != M4xVSS_kStateSaving ) { M4OSA_TRACE1_1( "Bad state when calling M4xVSS_SaveStop function! State is %d", xVSS_context->m_state); return M4ERR_STATE; } /* Free saving structures */ M4xVSS_internalFreeSaving(xVSS_context); if( xVSS_context->pOutputFile != M4OSA_NULL ) { free(xVSS_context->pOutputFile); xVSS_context->pOutputFile = M4OSA_NULL; } /* Change xVSS state */ xVSS_context->m_state = M4xVSS_kStateSaved; return M4NO_ERROR; } /** ****************************************************************************** * prototype M4OSA_ERR M4xVSS_Step(M4OSA_Context pContext, M4OSA_UInt8 *pProgress) * @brief This function executes differents tasks, depending of xVSS * internal state. * @note This function: * - analyses editing structure if called after M4xVSS_SendCommand * - generates preview file if called after M4xVSS_PreviewStart * - generates final edited file if called after M4xVSS_SaveStart * * @param pContext (IN) Pointer on the xVSS edit context * @param pProgress (IN/OUT) Pointer on an integer giving a * progress indication (between 0-100) * @return M4NO_ERROR: No error, the user must call M4xVSS_Step again * @return M4ERR_PARAMETER: At least one parameter is M4OSA_NULL * @return M4ERR_STATE: This function cannot not be called at this time * @return M4VSS3GPP_WAR_PREVIEW_READY: Preview file is generated * @return M4VSS3GPP_WAR_SAVING_DONE: Final edited file is generated * @return M4VSS3GPP_WAR_ANALYZING_DONE: Analyse is done ****************************************************************************** */ M4OSA_ERR M4xVSS_Step( M4OSA_Context pContext, M4OSA_UInt8 *pProgress ) { M4xVSS_Context *xVSS_context = (M4xVSS_Context *)pContext; M4VSS3GPP_EditContext pVssCtxt = xVSS_context->pCurrentEditContext; M4VSS3GPP_AudioMixingContext pAudioMixingCtxt = xVSS_context->pAudioMixContext; M4OSA_ERR err = M4NO_ERROR; M4OSA_UInt8 uiProgress = 0; switch( xVSS_context->m_state ) { case M4xVSS_kStateSaving: //case M4xVSS_kStateGeneratingPreview: { if( xVSS_context->editingStep == M4xVSS_kMicroStateEditing ) /* VSS -> creating effects, transitions ... */ { /* RC: to delete unecessary temp files on the fly */ M4VSS3GPP_InternalEditContext *pVSSContext = (M4VSS3GPP_InternalEditContext *)pVssCtxt; err = M4VSS3GPP_editStep(pVssCtxt, &uiProgress); if( ( err != M4NO_ERROR) && (err != M4VSS3GPP_WAR_EDITING_DONE) && (err != M4VSS3GPP_WAR_SWITCH_CLIP) ) { M4OSA_TRACE1_1( "M4xVSS_Step: M4VSS3GPP_editStep returned 0x%x\n", err); M4VSS3GPP_editCleanUp(pVssCtxt); /* TODO ? : Translate error code of VSS to an xVSS error code ? */ xVSS_context->pCurrentEditContext = M4OSA_NULL; return err; } /* RC: to delete unecessary temp files on the fly */ if( err == M4VSS3GPP_WAR_SWITCH_CLIP ) { #ifndef DO_NOT_REMOVE_TEMP_FILES /* It means we can delete the temporary file */ /* First step, check the temp file is not use somewhere else after */ M4OSA_UInt32 i; M4OSA_Int32 cmpResult = -1; for ( i = pVSSContext->uiCurrentClip; i < pVSSContext->uiClipNumber; i++ ) { if( pVSSContext->pClipList[pVSSContext->uiCurrentClip - 1].filePathSize == pVSSContext->pClipList[i].filePathSize ) { cmpResult = memcmp((void *)pVSSContext-> pClipList[pVSSContext->uiCurrentClip - 1].pFile, (void *)pVSSContext->pClipList[i].pFile, pVSSContext-> pClipList[pVSSContext->uiCurrentClip - 1].filePathSize); if( cmpResult == 0 ) { /* It means we found a corresponding file, we do not delete this temporary file */ break; } } } if( cmpResult != 0 ) { M4OSA_UInt32 ConvertedSize = 0; M4OSA_Char *toto; M4OSA_Char *pTmpStr; /* Convert result in UTF8 to check if we can delete it or not */ if( xVSS_context->UTFConversionContext.pConvToUTF8Fct != M4OSA_NULL && xVSS_context-> UTFConversionContext. pTempOutConversionBuffer != M4OSA_NULL ) { M4xVSS_internalConvertToUTF8(xVSS_context, (M4OSA_Void *)pVSSContext-> pClipList[pVSSContext->uiCurrentClip - 1].pFile, (M4OSA_Void *)xVSS_context-> UTFConversionContext. pTempOutConversionBuffer, &ConvertedSize); toto = (M4OSA_Char *)strstr((const char *)xVSS_context-> UTFConversionContext. pTempOutConversionBuffer, (const char *)xVSS_context->pTempPath); pTmpStr = xVSS_context->UTFConversionContext. pTempOutConversionBuffer; } else { toto = (M4OSA_Char *)strstr((const char *)pVSSContext-> pClipList[pVSSContext->uiCurrentClip - 1].pFile, (const char *)xVSS_context->pTempPath); pTmpStr = pVSSContext-> pClipList[pVSSContext->uiCurrentClip - 1].pFile; } if( toto != M4OSA_NULL ) { /* As temporary files can be imgXXX.3gp or vidXXX.3gp */ pTmpStr += (strlen((const char *)pTmpStr) - 10); /* Because temporary files have a length at most of 10 bytes */ toto = (M4OSA_Char *)strstr((const char *)pTmpStr, (const char *)"img"); if( toto != M4OSA_NULL ) { toto = (M4OSA_Char *)strstr((const char *)pTmpStr, (const char *)"vid"); } if( err == M4NO_ERROR ) /* It means the file is a temporary file, we can delete it */ { remove((const char *)pVSSContext-> pClipList[pVSSContext->uiCurrentClip - 1].pFile); } } } #endif /* DO_NOT_REMOVE_TEMP_FILES*/ /* */ err = M4NO_ERROR; } if( err == M4VSS3GPP_WAR_EDITING_DONE ) { xVSS_context->currentStep++; /* P4ME00003276: When a step is complete, increment currentStep and reset uiProgress unless progress would be wrong */ uiProgress = 0; err = M4xVSS_internalCloseEditedFile(xVSS_context); /* Fix for blrnxpsw#234---> */ if( err != M4NO_ERROR ) { if( err == ((M4OSA_UInt32)M4ERR_FILE_INVALID_POSITION) ) { err = M4xVSSERR_NO_MORE_SPACE; } M4OSA_TRACE1_1( "M4xVSS_internalCloseEditedFile returned an error: 0x%x", err); return err; } /*<---- Fix for blrnxpsw#234 */ if( xVSS_context->pCurrentEditSettings->xVSS.pBGMtrack != M4OSA_NULL ) { xVSS_context->editingStep = M4xVSS_kMicroStateAudioMixing; /* Open Audio mixing component */ err = M4xVSS_internalGenerateAudioMixFile(xVSS_context); if( err != M4NO_ERROR ) { M4OSA_TRACE1_1( "M4xVSS_internalGenerateAudioMixFile returned an error: 0x%x", err); /* TODO ? : Translate error code of VSS to an xVSS error code */ return err; } err = M4NO_ERROR; goto end_step; } else { err = M4VSS3GPP_WAR_SAVING_DONE; goto end_step; } } } else if( xVSS_context->editingStep == M4xVSS_kMicroStateAudioMixing ) /* Audio mixing: mix/replace audio track with given BGM */ { err = M4VSS3GPP_audioMixingStep(pAudioMixingCtxt, &uiProgress); if( ( err != M4NO_ERROR) && (err != M4VSS3GPP_WAR_END_OF_AUDIO_MIXING) ) { M4OSA_TRACE1_1( "M4VSS3GPP_audioMixingMain: M4VSS3GPP_audioMixingStep returned 0x%x\n", err); /* TODO ? : Translate error code of VSS to an xVSS error code */ return err; } if( err == M4VSS3GPP_WAR_END_OF_AUDIO_MIXING ) { xVSS_context->currentStep++; /* P4ME00003276: When a step is complete, increment currentStep and reset uiProgress unless progress would be wrong */ uiProgress = 0; err = M4xVSS_internalCloseAudioMixedFile(xVSS_context); if( err != M4NO_ERROR ) { M4OSA_TRACE1_1( "M4xVSS_internalCloseAudioMixedFile returned an error: 0x%x", err); /* TODO ? : Translate error code of VSS to an xVSS error code */ return err; } err = M4VSS3GPP_WAR_SAVING_DONE; goto end_step; } } else { M4OSA_TRACE1_0("Bad state in step function !"); return M4ERR_STATE; } } break; case M4xVSS_kStateAnalyzing: { if( xVSS_context->analyseStep == M4xVSS_kMicroStateAnalysePto3GPP ) /* Pto3GPP, analysing input parameters */ { if( xVSS_context->pPTo3GPPcurrentParams == M4OSA_NULL && xVSS_context->pPTo3GPPparamsList != M4OSA_NULL ) { xVSS_context->pPTo3GPPcurrentParams = xVSS_context-> pPTo3GPPparamsList; /* Current Pto3GPP Parameter is the first element of the list */ } else if( xVSS_context->pPTo3GPPcurrentParams != M4OSA_NULL && xVSS_context->pPTo3GPPparamsList != M4OSA_NULL ) { xVSS_context->pPTo3GPPcurrentParams = xVSS_context->pPTo3GPPcurrentParams-> pNext; /* Current Pto3GPP Parameter is the next element of the list */ if( xVSS_context->pPTo3GPPcurrentParams == M4OSA_NULL ) /* It means there is no next image to convert */ { /* We step to MCS phase */ xVSS_context->analyseStep = M4xVSS_kMicroStateAnalyzeMCS; err = M4NO_ERROR; goto end_step; } } else if( xVSS_context->pPTo3GPPparamsList == M4OSA_NULL ) { xVSS_context->analyseStep = M4xVSS_kMicroStateAnalyzeMCS; /* Change Analyzing micro state to MCS phase */ err = M4NO_ERROR; goto end_step; } /* Check if this file has to be converted or not */ /* If not, we just return M4NO_ERROR, and go to next file */ if( xVSS_context->pPTo3GPPcurrentParams->isCreated == M4OSA_FALSE ) { /* Opening Pto3GPP */ err = M4xVSS_internalStartConvertPictureTo3gp(xVSS_context); if( err != M4NO_ERROR ) { M4OSA_TRACE1_1("M4xVSS_Step: M4xVSS_internalStartConvertPictureTo3gp \ returned error: 0x%x", err) /* TODO ? : Translate error code of VSS to an xVSS error code */ return err; } xVSS_context->analyseStep = M4xVSS_kMicroStateConvertPto3GPP; } } else if( xVSS_context->analyseStep == M4xVSS_kMicroStateConvertPto3GPP ) /* Pto3GPP, converting */ { err = M4PTO3GPP_Step(xVSS_context->pM4PTO3GPP_Ctxt); /* update progress bar */ if(xVSS_context->pCallBackCtxt->m_NbImage > 1) { uiProgress = (xVSS_context->pCallBackCtxt->m_ImageCounter * 100) / (xVSS_context->pCallBackCtxt->m_NbImage -1); } if( ( err != M4NO_ERROR) && (err != ((M4OSA_UInt32)M4PTO3GPP_WAR_END_OF_PROCESSING)) ) { /* TO BE CHECKED NO LEAKS !!!!! */ M4OSA_TRACE1_1( "M4xVSS_Step: M4PTO3GPP_Step returned 0x%x\n", err); /* TODO ? : Translate error code of VSS to an xVSS error code */ return err; } else if( err == ((M4OSA_UInt32)M4PTO3GPP_WAR_END_OF_PROCESSING) ) { xVSS_context->currentStep++; /* P4ME00003276: When a step is complete, increment currentStep and reset uiProgress unless progress would be wrong */ uiProgress = 0; xVSS_context->analyseStep = M4xVSS_kMicroStateAnalysePto3GPP; /* We go back to analyze parameters to see if there is a next file to convert */ /* RC !!!!!!!! */ xVSS_context->pPTo3GPPcurrentParams->isCreated = M4OSA_TRUE; /* To avoid reconverting it if another SendCommand is called */ err = M4xVSS_internalStopConvertPictureTo3gp(xVSS_context); /*SS:blrnxpsw# 234 */ if( err == ((M4OSA_UInt32)M4ERR_FILE_INVALID_POSITION) ) { err = M4xVSSERR_NO_MORE_SPACE; } if( err != M4NO_ERROR ) { M4OSA_TRACE1_1("M4xVSS_Step:\ M4xVSS_internalStopConvertPictureTo3gp returned 0x%x", err); /* TODO ? : Translate error code of VSS to an xVSS error code */ return err; } } } else if( xVSS_context->analyseStep == M4xVSS_kMicroStateAnalyzeMCS ) /* MCS: analyzing input parameters */ { if( xVSS_context->pMCScurrentParams == M4OSA_NULL \ && xVSS_context->pMCSparamsList != M4OSA_NULL ) { xVSS_context->pMCScurrentParams = xVSS_context-> pMCSparamsList; /* Current MCS Parameter is the first element of the list */ } else if( xVSS_context->pMCScurrentParams != M4OSA_NULL \ && xVSS_context->pMCSparamsList != M4OSA_NULL ) { xVSS_context->pMCScurrentParams = xVSS_context->pMCScurrentParams-> pNext; /* Current MCS Parameter is the next element of the list */ if( xVSS_context->pMCScurrentParams == M4OSA_NULL ) /* It means there is no next image to convert */ { xVSS_context->analyseStep = M4xVSS_kMicroStateAnalysePto3GPP; /* Reinit Analyzing micro state */ xVSS_context->m_state = M4xVSS_kStateOpened; /* Change xVSS state */ err = M4VSS3GPP_WAR_ANALYZING_DONE; goto end_step; /* End of Analysis */ } } else if( xVSS_context->pMCSparamsList == M4OSA_NULL ) { xVSS_context->analyseStep = M4xVSS_kMicroStateAnalysePto3GPP; /* Reinit Analyzing micro state */ xVSS_context->m_state = M4xVSS_kStateOpened; /* Change xVSS state */ err = M4VSS3GPP_WAR_ANALYZING_DONE; goto end_step; /* End of Analysis */ } /* Check if this file has to be transcoded or not */ /* If not, we just return M4NO_ERROR, and go to next file */ if( xVSS_context->pMCScurrentParams->isCreated == M4OSA_FALSE ) { /* Opening MCS */ M4OSA_UInt32 rotationDegree = 0; err = M4xVSS_internalStartTranscoding(xVSS_context, &rotationDegree); if( err != M4NO_ERROR ) { M4OSA_TRACE1_1("M4xVSS_Step: M4xVSS_internalStartTranscoding returned\ error: 0x%x", err); return err; } int32_t index = xVSS_context->pMCScurrentParams->videoclipnumber; /* The cuts are done in the MCS, so we need to replace the beginCutTime and endCutTime to keep the entire video*/ xVSS_context->pSettings->pClipList[index]->uiBeginCutTime = 0; xVSS_context->pSettings->pClipList[index]->uiEndCutTime = 0; M4OSA_TRACE1_1("M4xVSS_Step: \ M4xVSS_internalStartTranscoding returned \ success; MCS context: 0x%x", xVSS_context->pMCS_Ctxt); xVSS_context->analyseStep = M4xVSS_kMicroStateTranscodeMCS; // Retain rotation info of trimmed / transcoded file xVSS_context->pSettings->pClipList[index]->\ ClipProperties.videoRotationDegrees = rotationDegree; } } else if( xVSS_context->analyseStep == M4xVSS_kMicroStateTranscodeMCS ) /* MCS: transcoding file */ { err = M4MCS_step(xVSS_context->pMCS_Ctxt, &uiProgress); /*SS:blrnxpsw# 234 */ if( err == ((M4OSA_UInt32)M4MCS_ERR_NOMORE_SPACE) ) { err = M4xVSSERR_NO_MORE_SPACE; } if( ( err != M4NO_ERROR) && (err != M4MCS_WAR_TRANSCODING_DONE) ) { /* TO BE CHECKED NO LEAKS !!!!! */ M4OSA_TRACE1_1("M4xVSS_Step: M4MCS_step returned 0x%x\n", err); /* TODO ? : Translate error code of MCS to an xVSS error code ? */ return err; } else if( err == M4MCS_WAR_TRANSCODING_DONE ) { xVSS_context->currentStep++; /* P4ME00003276: When a step is complete, increment currentStep and reset uiProgress unless progress would be wrong */ uiProgress = 0; xVSS_context->analyseStep = M4xVSS_kMicroStateAnalyzeMCS; /* We go back to analyze parameters to see if there is a next file to transcode */ /* RC !!!!!!!!!*/ xVSS_context->pMCScurrentParams->isCreated = M4OSA_TRUE; /* To avoid reconverting it if another SendCommand is called */ err = M4xVSS_internalStopTranscoding(xVSS_context); if( err != M4NO_ERROR ) { M4OSA_TRACE1_1("M4xVSS_Step:\ M4xVSS_internalStopTranscoding returned 0x%x", err); /* TODO ? : Translate error code of MCS to an xVSS error code ? */ return err; } } } else { M4OSA_TRACE1_0("Bad micro state in analyzing state") return M4ERR_STATE; } } break; default: M4OSA_TRACE1_1( "Bad state when calling M4xVSS_Step function! State is %d", xVSS_context->m_state); return M4ERR_STATE; } end_step: /* Compute progression */ if( xVSS_context->nbStepTotal != 0 ) { *pProgress = (M4OSA_UInt8)(( ( xVSS_context->currentStep * 100) \ / (xVSS_context->nbStepTotal)) + (uiProgress / (xVSS_context->nbStepTotal))); if( *pProgress > 100 ) { *pProgress = 100; } } else { *pProgress = 100; } return err; } /** ****************************************************************************** * prototype M4OSA_ERR M4xVSS_CloseCommand(M4OSA_Context pContext) * @brief This function deletes current editing profile, unallocate * ressources and change xVSS internal state. * @note After this function, the user can call a new M4xVSS_SendCommand * * @param pContext (IN) Pointer on the xVSS edit context * @return M4NO_ERROR: No error * @return M4ERR_PARAMETER: At least one parameter is M4OSA_NULL * @return M4ERR_STATE: This function cannot not be called at this time ****************************************************************************** */ M4OSA_ERR M4xVSS_CloseCommand( M4OSA_Context pContext ) { M4xVSS_Context *xVSS_context = (M4xVSS_Context *)pContext; M4OSA_ERR err = M4NO_ERROR; /* Check state */ /* Depending of the state, differents things have to be done */ switch( xVSS_context->m_state ) { case M4xVSS_kStateOpened: /* Nothing to do here */ err = M4xVSS_internalFreeSaving(xVSS_context); break; case M4xVSS_kStateSaving: { if( xVSS_context->editingStep == M4xVSS_kMicroStateEditing ) { err = M4xVSS_internalCloseEditedFile(xVSS_context); if( err != M4NO_ERROR ) { /* Fix for blrnxpsw#234---->*/ if( err == ((M4OSA_UInt32)M4ERR_FILE_INVALID_POSITION) ) { err = M4xVSSERR_NO_MORE_SPACE; } M4OSA_TRACE1_1("M4xVSS_CloseCommand:\ M4xVSS_internalCloseEditedFile returned an error: 0x%x", err); /* we are retaining error here and returning error in the end of the function as to aviod memory leak*/ //return err; } } else if( xVSS_context->editingStep == M4xVSS_kMicroStateAudioMixing ) { err = M4xVSS_internalCloseAudioMixedFile(xVSS_context); if( err != M4NO_ERROR ) { /* Fix for blrnxpsw#234---->*/ if( err == ((M4OSA_UInt32)M4ERR_FILE_INVALID_POSITION) ) { err = M4xVSSERR_NO_MORE_SPACE; } M4OSA_TRACE1_1("M4xVSS_CloseCommand: \ M4xVSS_internalCloseAudioMixedFile returned an error: 0x%x", err); /* we are retaining error here and returning error in the end of the function as to aviod memory leak*/ //return err; /* <----Fix for blrnxpsw#234*/ } } err = M4xVSS_internalFreeSaving(xVSS_context); /* We free this pointer only if a BGM track is present, because in that case, this pointer owns to us */ if( xVSS_context->pSettings->xVSS.pBGMtrack != M4OSA_NULL ) { /*if(M4OSA_NULL != xVSS_context->pSettings->pOutputFile) { free(xVSS_context->pSettings->pOutputFile); xVSS_context->pSettings->pOutputFile = M4OSA_NULL; }*/ /*if(M4OSA_NULL != xVSS_context->pSettings->pTemporaryFile) { free(xVSS_context->pSettings->pTemporaryFile); xVSS_context->pSettings->pTemporaryFile = M4OSA_NULL; }*/ } } break; case M4xVSS_kStateSaved: break; case M4xVSS_kStateAnalyzing: { if( xVSS_context->analyseStep == M4xVSS_kMicroStateConvertPto3GPP ) { /* Free Pto3GPP module */ err = M4xVSS_internalStopConvertPictureTo3gp(xVSS_context); /* Fix for blrnxpsw#234---->*/ if( err != M4NO_ERROR ) { if( err == ((M4OSA_UInt32)M4ERR_FILE_INVALID_POSITION) ) { err = M4xVSSERR_NO_MORE_SPACE; } M4OSA_TRACE1_1("M4xVSS_Step: \ M4xVSS_internalStopConvertPictureTo3gp returned 0x%x", err); /* we are retaining error here and returning error in the end of the function as to aviod memory leak*/ //return err; } /* <-----Fix for blrnxpsw#234>*/ } else if( xVSS_context->analyseStep == M4xVSS_kMicroStateTranscodeMCS ) { /* Free MCS module */ err = M4MCS_abort(xVSS_context->pMCS_Ctxt); /* Fix for blrnxpsw#234---->*/ if( err != M4NO_ERROR ) { if( err == ((M4OSA_UInt32)M4ERR_FILE_INVALID_POSITION) ) { err = M4xVSSERR_NO_MORE_SPACE; } M4OSA_TRACE1_1("M4xVSS_Step: M4MCS_abort returned 0x%x", err); /* we are retaining error here and returning error in the end of the function as to aviod memory leak*/ //return err; } /* <---Fix for blrnxpsw#234*/ } } break; default: M4OSA_TRACE1_1( "Bad state when calling M4xVSS_CloseCommand function! State is %d", xVSS_context->m_state); return M4ERR_STATE; } /* Free Send command */ M4xVSS_freeCommand(xVSS_context); xVSS_context->m_state = M4xVSS_kStateInitialized; /* Change xVSS state */ return err; } /** ****************************************************************************** * prototype M4OSA_ERR M4xVSS_CleanUp(M4OSA_Context pContext) * @brief This function deletes all xVSS ressources * @note This function must be called after M4xVSS_CloseCommand. * * @param pContext (IN) Pointer on the xVSS edit context * @return M4NO_ERROR: No error * @return M4ERR_PARAMETER: At least one parameter is M4OSA_NULL * @return M4ERR_STATE: This function cannot not be called at this time ****************************************************************************** */ M4OSA_ERR M4xVSS_CleanUp( M4OSA_Context pContext ) { M4xVSS_Context *xVSS_context = (M4xVSS_Context *)pContext; M4OSA_TRACE3_0("M4xVSS_CleanUp:entering"); /* Check state */ if( xVSS_context->m_state != M4xVSS_kStateInitialized ) { M4OSA_TRACE1_1(\ "Bad state when calling M4xVSS_CleanUp function! State is %d",\ xVSS_context->m_state); return M4ERR_STATE; } /** * UTF conversion: free temporary buffer*/ if( xVSS_context->UTFConversionContext.pTempOutConversionBuffer != M4OSA_NULL ) { free(xVSS_context-> UTFConversionContext.pTempOutConversionBuffer); xVSS_context->UTFConversionContext.pTempOutConversionBuffer = M4OSA_NULL; } free(xVSS_context->pTempPath); xVSS_context->pTempPath = M4OSA_NULL; free(xVSS_context->pSettings); xVSS_context->pSettings = M4OSA_NULL; free(xVSS_context); xVSS_context = M4OSA_NULL; M4OSA_TRACE3_0("M4xVSS_CleanUp:leaving "); return M4NO_ERROR; } /** ****************************************************************************** * prototype M4xVSS_GetVersion(M4_VersionInfo *pVersion) * @brief This function get the version of the Video Studio 2.1 * * @param pVersion (IN) Pointer on the version info struct * @return M4NO_ERROR: No error * @return M4ERR_PARAMETER: At least one parameter is M4OSA_NULL ****************************************************************************** */ M4OSA_ERR M4xVSS_GetVersion( M4_VersionInfo *pVersion ) { /* Just used for a grep in code */ /* CHANGE_VERSION_HERE */ static const M4OSA_Char cVersion[26] = "NXPSW_VideoStudio21_1_3_0"; if( M4OSA_NULL == pVersion ) { return M4ERR_PARAMETER; } pVersion->m_major = M4_xVSS_MAJOR; pVersion->m_minor = M4_xVSS_MINOR; pVersion->m_revision = M4_xVSS_REVISION; pVersion->m_structSize = sizeof(M4_VersionInfo); return M4NO_ERROR; } /** ****************************************************************************** * M4OSA_ERR M4xVSS_CreateClipSettings() * @brief Allows filling a clip settings structure with default values * * @note WARNING: pClipSettings->Effects[ ] will be allocated in this function. * pClipSettings->pFile will be allocated in this function. * * @param pClipSettings (IN) Pointer to a valid M4VSS3GPP_ClipSettings structure * @param pFile (IN) Clip file name * @param filePathSize (IN) Size of the clip path (needed for the UTF16 conversion) * @param nbEffects (IN) Nb of effect settings to allocate * @return M4NO_ERROR: No error * @return M4ERR_PARAMETER: pClipSettings is M4OSA_NULL (debug only) ****************************************************************************** */ M4OSA_ERR M4xVSS_CreateClipSettings( M4VSS3GPP_ClipSettings *pClipSettings, M4OSA_Void *pFile, M4OSA_UInt32 filePathSize, M4OSA_UInt8 nbEffects ) { M4OSA_ERR err = M4NO_ERROR; M4OSA_TRACE3_1("M4xVSS_CreateClipSettings called with pClipSettings=0x%p", pClipSettings); /** * Check input parameter */ M4OSA_DEBUG_IF2((M4OSA_NULL == pClipSettings), M4ERR_PARAMETER, "M4xVSS_CreateClipSettings: pClipSettings is NULL"); /* Create inherited VSS3GPP stuff */ /*err = M4VSS3GPP_editCreateClipSettings(pClipSettings, pFile,nbEffects);*/ /*FB: add clip path size (needed for UTF 16 conversion)*/ err = M4VSS3GPP_editCreateClipSettings(pClipSettings, pFile, filePathSize, nbEffects); if( M4NO_ERROR != err ) { M4OSA_TRACE1_1("M4xVSS_CreateClipSettings :\ ERROR in M4VSS3GPP_editCreateClipSettings = 0x%x", err); return err; } /* Set the clip settings to default */ pClipSettings->xVSS.uiBeginCutPercent = 0; pClipSettings->xVSS.uiEndCutPercent = 0; pClipSettings->xVSS.uiDuration = 0; pClipSettings->xVSS.isPanZoom = M4OSA_FALSE; pClipSettings->xVSS.PanZoomTopleftXa = 0; pClipSettings->xVSS.PanZoomTopleftYa = 0; pClipSettings->xVSS.PanZoomTopleftXb = 0; pClipSettings->xVSS.PanZoomTopleftYb = 0; pClipSettings->xVSS.PanZoomXa = 0; pClipSettings->xVSS.PanZoomXb = 0; /** * Return with no error */ M4OSA_TRACE3_0("M4xVSS_CreateClipSettings(): returning M4NO_ERROR"); return M4NO_ERROR; } /** ****************************************************************************** * M4OSA_ERR M4xVSS_DuplicateClipSettings() * @brief Duplicates a clip settings structure, performing allocations if required * * @param pClipSettingsDest (IN) Pointer to a valid M4VSS3GPP_ClipSettings structure * @param pClipSettingsOrig (IN) Pointer to a valid M4VSS3GPP_ClipSettings structure * @param bCopyEffects (IN) Flag to know if we have to duplicate effects * @return M4NO_ERROR: No error * @return M4ERR_PARAMETER: pClipSettings is M4OSA_NULL (debug only) ****************************************************************************** */ M4OSA_ERR M4xVSS_DuplicateClipSettings( M4VSS3GPP_ClipSettings *pClipSettingsDest, M4VSS3GPP_ClipSettings *pClipSettingsOrig, M4OSA_Bool bCopyEffects ) { M4OSA_ERR err = M4NO_ERROR; M4OSA_TRACE3_2( "M4xVSS_DuplicateClipSettings called with dest=0x%p src=0x%p", pClipSettingsDest, pClipSettingsOrig); /* Check input parameter */ M4OSA_DEBUG_IF2((M4OSA_NULL == pClipSettingsDest), M4ERR_PARAMETER, "M4xVSS_DuplicateClipSettings: pClipSettingsDest is NULL"); M4OSA_DEBUG_IF2((M4OSA_NULL == pClipSettingsOrig), M4ERR_PARAMETER, "M4xVSS_DuplicateClipSettings: pClipSettingsOrig is NULL"); /* Call inherited VSS3GPP duplication */ err = M4VSS3GPP_editDuplicateClipSettings(pClipSettingsDest, pClipSettingsOrig, bCopyEffects); if( M4NO_ERROR != err ) { M4OSA_TRACE1_1("M4xVSS_CreateClipSettings :\ ERROR in M4VSS3GPP_editDuplicateClipSettings = 0x%x", err); return err; } /* Return with no error */ M4OSA_TRACE3_0("M4xVSS_DuplicateClipSettings(): returning M4NO_ERROR"); return M4NO_ERROR; } /** ****************************************************************************** * M4OSA_ERR M4xVSS_FreeClipSettings() * @brief Free the pointers allocated in the ClipSetting structure (pFile, Effects, ...). * * @param pClipSettings (IN) Pointer to a valid M4VSS3GPP_ClipSettings structure * @return M4NO_ERROR: No error * @return M4ERR_PARAMETER: pClipSettings is M4OSA_NULL (debug only) ****************************************************************************** */ M4OSA_ERR M4xVSS_FreeClipSettings( M4VSS3GPP_ClipSettings *pClipSettings ) { /** * Check input parameter */ M4OSA_DEBUG_IF2((M4OSA_NULL == pClipSettings), M4ERR_PARAMETER, "M4xVSS_FreeClipSettings: pClipSettings is NULL"); /* Free inherited VSS3GPP stuff */ M4VSS3GPP_editFreeClipSettings(pClipSettings); return M4NO_ERROR; } /** ****************************************************************************** * prototype M4OSA_ERR M4xVSS_getMCSContext(M4OSA_Context pContext, M4OSA_Context* mcsContext) * @brief This function returns the MCS context within the xVSS internal context * @note This function must be called only after VSS state has moved to analyzing state or * beyond * * @param pContext (IN) Pointer on the xVSS edit context * @param mcsContext (OUT) Pointer to pointer of mcs context to return * @return M4NO_ERROR: No error * @return M4ERR_PARAMETER: At least one parameter is M4OSA_NULL * @return M4ERR_STATE: This function cannot not be called at this time ****************************************************************************** */ M4OSA_ERR M4xVSS_getMCSContext( M4OSA_Context pContext, M4OSA_Context *mcsContext ) { M4xVSS_Context *xVSS_context = (M4xVSS_Context *)pContext; M4OSA_ERR err = M4NO_ERROR; /** * Check input parameter */ M4OSA_DEBUG_IF2((M4OSA_NULL == pContext), M4ERR_PARAMETER, "M4xVSS_getMCSContext: pContext is NULL"); if( xVSS_context->m_state == M4xVSS_kStateInitialized ) { M4OSA_TRACE1_1("M4xVSS_getMCSContext: Bad state! State is %d",\ xVSS_context->m_state); return M4ERR_STATE; } *mcsContext = xVSS_context->pMCS_Ctxt; return err; } /** ****************************************************************************** * prototype M4OSA_ERR M4xVSS_getVSS3GPPContext(M4OSA_Context pContext, * M4OSA_Context* mcsContext) * @brief This function returns the VSS3GPP context within the xVSS internal context * @note This function must be called only after VSS state has moved to Generating preview * or beyond * @param pContext (IN) Pointer on the xVSS edit context * @param vss3gppContext (OUT) Pointer to pointer of vss3gpp context to return * @return M4NO_ERROR: No error * @return M4ERR_PARAMETER: At least one parameter is M4OSA_NULL * @return M4ERR_STATE: This function cannot not be called at this time ****************************************************************************** */ M4OSA_ERR M4xVSS_getVSS3GPPContext( M4OSA_Context pContext, M4OSA_Context *vss3gppContext ) { M4xVSS_Context *xVSS_context = (M4xVSS_Context *)pContext; M4OSA_ERR err = M4NO_ERROR; /** * Check input parameter */ M4OSA_DEBUG_IF2((M4OSA_NULL == pContext), M4ERR_PARAMETER, "M4xVSS_getVSS3GPPContext: pContext is NULL"); if( xVSS_context->m_state < M4xVSS_kStateSaving ) { M4OSA_TRACE1_1("M4xVSS_getVSS3GPPContext: Bad state! State is %d",\ xVSS_context->m_state); return M4ERR_STATE; } *vss3gppContext = xVSS_context->pCurrentEditContext; return err; } M4OSA_ERR M4xVSS_getVideoDecoderCapabilities(M4DECODER_VideoDecoders **decoders) { M4OSA_ERR err = M4NO_ERROR; // Call the decoder api directly // to get all the video decoder capablities. err = VideoEditorVideoDecoder_getVideoDecodersAndCapabilities(decoders); return err; }