/*!
* \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. Load more
/*! * \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);