shithub: openh264

ref: 9b21ece789c066db96be8810f0892560adcd63b8
dir: /codec/encoder/core/inc/param_svc.h/

View raw version
/*!
 * \copy
 *     Copyright (c)  2009-2013, Cisco Systems
 *     All rights reserved.
 *
 *     Redistribution and use in source and binary forms, with or without
 *     modification, are permitted provided that the following conditions
 *     are met:
 *
 *        * Redistributions of source code must retain the above copyright
 *          notice, this list of conditions and the following disclaimer.
 *
 *        * Redistributions in binary form must reproduce the above copyright
 *          notice, this list of conditions and the following disclaimer in
 *          the documentation and/or other materials provided with the
 *          distribution.
 *
 *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *     FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *     COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *     ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *     POSSIBILITY OF SUCH DAMAGE.
 *
 *
 * \file	param_svc.h
 *
 * \brief	Configurable parameters in H.264/SVC Encoder
 *
 * \date	4/20/2009 Created
 *
 *************************************************************************************
 */
#if !defined(WELS_ENCODER_PARAMETER_SVC_H__)
#define WELS_ENCODER_PARAMETER_SVC_H__

#include <string.h>
#include <math.h>
#include "typedefs.h"
#include "codec_def.h"
#include "macros.h"
#include "wels_const.h"
#include "wels_common_basis.h"
#include "rc.h"
#include "svc_enc_slice_segment.h"
#include "as264_common.h"

