Ethan HuggInitial Commit70e5e6212 years agoHistory
1194 lines · 42.7 KB · C++
RawDownload
/*!
 * \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	svc_encode_slice.c
 *
 * \brief	svc encoding slice 
 *
 * \date	2009.07.27 Created
 *
 *************************************************************************************
 */

#include <string.h>
#include <assert.h>
#include "ls_defines.h"
#include "svc_encode_slice.h"
#include "svc_enc_golomb.h"
#include "svc_base_layer_md.h"
#include "svc_encode_mb.h"
#include "mv_pred.h"
#include "svc_set_mb_syn_cavlc.h"
#include "encode_mb_aux.h"
#include "decode_mb_aux.h"
#include "svc_mode_decision.h"
#include "cpu_core.h"
#include "svc_motion_estimate.h"
#include "sample.h"
#include "wels_func_ptr_def.h"
#include "utils.h"

namespace WelsSVCEnc {
//#define ENC_TRACE
 
typedef void (*PWelsCodingSliceFunc)( sWelsEncCtx *pCtx, SSlice *pSlice );
typedef void (*PWelsSliceHeaderWriteFunc)( SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice *pSlice, int32_t* pPpsIdDelta );

void UpdateNonZeroCountCache(SMB *pMb, SMbCache *pMbCache)
{
	ST32(&pMbCache->iNonZeroCoeffCount[9], LD32(&pMb->pNonZeroCount[ 0]));
	ST32(&pMbCache->iNonZeroCoeffCount[17], LD32(&pMb->pNonZeroCount[ 4]));
	ST32(&pMbCache->iNonZeroCoeffCount[25], LD32(&pMb->pNonZeroCount[ 8]));
	ST32(&pMbCache->iNonZeroCoeffCount[33], LD32(&pMb->pNonZeroCount[12]));	
	
	ST16(&pMbCache->iNonZeroCoeffCount[14], LD16(&pMb->pNonZeroCount[16]));
	ST16(&pMbCache->iNonZeroCoeffCount[38], LD16(&pMb->pNonZeroCount[18]));
	ST16(&pMbCache->iNonZeroCoeffCount[22], LD16(&pMb->pNonZeroCount[20]));
	ST16(&pMbCache->iNonZeroCoeffCount[46], LD16(&pMb->pNonZeroCount[22]));
}

void WelsSliceHeaderScalExtInit( SDqLayer* pCurLayer, SSlice *pSlice )
{
	SSliceHeaderExt* pSliceHeadExt	= &pSlice->sSliceHeaderExt;
	SNalUnitHeaderExt* pNalHeadExt= &pCurLayer->sLayerInfo.sNalHeaderExt;
	
	uint8_t uiDependencyId	= pNalHeadExt->uiDependencyId;

	pSliceHeadExt->bSliceSkipFlag = false;	

	if ( uiDependencyId > 0 ) //spatial EL
	{
		//bothe adaptive and default flags should equal to 0.
		pSliceHeadExt->bAdaptiveBaseModeFlag     = 
			pSliceHeadExt->bAdaptiveMotionPredFlag   = 
			pSliceHeadExt->bAdaptiveResidualPredFlag = false;

		pSliceHeadExt->bDefaultBaseModeFlag     = 
			pSliceHeadExt->bDefaultMotionPredFlag   =
			pSliceHeadExt->bDefaultResidualPredFlag = false;
	}
}

void WelsSliceHeaderExtInit( sWelsEncCtx* pEncCtx, SDqLayer* pCurLayer, SSlice *pSlice )
{
	SSliceHeaderExt* pCurSliceExt = &pSlice->sSliceHeaderExt;
	SSliceHeader* pCurSliceHeader  = &pCurSliceExt->sSliceHeader;	
	
	pCurSliceHeader->eSliceType	= pEncCtx->eSliceType;

	pCurSliceExt->bStoreRefBasePicFlag = false;	

	pCurSliceHeader->iFirstMbInSlice = WelsGetFirstMbOfSlice( pCurLayer->pSliceEncCtx, pSlice->uiSliceIdx );

	pCurSliceHeader->iFrameNum      = pEncCtx->iFrameNum;	
	pCurSliceHeader->uiIdrPicId     = pEncCtx->sPSOVector.uiIdrPicId; //??

	pCurSliceHeader->iPicOrderCntLsb          = pEncCtx->pEncPic->iFramePoc;	// 0

	if ( P_SLICE == pEncCtx->eSliceType  )
	{
		pCurSliceHeader->uiNumRefIdxL0Active	= 1;
		if ( pCurSliceHeader->uiRefCount > 0 && 
			pCurSliceHeader->uiRefCount < pCurLayer->sLayerInfo.pSpsP->iNumRefFrames )
		{
			pCurSliceHeader->bNumRefIdxActiveOverrideFlag = true;
			pCurSliceHeader->uiNumRefIdxL0Active	= pCurSliceHeader->uiRefCount;
		}
		//to solve mismatch between debug&release
		else
		{
			pCurSliceHeader->bNumRefIdxActiveOverrideFlag = false;
		}
	}

	pCurSliceHeader->iSliceQpDelta = pEncCtx->iGlobalQp - pCurLayer->sLayerInfo.pPpsP->iPicInitQp;

	//for deblocking initial
	pCurSliceHeader->uiDisableDeblockingFilterIdc			= pCurLayer->iLoopFilterDisableIdc;
	pCurSliceHeader->iSliceAlphaC0Offset					= pCurLayer->iLoopFilterAlphaC0Offset;	//	need update iSliceAlphaC0Offset & iSliceBetaOffset for pSlice-header if loop_filter_idc != 1
	pCurSliceHeader->iSliceBetaOffset						= pCurLayer->iLoopFilterBetaOffset;
	pCurSliceExt->uiDisableInterLayerDeblockingFilterIdc = pCurLayer->uiDisableInterLayerDeblockingFilterIdc;

	if ( pSlice->bSliceHeaderExtFlag )
	{
		WelsSliceHeaderScalExtInit( pCurLayer, pSlice );
	}
	else
	{
		//both adaptive and default flags should equal to 0.
		pCurSliceExt->bAdaptiveBaseModeFlag		= 
		pCurSliceExt->bAdaptiveMotionPredFlag		= 
		pCurSliceExt->bAdaptiveResidualPredFlag	= false;
		
		pCurSliceExt->bDefaultBaseModeFlag		= 
		pCurSliceExt->bDefaultMotionPredFlag		=
		pCurSliceExt->bDefaultResidualPredFlag	= false;
	}
}

/* count MB types if enabled FRAME_INFO_OUTPUT*/
#if defined(MB_TYPES_CHECK)
void WelsCountMbType(int32_t (*iMbCount)[18], const EWelsSliceType keSt, const SMB* kpMb)
{	
	if (NULL == iMbCount)
		return;
	
	switch( kpMb->uiMbType ) {
	case MB_TYPE_INTRA4x4:
		++ iMbCount[keSt][Intra4x4];
		break;
	case MB_TYPE_INTRA16x16:
		++ iMbCount[keSt][Intra16x16];
		break;
	case MB_TYPE_SKIP:
		++ iMbCount[keSt][PSkip];
		break;
	case MB_TYPE_16x16:
		++ iMbCount[keSt][Inter16x16];
		break;
	case MB_TYPE_16x8:
		++ iMbCount[keSt][Inter16x8];
		break;
	case MB_TYPE_8x16:
		++ iMbCount[eSt][Inter8x16];
		break;
	case MB_TYPE_8x8:
		++ iMbCount[keSt][Inter8x8];
		break;
	case MB_TYPE_INTRA_BL:
		++ iMbCount[keSt][7];
		break;
	default:
		break;
	}
}
#endif//MB_TYPES_CHECK

/*!
* \brief	write reference picture list on reordering syntax in Slice header	
*/
void WriteReferenceReorder( SBitStringAux *pBs, SSliceHeader *sSliceHeader )
{
	SRefPicListReorderSyntax *pRefOrdering	= &sSliceHeader->sRefReordering;
	uint8_t eSliceType						= sSliceHeader->eSliceType % 5;
	int16_t n = 0;

	if (  I_SLICE != eSliceType && SI_SLICE != eSliceType )	// !I && !SI
	{
		BsWriteOneBit( pBs, true );
//		{
			uint16_t uiReorderingOfPicNumsIdc;
			do 
			{
				uiReorderingOfPicNumsIdc = pRefOrdering->SReorderingSyntax[n].uiReorderingOfPicNumsIdc; 
				BsWriteUE( pBs, uiReorderingOfPicNumsIdc );
				if ( 0 == uiReorderingOfPicNumsIdc || 1 == uiReorderingOfPicNumsIdc )
					BsWriteUE( pBs, pRefOrdering->SReorderingSyntax[n].uiAbsDiffPicNumMinus1 );
				else if ( 2 == uiReorderingOfPicNumsIdc )
					BsWriteUE( pBs, pRefOrdering->SReorderingSyntax[n].iLongTermPicNum );

				n ++;
			} while ( 3 != uiReorderingOfPicNumsIdc );
//		}
	}
}

/*!
* \brief	write reference picture marking syntax in pSlice header	
*/
void WriteRefPicMarking( SBitStringAux *pBs, SSliceHeader *pSliceHeader, SNalUnitHeaderExt *pNalHdrExt )
{
	SRefPicMarking *sRefMarking	= &pSliceHeader->sRefMarking;
	int16_t n = 0;	

	if ( pNalHdrExt->bIdrFlag )
	{
		BsWriteOneBit( pBs, sRefMarking->bNoOutputOfPriorPicsFlag );
		BsWriteOneBit( pBs, sRefMarking->bLongTermRefFlag );
	}
	else 
	{
		BsWriteOneBit( pBs, sRefMarking->bAdaptiveRefPicMarkingModeFlag );

		if ( sRefMarking->bAdaptiveRefPicMarkingModeFlag )
		{
			int32_t iMmcoType;
			do 
			{
				iMmcoType = sRefMarking->SMmcoRef[n].iMmcoType;
				BsWriteUE( pBs, iMmcoType );
				if ( 1 == iMmcoType || 3 == iMmcoType )
					BsWriteUE( pBs, sRefMarking->SMmcoRef[n].iDiffOfPicNum - 1 );

				if ( 2 == iMmcoType )
					BsWriteUE( pBs, sRefMarking->SMmcoRef[n].iLongTermPicNum );

				if ( 3 == iMmcoType || 6 == iMmcoType )
					BsWriteUE( pBs, sRefMarking->SMmcoRef[n].iLongTermFrameIdx );

				if ( 4 == iMmcoType )
					BsWriteUE( pBs, sRefMarking->SMmcoRef[n].iMaxLongTermFrameIdx + 1 );

				n ++;
			} while ( 0 != iMmcoType );
		}

	}
}

void WelsSliceHeaderWrite( SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice *pSlice, int32_t* pPpsIdDelta )
{
	SWelsSPS* pSps = pCurLayer->sLayerInfo.pSpsP;
	SWelsPPS* pPps = pCurLayer->sLayerInfo.pPpsP;
	SSliceHeader* pSliceHeader      = &pSlice->sSliceHeaderExt.sSliceHeader;	
	SNalUnitHeaderExt* pNalHead   = &pCurLayer->sLayerInfo.sNalHeaderExt;	

	BsWriteUE( pBs, pSliceHeader->iFirstMbInSlice );
	BsWriteUE( pBs, pSliceHeader->eSliceType );   /* same type things */

	BsWriteUE( pBs, pSliceHeader->pPps->iPpsId + pPpsIdDelta[pSliceHeader->pPps->iPpsId] );

	BsWriteBits( pBs, pSps->uiLog2MaxFrameNum, pSliceHeader->iFrameNum );

	if( pNalHead->bIdrFlag ) /* NAL IDR */
	{
		BsWriteUE( pBs, pSliceHeader->uiIdrPicId );
	}

	BsWriteBits( pBs, pSps->iLog2MaxPocLsb, pSliceHeader->iPicOrderCntLsb );

	if ( P_SLICE == pSliceHeader->eSliceType )
	{
		BsWriteOneBit( pBs, pSliceHeader->bNumRefIdxActiveOverrideFlag );
		if ( pSliceHeader->bNumRefIdxActiveOverrideFlag )
		{
			BsWriteUE( pBs, pSliceHeader->uiNumRefIdxL0Active - 1 );
		}
	}

	if ( !pNalHead->bIdrFlag )
		WriteReferenceReorder( pBs, pSliceHeader );

	if ( pNalHead->sNalHeader.uiNalRefIdc )
	{
		WriteRefPicMarking( pBs, pSliceHeader, pNalHead );
	}	

	BsWriteSE( pBs, pSliceHeader->iSliceQpDelta );      /* pSlice qp delta */

	if( pPps->bDeblockingFilterControlPresentFlag )
	{
		switch( pSliceHeader->uiDisableDeblockingFilterIdc )
		{
		case 0:
		case 3:
		case 4:
		case 6:
			BsWriteUE( pBs, 0 );
			break;
		case 1:
			BsWriteUE( pBs, 1 );
			break;
		case 2:
		case 5:
			BsWriteUE( pBs, 2 );
			break;
		default :
			fprintf( stderr, "pData error for deblocking" );
			break;
		}
		if ( 1 != pSliceHeader->uiDisableDeblockingFilterIdc )
		{
			BsWriteSE( pBs, pSliceHeader->iSliceAlphaC0Offset >> 1 );
			BsWriteSE( pBs, pSliceHeader->iSliceBetaOffset >> 1 );
		}
	}	
}

void WelsSliceHeaderExtWrite( SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice *pSlice, int32_t *pPpsIdDelta )
{
	SWelsSPS* pSps           = pCurLayer->sLayerInfo.pSpsP;	
	SWelsPPS* pPps           = pCurLayer->sLayerInfo.pPpsP;
	SSubsetSps* pSubSps = pCurLayer->sLayerInfo.pSubsetSpsP;
	SSliceHeaderExt* pSliceHeadExt = &pSlice->sSliceHeaderExt;
	SSliceHeader* pSliceHeader      = &pSliceHeadExt->sSliceHeader;
	SNalUnitHeaderExt* pNalHead   = &pCurLayer->sLayerInfo.sNalHeaderExt;

	BsWriteUE( pBs, pSliceHeader->iFirstMbInSlice );
	BsWriteUE( pBs, pSliceHeader->eSliceType );   /* same type things */

	BsWriteUE( pBs, pSliceHeader->pPps->iPpsId + pPpsIdDelta[pSliceHeader->pPps->iPpsId] );

	BsWriteBits( pBs, pSps->uiLog2MaxFrameNum, pSliceHeader->iFrameNum );

	if( pNalHead->bIdrFlag ) /* NAL IDR */
	{
		BsWriteUE( pBs, pSliceHeader->uiIdrPicId );
	}

	BsWriteBits( pBs, pSps->iLog2MaxPocLsb, pSliceHeader->iPicOrderCntLsb );
//	{
		if ( P_SLICE == pSliceHeader->eSliceType )
		{
			BsWriteOneBit( pBs, pSliceHeader->bNumRefIdxActiveOverrideFlag );
			if ( pSliceHeader->bNumRefIdxActiveOverrideFlag )
			{
				BsWriteUE( pBs, pSliceHeader->uiNumRefIdxL0Active - 1 );
			}
		}

		if ( !pNalHead->bIdrFlag )
			WriteReferenceReorder( pBs, pSliceHeader );

		if ( pNalHead->sNalHeader.uiNalRefIdc )
		{
			WriteRefPicMarking( pBs, pSliceHeader, pNalHead );

			if ( !pSubSps->sSpsSvcExt.bSliceHeaderRestrictionFlag )
			{
				BsWriteOneBit( pBs, pSliceHeadExt->bStoreRefBasePicFlag );
			}
		}
//	}

	BsWriteSE( pBs, pSliceHeader->iSliceQpDelta );      /* pSlice qp delta */

	if( pPps->bDeblockingFilterControlPresentFlag )
	{
		BsWriteUE( pBs, pSliceHeader->uiDisableDeblockingFilterIdc );
		if ( 1 != pSliceHeader->uiDisableDeblockingFilterIdc )
		{
			BsWriteSE( pBs, pSliceHeader->iSliceAlphaC0Offset >> 1 );
			BsWriteSE( pBs, pSliceHeader->iSliceBetaOffset >> 1 );
		}
	}	

#if !defined(DISABLE_FMO_FEATURE)
	if ( pPps->uiNumSliceGroups > 1  &&
		pPps->uiSliceGroupMapType >= 3 && 
		pPps->uiSliceGroupMapType <= 5 )
	{
		int32_t iNumBits;
		if ( pPps->uiSliceGroupChangeRate )
		{
			iNumBits = WELS_CEILLOG2(1 + pPps->uiPicSizeInMapUnits / pPps->uiSliceGroupChangeRate);
			BsWriteBits( pBs, iNumBits, pSliceHeader->iSliceGroupChangeCycle );	
		}
	}
#endif//!DISABLE_FMO_FEATURE

	if ( false )
	{
		BsWriteOneBit( pBs, pSliceHeadExt->bSliceSkipFlag );
		if ( pSliceHeadExt->bSliceSkipFlag )
		{
			BsWriteUE( pBs, pSliceHeadExt->uiNumMbsInSlice - 1 );
		}
		else
		{
			BsWriteOneBit( pBs, pSliceHeadExt->bAdaptiveBaseModeFlag );
			if ( !pSliceHeadExt->bAdaptiveBaseModeFlag )  
			{
				BsWriteOneBit( pBs, pSliceHeadExt->bDefaultBaseModeFlag );
			}

			if ( !pSliceHeadExt->bDefaultBaseModeFlag )
			{
				BsWriteOneBit( pBs, 0 );
				BsWriteOneBit( pBs, 0 );
			}

			BsWriteOneBit( pBs, pSliceHeadExt->bAdaptiveResidualPredFlag );
			if ( !pSliceHeadExt->bAdaptiveResidualPredFlag )
			{
				BsWriteOneBit( pBs, 0);
			}
		}
		if ( 1 == pSubSps->sSpsSvcExt.bAdaptiveTcoeffLevelPredFlag )
		{
			BsWriteOneBit( pBs, pSliceHeadExt->bTcoeffLevelPredFlag );
		}

	}

	if ( !pSubSps->sSpsSvcExt.bSliceHeaderRestrictionFlag )
	{
		BsWriteBits( pBs, 4, 0 );
		BsWriteBits( pBs, 4, 15 );
	}
}

//only BaseLayer inter MB and SpatialLayer (uiQualityId = 0) inter MB calling this pFunc.
//only for inter part
void WelsInterMbEncode( sWelsEncCtx* pEncCtx, SSlice *pSlice, SMB* pCurMb )
{
	SMbCache* pMbCache = &pSlice->sMbCacheInfo;

	WelsDctMb(pMbCache->pCoeffLevel,  pMbCache->SPicData.pEncMb[0], pEncCtx->pCurDqLayer->iEncStride[0], pMbCache->pMemPredLuma, pEncCtx->pFuncList->pfDctFourT4 );
	WelsEncInterY( pEncCtx->pFuncList, pCurMb, pMbCache );
}


//only BaseLayer inter MB and SpatialLayer (uiQualityId = 0) inter MB calling this pFunc.
//only for I SSlice
void WelsIMbChromaEncode( sWelsEncCtx* pEncCtx, SMB* pCurMb, SMbCache *pMbCache )
{
	SWelsFuncPtrList *pFunc	= pEncCtx->pFuncList;
	SDqLayer* pCurLayer			= pEncCtx->pCurDqLayer;	
	const int32_t kiEncStride	= pCurLayer->iEncStride[1];
	const int32_t kiCsStride		= pCurLayer->iCsStride[1];
	int16_t *pCurRS				= pMbCache->pCoeffLevel;
	uint8_t* pBestPred			= pMbCache->pBestPredIntraChroma;
	uint8_t* pCsCb				= pMbCache->SPicData.pCsMb[1];
	uint8_t* pCsCr				= pMbCache->SPicData.pCsMb[2];

	//cb
	pFunc->pfDctFourT4( pCurRS,    pMbCache->SPicData.pEncMb[1], kiEncStride, pBestPred,    8);
	WelsEncRecUV( pFunc, pCurMb, pMbCache, pCurRS,    1 );
	pFunc->pfIDctFourT4( pCsCb, kiCsStride, pBestPred,    8, pCurRS    );
	
	//cr
	pFunc->pfDctFourT4( pCurRS+64, pMbCache->SPicData.pEncMb[2], kiEncStride, pBestPred+64, 8);
	WelsEncRecUV( pFunc, pCurMb, pMbCache, pCurRS+64, 2 );
	pFunc->pfIDctFourT4( pCsCr, kiCsStride, pBestPred+64, 8, pCurRS+64 );
}


//only BaseLayer inter MB and SpatialLayer (uiQualityId = 0) inter MB calling this pFunc.
//for P SSlice (intra part + inter part)
void WelsPMbChromaEncode( sWelsEncCtx* pEncCtx, SSlice *pSlice, SMB* pCurMb )
{
	SWelsFuncPtrList *pFunc	= pEncCtx->pFuncList;	
	SDqLayer* pCurLayer			= pEncCtx->pCurDqLayer;	
	const int32_t kiEncStride	= pCurLayer->iEncStride[1];
	SMbCache* pMbCache			= &pSlice->sMbCacheInfo;
	int16_t *pCurRS				= pMbCache->pCoeffLevel+256;
	uint8_t* pBestPred			= pMbCache->pMemPredChroma;		

	pFunc->pfDctFourT4(pCurRS,		pMbCache->SPicData.pEncMb[1],	kiEncStride,		pBestPred,		8);	
	pFunc->pfDctFourT4(pCurRS+64,	pMbCache->SPicData.pEncMb[2],	kiEncStride,		pBestPred+64,	8);	
	
	WelsEncRecUV(pFunc, pCurMb, pMbCache, pCurRS, 1);
	WelsEncRecUV(pFunc, pCurMb, pMbCache, pCurRS+64, 2);

Lines 1–500 of 1194.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t