#include "au_set.h"
#include "svc_enc_golomb.h"
#include "macros.h"
#include "wels_common_defs.h"
using namespace WelsCommon;
namespace WelsEnc {
static inline int32_t WelsCheckLevelLimitation (const SWelsSPS* kpSps, const SLevelLimits* kpLevelLimit,
float fFrameRate, int32_t iTargetBitRate) {
uint32_t uiPicWidthInMBs = kpSps->iMbWidth;
uint32_t uiPicHeightInMBs = kpSps->iMbHeight;
uint32_t uiPicInMBs = uiPicWidthInMBs * uiPicHeightInMBs;
uint32_t uiNumRefFrames = kpSps->iNumRefFrames;
if (kpLevelLimit->uiMaxMBPS < (uint32_t) (uiPicInMBs * fFrameRate))
return 0;
if (kpLevelLimit->uiMaxFS < uiPicInMBs)
return 0;
if ((kpLevelLimit->uiMaxFS << 3) < (uiPicWidthInMBs * uiPicWidthInMBs))
return 0;
if ((kpLevelLimit->uiMaxFS << 3) < (uiPicHeightInMBs * uiPicHeightInMBs))
return 0;
if (kpLevelLimit->uiMaxDPBMbs < uiNumRefFrames * uiPicInMBs)
return 0;
if ((iTargetBitRate != UNSPECIFIED_BIT_RATE)
&& ((int32_t) kpLevelLimit->uiMaxBR * 1200) < iTargetBitRate) return 0;
return 1;
}
int32_t WelsAdjustLevel (SSpatialLayerConfig* pSpatialLayer, const SLevelLimits* pCurLevel) {
int32_t iMaxBitrate = pSpatialLayer->iMaxSpatialBitrate;
do {
if (iMaxBitrate <= (int32_t) (pCurLevel->uiMaxBR * CpbBrNalFactor)) {
pSpatialLayer->uiLevelIdc = pCurLevel->uiLevelIdc;
return 0;
}
pCurLevel++;
} while (pCurLevel->uiLevelIdc != LEVEL_5_2);
return 1;
}
static int32_t WelsCheckNumRefSetting (SLogContext* pLogCtx, SWelsSvcCodingParam* pParam, bool bStrictCheck) {
int32_t iCurrentSupportedLtrNum = (pParam->iUsageType == CAMERA_VIDEO_REAL_TIME) ? LONG_TERM_REF_NUM :
LONG_TERM_REF_NUM_SCREEN;
if ((pParam->bEnableLongTermReference) && (iCurrentSupportedLtrNum != pParam->iLTRRefNum)) {
WelsLog (pLogCtx, WELS_LOG_WARNING, "iLTRRefNum(%d) does not equal to currently supported %d, will be reset",
pParam->iLTRRefNum, iCurrentSupportedLtrNum);
pParam->iLTRRefNum = iCurrentSupportedLtrNum;
} else if (!pParam->bEnableLongTermReference) {
pParam->iLTRRefNum = 0;
}
int32_t iCurrentStrNum = ((pParam->iUsageType == SCREEN_CONTENT_REAL_TIME && pParam->bEnableLongTermReference)
? (WELS_MAX (1, WELS_LOG2 (pParam->uiGopSize)))
: (WELS_MAX (1, (pParam->uiGopSize >> 1))));
int32_t iNeededRefNum = (pParam->uiIntraPeriod != 1) ? (iCurrentStrNum + pParam->iLTRRefNum) : 0;
iNeededRefNum = WELS_CLIP3 (iNeededRefNum,
MIN_REF_PIC_COUNT,
(pParam->iUsageType == CAMERA_VIDEO_REAL_TIME) ? MAX_REFERENCE_PICTURE_COUNT_NUM_CAMERA :
MAX_REFERENCE_PICTURE_COUNT_NUM_SCREEN);
if (pParam->iNumRefFrame == AUTO_REF_PIC_COUNT) {
pParam->iNumRefFrame = iNeededRefNum;
} else if (pParam->iNumRefFrame < iNeededRefNum) {
WelsLog (pLogCtx, WELS_LOG_WARNING,
"iNumRefFrame(%d) setting does not support the temporal and LTR setting, will be reset to %d",
pParam->iNumRefFrame, iNeededRefNum);
if (bStrictCheck) {
return ENC_RETURN_UNSUPPORTED_PARA;
}
pParam->iNumRefFrame = iNeededRefNum;
}
if (pParam->iMaxNumRefFrame < pParam->iNumRefFrame) {
pParam->iMaxNumRefFrame = pParam->iNumRefFrame;
}
pParam->iNumRefFrame = iNeededRefNum;
return ENC_RETURN_SUCCESS;
}
int32_t WelsCheckRefFrameLimitationNumRefFirst (SLogContext* pLogCtx, SWelsSvcCodingParam* pParam) {
if (WelsCheckNumRefSetting (pLogCtx, pParam, false)) {
return ENC_RETURN_UNSUPPORTED_PARA;
}
return ENC_RETURN_SUCCESS;
}
int32_t WelsCheckRefFrameLimitationLevelIdcFirst (SLogContext* pLogCtx, SWelsSvcCodingParam* pParam) {
if ((pParam->iNumRefFrame == AUTO_REF_PIC_COUNT) || (pParam->iMaxNumRefFrame == AUTO_REF_PIC_COUNT)) {
return ENC_RETURN_SUCCESS;
}
WelsCheckNumRefSetting (pLogCtx, pParam, false);
int32_t i = 0;
int32_t iRefFrame;
for (i = 0; i < pParam->iSpatialLayerNum; ++ i) {
SSpatialLayerConfig* pSpatialLayer = &pParam->sSpatialLayers[i];
if (pSpatialLayer->uiLevelIdc == LEVEL_UNKNOWN) {
continue;
}
uint32_t uiPicInMBs = ((pSpatialLayer->iVideoHeight + 15) >> 4) * ((pSpatialLayer->iVideoWidth + 15) >> 4);
iRefFrame = g_ksLevelLimits[pSpatialLayer->uiLevelIdc - 1].uiMaxDPBMbs / uiPicInMBs;
if (iRefFrame < pParam->iMaxNumRefFrame) {
WelsLog (pLogCtx, WELS_LOG_WARNING, "iMaxNumRefFrame(%d) adjusted to %d because of limitation from uiLevelIdc=%d",
pParam->iMaxNumRefFrame, iRefFrame, pSpatialLayer->uiLevelIdc);
pParam->iMaxNumRefFrame = iRefFrame;
if (iRefFrame < pParam->iNumRefFrame) {
WelsLog (pLogCtx, WELS_LOG_WARNING, "iNumRefFrame(%d) adjusted to %d because of limitation from uiLevelIdc=%d",
pParam->iNumRefFrame, iRefFrame, pSpatialLayer->uiLevelIdc);
pParam->iNumRefFrame = iRefFrame;
}
} else {
WelsLog (pLogCtx, WELS_LOG_INFO,
"iMaxNumRefFrame(%d) adjusted to %d because of uiLevelIdc=%d -- under level-idc first strategy ",
pParam->iMaxNumRefFrame, iRefFrame, pSpatialLayer->uiLevelIdc);
pParam->iMaxNumRefFrame = iRefFrame;
}
}
return ENC_RETURN_SUCCESS;
}
static inline ELevelIdc WelsGetLevelIdc (const SWelsSPS* kpSps, float fFrameRate, int32_t iTargetBitRate) {
int32_t iOrder;
for (iOrder = 0; iOrder < LEVEL_NUMBER; iOrder++) {
if (WelsCheckLevelLimitation (kpSps, & (g_ksLevelLimits[iOrder]), fFrameRate, iTargetBitRate)) {
return (g_ksLevelLimits[iOrder].uiLevelIdc);
}
}
return LEVEL_5_1; }
int32_t WelsWriteVUI (SWelsSPS* pSps, SBitStringAux* pBitStringAux) {
SBitStringAux* pLocalBitStringAux = pBitStringAux;
assert (pSps != NULL && pBitStringAux != NULL);
BsWriteOneBit (pLocalBitStringAux, pSps->bAspectRatioPresent); if (pSps->bAspectRatioPresent) {
BsWriteBits (pLocalBitStringAux, 8, pSps->eAspectRatio); if (pSps->eAspectRatio == ASP_EXT_SAR) {
BsWriteBits (pLocalBitStringAux, 16, pSps->sAspectRatioExtWidth); BsWriteBits (pLocalBitStringAux, 16, pSps->sAspectRatioExtHeight); }
}
BsWriteOneBit (pLocalBitStringAux, false);
BsWriteOneBit (pLocalBitStringAux, pSps->bVideoSignalTypePresent); if (pSps->bVideoSignalTypePresent) {
BsWriteBits (pLocalBitStringAux, 3, pSps->uiVideoFormat);
BsWriteOneBit (pLocalBitStringAux, pSps->bFullRange);
BsWriteOneBit (pLocalBitStringAux, pSps->bColorDescriptionPresent);
if (pSps->bColorDescriptionPresent) {
BsWriteBits (pLocalBitStringAux, 8, pSps->uiColorPrimaries);
BsWriteBits (pLocalBitStringAux, 8, pSps->uiTransferCharacteristics);
BsWriteBits (pLocalBitStringAux, 8, pSps->uiColorMatrix);
}
}
BsWriteOneBit (pLocalBitStringAux, false); BsWriteOneBit (pLocalBitStringAux, false); BsWriteOneBit (pLocalBitStringAux, false); BsWriteOneBit (pLocalBitStringAux, false); BsWriteOneBit (pLocalBitStringAux, false); BsWriteOneBit (pLocalBitStringAux, true);
BsWriteOneBit (pLocalBitStringAux, true); BsWriteUE (pLocalBitStringAux, 0); BsWriteUE (pLocalBitStringAux, 0); BsWriteUE (pLocalBitStringAux, 16); BsWriteUE (pLocalBitStringAux, 16);
BsWriteUE (pLocalBitStringAux, 0); BsWriteUE (pLocalBitStringAux, pSps->iNumRefFrames);
return 0;
}
int32_t WelsWriteSpsSyntax (SWelsSPS* pSps, SBitStringAux* pBitStringAux, int32_t* pSpsIdDelta, bool bBaseLayer) {
SBitStringAux* pLocalBitStringAux = pBitStringAux;
assert (pSps != NULL && pBitStringAux != NULL);
BsWriteBits (pLocalBitStringAux, 8, pSps->uiProfileIdc);
BsWriteOneBit (pLocalBitStringAux, pSps->bConstraintSet0Flag); BsWriteOneBit (pLocalBitStringAux, pSps->bConstraintSet1Flag); BsWriteOneBit (pLocalBitStringAux, pSps->bConstraintSet2Flag); BsWriteOneBit (pLocalBitStringAux, pSps->bConstraintSet3Flag); if (PRO_HIGH == pSps->uiProfileIdc || PRO_EXTENDED == pSps->uiProfileIdc ||
PRO_MAIN == pSps->uiProfileIdc) {
BsWriteOneBit (pLocalBitStringAux, 1); BsWriteOneBit (pLocalBitStringAux, 1); BsWriteBits (pLocalBitStringAux, 2, 0); } else {
BsWriteBits (pLocalBitStringAux, 4, 0); }
BsWriteBits (pLocalBitStringAux, 8, pSps->iLevelIdc); BsWriteUE (pLocalBitStringAux, pSps->uiSpsId + pSpsIdDelta[pSps->uiSpsId]);
if (PRO_SCALABLE_BASELINE == pSps->uiProfileIdc || PRO_SCALABLE_HIGH == pSps->uiProfileIdc ||
PRO_HIGH == pSps->uiProfileIdc || PRO_HIGH10 == pSps->uiProfileIdc ||
PRO_HIGH422 == pSps->uiProfileIdc || PRO_HIGH444 == pSps->uiProfileIdc ||
PRO_CAVLC444 == pSps->uiProfileIdc || 44 == pSps->uiProfileIdc) {
BsWriteUE (pLocalBitStringAux, 1); BsWriteUE (pLocalBitStringAux, 0); BsWriteUE (pLocalBitStringAux, 0); BsWriteOneBit (pLocalBitStringAux, 0); BsWriteOneBit (pLocalBitStringAux, 0); }
BsWriteUE (pLocalBitStringAux, pSps->uiLog2MaxFrameNum - 4); BsWriteUE (pLocalBitStringAux, pSps->uiPocType); if (pSps->uiPocType == 0) {
BsWriteUE (pLocalBitStringAux, pSps->iLog2MaxPocLsb - 4); } else if (pSps->uiPocType == 1) {
assert (0);
} else {
}
BsWriteUE (pLocalBitStringAux, pSps->iNumRefFrames); BsWriteOneBit (pLocalBitStringAux, pSps->bGapsInFrameNumValueAllowedFlag); BsWriteUE (pLocalBitStringAux, pSps->iMbWidth - 1); BsWriteUE (pLocalBitStringAux, pSps->iMbHeight - 1); BsWriteOneBit (pLocalBitStringAux, true);
uint8_t d8x8 = 0;
if (pSps->iLevelIdc >= 30)
d8x8 = 1;
BsWriteOneBit (pLocalBitStringAux, d8x8);
BsWriteOneBit (pLocalBitStringAux, pSps->bFrameCroppingFlag); if (pSps->bFrameCroppingFlag) {
BsWriteUE (pLocalBitStringAux, pSps->sFrameCrop.iCropLeft); BsWriteUE (pLocalBitStringAux, pSps->sFrameCrop.iCropRight); BsWriteUE (pLocalBitStringAux, pSps->sFrameCrop.iCropTop); BsWriteUE (pLocalBitStringAux, pSps->sFrameCrop.iCropBottom); }
if (bBaseLayer) {
BsWriteOneBit (pLocalBitStringAux, true); WelsWriteVUI (pSps, pBitStringAux);
} else {
BsWriteOneBit (pLocalBitStringAux, false);
}
return 0;
}
int32_t WelsWriteSpsNal (SWelsSPS* pSps, SBitStringAux* pBitStringAux, int32_t* pSpsIdDelta) {
WelsWriteSpsSyntax (pSps, pBitStringAux, pSpsIdDelta, true);
BsRbspTrailingBits (pBitStringAux);
return 0;
}
int32_t WelsWriteSubsetSpsSyntax (SSubsetSps* pSubsetSps, SBitStringAux* pBitStringAux , int32_t* pSpsIdDelta) {
SWelsSPS* pSps = &pSubsetSps->pSps;
WelsWriteSpsSyntax (pSps, pBitStringAux, pSpsIdDelta, false);
if (pSps->uiProfileIdc == PRO_SCALABLE_BASELINE || pSps->uiProfileIdc == PRO_SCALABLE_HIGH) {
SSpsSvcExt* pSubsetSpsExt = &pSubsetSps->sSpsSvcExt;
BsWriteOneBit (pBitStringAux, true);
BsWriteBits (pBitStringAux, 2, pSubsetSpsExt->iExtendedSpatialScalability);
BsWriteOneBit (pBitStringAux, 0);
BsWriteBits (pBitStringAux, 2, 1);
if (pSubsetSpsExt->iExtendedSpatialScalability == 1) {
BsWriteOneBit (pBitStringAux, 0);
BsWriteBits (pBitStringAux, 2, 1);
BsWriteSE (pBitStringAux, 0);
BsWriteSE (pBitStringAux, 0);
BsWriteSE (pBitStringAux, 0);
BsWriteSE (pBitStringAux, 0);
}
BsWriteOneBit (pBitStringAux, pSubsetSpsExt->bSeqTcoeffLevelPredFlag);
if (pSubsetSpsExt->bSeqTcoeffLevelPredFlag) {
BsWriteOneBit (pBitStringAux, pSubsetSpsExt->bAdaptiveTcoeffLevelPredFlag);
}
BsWriteOneBit (pBitStringAux, pSubsetSpsExt->bSliceHeaderRestrictionFlag);
BsWriteOneBit (pBitStringAux, false);
}
BsWriteOneBit (pBitStringAux, false);
BsRbspTrailingBits (pBitStringAux);
return 0;
}
int32_t WelsWritePpsSyntax (SWelsPPS* pPps, SBitStringAux* pBitStringAux,
IWelsParametersetStrategy* pParametersetStrategy) {
SBitStringAux* pLocalBitStringAux = pBitStringAux;
BsWriteUE (pLocalBitStringAux, pPps->iPpsId + pParametersetStrategy->GetPpsIdOffset (pPps->iPpsId));
BsWriteUE (pLocalBitStringAux, pPps->iSpsId + pParametersetStrategy->GetSpsIdOffset (pPps->iPpsId, pPps->iSpsId));
BsWriteOneBit (pLocalBitStringAux, pPps->bEntropyCodingModeFlag);
BsWriteOneBit (pLocalBitStringAux, false);
#ifdef DISABLE_FMO_FEATURE
BsWriteUE (pLocalBitStringAux, 0);
#else
BsWriteUE (pLocalBitStringAux, pPps->uiNumSliceGroups - 1);
if (pPps->uiNumSliceGroups > 1) {
uint32_t i, uiNumBits;
BsWriteUE (pLocalBitStringAux, pPps->uiSliceGroupMapType);
switch (pPps->uiSliceGroupMapType) {
case 0:
for (i = 0; i < pPps->uiNumSliceGroups; i ++) {
BsWriteUE (pLocalBitStringAux, pPps->uiRunLength[i] - 1);
}
break;
case 2:
for (i = 0; i < pPps->uiNumSliceGroups; i ++) {
BsWriteUE (pLocalBitStringAux, pPps->uiTopLeft[i]);
BsWriteUE (pLocalBitStringAux, pPps->uiBottomRight[i]);
}
break;
case 3:
case 4:
case 5:
BsWriteOneBit (pLocalBitStringAux, pPps->bSliceGroupChangeDirectionFlag);
BsWriteUE (pLocalBitStringAux, pPps->uiSliceGroupChangeRate - 1);
break;
case 6:
BsWriteUE (pLocalBitStringAux, pPps->uiPicSizeInMapUnits - 1);
uiNumBits = 0; for (i = 0; i < pPps->uiPicSizeInMapUnits; i ++) {
BsWriteBits (pLocalBitStringAux, uiNumBits, pPps->uiSliceGroupId[i]);
}
break;
default:
break;
}
}
#endif
BsWriteUE (pLocalBitStringAux, 0);
BsWriteUE (pLocalBitStringAux, 0);
BsWriteOneBit (pLocalBitStringAux, false);
BsWriteBits (pLocalBitStringAux, 2, 0);
BsWriteSE (pLocalBitStringAux, pPps->iPicInitQp - 26);
BsWriteSE (pLocalBitStringAux, pPps->iPicInitQs - 26);
BsWriteSE (pLocalBitStringAux, pPps->uiChromaQpIndexOffset);
BsWriteOneBit (pLocalBitStringAux, pPps->bDeblockingFilterControlPresentFlag);
BsWriteOneBit (pLocalBitStringAux, false);
BsWriteOneBit (pLocalBitStringAux, false);
BsRbspTrailingBits (pLocalBitStringAux);
return 0;
}
static inline bool WelsGetPaddingOffset (int32_t iActualWidth, int32_t iActualHeight, int32_t iWidth,
int32_t iHeight, SCropOffset& pOffset) {
if ((iWidth < iActualWidth) || (iHeight < iActualHeight))
return false;
iActualWidth -= (iActualWidth & 1);
iActualHeight -= (iActualHeight & 1);
pOffset.iCropLeft = 0;
pOffset.iCropRight = (iWidth - iActualWidth) / 2;
pOffset.iCropTop = 0;
pOffset.iCropBottom = (iHeight - iActualHeight) / 2;
return (iWidth > iActualWidth) || (iHeight > iActualHeight);
}
int32_t WelsInitSps (SWelsSPS* pSps, SSpatialLayerConfig* pLayerParam, SSpatialLayerInternal* pLayerParamInternal,
const uint32_t kuiIntraPeriod, const int32_t kiNumRefFrame,
const uint32_t kuiSpsId, const bool kbEnableFrameCropping, bool bEnableRc,
const int32_t kiDlayerCount, bool bSVCBaselayer) {
memset (pSps, 0, sizeof (SWelsSPS));
pSps->uiSpsId = kuiSpsId;
pSps->iMbWidth = (pLayerParam->iVideoWidth + 15) >> 4;
pSps->iMbHeight = (pLayerParam->iVideoHeight + 15) >> 4;
pSps->uiLog2MaxFrameNum = 15; pSps->uiPocType = 2;
pSps->iLog2MaxPocLsb = 1 + pSps->uiLog2MaxFrameNum;
pSps->iNumRefFrames = kiNumRefFrame;
if (kbEnableFrameCropping) {
pSps->bFrameCroppingFlag = WelsGetPaddingOffset (pLayerParamInternal->iActualWidth, pLayerParamInternal->iActualHeight,
pLayerParam->iVideoWidth, pLayerParam->iVideoHeight, pSps->sFrameCrop);
} else {
pSps->bFrameCroppingFlag = false;
}
pSps->uiProfileIdc = pLayerParam->uiProfileIdc ? pLayerParam->uiProfileIdc : PRO_BASELINE;
if (pLayerParam->uiProfileIdc == PRO_BASELINE) {
pSps->bConstraintSet0Flag = true;
}
if (pLayerParam->uiProfileIdc <= PRO_MAIN) {
pSps->bConstraintSet1Flag = true;
}
if ((kiDlayerCount > 1) && bSVCBaselayer) {
pSps->bConstraintSet2Flag = true;
}
ELevelIdc uiLevel = WelsGetLevelIdc (pSps, pLayerParamInternal->fOutputFrameRate, pLayerParam->iSpatialBitrate);
if ((uiLevel == LEVEL_1_B) &&
((pSps->uiProfileIdc == PRO_BASELINE) || (pSps->uiProfileIdc == PRO_MAIN) || (pSps->uiProfileIdc == PRO_EXTENDED))) {
uiLevel = LEVEL_1_1;
pSps->bConstraintSet3Flag = true;
}
if ((pLayerParam->uiLevelIdc == LEVEL_UNKNOWN) || (pLayerParam->uiLevelIdc < uiLevel)) {
pLayerParam->uiLevelIdc = uiLevel;
}
pSps->iLevelIdc = pLayerParam->uiLevelIdc;
if ((kiDlayerCount == 1) && (pSps->iNumRefFrames == 1))
pSps->bGapsInFrameNumValueAllowedFlag = false;
else
pSps->bGapsInFrameNumValueAllowedFlag = true;
pSps->bVuiParamPresentFlag = true;
pSps->bAspectRatioPresent = pLayerParam->bAspectRatioPresent;
pSps->eAspectRatio = pLayerParam->eAspectRatio;
pSps->sAspectRatioExtWidth = pLayerParam->sAspectRatioExtWidth;
pSps->sAspectRatioExtHeight = pLayerParam->sAspectRatioExtHeight;
pSps->bVideoSignalTypePresent = pLayerParam->bVideoSignalTypePresent;
pSps->uiVideoFormat = pLayerParam->uiVideoFormat;
pSps->bFullRange = pLayerParam->bFullRange;
pSps->bColorDescriptionPresent = pLayerParam->bColorDescriptionPresent;
pSps->uiColorPrimaries = pLayerParam->uiColorPrimaries;
pSps->uiTransferCharacteristics = pLayerParam->uiTransferCharacteristics;
pSps->uiColorMatrix = pLayerParam->uiColorMatrix;
return 0;
}
int32_t WelsInitSubsetSps (SSubsetSps* pSubsetSps, SSpatialLayerConfig* pLayerParam,
SSpatialLayerInternal* pLayerParamInternal,
const uint32_t kuiIntraPeriod, const int32_t kiNumRefFrame,
const uint32_t kuiSpsId, const bool kbEnableFrameCropping, bool bEnableRc,
const int32_t kiDlayerCount) {
SWelsSPS* pSps = &pSubsetSps->pSps;
memset (pSubsetSps, 0, sizeof (SSubsetSps));
WelsInitSps (pSps, pLayerParam, pLayerParamInternal, kuiIntraPeriod, kiNumRefFrame, kuiSpsId, kbEnableFrameCropping,
bEnableRc, kiDlayerCount, false);
pSps->uiProfileIdc = pLayerParam->uiProfileIdc ;
pSubsetSps->sSpsSvcExt.iExtendedSpatialScalability = 0;
pSubsetSps->sSpsSvcExt.bAdaptiveTcoeffLevelPredFlag = false;
pSubsetSps->sSpsSvcExt.bSeqTcoeffLevelPredFlag = false;
pSubsetSps->sSpsSvcExt.bSliceHeaderRestrictionFlag = true;
return 0;
}
int32_t WelsInitPps (SWelsPPS* pPps,
SWelsSPS* pSps,
SSubsetSps* pSubsetSps,
const uint32_t kuiPpsId,
const bool kbDeblockingFilterPresentFlag,
const bool kbUsingSubsetSps,
const bool kbEntropyCodingModeFlag) {
SWelsSPS* pUsedSps = NULL;
if (pPps == NULL || (pSps == NULL && pSubsetSps == NULL))
return 1;
if (!kbUsingSubsetSps) {
assert (pSps != NULL);
if (NULL == pSps)
return 1;
pUsedSps = pSps;
} else {
assert (pSubsetSps != NULL);
if (NULL == pSubsetSps)
return 1;
pUsedSps = &pSubsetSps->pSps;
}
pPps->iPpsId = kuiPpsId;
pPps->iSpsId = pUsedSps->uiSpsId;
pPps->bEntropyCodingModeFlag = kbEntropyCodingModeFlag;
#if !defined(DISABLE_FMO_FEATURE)
pPps->uiNumSliceGroups = 1; if (pPps->uiNumSliceGroups > 1) {
pPps->uiSliceGroupMapType = 0; if (pPps->uiSliceGroupMapType == 0) {
uint32_t uiGroup = 0;
while (uiGroup < pPps->uiNumSliceGroups) {
pPps->uiRunLength[uiGroup] = 25;
++ uiGroup;
}
} else if (pPps->uiSliceGroupMapType == 2) {
memset (&pPps->uiTopLeft[0], 0, MAX_SLICEGROUP_IDS * sizeof (pPps->uiTopLeft[0]));
memset (&pPps->uiBottomRight[0], 0, MAX_SLICEGROUP_IDS * sizeof (pPps->uiBottomRight[0]));
} else if (pPps->uiSliceGroupMapType >= 3 &&
pPps->uiSliceGroupMapType <= 5) {
pPps->bSliceGroupChangeDirectionFlag = false;
pPps->uiSliceGroupChangeRate = 0;
} else if (pPps->uiSliceGroupMapType == 6) {
pPps->uiPicSizeInMapUnits = 1;
memset (&pPps->uiSliceGroupId[0], 0, MAX_SLICEGROUP_IDS * sizeof (pPps->uiSliceGroupId[0]));
}
}
#endif
pPps->iPicInitQp = 26;
pPps->iPicInitQs = 26;
pPps->uiChromaQpIndexOffset = 0;
pPps->bDeblockingFilterControlPresentFlag = kbDeblockingFilterPresentFlag;
return 0;
}
}