namespace WelsSVCEnc {

#define   INVALID_TEMPORAL_ID   ((uint8_t)0xff)

extern const uint8_t   g_kuiTemporalIdListTable[MAX_TEMPORAL_LEVEL][MAX_GOP_SIZE + 1];

/*!
* \brief	get Logarithms base 2 of (upper/base)
* \param	base	based scaler
* \param	upper	input upper value
* \return	2 based scaling factor
*/
static __inline uint32_t GetLogFactor( real32_t base, real32_t upper )
{
	const double dLog2factor	= log10(1.0 * upper / base) / log10(2.0);
	const double dEpsilon		= 0.0001;
	const double dRound		= floor( dLog2factor + 0.5 );	

	if( dLog2factor < dRound+dEpsilon && dRound < dLog2factor+dEpsilon )
	{
		return (uint32_t)(dRound);
	}
	return UINT_MAX;
}

/*
 *	Dependency Layer Parameter
 */
typedef struct TagDLayerParam {
	int32_t		iActualWidth;			// input source picture actual width
	int32_t		iActualHeight;			// input source picture actual height
	int32_t		iFrameWidth;			// frame width
	int32_t		iFrameHeight;			// frame height

	int32_t		iSpatialBitrate;

	/* temporal settings related */
	int32_t		iTemporalResolution;
	int32_t		iDecompositionStages;	
	uint8_t     uiCodingIdx2TemporalId[(1<<MAX_TEMPORAL_LEVEL)+1];

	uint8_t		uiProfileIdc;			// value of profile IDC (0 for auto-detection)	

	int8_t		iHighestTemporalId;
	//	uint8_t		uiDependencyId;
	int8_t      iDLayerQp;

	SMulSliceOption sMso;	// multiple slice options

	float		fInputFrameRate;		// input frame rate
	float		fOutputFrameRate;		// output frame rate

#ifdef ENABLE_FRAME_DUMP
	str_t		sRecFileName[MAX_FNAME_LEN];	// file to be constructed
#endif//ENABLE_FRAME_DUMP	
} SDLayerParam;

/*
 *	Cisco OpenH264 Encoder Parameter Configuration
 */
typedef struct TagWelsSvcCodingParam {	
	SDLayerParam	sDependencyLayers[MAX_DEPENDENCY_LAYER];

	/* General */
#ifdef ENABLE_TRACE_FILE
    str_t			sTracePath[MAX_FNAME_LEN];		// log file for wels encoder
#endif

	uint32_t	uiGopSize;			// GOP size (at maximal frame rate: 16)
	uint32_t	uiIntraPeriod;		// intra period (multiple of GOP size as desired)
	int32_t		iNumRefFrame;		// number of reference frame used

	int32_t     iActualPicWidth;    //   actual input picture width
	int32_t     iActualPicHeight;   //   actual input picture height

	struct {
		int32_t iLeft;
		int32_t iTop;
		int32_t iWidth;
		int32_t iHeight;
	}SUsedPicRect;	// the rect in input picture that encoder actually used

	str_t       *pCurPath; // record current lib path such as:/pData/pData/com.wels.enc/lib/ 

	float		fMaxFrameRate;		// maximal frame rate [Hz / fps]
	int32_t		iInputCsp;			// color space of input sequence	
	uint32_t	uiFrameToBeCoded;	// frame to be encoded (at input frame rate)	

	int32_t		iTargetBitrate;			// overall target bitrate introduced in RC module	
	int16_t		iMultipleThreadIdc;		// 1	# 0: auto(dynamic imp. internal encoder); 1: multiple threads imp. disabled; > 1: count number of threads;
	int16_t		iCountThreadsNum;			//		# derived from disable_multiple_slice_idc (=0 or >1) means;

	int32_t		iLTRRefNum;
	uint32_t    uiLtrMarkPeriod;	//the min distance of two int32_t references

	bool_t		bDeblockingParallelFlag;	// deblocking filter parallelization control flag
	bool_t		bMgsT0OnlyStrategy; //MGS_T0_only_strategy
    bool_t		bEnableSSEI;		
	bool_t		bEnableFrameCroppingFlag;	// enable frame cropping flag: TRUE alwayse in application
	
	bool_t		bEnableCropPic;			// enable cropping source picture. , 8/25/2010
											// FALSE: Streaming Video Sharing; TRUE: Video Conferencing Meeting;
	int8_t		iDecompStages;		// GOP size dependency		

	/* Deblocking loop filter */
	int8_t		iLoopFilterDisableIdc;	// 0: on, 1: off, 2: on except for slice boundaries
	int8_t		iLoopFilterAlphaC0Offset;// AlphaOffset: valid range [-6, 6], default 0

	int8_t		iLoopFilterBetaOffset;	// BetaOffset:	valid range [-6, 6], default 0	
	int8_t		iInterLayerLoopFilterDisableIdc; // Employed based upon inter-layer, same comment as above
	int8_t		iInterLayerLoopFilterAlphaC0Offset;	// InterLayerLoopFilterAlphaC0Offset
	int8_t		iInterLayerLoopFilterBetaOffset;	// InterLayerLoopFilterBetaOffset

	/* Rate Control */
	bool_t		bEnableRc;
	int8_t		iRCMode;	
	int8_t		iPaddingFlag;
	/* denoise control */
	bool_t      bEnableDenoise;				

	/* scene change detection control */
	bool_t      bEnableSceneChangeDetect;	 
	// background detection control
	bool_t		bEnableBackgroundDetection; 
	/* adaptive quantization control */
	bool_t		bEnableAdaptiveQuant;	         
	/* long term reference control */
	bool_t      bEnableLongTermReference;

	/* pSps pPps id addition control */
	bool_t      bEnableSpsPpsIdAddition;
	/* Layer definition */
	bool_t		bPrefixNalAddingCtrl;
	int8_t		iNumDependencyLayer;	// number of dependency(Spatial/CGS) layers used to be encoded
	int8_t		iNumTemporalLayer;		// number of temporal layer specified
    

    
public:
	TagWelsSvcCodingParam(const bool_t kbEnableRc = true)
	{
		FillDefault( kbEnableRc );
	}
	~TagWelsSvcCodingParam()	{}

	void FillDefault( const bool_t kbEnableRc )
	{
		uiGopSize			= 1;			// GOP size (at maximal frame rate: 16)
		uiIntraPeriod		= 0;			// intra period (multiple of GOP size as desired)
		iNumRefFrame		= MIN_REF_PIC_COUNT;	// number of reference frame used

		iActualPicWidth	= 0;    //   actual input picture width
		iActualPicHeight	= 0;	//   actual input picture height
		SUsedPicRect.iLeft	=
		SUsedPicRect.iTop	=
		SUsedPicRect.iWidth	=
		SUsedPicRect.iHeight= 0;	// the rect in input picture that encoder actually used

		pCurPath			= NULL; // record current lib path such as:/pData/pData/com.wels.enc/lib/ 

		fMaxFrameRate		= MAX_FRAME_RATE;	// maximal frame rate [Hz / fps]		
		iInputCsp			= videoFormatI420;	// input sequence color space in default
		uiFrameToBeCoded	= (uint32_t)-1;		// frame to be encoded (at input frame rate)

		iTargetBitrate			= 0;	// overall target bitrate introduced in RC module
		bDeblockingParallelFlag= false;	// deblocking filter parallelization control flag
#ifdef MT_ENABLED
		iMultipleThreadIdc		= 0;	// auto to detect cpu cores inside
#else
		iMultipleThreadIdc		= 1;	// 1 # 0: auto(dynamic imp. internal encoder); 1: multiple threads imp. disabled; > 1: count number of threads;
#endif//MT_ENABLED
		iCountThreadsNum		= 1;	//		# derived from disable_multiple_slice_idc (=0 or >1) means;

		iLTRRefNum				= 0;
		uiLtrMarkPeriod			= 30;	//the min distance of two int32_t references		

		bMgsT0OnlyStrategy			= true;	// Strategy of have MGS only at T0 frames (0: do not use this strategy; 1: use this strategy) 
		bEnableSSEI					= true;
		bEnableFrameCroppingFlag	= true;	// enable frame cropping flag: TRUE alwayse in application
		bEnableCropPic				= true;	// enable cropping source picture. , 8/25/2010
		// FALSE: Streaming Video Sharing; TRUE: Video Conferencing Meeting;
		iDecompStages				= 0;	// GOP size dependency, unknown here and be revised later

		/* Deblocking loop filter */
		iLoopFilterDisableIdc		= 1;	// 0: on, 1: off, 2: on except for slice boundaries
		iLoopFilterAlphaC0Offset	= 0;	// AlphaOffset: valid range [-6, 6], default 0
		iLoopFilterBetaOffset		= 0;	// BetaOffset:	valid range [-6, 6], default 0
		iInterLayerLoopFilterDisableIdc		= 1;	// Employed based upon inter-layer, same comment as above
		iInterLayerLoopFilterAlphaC0Offset	= 0;	// InterLayerLoopFilterAlphaC0Offset
		iInterLayerLoopFilterBetaOffset		= 0;	// InterLayerLoopFilterBetaOffset

		/* Rate Control */
		bEnableRc		= kbEnableRc;	
		iRCMode			= 0;	
		iPaddingFlag	= 0;
		
		bEnableDenoise				= false;	// denoise control		
		bEnableSceneChangeDetect	= true;		// scene change detection control		
		bEnableBackgroundDetection	= true;		// background detection control		
		bEnableAdaptiveQuant		= true;		// adaptive quantization control		
		bEnableLongTermReference	= false;	// long term reference control		
		bEnableSpsPpsIdAddition	= true;		// pSps pPps id addition control		
		bPrefixNalAddingCtrl		= true;		// prefix NAL adding control
		iNumDependencyLayer		= 0;		// number of dependency(Spatial/CGS) layers used to be encoded
		iNumTemporalLayer			= 0;		// number of temporal layer specified		
	}

	int32_t ParamTranscode( SVCEncodingParam& pCodingParam, const bool_t kbEnableRc = true )
	{		
		pCodingParam.fFrameRate		= WELS_CLIP3(pCodingParam.fFrameRate, MIN_FRAME_RATE, MAX_FRAME_RATE);
		iInputCsp		= pCodingParam.iInputCsp;		// color space of input sequence	
		uiFrameToBeCoded	= (uint32_t)-1;		// frame to be encoded (at input frame rate), -1 dependents on length of input sequence

		iActualPicWidth   = pCodingParam.iPicWidth;
		iActualPicHeight  = pCodingParam.iPicHeight; 

		SUsedPicRect.iLeft = 0;
		SUsedPicRect.iTop  = 0;
		SUsedPicRect.iWidth = ((iActualPicWidth >> 1) << 1);
		SUsedPicRect.iHeight = ((iActualPicHeight >> 1) << 1);

		/* Deblocking loop filter */
#ifdef MT_ENABLED
		iLoopFilterDisableIdc	= 2;//pCodingParam.iLoopFilterDisableIdc;	// 0: on, 1: off, 2: on except for slice boundaries, 
#else
		iLoopFilterDisableIdc	= 0;	// 0: on, 1: off, 2: on except for slice boundaries
#endif
		iLoopFilterAlphaC0Offset= 0;	// AlphaOffset: valid range [-6, 6], default 0
		iLoopFilterBetaOffset	= 0;	// BetaOffset:	valid range [-6, 6], default 0
		iInterLayerLoopFilterDisableIdc	= iLoopFilterDisableIdc;	// Employed based upon inter-layer, same comment as above
		iInterLayerLoopFilterAlphaC0Offset= 0;
		iInterLayerLoopFilterBetaOffset	= 0;

		bEnableFrameCroppingFlag	= true;

		/* Rate Control */
		bEnableRc			= kbEnableRc;
		if (pCodingParam.iRCMode != RC_MODE0 && pCodingParam.iRCMode != RC_MODE1)
			iRCMode = RC_MODE1;
		else
			iRCMode = pCodingParam.iRCMode;    // rc mode
		iPaddingFlag= pCodingParam.iPaddingFlag;

		iTargetBitrate		= pCodingParam.iTargetBitrate;	// target bitrate

		/* Denoise Control */
		bEnableDenoise = pCodingParam.bEnableDenoise ? true : false;    // Denoise Control  // only support 0 or 1 now  	

		/* Scene change detection control */
		bEnableSceneChangeDetect	= true;	   

		/* Background detection Control */
		bEnableBackgroundDetection = pCodingParam.bEnableBackgroundDetection ? true : false; 

		/* Adaptive quantization control */
		bEnableAdaptiveQuant	= pCodingParam.bEnableAdaptiveQuant ? true : false;	   

		/* Enable cropping source picture */
		bEnableCropPic	= pCodingParam.bEnableCropPic ? true : false;

		/* Enable int32_t term reference */
		bEnableLongTermReference	= pCodingParam.bEnableLongTermReference ? true : false;
		uiLtrMarkPeriod = pCodingParam.iLtrMarkPeriod;

		/* For ssei information */
		bEnableSSEI		= true;

		/* Layer definition */
		iNumDependencyLayer	= (int8_t)WELS_CLIP3(pCodingParam.iSpatialLayerNum, 1, MAX_DEPENDENCY_LAYER); // number of dependency(Spatial/CGS) layers used to be encoded
		pCodingParam.iTemporalLayerNum = (int8_t)WELS_CLIP3(pCodingParam.iTemporalLayerNum, 1, MAX_TEMPORAL_LEVEL);	// safe valid iTemporalLayerNum		
		iNumTemporalLayer		= (int8_t)pCodingParam.iTemporalLayerNum;//(int8_t)WELS_CLIP3(pCodingParam.iTemporalLayerNum, 1, MAX_TEMPORAL_LEVEL);// number of temporal layer specified		

		uiGopSize			= 1 << (iNumTemporalLayer-1);	// Override GOP size based temporal layer
		iDecompStages		= iNumTemporalLayer-1;	// WELS_LOG2( uiGopSize );// GOP size dependency
		uiIntraPeriod		= pCodingParam.iIntraPeriod;// intra period (multiple of GOP size as desired)
		if ( uiIntraPeriod == (uint32_t)(-1) )
			uiIntraPeriod = 0;
		else if ( uiIntraPeriod & uiGopSize )	// none multiple of GOP size
			uiIntraPeriod = ((uiIntraPeriod+uiGopSize-1) / uiGopSize) * uiGopSize;

		iLTRRefNum = bEnableLongTermReference ? LONG_TERM_REF_NUM : 0;
		iNumRefFrame		= ((uiGopSize>>1)>1)?((uiGopSize>>1)+iLTRRefNum):(MIN_REF_PIC_COUNT+iLTRRefNum);
		iNumRefFrame		= WELS_CLIP3( iNumRefFrame, MIN_REF_PIC_COUNT, MAX_REFERENCE_PICTURE_COUNT_NUM );	

		uiLtrMarkPeriod  = pCodingParam.iLtrMarkPeriod;

		bPrefixNalAddingCtrl	= pCodingParam.bPrefixNalAddingCtrl;	
		
		bEnableSpsPpsIdAddition = pCodingParam.bEnableSpsPpsIdAddition;//For SVC meeting application, to avoid mosaic issue caused by cross-IDR reference. 
		                                                               //SHOULD enable this feature.  

		SDLayerParam *pDlp		= &sDependencyLayers[0];
		float fMaxFr			= .0f;
		uint8_t uiProfileIdc		= PRO_BASELINE;
		int8_t iIdxSpatial	= 0;
		while(iIdxSpatial < iNumDependencyLayer)
		{
			pDlp->uiProfileIdc		= uiProfileIdc;	

			pCodingParam.sSpatialLayers[iIdxSpatial].fFrameRate	= WELS_CLIP3(pCodingParam.sSpatialLayers[iIdxSpatial].fFrameRate, MIN_FRAME_RATE, pCodingParam.fFrameRate);
			pDlp->fInputFrameRate	= 
			pDlp->fOutputFrameRate	= WELS_CLIP3(pCodingParam.sSpatialLayers[iIdxSpatial].fFrameRate, MIN_FRAME_RATE, MAX_FRAME_RATE);
			if (pDlp->fInputFrameRate > fMaxFr+EPSN)
				fMaxFr = pDlp->fInputFrameRate;

#ifdef ENABLE_FRAME_DUMP
			pDlp->sRecFileName[0]	= '\0';	// file to be constructed
#endif//ENABLE_FRAME_DUMP
			pDlp->iFrameWidth		= pCodingParam.sSpatialLayers[iIdxSpatial].iVideoWidth;	// frame width
			pDlp->iFrameHeight		= pCodingParam.sSpatialLayers[iIdxSpatial].iVideoHeight;// frame height
			pDlp->iSpatialBitrate	= pCodingParam.sSpatialLayers[iIdxSpatial].iSpatialBitrate;	// target bitrate for current spatial layer


			//multi slice
			pDlp->sMso.uiSliceMode = (SliceMode)pCodingParam.sSpatialLayers[iIdxSpatial].sSliceCfg.uiSliceMode;
			pDlp->sMso.sSliceArgument.uiSliceSizeConstraint 
				= (uint32_t)(pCodingParam.sSpatialLayers[iIdxSpatial].sSliceCfg.sSliceArgument.uiSliceSizeConstraint);
			pDlp->sMso.sSliceArgument.iSliceNum 
				= pCodingParam.sSpatialLayers[iIdxSpatial].sSliceCfg.sSliceArgument.uiSliceNum;
			const int32_t kiLesserSliceNum = ((MAX_SLICES_NUM < MAX_SLICES_NUM_TMP) ? MAX_SLICES_NUM : MAX_SLICES_NUM_TMP);  
			memcpy(pDlp->sMso.sSliceArgument.uiSliceMbNum, pCodingParam.sSpatialLayers[iIdxSpatial].sSliceCfg.sSliceArgument.uiSliceMbNum,	// confirmed_safe_unsafe_usage
				kiLesserSliceNum * sizeof(uint32_t) ) ;

			pDlp->iDLayerQp = SVC_QUALITY_BASE_QP;

			uiProfileIdc	= PRO_SCALABLE_BASELINE;
			++ pDlp;
			++ iIdxSpatial;
		}

		fMaxFrameRate	= fMaxFr;

		SetActualPicResolution();

		return 0;
	}

	// assuming that the width/height ratio of all spatial layers are the same
	
	void SetActualPicResolution()
	{
		int32_t iSpatialIdx			= iNumDependencyLayer-1;
		SDLayerParam *pDlayer		= &sDependencyLayers[iSpatialIdx];

		for (; iSpatialIdx >= 0; iSpatialIdx -- )
		{
			pDlayer	= &sDependencyLayers[iSpatialIdx];

			pDlayer->iActualWidth = pDlayer->iFrameWidth;
			pDlayer->iActualHeight = pDlayer->iFrameHeight;
			pDlayer->iFrameWidth = WELS_ALIGN(pDlayer->iActualWidth, MB_WIDTH_LUMA);
			pDlayer->iFrameHeight = WELS_ALIGN(pDlayer->iActualHeight, MB_HEIGHT_LUMA);
		}
	}

	/*!
	* \brief	determined key coding tables for temporal scalability, uiProfileIdc etc for each spatial layer settings
	* \param	SWelsSvcCodingParam, and carried with known GOP size, max, input and output frame rate of each spatial
	* \return	NONE (should ensure valid parameter before this procedure)
	*/
	void DetermineTemporalSettings()
	{		
		const int32_t iDecStages		= WELS_LOG2( uiGopSize );	// (int8_t)GetLogFactor(1.0f, 1.0f * pcfg->uiGopSize);	//log2(uiGopSize)
		const uint8_t *pTemporalIdList	= &g_kuiTemporalIdListTable[iDecStages][0];
		SDLayerParam *pDlp				= &sDependencyLayers[0];
		uint8_t uiProfileIdc				= PRO_BASELINE;
		int8_t i						= 0;

		while (i < iNumDependencyLayer )
		{
			const uint32_t kuiLogFactorInOutRate	= GetLogFactor(pDlp->fOutputFrameRate, pDlp->fInputFrameRate);
			const uint32_t kuiLogFactorMaxInRate	= GetLogFactor(pDlp->fInputFrameRate, fMaxFrameRate);
			int32_t iNotCodedMask= 0;
			int8_t iMaxTemporalId = 0;

			memset(pDlp->uiCodingIdx2TemporalId, INVALID_TEMPORAL_ID, sizeof(pDlp->uiCodingIdx2TemporalId));
			pDlp->uiProfileIdc = uiProfileIdc;	// PRO_BASELINE, PRO_SCALABLE_BASELINE;			

			iNotCodedMask	= (1 << (kuiLogFactorInOutRate + kuiLogFactorMaxInRate)) - 1;
			for (uint32_t uiFrameIdx = 0; uiFrameIdx <= uiGopSize; ++ uiFrameIdx){						
				if( 0 == (uiFrameIdx & iNotCodedMask) ) {				
					const int8_t kiTemporalId = pTemporalIdList[uiFrameIdx];						
					pDlp->uiCodingIdx2TemporalId[uiFrameIdx] = kiTemporalId;
					if ( kiTemporalId > iMaxTemporalId )
					{
						iMaxTemporalId = kiTemporalId;
					}
				}
			}

			pDlp->iHighestTemporalId	= iMaxTemporalId;
			pDlp->iTemporalResolution	= kuiLogFactorMaxInRate + kuiLogFactorInOutRate;
			pDlp->iDecompositionStages	= iDecStages - kuiLogFactorMaxInRate - kuiLogFactorInOutRate;

			uiProfileIdc	= PRO_SCALABLE_BASELINE;		
			++ pDlp;
			++ i;
		}
		iDecompStages = (int8_t)iDecStages;
	}

} SWelsSvcCodingParam;

static inline int32_t FreeCodingParam( SWelsSvcCodingParam **pParam, CMemoryAlign *pMa )
{
	if (pParam == NULL || *pParam == NULL || pMa == NULL)
		return 1;	
	pMa->WelsFree(*pParam, "SWelsSvcCodingParam");
	*pParam = NULL;
	return 0;
}

static inline int32_t AllocCodingParam( SWelsSvcCodingParam **pParam, CMemoryAlign *pMa, const int32_t kiRequestNumSpatial )
{
	if ( pParam == NULL || pMa == NULL || kiRequestNumSpatial < 1 || kiRequestNumSpatial > MAX_SPATIAL_LAYER_NUM )
		return 1;	
	if (*pParam != NULL)
	{
		FreeCodingParam( pParam, pMa );
	}
	SWelsSvcCodingParam *pCodingParam = (SWelsSvcCodingParam *)pMa->WelsMalloc(sizeof(SWelsSvcCodingParam), "SWelsSvcCodingParam");
	if ( NULL == pCodingParam )
		return 1;
	*pParam = pCodingParam;
	return 0;
}

}//end of namespace WelsSVCEnc

#endif//WELS_ENCODER_PARAMETER_SVC_H__