/*! * \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 mv_pred.c * * \brief Get MV predictor and update motion vector of mb cache * * \date 05/22/2009 Created * ************************************************************************************* */ #include "mv_pred.h"#include "ls_defines.h"#include "mb_cache.h"#include "parse_mb_syn_cabac.h" static inline void SetRectBlock (void* vp, int32_t w, const int32_t h, int32_t stride, const uint32_t val, const int32_t size) { uint8_t* p = (uint8_t*)vp; w *= size; if (w == 1 && h == 4) { * (uint8_t*) (p + 0 * stride) = * (uint8_t*) (p + 1 * stride) = * (uint8_t*) (p + 2 * stride) = * (uint8_t*) (p + 3 * stride) = (uint8_t)val; } else if (w == 2 && h == 2) { * (uint16_t*) (p + 0 * stride) = * (uint16_t*) (p + 1 * stride) = size == 4 ? (uint16_t)val : (uint16_t) (val * 0x0101U); } else if (w == 2 && h == 4) { * (uint16_t*) (p + 0 * stride) = * (uint16_t*) (p + 1 * stride) = * (uint16_t*) (p + 2 * stride) = * (uint16_t*) (p + 3 * stride) = size == 4 ? (uint16_t)val : (uint16_t) (val * 0x0101U); } else if (w == 4 && h == 2) { * (uint32_t*) (p + 0 * stride) = * (uint32_t*) (p + 1 * stride) = size == 4 ? val : (uint32_t) (val * 0x01010101UL); } else if (w == 4 && h == 4) { * (uint32_t*) (p + 0 * stride) = * (uint32_t*) (p + 1 * stride) = * (uint32_t*) (p + 2 * stride) = * (uint32_t*) (p + 3 * stride) = size == 4 ? val : (uint32_t) (val * 0x01010101UL); } else if (w == 8 && h == 1) { * (uint32_t*) (p + 0 * stride) = * (uint32_t*) (p + 0 * stride + 4) = size == 4 ? val : (uint32_t) (val * 0x01010101UL); } else if (w == 8 && h == 2) { * (uint32_t*) (p + 0 * stride) = * (uint32_t*) (p + 0 * stride + 4) = * (uint32_t*) (p + 1 * stride) = * (uint32_t*) (p + 1 * stride + 4) = size == 4 ? val : (uint32_t) (val * 0x01010101UL); } else if (w == 8 && h == 4) { * (uint32_t*) (p + 0 * stride) = * (uint32_t*) (p + 0 * stride + 4) = * (uint32_t*) (p + 1 * stride) = * (uint32_t*) (p + 1 * stride + 4) = * (uint32_t*) (p + 2 * stride) = * (uint32_t*) (p + 2 * stride + 4) = * (uint32_t*) (p + 3 * stride) = * (uint32_t*) (p + 3 * stride + 4) = size == 4 ? val : (uint32_t) (val * 0x01010101UL); } else if (w == 16 && h == 2) { * (uint32_t*) (p + 0 * stride + 0) = * (uint32_t*) (p + 0 * stride + 4) = * (uint32_t*) (p + 0 * stride + 8) = * (uint32_t*) (p + 0 * stride + 12) = * (uint32_t*) (p + 1 * stride + 0) = * (uint32_t*) (p + 1 * stride + 4) = * (uint32_t*) (p + 1 * stride + 8) = * (uint32_t*) (p + 1 * stride + 12) = size == 4 ? val : (uint32_t) (val * 0x01010101UL); } else if (w == 16 && h == 3) { * (uint32_t*) (p + 0 * stride + 0) = * (uint32_t*) (p + 0 * stride + 4) = * (uint32_t*) (p + 0 * stride + 8) = * (uint32_t*) (p + 0 * stride + 12) = * (uint32_t*) (p + 1 * stride + 0) = * (uint32_t*) (p + 1 * stride + 4) = * (uint32_t*) (p + 1 * stride + 8) = * (uint32_t*) (p + 1 * stride + 12) = * (uint32_t*) (p + 2 * stride + 0) = * (uint32_t*) (p + 2 * stride + 4) = * (uint32_t*) (p + 2 * stride + 8) = * (uint32_t*) (p + 2 * stride + 12) = size == 4 ? val : (uint32_t) (val * 0x01010101UL); } else if (w == 16 && h == 4) { * (uint32_t*) (p + 0 * stride + 0) = * (uint32_t*) (p + 0 * stride + 4) = * (uint32_t*) (p + 0 * stride + 8) = * (uint32_t*) (p + 0 * stride + 12) = * (uint32_t*) (p + 1 * stride + 0) = * (uint32_t*) (p + 1 * stride + 4) = * (uint32_t*) (p + 1 * stride + 8) = * (uint32_t*) (p + 1 * stride + 12) = * (uint32_t*) (p + 2 * stride + 0) = * (uint32_t*) (p + 2 * stride + 4) = * (uint32_t*) (p + 2 * stride + 8) = * (uint32_t*) (p + 2 * stride + 12) = * (uint32_t*) (p + 3 * stride + 0) = * (uint32_t*) (p + 3 * stride + 4) = * (uint32_t*) (p + 3 * stride + 8) = * (uint32_t*) (p + 3 * stride + 12) = size == 4 ? val : (uint32_t) (val * 0x01010101UL); }}void CopyRectBlock4Cols (void* vdst, void* vsrc, const int32_t stride_dst, const int32_t stride_src, int32_t w, const int32_t size) { uint8_t* dst = (uint8_t*)vdst; uint8_t* src = (uint8_t*)vsrc; w *= size; if (w == 1) { dst[stride_dst * 0] = src[stride_src * 0]; dst[stride_dst * 1] = src[stride_src * 1]; dst[stride_dst * 2] = src[stride_src * 2]; dst[stride_dst * 3] = src[stride_src * 3]; } else if (w == 2) { * (uint16_t*) (&dst[stride_dst * 0]) = * (uint16_t*) (&src[stride_src * 0]); * (uint16_t*) (&dst[stride_dst * 1]) = * (uint16_t*) (&src[stride_src * 1]); * (uint16_t*) (&dst[stride_dst * 2]) = * (uint16_t*) (&src[stride_src * 2]); * (uint16_t*) (&dst[stride_dst * 3]) = * (uint16_t*) (&src[stride_src * 3]); } else if (w == 4) { * (uint32_t*) (&dst[stride_dst * 0]) = * (uint32_t*) (&src[stride_src * 0]); * (uint32_t*) (&dst[stride_dst * 1]) = * (uint32_t*) (&src[stride_src * 1]); * (uint32_t*) (&dst[stride_dst * 2]) = * (uint32_t*) (&src[stride_src * 2]); * (uint32_t*) (&dst[stride_dst * 3]) = * (uint32_t*) (&src[stride_src * 3]); } else if (w == 16) { memcpy (&dst[stride_dst * 0], &src[stride_src * 0], 16); memcpy (&dst[stride_dst * 1], &src[stride_src * 1], 16); memcpy (&dst[stride_dst * 2], &src[stride_src * 2], 16); memcpy (&dst[stride_dst * 3], &src[stride_src * 3], 16); }}void PredPSkipMvFromNeighbor (PDqLayer pCurDqLayer, int16_t iMvp[2]) { bool bTopAvail, bLeftTopAvail, bRightTopAvail, bLeftAvail; int32_t iCurSliceIdc, iTopSliceIdc, iLeftTopSliceIdc, iRightTopSliceIdc, iLeftSliceIdc; int32_t iLeftTopType, iRightTopType, iTopType, iLeftType; int32_t iCurX, iCurY, iCurXy, iLeftXy = 0, iTopXy = 0, iLeftTopXy = 0, iRightTopXy = 0; int8_t iLeftRef; int8_t iTopRef; int8_t iRightTopRef; int8_t iLeftTopRef; int8_t iDiagonalRef; int8_t iMatchRef; int16_t iMvA[2], iMvB[2], iMvC[2], iMvD[2]; iCurXy = pCurDqLayer->iMbXyIndex; iCurX = pCurDqLayer->iMbX; iCurY = pCurDqLayer->iMbY; iCurSliceIdc = pCurDqLayer->pSliceIdc[iCurXy]; if (iCurX != 0) { iLeftXy = iCurXy - 1; iLeftSliceIdc = pCurDqLayer->pSliceIdc[iLeftXy]; bLeftAvail = (iLeftSliceIdc == iCurSliceIdc); } else { bLeftAvail = 0; } if (iCurY != 0) { iTopXy = iCurXy - pCurDqLayer->iMbWidth; iTopSliceIdc = pCurDqLayer->pSliceIdc[iTopXy]; bTopAvail = (iTopSliceIdc == iCurSliceIdc); if (iCurX != 0) { iLeftTopXy = iTopXy - 1; iLeftTopSliceIdc = pCurDqLayer->pSliceIdc[iLeftTopXy]; bLeftTopAvail = (iLeftTopSliceIdc == iCurSliceIdc); } else { bLeftTopAvail = 0; } if (iCurX != (pCurDqLayer->iMbWidth - 1)) { iRightTopXy = iTopXy + 1; iRightTopSliceIdc = pCurDqLayer->pSliceIdc[iRightTopXy]; bRightTopAvail = (iRightTopSliceIdc == iCurSliceIdc); } else { bRightTopAvail = 0; } } else { bTopAvail = 0; bLeftTopAvail = 0; bRightTopAvail = 0; } iLeftType = ((iCurX != 0 && bLeftAvail) ? GetMbType (pCurDqLayer)[iLeftXy] : 0); iTopType = ((iCurY != 0 && bTopAvail) ? GetMbType (pCurDqLayer)[iTopXy] : 0); iLeftTopType = ((iCurX != 0 && iCurY != 0 && bLeftTopAvail) ? GetMbType (pCurDqLayer)[iLeftTopXy] : 0); iRightTopType = ((iCurX != pCurDqLayer->iMbWidth - 1 && iCurY != 0 && bRightTopAvail) ? GetMbType (pCurDqLayer)[iRightTopXy] : 0); /*get neb mv&iRefIdxArray*/ /*left*/ if (bLeftAvail && IS_INTER (iLeftType)) { ST32 (iMvA, LD32 (pCurDqLayer->pDec ? pCurDqLayer->pDec->pMv[0][iLeftXy][3] : pCurDqLayer->pMv[0][iLeftXy][3])); iLeftRef = pCurDqLayer->pDec ? pCurDqLayer->pDec->pRefIndex[0][iLeftXy][3] : pCurDqLayer->pRefIndex[0][iLeftXy][3]; } else { ST32 (iMvA, 0); if (0 == bLeftAvail) { //not available iLeftRef = REF_NOT_AVAIL; } else { //available but is intra mb type iLeftRef = REF_NOT_IN_LIST; } } if (REF_NOT_AVAIL == iLeftRef || (0 == iLeftRef && 0 == * (int32_t*)iMvA)) { ST32 (iMvp, 0); return; } /*top*/ if (bTopAvail && IS_INTER (iTopType)) { ST32 (iMvB, LD32 (pCurDqLayer->pDec ? pCurDqLayer->pDec->pMv[0][iTopXy][12] : pCurDqLayer->pMv[0][iTopXy][12])); iTopRef = pCurDqLayer->pDec ? pCurDqLayer->pDec->pRefIndex[0][iTopXy][12] : pCurDqLayer->pRefIndex[0][iTopXy][12]; } else { ST32 (iMvB, 0); if (0 == bTopAvail) { //not available iTopRef = REF_NOT_AVAIL; } else { //available but is intra mb type iTopRef = REF_NOT_IN_LIST; } } if (REF_NOT_AVAIL == iTopRef || (0 == iTopRef && 0 == * (int32_t*)iMvB)) { ST32 (iMvp, 0); return; } /*right_top*/ if (bRightTopAvail && IS_INTER (iRightTopType)) { ST32 (iMvC, LD32 (pCurDqLayer->pDec ? pCurDqLayer->pDec->pMv[0][iRightTopXy][12] : pCurDqLayer->pMv[0][iRightTopXy][12])); iRightTopRef = pCurDqLayer->pDec ? pCurDqLayer->pDec->pRefIndex[0][iRightTopXy][12] : pCurDqLayer->pRefIndex[0][iRightTopXy][12]; } else { ST32 (iMvC, 0); if (0 == bRightTopAvail) { //not available iRightTopRef = REF_NOT_AVAIL; } else { //available but is intra mb type iRightTopRef = REF_NOT_IN_LIST; } } /*left_top*/ if (bLeftTopAvail && IS_INTER (iLeftTopType)) { ST32 (iMvD, LD32 (pCurDqLayer->pDec ? pCurDqLayer->pDec->pMv[0][iLeftTopXy][15] : pCurDqLayer->pMv[0][iLeftTopXy][15])); iLeftTopRef = pCurDqLayer->pDec ? pCurDqLayer->pDec->pRefIndex[0][iLeftTopXy][15] : pCurDqLayer->pRefIndex[0][iLeftTopXy][15]; } else { ST32 (iMvD, 0); if (0 == bLeftTopAvail) { //not available iLeftTopRef = REF_NOT_AVAIL; } else { //available but is intra mb type iLeftTopRef = REF_NOT_IN_LIST; } } iDiagonalRef = iRightTopRef; if (REF_NOT_AVAIL == iDiagonalRef) { iDiagonalRef = iLeftTopRef; * (int32_t*)iMvC = * (int32_t*)iMvD; } if (REF_NOT_AVAIL == iTopRef && REF_NOT_AVAIL == iDiagonalRef && iLeftRef >= REF_NOT_IN_LIST) { ST32 (iMvp, LD32 (iMvA)); return; } iMatchRef = (0 == iLeftRef) + (0 == iTopRef) + (0 == iDiagonalRef); if (1 == iMatchRef) { if (0 == iLeftRef) { ST32 (iMvp, LD32 (iMvA)); } else if (0 == iTopRef) { ST32 (iMvp, LD32 (iMvB)); } else { ST32 (iMvp, LD32 (iMvC)); } } else { iMvp[0] = WelsMedian (iMvA[0], iMvB[0], iMvC[0]); iMvp[1] = WelsMedian (iMvA[1], iMvB[1], iMvC[1]); }} int32_t GetColocatedMb (PWelsDecoderContext pCtx, MbType *mbType, SubMbType *subMbType) { PDqLayer pCurDqLayer = pCtx->pCurDqLayer; int32_t iMbXy = pCurDqLayer->iMbXyIndex; uint32_t is8x8 = IS_Inter_8x8 (GetMbType (pCurDqLayer)[iMbXy]); *mbType = GetMbType (pCurDqLayer)[iMbXy]; PPicture colocPic = pCtx->sRefPic.pRefList[LIST_1][0]; if (GetThreadCount (pCtx) > 1) { if (16 * pCurDqLayer->iMbY > pCtx->lastReadyHeightOffset[1][0]) { if (colocPic->pReadyEvent[pCurDqLayer->iMbY].isSignaled != 1) { WAIT_EVENT (&colocPic->pReadyEvent[pCurDqLayer->iMbY], WELS_DEC_THREAD_WAIT_INFINITE); } pCtx->lastReadyHeightOffset[1][0] = 16 * pCurDqLayer->iMbY; } } if (colocPic == NULL) { SLogContext* pLogCtx = & (pCtx->sLogCtx); WelsLog (pLogCtx, WELS_LOG_ERROR, "Colocated Ref Picture for B-Slice is lost, B-Slice decoding cannot be continued!"); return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_DATA, ERR_INFO_REFERENCE_PIC_LOST); } MbType coloc_mbType = colocPic->pMbType[iMbXy]; if (coloc_mbType == MB_TYPE_SKIP) { //This indicates the colocated MB is P SKIP MB coloc_mbType |= MB_TYPE_16x16 | MB_TYPE_P0L0 | MB_TYPE_P1L0; } if (IS_Inter_8x8 (coloc_mbType) && !pCtx->pSps->bDirect8x8InferenceFlag) { *subMbType = SUB_MB_TYPE_4x4 | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_DIRECT; *mbType |= MB_TYPE_8x8 | MB_TYPE_L0 | MB_TYPE_L1; } else if (!is8x8 && (IS_INTER_16x16 (coloc_mbType) || IS_INTRA (coloc_mbType)/* || IS_SKIP(coloc_mbType)*/)) { *subMbType = SUB_MB_TYPE_8x8 | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_DIRECT; *mbType |= MB_TYPE_16x16 | MB_TYPE_L0 | MB_TYPE_L1; } else { *subMbType = SUB_MB_TYPE_8x8 | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_DIRECT; *mbType |= MB_TYPE_8x8 | MB_TYPE_L0 | MB_TYPE_L1; } if (IS_INTRA (coloc_mbType)) { SetRectBlock (pCurDqLayer->iColocIntra, 4, 4, 4 * sizeof (int8_t), 1, sizeof (int8_t)); return ERR_NONE; } SetRectBlock (pCurDqLayer->iColocIntra, 4, 4, 4 * sizeof (int8_t), 0, sizeof (int8_t)); if (IS_INTER_16x16 (*mbType)) { int16_t iMVZero[2] = { 0 }; int16_t* pMv = IS_TYPE_L1 (coloc_mbType) ? colocPic->pMv[LIST_1][iMbXy][0] : iMVZero; ST32 (pCurDqLayer->iColocMv[LIST_0][0], LD32 (colocPic->pMv[LIST_0][iMbXy][0])); ST32 (pCurDqLayer->iColocMv[LIST_1][0], LD32 (pMv)); pCurDqLayer->iColocRefIndex[LIST_0][0] = colocPic->pRefIndex[LIST_0][iMbXy][0]; pCurDqLayer->iColocRefIndex[LIST_1][0] = IS_TYPE_L1 (coloc_mbType) ? colocPic->pRefIndex[LIST_1][iMbXy][0] : REF_NOT_IN_LIST; } else { if (!pCtx->pSps->bDirect8x8InferenceFlag) { CopyRectBlock4Cols (pCurDqLayer->iColocMv[LIST_0], colocPic->pMv[LIST_0][iMbXy], 16, 16, 4, 4); CopyRectBlock4Cols (pCurDqLayer->iColocRefIndex[LIST_0], colocPic->pRefIndex[LIST_0][iMbXy], 4, 4, 4, 1); if (IS_TYPE_L1 (coloc_mbType)) { CopyRectBlock4Cols (pCurDqLayer->iColocMv[LIST_1], colocPic->pMv[LIST_1][iMbXy], 16, 16, 4, 4); CopyRectBlock4Cols (pCurDqLayer->iColocRefIndex[LIST_1], colocPic->pRefIndex[LIST_1][iMbXy], 4, 4, 4, 1); } else { // only forward prediction SetRectBlock (pCurDqLayer->iColocRefIndex[LIST_1], 4, 4, 4, (uint8_t)REF_NOT_IN_LIST, 1); } } else { for (int32_t listIdx = 0; listIdx < 1 + !! (coloc_mbType & MB_TYPE_L1); listIdx++) { SetRectBlock (pCurDqLayer->iColocMv[listIdx][0], 2, 2, 16, LD32 (colocPic->pMv[listIdx][iMbXy][0]), 4); SetRectBlock (pCurDqLayer->iColocMv[listIdx][2], 2, 2, 16, LD32 (colocPic->pMv[listIdx][iMbXy][3]), 4); SetRectBlock (pCurDqLayer->iColocMv[listIdx][8], 2, 2, 16, LD32 (colocPic->pMv[listIdx][iMbXy][12]), 4); SetRectBlock (pCurDqLayer->iColocMv[listIdx][10], 2, 2, 16, LD32 (colocPic->pMv[listIdx][iMbXy][15]), 4); SetRectBlock (&pCurDqLayer->iColocRefIndex[listIdx][0], 2, 2, 4, colocPic->pRefIndex[listIdx][iMbXy][0], 1); SetRectBlock (&pCurDqLayer->iColocRefIndex[listIdx][2], 2, 2, 4, colocPic->pRefIndex[listIdx][iMbXy][3], 1); SetRectBlock (&pCurDqLayer->iColocRefIndex[listIdx][8], 2, 2, 4, colocPic->pRefIndex[listIdx][iMbXy][12], 1); SetRectBlock (&pCurDqLayer->iColocRefIndex[listIdx][10], 2, 2, 4, colocPic->pRefIndex[listIdx][iMbXy][15], 1); } if (! (coloc_mbType & MB_TYPE_L1)) // only forward prediction SetRectBlock (&pCurDqLayer->iColocRefIndex[1][0], 4, 4, 4, (uint8_t)REF_NOT_IN_LIST, 1); } } return ERR_NONE;} int32_t PredMvBDirectSpatial (PWelsDecoderContext pCtx, int16_t iMvp[LIST_A][2], int8_t ref[LIST_A], SubMbType *subMbType) { int32_t ret; PDqLayer pCurDqLayer = pCtx->pCurDqLayer; int32_t iMbXy = pCurDqLayer->iMbXyIndex; bool bSkipOrDirect = (IS_SKIP (GetMbType (pCurDqLayer)[iMbXy]) | IS_DIRECT (GetMbType (pCurDqLayer)[iMbXy])) > 0; MbType mbType; ret = GetColocatedMb (pCtx, &mbType, subMbType); if (ret != ERR_NONE) { return ret; } bool bTopAvail, bLeftTopAvail, bRightTopAvail, bLeftAvail; int32_t iLeftTopType, iRightTopType, iTopType, iLeftType; int32_t iCurSliceIdc, iTopSliceIdc, iLeftTopSliceIdc, iRightTopSliceIdc, iLeftSliceIdc; int32_t iCurX, iCurY, iCurXy, iLeftXy = 0, iTopXy = 0, iLeftTopXy = 0, iRightTopXy = 0; int8_t iLeftRef[LIST_A]; int8_t iTopRef[LIST_A]; int8_t iRightTopRef[LIST_A]; int8_t iLeftTopRef[LIST_A]; int8_t iDiagonalRef[LIST_A]; int16_t iMvA[LIST_A][2], iMvB[LIST_A][2], iMvC[LIST_A][2], iMvD[LIST_A][2]; iCurXy = pCurDqLayer->iMbXyIndex; iCurX = pCurDqLayer->iMbX; iCurY = pCurDqLayer->iMbY; iCurSliceIdc = pCurDqLayer->pSliceIdc[iCurXy]; if (iCurX != 0) { iLeftXy = iCurXy - 1; iLeftSliceIdc = pCurDqLayer->pSliceIdc[iLeftXy]; bLeftAvail = (iLeftSliceIdc == iCurSliceIdc); } else { bLeftAvail = 0; } if (iCurY != 0) { iTopXy = iCurXy - pCurDqLayer->iMbWidth; iTopSliceIdc = pCurDqLayer->pSliceIdc[iTopXy]; bTopAvail = (iTopSliceIdc == iCurSliceIdc); if (iCurX != 0) { iLeftTopXy = iTopXy - 1; iLeftTopSliceIdc = pCurDqLayer->pSliceIdc[iLeftTopXy]; bLeftTopAvail = (iLeftTopSliceIdc == iCurSliceIdc); } else { bLeftTopAvail = 0; } if (iCurX != (pCurDqLayer->iMbWidth - 1)) { iRightTopXy = iTopXy + 1; iRightTopSliceIdc = pCurDqLayer->pSliceIdc[iRightTopXy]; bRightTopAvail = (iRightTopSliceIdc == iCurSliceIdc); } else { bRightTopAvail = 0; } } else { bTopAvail = 0; bLeftTopAvail = 0; bRightTopAvail = 0; } iLeftType = ((iCurX != 0 && bLeftAvail) ? GetMbType (pCurDqLayer)[iLeftXy] : 0); iTopType = ((iCurY != 0 && bTopAvail) ? GetMbType (pCurDqLayer)[iTopXy] : 0); iLeftTopType = ((iCurX != 0 && iCurY != 0 && bLeftTopAvail) ? GetMbType (pCurDqLayer)[iLeftTopXy] : 0); iRightTopType = ((iCurX != pCurDqLayer->iMbWidth - 1 && iCurY != 0 && bRightTopAvail) ? GetMbType (pCurDqLayer)[iRightTopXy] : 0); /*get neb mv&iRefIdxArray*/ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) { /*left*/ if (bLeftAvail && IS_INTER (iLeftType)) { ST32 (iMvA[listIdx], LD32 (pCurDqLayer->pDec ? pCurDqLayer->pDec->pMv[listIdx][iLeftXy][3] : pCurDqLayer->pMv[listIdx][iLeftXy][3])); iLeftRef[listIdx] = pCurDqLayer->pDec ? pCurDqLayer->pDec->pRefIndex[listIdx][iLeftXy][3] : pCurDqLayer->pRefIndex[listIdx][iLeftXy][3]; } else { ST32 (iMvA[listIdx], 0); if (0 == bLeftAvail) { //not available iLeftRef[listIdx] = REF_NOT_AVAIL; } else { //available but is intra mb type iLeftRef[listIdx] = REF_NOT_IN_LIST; } } /*top*/ if (bTopAvail && IS_INTER (iTopType)) { ST32 (iMvB[listIdx], LD32 (pCurDqLayer->pDec ? pCurDqLayer->pDec->pMv[listIdx][iTopXy][12] : pCurDqLayer->pMv[listIdx][iTopXy][12])); iTopRef[listIdx] = pCurDqLayer->pDec ? pCurDqLayer->pDec->pRefIndex[listIdx][iTopXy][12] : pCurDqLayer->pRefIndex[listIdx][iTopXy][12]; } else { ST32 (iMvB[listIdx], 0); if (0 == bTopAvail) { //not available iTopRef[listIdx] = REF_NOT_AVAIL; } else { //available but is intra mb type iTopRef[listIdx] = REF_NOT_IN_LIST; } } /*right_top*/ if (bRightTopAvail && IS_INTER (iRightTopType)) { ST32 (iMvC[listIdx], LD32 (pCurDqLayer->pDec ? pCurDqLayer->pDec->pMv[listIdx][iRightTopXy][12] : pCurDqLayer->pMv[listIdx][iRightTopXy][12])); iRightTopRef[listIdx] = pCurDqLayer->pDec ? pCurDqLayer->pDec->pRefIndex[listIdx][iRightTopXy][12] : pCurDqLayer->pRefIndex[listIdx][iRightTopXy][12]; } else { ST32 (iMvC[listIdx], 0);Lines 1–500 of 1178. 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 mv_pred.c * * \brief Get MV predictor and update motion vector of mb cache * * \date 05/22/2009 Created * ************************************************************************************* */ #include "mv_pred.h" #include "ls_defines.h" #include "mb_cache.h" #include "parse_mb_syn_cabac.h" static inline void SetRectBlock (void* vp, int32_t w, const int32_t h, int32_t stride, const uint32_t val, const int32_t size) { uint8_t* p = (uint8_t*)vp; w *= size; if (w == 1 && h == 4) { * (uint8_t*) (p + 0 * stride) = * (uint8_t*) (p + 1 * stride) = * (uint8_t*) (p + 2 * stride) = * (uint8_t*) (p + 3 * stride) = (uint8_t)val; } else if (w == 2 && h == 2) { * (uint16_t*) (p + 0 * stride) = * (uint16_t*) (p + 1 * stride) = size == 4 ? (uint16_t)val : (uint16_t) (val * 0x0101U); } else if (w == 2 && h == 4) { * (uint16_t*) (p + 0 * stride) = * (uint16_t*) (p + 1 * stride) = * (uint16_t*) (p + 2 * stride) = * (uint16_t*) (p + 3 * stride) = size == 4 ? (uint16_t)val : (uint16_t) (val * 0x0101U); } else if (w == 4 && h == 2) { * (uint32_t*) (p + 0 * stride) = * (uint32_t*) (p + 1 * stride) = size == 4 ? val : (uint32_t) (val * 0x01010101UL); } else if (w == 4 && h == 4) { * (uint32_t*) (p + 0 * stride) = * (uint32_t*) (p + 1 * stride) = * (uint32_t*) (p + 2 * stride) = * (uint32_t*) (p + 3 * stride) = size == 4 ? val : (uint32_t) (val * 0x01010101UL); } else if (w == 8 && h == 1) { * (uint32_t*) (p + 0 * stride) = * (uint32_t*) (p + 0 * stride + 4) = size == 4 ? val : (uint32_t) (val * 0x01010101UL); } else if (w == 8 && h == 2) { * (uint32_t*) (p + 0 * stride) = * (uint32_t*) (p + 0 * stride + 4) = * (uint32_t*) (p + 1 * stride) = * (uint32_t*) (p + 1 * stride + 4) = size == 4 ? val : (uint32_t) (val * 0x01010101UL); } else if (w == 8 && h == 4) { * (uint32_t*) (p + 0 * stride) = * (uint32_t*) (p + 0 * stride + 4) = * (uint32_t*) (p + 1 * stride) = * (uint32_t*) (p + 1 * stride + 4) = * (uint32_t*) (p + 2 * stride) = * (uint32_t*) (p + 2 * stride + 4) = * (uint32_t*) (p + 3 * stride) = * (uint32_t*) (p + 3 * stride + 4) = size == 4 ? val : (uint32_t) (val * 0x01010101UL); } else if (w == 16 && h == 2) { * (uint32_t*) (p + 0 * stride + 0) = * (uint32_t*) (p + 0 * stride + 4) = * (uint32_t*) (p + 0 * stride + 8) = * (uint32_t*) (p + 0 * stride + 12) = * (uint32_t*) (p + 1 * stride + 0) = * (uint32_t*) (p + 1 * stride + 4) = * (uint32_t*) (p + 1 * stride + 8) = * (uint32_t*) (p + 1 * stride + 12) = size == 4 ? val : (uint32_t) (val * 0x01010101UL); } else if (w == 16 && h == 3) { * (uint32_t*) (p + 0 * stride + 0) = * (uint32_t*) (p + 0 * stride + 4) = * (uint32_t*) (p + 0 * stride + 8) = * (uint32_t*) (p + 0 * stride + 12) = * (uint32_t*) (p + 1 * stride + 0) = * (uint32_t*) (p + 1 * stride + 4) = * (uint32_t*) (p + 1 * stride + 8) = * (uint32_t*) (p + 1 * stride + 12) = * (uint32_t*) (p + 2 * stride + 0) = * (uint32_t*) (p + 2 * stride + 4) = * (uint32_t*) (p + 2 * stride + 8) = * (uint32_t*) (p + 2 * stride + 12) = size == 4 ? val : (uint32_t) (val * 0x01010101UL); } else if (w == 16 && h == 4) { * (uint32_t*) (p + 0 * stride + 0) = * (uint32_t*) (p + 0 * stride + 4) = * (uint32_t*) (p + 0 * stride + 8) = * (uint32_t*) (p + 0 * stride + 12) = * (uint32_t*) (p + 1 * stride + 0) = * (uint32_t*) (p + 1 * stride + 4) = * (uint32_t*) (p + 1 * stride + 8) = * (uint32_t*) (p + 1 * stride + 12) = * (uint32_t*) (p + 2 * stride + 0) = * (uint32_t*) (p + 2 * stride + 4) = * (uint32_t*) (p + 2 * stride + 8) = * (uint32_t*) (p + 2 * stride + 12) = * (uint32_t*) (p + 3 * stride + 0) = * (uint32_t*) (p + 3 * stride + 4) = * (uint32_t*) (p + 3 * stride + 8) = * (uint32_t*) (p + 3 * stride + 12) = size == 4 ? val : (uint32_t) (val * 0x01010101UL); } } void CopyRectBlock4Cols (void* vdst, void* vsrc, const int32_t stride_dst, const int32_t stride_src, int32_t w, const int32_t size) { uint8_t* dst = (uint8_t*)vdst; uint8_t* src = (uint8_t*)vsrc; w *= size; if (w == 1) { dst[stride_dst * 0] = src[stride_src * 0]; dst[stride_dst * 1] = src[stride_src * 1]; dst[stride_dst * 2] = src[stride_src * 2]; dst[stride_dst * 3] = src[stride_src * 3]; } else if (w == 2) { * (uint16_t*) (&dst[stride_dst * 0]) = * (uint16_t*) (&src[stride_src * 0]); * (uint16_t*) (&dst[stride_dst * 1]) = * (uint16_t*) (&src[stride_src * 1]); * (uint16_t*) (&dst[stride_dst * 2]) = * (uint16_t*) (&src[stride_src * 2]); * (uint16_t*) (&dst[stride_dst * 3]) = * (uint16_t*) (&src[stride_src * 3]); } else if (w == 4) { * (uint32_t*) (&dst[stride_dst * 0]) = * (uint32_t*) (&src[stride_src * 0]); * (uint32_t*) (&dst[stride_dst * 1]) = * (uint32_t*) (&src[stride_src * 1]); * (uint32_t*) (&dst[stride_dst * 2]) = * (uint32_t*) (&src[stride_src * 2]); * (uint32_t*) (&dst[stride_dst * 3]) = * (uint32_t*) (&src[stride_src * 3]); } else if (w == 16) { memcpy (&dst[stride_dst * 0], &src[stride_src * 0], 16); memcpy (&dst[stride_dst * 1], &src[stride_src * 1], 16); memcpy (&dst[stride_dst * 2], &src[stride_src * 2], 16); memcpy (&dst[stride_dst * 3], &src[stride_src * 3], 16); } } void PredPSkipMvFromNeighbor (PDqLayer pCurDqLayer, int16_t iMvp[2]) { bool bTopAvail, bLeftTopAvail, bRightTopAvail, bLeftAvail; int32_t iCurSliceIdc, iTopSliceIdc, iLeftTopSliceIdc, iRightTopSliceIdc, iLeftSliceIdc; int32_t iLeftTopType, iRightTopType, iTopType, iLeftType; int32_t iCurX, iCurY, iCurXy, iLeftXy = 0, iTopXy = 0, iLeftTopXy = 0, iRightTopXy = 0; int8_t iLeftRef; int8_t iTopRef; int8_t iRightTopRef; int8_t iLeftTopRef; int8_t iDiagonalRef; int8_t iMatchRef; int16_t iMvA[2], iMvB[2], iMvC[2], iMvD[2]; iCurXy = pCurDqLayer->iMbXyIndex; iCurX = pCurDqLayer->iMbX; iCurY = pCurDqLayer->iMbY; iCurSliceIdc = pCurDqLayer->pSliceIdc[iCurXy]; if (iCurX != 0) { iLeftXy = iCurXy - 1; iLeftSliceIdc = pCurDqLayer->pSliceIdc[iLeftXy]; bLeftAvail = (iLeftSliceIdc == iCurSliceIdc); } else { bLeftAvail = 0; } if (iCurY != 0) { iTopXy = iCurXy - pCurDqLayer->iMbWidth; iTopSliceIdc = pCurDqLayer->pSliceIdc[iTopXy]; bTopAvail = (iTopSliceIdc == iCurSliceIdc); if (iCurX != 0) { iLeftTopXy = iTopXy - 1; iLeftTopSliceIdc = pCurDqLayer->pSliceIdc[iLeftTopXy]; bLeftTopAvail = (iLeftTopSliceIdc == iCurSliceIdc); } else { bLeftTopAvail = 0; } if (iCurX != (pCurDqLayer->iMbWidth - 1)) { iRightTopXy = iTopXy + 1; iRightTopSliceIdc = pCurDqLayer->pSliceIdc[iRightTopXy]; bRightTopAvail = (iRightTopSliceIdc == iCurSliceIdc); } else { bRightTopAvail = 0; } } else { bTopAvail = 0; bLeftTopAvail = 0; bRightTopAvail = 0; } iLeftType = ((iCurX != 0 && bLeftAvail) ? GetMbType (pCurDqLayer)[iLeftXy] : 0); iTopType = ((iCurY != 0 && bTopAvail) ? GetMbType (pCurDqLayer)[iTopXy] : 0); iLeftTopType = ((iCurX != 0 && iCurY != 0 && bLeftTopAvail) ? GetMbType (pCurDqLayer)[iLeftTopXy] : 0); iRightTopType = ((iCurX != pCurDqLayer->iMbWidth - 1 && iCurY != 0 && bRightTopAvail) ? GetMbType (pCurDqLayer)[iRightTopXy] : 0); /*get neb mv&iRefIdxArray*/ /*left*/ if (bLeftAvail && IS_INTER (iLeftType)) { ST32 (iMvA, LD32 (pCurDqLayer->pDec ? pCurDqLayer->pDec->pMv[0][iLeftXy][3] : pCurDqLayer->pMv[0][iLeftXy][3])); iLeftRef = pCurDqLayer->pDec ? pCurDqLayer->pDec->pRefIndex[0][iLeftXy][3] : pCurDqLayer->pRefIndex[0][iLeftXy][3]; } else { ST32 (iMvA, 0); if (0 == bLeftAvail) { //not available iLeftRef = REF_NOT_AVAIL; } else { //available but is intra mb type iLeftRef = REF_NOT_IN_LIST; } } if (REF_NOT_AVAIL == iLeftRef || (0 == iLeftRef && 0 == * (int32_t*)iMvA)) { ST32 (iMvp, 0); return; } /*top*/ if (bTopAvail && IS_INTER (iTopType)) { ST32 (iMvB, LD32 (pCurDqLayer->pDec ? pCurDqLayer->pDec->pMv[0][iTopXy][12] : pCurDqLayer->pMv[0][iTopXy][12])); iTopRef = pCurDqLayer->pDec ? pCurDqLayer->pDec->pRefIndex[0][iTopXy][12] : pCurDqLayer->pRefIndex[0][iTopXy][12]; } else { ST32 (iMvB, 0); if (0 == bTopAvail) { //not available iTopRef = REF_NOT_AVAIL; } else { //available but is intra mb type iTopRef = REF_NOT_IN_LIST; } } if (REF_NOT_AVAIL == iTopRef || (0 == iTopRef && 0 == * (int32_t*)iMvB)) { ST32 (iMvp, 0); return; } /*right_top*/ if (bRightTopAvail && IS_INTER (iRightTopType)) { ST32 (iMvC, LD32 (pCurDqLayer->pDec ? pCurDqLayer->pDec->pMv[0][iRightTopXy][12] : pCurDqLayer->pMv[0][iRightTopXy][12])); iRightTopRef = pCurDqLayer->pDec ? pCurDqLayer->pDec->pRefIndex[0][iRightTopXy][12] : pCurDqLayer->pRefIndex[0][iRightTopXy][12]; } else { ST32 (iMvC, 0); if (0 == bRightTopAvail) { //not available iRightTopRef = REF_NOT_AVAIL; } else { //available but is intra mb type iRightTopRef = REF_NOT_IN_LIST; } } /*left_top*/ if (bLeftTopAvail && IS_INTER (iLeftTopType)) { ST32 (iMvD, LD32 (pCurDqLayer->pDec ? pCurDqLayer->pDec->pMv[0][iLeftTopXy][15] : pCurDqLayer->pMv[0][iLeftTopXy][15])); iLeftTopRef = pCurDqLayer->pDec ? pCurDqLayer->pDec->pRefIndex[0][iLeftTopXy][15] : pCurDqLayer->pRefIndex[0][iLeftTopXy][15]; } else { ST32 (iMvD, 0); if (0 == bLeftTopAvail) { //not available iLeftTopRef = REF_NOT_AVAIL; } else { //available but is intra mb type iLeftTopRef = REF_NOT_IN_LIST; } } iDiagonalRef = iRightTopRef; if (REF_NOT_AVAIL == iDiagonalRef) { iDiagonalRef = iLeftTopRef; * (int32_t*)iMvC = * (int32_t*)iMvD; } if (REF_NOT_AVAIL == iTopRef && REF_NOT_AVAIL == iDiagonalRef && iLeftRef >= REF_NOT_IN_LIST) { ST32 (iMvp, LD32 (iMvA)); return; } iMatchRef = (0 == iLeftRef) + (0 == iTopRef) + (0 == iDiagonalRef); if (1 == iMatchRef) { if (0 == iLeftRef) { ST32 (iMvp, LD32 (iMvA)); } else if (0 == iTopRef) { ST32 (iMvp, LD32 (iMvB)); } else { ST32 (iMvp, LD32 (iMvC)); } } else { iMvp[0] = WelsMedian (iMvA[0], iMvB[0], iMvC[0]); iMvp[1] = WelsMedian (iMvA[1], iMvB[1], iMvC[1]); } } int32_t GetColocatedMb (PWelsDecoderContext pCtx, MbType *mbType, SubMbType *subMbType) { PDqLayer pCurDqLayer = pCtx->pCurDqLayer; int32_t iMbXy = pCurDqLayer->iMbXyIndex; uint32_t is8x8 = IS_Inter_8x8 (GetMbType (pCurDqLayer)[iMbXy]); *mbType = GetMbType (pCurDqLayer)[iMbXy]; PPicture colocPic = pCtx->sRefPic.pRefList[LIST_1][0]; if (GetThreadCount (pCtx) > 1) { if (16 * pCurDqLayer->iMbY > pCtx->lastReadyHeightOffset[1][0]) { if (colocPic->pReadyEvent[pCurDqLayer->iMbY].isSignaled != 1) { WAIT_EVENT (&colocPic->pReadyEvent[pCurDqLayer->iMbY], WELS_DEC_THREAD_WAIT_INFINITE); } pCtx->lastReadyHeightOffset[1][0] = 16 * pCurDqLayer->iMbY; } } if (colocPic == NULL) { SLogContext* pLogCtx = & (pCtx->sLogCtx); WelsLog (pLogCtx, WELS_LOG_ERROR, "Colocated Ref Picture for B-Slice is lost, B-Slice decoding cannot be continued!"); return GENERATE_ERROR_NO (ERR_LEVEL_SLICE_DATA, ERR_INFO_REFERENCE_PIC_LOST); } MbType coloc_mbType = colocPic->pMbType[iMbXy]; if (coloc_mbType == MB_TYPE_SKIP) { //This indicates the colocated MB is P SKIP MB coloc_mbType |= MB_TYPE_16x16 | MB_TYPE_P0L0 | MB_TYPE_P1L0; } if (IS_Inter_8x8 (coloc_mbType) && !pCtx->pSps->bDirect8x8InferenceFlag) { *subMbType = SUB_MB_TYPE_4x4 | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_DIRECT; *mbType |= MB_TYPE_8x8 | MB_TYPE_L0 | MB_TYPE_L1; } else if (!is8x8 && (IS_INTER_16x16 (coloc_mbType) || IS_INTRA (coloc_mbType)/* || IS_SKIP(coloc_mbType)*/)) { *subMbType = SUB_MB_TYPE_8x8 | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_DIRECT; *mbType |= MB_TYPE_16x16 | MB_TYPE_L0 | MB_TYPE_L1; } else { *subMbType = SUB_MB_TYPE_8x8 | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_DIRECT; *mbType |= MB_TYPE_8x8 | MB_TYPE_L0 | MB_TYPE_L1; } if (IS_INTRA (coloc_mbType)) { SetRectBlock (pCurDqLayer->iColocIntra, 4, 4, 4 * sizeof (int8_t), 1, sizeof (int8_t)); return ERR_NONE; } SetRectBlock (pCurDqLayer->iColocIntra, 4, 4, 4 * sizeof (int8_t), 0, sizeof (int8_t)); if (IS_INTER_16x16 (*mbType)) { int16_t iMVZero[2] = { 0 }; int16_t* pMv = IS_TYPE_L1 (coloc_mbType) ? colocPic->pMv[LIST_1][iMbXy][0] : iMVZero; ST32 (pCurDqLayer->iColocMv[LIST_0][0], LD32 (colocPic->pMv[LIST_0][iMbXy][0])); ST32 (pCurDqLayer->iColocMv[LIST_1][0], LD32 (pMv)); pCurDqLayer->iColocRefIndex[LIST_0][0] = colocPic->pRefIndex[LIST_0][iMbXy][0]; pCurDqLayer->iColocRefIndex[LIST_1][0] = IS_TYPE_L1 (coloc_mbType) ? colocPic->pRefIndex[LIST_1][iMbXy][0] : REF_NOT_IN_LIST; } else { if (!pCtx->pSps->bDirect8x8InferenceFlag) { CopyRectBlock4Cols (pCurDqLayer->iColocMv[LIST_0], colocPic->pMv[LIST_0][iMbXy], 16, 16, 4, 4); CopyRectBlock4Cols (pCurDqLayer->iColocRefIndex[LIST_0], colocPic->pRefIndex[LIST_0][iMbXy], 4, 4, 4, 1); if (IS_TYPE_L1 (coloc_mbType)) { CopyRectBlock4Cols (pCurDqLayer->iColocMv[LIST_1], colocPic->pMv[LIST_1][iMbXy], 16, 16, 4, 4); CopyRectBlock4Cols (pCurDqLayer->iColocRefIndex[LIST_1], colocPic->pRefIndex[LIST_1][iMbXy], 4, 4, 4, 1); } else { // only forward prediction SetRectBlock (pCurDqLayer->iColocRefIndex[LIST_1], 4, 4, 4, (uint8_t)REF_NOT_IN_LIST, 1); } } else { for (int32_t listIdx = 0; listIdx < 1 + !! (coloc_mbType & MB_TYPE_L1); listIdx++) { SetRectBlock (pCurDqLayer->iColocMv[listIdx][0], 2, 2, 16, LD32 (colocPic->pMv[listIdx][iMbXy][0]), 4); SetRectBlock (pCurDqLayer->iColocMv[listIdx][2], 2, 2, 16, LD32 (colocPic->pMv[listIdx][iMbXy][3]), 4); SetRectBlock (pCurDqLayer->iColocMv[listIdx][8], 2, 2, 16, LD32 (colocPic->pMv[listIdx][iMbXy][12]), 4); SetRectBlock (pCurDqLayer->iColocMv[listIdx][10], 2, 2, 16, LD32 (colocPic->pMv[listIdx][iMbXy][15]), 4); SetRectBlock (&pCurDqLayer->iColocRefIndex[listIdx][0], 2, 2, 4, colocPic->pRefIndex[listIdx][iMbXy][0], 1); SetRectBlock (&pCurDqLayer->iColocRefIndex[listIdx][2], 2, 2, 4, colocPic->pRefIndex[listIdx][iMbXy][3], 1); SetRectBlock (&pCurDqLayer->iColocRefIndex[listIdx][8], 2, 2, 4, colocPic->pRefIndex[listIdx][iMbXy][12], 1); SetRectBlock (&pCurDqLayer->iColocRefIndex[listIdx][10], 2, 2, 4, colocPic->pRefIndex[listIdx][iMbXy][15], 1); } if (! (coloc_mbType & MB_TYPE_L1)) // only forward prediction SetRectBlock (&pCurDqLayer->iColocRefIndex[1][0], 4, 4, 4, (uint8_t)REF_NOT_IN_LIST, 1); } } return ERR_NONE; } int32_t PredMvBDirectSpatial (PWelsDecoderContext pCtx, int16_t iMvp[LIST_A][2], int8_t ref[LIST_A], SubMbType *subMbType) { int32_t ret; PDqLayer pCurDqLayer = pCtx->pCurDqLayer; int32_t iMbXy = pCurDqLayer->iMbXyIndex; bool bSkipOrDirect = (IS_SKIP (GetMbType (pCurDqLayer)[iMbXy]) | IS_DIRECT (GetMbType (pCurDqLayer)[iMbXy])) > 0; MbType mbType; ret = GetColocatedMb (pCtx, &mbType, subMbType); if (ret != ERR_NONE) { return ret; } bool bTopAvail, bLeftTopAvail, bRightTopAvail, bLeftAvail; int32_t iLeftTopType, iRightTopType, iTopType, iLeftType; int32_t iCurSliceIdc, iTopSliceIdc, iLeftTopSliceIdc, iRightTopSliceIdc, iLeftSliceIdc; int32_t iCurX, iCurY, iCurXy, iLeftXy = 0, iTopXy = 0, iLeftTopXy = 0, iRightTopXy = 0; int8_t iLeftRef[LIST_A]; int8_t iTopRef[LIST_A]; int8_t iRightTopRef[LIST_A]; int8_t iLeftTopRef[LIST_A]; int8_t iDiagonalRef[LIST_A]; int16_t iMvA[LIST_A][2], iMvB[LIST_A][2], iMvC[LIST_A][2], iMvD[LIST_A][2]; iCurXy = pCurDqLayer->iMbXyIndex; iCurX = pCurDqLayer->iMbX; iCurY = pCurDqLayer->iMbY; iCurSliceIdc = pCurDqLayer->pSliceIdc[iCurXy]; if (iCurX != 0) { iLeftXy = iCurXy - 1; iLeftSliceIdc = pCurDqLayer->pSliceIdc[iLeftXy]; bLeftAvail = (iLeftSliceIdc == iCurSliceIdc); } else { bLeftAvail = 0; } if (iCurY != 0) { iTopXy = iCurXy - pCurDqLayer->iMbWidth; iTopSliceIdc = pCurDqLayer->pSliceIdc[iTopXy]; bTopAvail = (iTopSliceIdc == iCurSliceIdc); if (iCurX != 0) { iLeftTopXy = iTopXy - 1; iLeftTopSliceIdc = pCurDqLayer->pSliceIdc[iLeftTopXy]; bLeftTopAvail = (iLeftTopSliceIdc == iCurSliceIdc); } else { bLeftTopAvail = 0; } if (iCurX != (pCurDqLayer->iMbWidth - 1)) { iRightTopXy = iTopXy + 1; iRightTopSliceIdc = pCurDqLayer->pSliceIdc[iRightTopXy]; bRightTopAvail = (iRightTopSliceIdc == iCurSliceIdc); } else { bRightTopAvail = 0; } } else { bTopAvail = 0; bLeftTopAvail = 0; bRightTopAvail = 0; } iLeftType = ((iCurX != 0 && bLeftAvail) ? GetMbType (pCurDqLayer)[iLeftXy] : 0); iTopType = ((iCurY != 0 && bTopAvail) ? GetMbType (pCurDqLayer)[iTopXy] : 0); iLeftTopType = ((iCurX != 0 && iCurY != 0 && bLeftTopAvail) ? GetMbType (pCurDqLayer)[iLeftTopXy] : 0); iRightTopType = ((iCurX != pCurDqLayer->iMbWidth - 1 && iCurY != 0 && bRightTopAvail) ? GetMbType (pCurDqLayer)[iRightTopXy] : 0); /*get neb mv&iRefIdxArray*/ for (int32_t listIdx = LIST_0; listIdx < LIST_A; ++listIdx) { /*left*/ if (bLeftAvail && IS_INTER (iLeftType)) { ST32 (iMvA[listIdx], LD32 (pCurDqLayer->pDec ? pCurDqLayer->pDec->pMv[listIdx][iLeftXy][3] : pCurDqLayer->pMv[listIdx][iLeftXy][3])); iLeftRef[listIdx] = pCurDqLayer->pDec ? pCurDqLayer->pDec->pRefIndex[listIdx][iLeftXy][3] : pCurDqLayer->pRefIndex[listIdx][iLeftXy][3]; } else { ST32 (iMvA[listIdx], 0); if (0 == bLeftAvail) { //not available iLeftRef[listIdx] = REF_NOT_AVAIL; } else { //available but is intra mb type iLeftRef[listIdx] = REF_NOT_IN_LIST; } } /*top*/ if (bTopAvail && IS_INTER (iTopType)) { ST32 (iMvB[listIdx], LD32 (pCurDqLayer->pDec ? pCurDqLayer->pDec->pMv[listIdx][iTopXy][12] : pCurDqLayer->pMv[listIdx][iTopXy][12])); iTopRef[listIdx] = pCurDqLayer->pDec ? pCurDqLayer->pDec->pRefIndex[listIdx][iTopXy][12] : pCurDqLayer->pRefIndex[listIdx][iTopXy][12]; } else { ST32 (iMvB[listIdx], 0); if (0 == bTopAvail) { //not available iTopRef[listIdx] = REF_NOT_AVAIL; } else { //available but is intra mb type iTopRef[listIdx] = REF_NOT_IN_LIST; } } /*right_top*/ if (bRightTopAvail && IS_INTER (iRightTopType)) { ST32 (iMvC[listIdx], LD32 (pCurDqLayer->pDec ? pCurDqLayer->pDec->pMv[listIdx][iRightTopXy][12] : pCurDqLayer->pMv[listIdx][iRightTopXy][12])); iRightTopRef[listIdx] = pCurDqLayer->pDec ? pCurDqLayer->pDec->pRefIndex[listIdx][iRightTopXy][12] : pCurDqLayer->pRefIndex[listIdx][iRightTopXy][12]; } else { ST32 (iMvC[listIdx], 0);