#include "fmo.h"
#include "memory_align.h"
#include "error_code.h"
namespace WelsDec {
static inline int32_t FmoGenerateMbAllocMapType0 (PFmo pFmo, PPps pPps) {
uint32_t uiNumSliceGroups = 0;
int32_t iMbNum = 0;
int32_t i = 0;
WELS_VERIFY_RETURN_IF (ERR_INFO_INVALID_PARAM, (NULL == pFmo || NULL == pPps))
uiNumSliceGroups = pPps->uiNumSliceGroups;
iMbNum = pFmo->iCountMbNum;
WELS_VERIFY_RETURN_IF (ERR_INFO_INVALID_PARAM, (NULL == pFmo->pMbAllocMap || iMbNum <= 0
|| uiNumSliceGroups > MAX_SLICEGROUP_IDS))
do {
uint8_t uiGroup = 0;
do {
const int32_t kiRunIdx = pPps->uiRunLength[uiGroup];
int32_t j = 0;
do {
pFmo->pMbAllocMap[i + j] = uiGroup;
++ j;
} while (j < kiRunIdx && i + j < iMbNum);
i += kiRunIdx;
++ uiGroup;
} while (uiGroup < uiNumSliceGroups && i < iMbNum);
} while (i < iMbNum);
return ERR_NONE; }
static inline int32_t FmoGenerateMbAllocMapType1 (PFmo pFmo, PPps pPps, const int32_t kiMbWidth) {
uint32_t uiNumSliceGroups = 0;
int32_t iMbNum = 0;
int32_t i = 0;
WELS_VERIFY_RETURN_IF (ERR_INFO_INVALID_PARAM, (NULL == pFmo || NULL == pPps))
uiNumSliceGroups = pPps->uiNumSliceGroups;
iMbNum = pFmo->iCountMbNum;
WELS_VERIFY_RETURN_IF (ERR_INFO_INVALID_PARAM, (NULL == pFmo->pMbAllocMap || iMbNum <= 0 || kiMbWidth == 0
|| uiNumSliceGroups > MAX_SLICEGROUP_IDS))
do {
pFmo->pMbAllocMap[i] = (uint8_t) (((i % kiMbWidth) + (((i / kiMbWidth) * uiNumSliceGroups) >> 1)) % uiNumSliceGroups);
++ i;
} while (i < iMbNum);
return ERR_NONE; }
static inline int32_t FmoGenerateSliceGroup (PFmo pFmo, const PPps kpPps, const int32_t kiMbWidth,
const int32_t kiMbHeight, CMemoryAlign* pMa) {
int32_t iNumMb = 0;
int32_t iErr = 0;
bool bResolutionChanged = false;
WELS_VERIFY_RETURN_IF (ERR_INFO_INVALID_PARAM, (NULL == pFmo || NULL == kpPps))
iNumMb = kiMbWidth * kiMbHeight;
if (0 == iNumMb)
return ERR_INFO_INVALID_PARAM;
pMa->WelsFree (pFmo->pMbAllocMap, "_fmo->pMbAllocMap");
pFmo->pMbAllocMap = (uint8_t*)pMa->WelsMallocz (iNumMb * sizeof (uint8_t), "_fmo->pMbAllocMap");
WELS_VERIFY_RETURN_IF (ERR_INFO_OUT_OF_MEMORY, (NULL == pFmo->pMbAllocMap))
pFmo->iCountMbNum = iNumMb;
if (kpPps->uiNumSliceGroups < 2 && iNumMb > 0) { memset (pFmo->pMbAllocMap, 0, iNumMb * sizeof (int8_t));
pFmo->iSliceGroupCount = 1;
return ERR_NONE;
}
if (bResolutionChanged || ((int32_t)kpPps->uiSliceGroupMapType != pFmo->iSliceGroupType)
|| ((int32_t)kpPps->uiNumSliceGroups != pFmo->iSliceGroupCount)) {
switch (kpPps->uiSliceGroupMapType) {
case 0:
iErr = FmoGenerateMbAllocMapType0 (pFmo, kpPps);
break;
case 1:
iErr = FmoGenerateMbAllocMapType1 (pFmo, kpPps, kiMbWidth);
break;
case 2:
case 3:
case 4:
case 5:
case 6:
iErr = 1;
break;
default:
return ERR_INFO_UNSUPPORTED_FMOTYPE;
}
}
if (0 == iErr) { pFmo->iSliceGroupCount = kpPps->uiNumSliceGroups;
pFmo->iSliceGroupType = kpPps->uiSliceGroupMapType;
}
return iErr;
}
int32_t InitFmo (PFmo pFmo, PPps pPps, const int32_t kiMbWidth, const int32_t kiMbHeight, CMemoryAlign* pMa) {
return FmoGenerateSliceGroup (pFmo, pPps, kiMbWidth, kiMbHeight, pMa);
}
void UninitFmoList (PFmo pFmo, const int32_t kiCnt, const int32_t kiAvail, CMemoryAlign* pMa) {
PFmo pIter = pFmo;
int32_t i = 0;
int32_t iFreeNodes = 0;
if (NULL == pIter || kiAvail <= 0 || kiCnt < kiAvail)
return;
while (i < kiCnt) {
if (pIter != NULL && pIter->bActiveFlag) {
if (NULL != pIter->pMbAllocMap) {
pMa->WelsFree (pIter->pMbAllocMap, "pIter->pMbAllocMap");
pIter->pMbAllocMap = NULL;
}
pIter->iSliceGroupCount = 0;
pIter->iSliceGroupType = -1;
pIter->iCountMbNum = 0;
pIter->bActiveFlag = false;
++ iFreeNodes;
if (iFreeNodes >= kiAvail)
break;
}
++ pIter;
++ i;
}
}
bool FmoParamSetsChanged (PFmo pFmo, const int32_t kiCountNumMb, const int32_t kiSliceGroupType,
const int32_t kiSliceGroupCount) {
WELS_VERIFY_RETURN_IF (false, (NULL == pFmo))
return ((!pFmo->bActiveFlag)
|| (kiCountNumMb != pFmo->iCountMbNum)
|| (kiSliceGroupType != pFmo->iSliceGroupType)
|| (kiSliceGroupCount != pFmo->iSliceGroupCount));
}
int32_t FmoParamUpdate (PFmo pFmo, PSps pSps, PPps pPps, int32_t* pActiveFmoNum, CMemoryAlign* pMa) {
const uint32_t kuiMbWidth = pSps->iMbWidth;
const uint32_t kuiMbHeight = pSps->iMbHeight;
int32_t iRet = ERR_NONE;
if (FmoParamSetsChanged (pFmo, kuiMbWidth * kuiMbHeight, pPps->uiSliceGroupMapType, pPps->uiNumSliceGroups)) {
iRet = InitFmo (pFmo, pPps, kuiMbWidth, kuiMbHeight, pMa);
WELS_VERIFY_RETURN_IF (iRet, iRet);
if (!pFmo->bActiveFlag && *pActiveFmoNum < MAX_PPS_COUNT) {
++ (*pActiveFmoNum);
pFmo->bActiveFlag = true;
}
}
return iRet;
}
int32_t FmoMbToSliceGroup (PFmo pFmo, const MB_XY_T kiMbXy) {
const int32_t kiMbNum = pFmo->iCountMbNum;
const uint8_t* kpMbMap = pFmo->pMbAllocMap;
if (kiMbXy < 0 || kiMbXy >= kiMbNum || kpMbMap == NULL)
return -1;
return kpMbMap[ kiMbXy ];
}
MB_XY_T FmoNextMb (PFmo pFmo, const MB_XY_T kiMbXy) {
const int32_t kiTotalMb = pFmo->iCountMbNum;
const uint8_t* kpMbMap = pFmo->pMbAllocMap;
MB_XY_T iNextMb = kiMbXy;
const uint8_t kuiSliceGroupIdc = (uint8_t)FmoMbToSliceGroup (pFmo, kiMbXy);
if (kuiSliceGroupIdc == (uint8_t) (-1))
return -1;
do {
++ iNextMb;
if (iNextMb >= kiTotalMb) {
iNextMb = -1;
break;
}
if (kpMbMap[iNextMb] == kuiSliceGroupIdc) {
break;
}
} while (1);
return iNextMb;
}
}