/***************************************************************************** * Copyright (C) 2013-2020 MulticoreWare, Inc * * Authors: Steve Borho * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA. * * This program is also available under a commercial proprietary license. * For more information, contact us at license @ x265.com. *****************************************************************************/ #include "common.h" #include "frame.h" #include "piclist.h" #include "picyuv.h" #include "slice.h" using namespace X265_NS; #if ENABLE_MULTIVIEW void Slice::createInterLayerReferencePictureSet(PicList& picList, PicList& refPicSetInterLayer0, PicList& refPicSetInterLayer1) { for (int i = 0; i < 1; i++) { int layerIdRef = 0;// getRefPicLayerId(i); Frame* refPic = picList.getPOC(m_poc, 0); int viewIdCur = 0; int viewIdZero = 1; int viewIdRef = 1; if ((viewIdCur <= viewIdZero && viewIdCur <= viewIdRef) || (viewIdCur >= viewIdZero && viewIdCur >= viewIdRef)) { refPicSetInterLayer0.pushBackSubDPB(*refPic); } else { refPicSetInterLayer1.pushBackSubDPB(*refPic); } } } #endif void Slice::setRefPicList(PicList& picList, PicList& refPicSetInterLayer0, PicList& refPicSetInterLayer1, int sLayerId) { bool checkNumPocTotalCurr = m_param->bEnableSCC ? false : true; if (m_sliceType == I_SLICE) { memset(m_refFrameList, 0, sizeof(m_refFrameList)); memset(m_refReconPicList, 0, sizeof(m_refReconPicList)); memset(m_refPOCList, 0, sizeof(m_refPOCList)); m_numRefIdx[1] = m_numRefIdx[0] = 0; #if ENABLE_SCC_EXT if (!checkNumPocTotalCurr) { if (m_rps.numberOfPictures == 0) { Frame* prevPic = picList.getPOC(X265_MAX(0, m_poc - 1)); if (prevPic->m_poc != X265_MAX(0, m_poc - 1)) { prevPic = picList.getPOC(m_poc); } m_lastEncPic = prevPic; } return; } #endif return; } #if ENABLE_SCC_EXT || ENABLE_MULTIVIEW || ENABLE_ALPHA /*Reset the number of references for I-slice marked as P-slice*/ if ((m_param->bEnableSCC || sLayerId) && m_sliceType != m_origSliceType) { memset(m_refFrameList, 0, sizeof(m_refFrameList)); memset(m_refReconPicList, 0, sizeof(m_refReconPicList)); memset(m_refPOCList, 0, sizeof(m_refPOCList)); m_numRefIdx[0] = 1; } #endif #if ENABLE_SCC_EXT if (!checkNumPocTotalCurr && m_rps.numberOfPictures == 0) { Frame* prevPic = picList.getPOC(X265_MAX(0, m_poc - 1)); if (prevPic->m_poc != X265_MAX(0, m_poc - 1)) { prevPic = picList.getPOC(m_poc); } m_lastEncPic = prevPic; } #endif Frame* refPic = NULL; Frame* refPicSetStCurr0[MAX_NUM_REF]; Frame* refPicSetStCurr1[MAX_NUM_REF]; Frame* refPicSetLtCurr[MAX_NUM_REF]; int numPocStCurr0 = 0; int numPocStCurr1 = 0; int numPocLtCurr = 0; int i; for (i = 0; i < m_rps.numberOfNegativePictures; i++) { if (m_rps.bUsed[i] && m_origSliceType != I_SLICE) { refPic = picList.getPOC(m_poc + m_rps.deltaPOC[i], m_rps.deltaPOC[i] ? sLayerId : 0); refPicSetStCurr0[numPocStCurr0] = refPic; numPocStCurr0++; } } for (; i < m_rps.numberOfNegativePictures + m_rps.numberOfPositivePictures; i++) { if (m_rps.bUsed[i] && m_origSliceType != I_SLICE) { refPic = picList.getPOC(m_poc + m_rps.deltaPOC[i], m_rps.deltaPOC[i] ? sLayerId : 0); refPicSetStCurr1[numPocStCurr1] = refPic; numPocStCurr1++; } } X265_CHECK(m_rps.numberOfPictures == m_rps.numberOfNegativePictures + m_rps.numberOfPositivePictures, "unexpected picture in RPS\n"); // ref_pic_list_init Frame* rpsCurrList0[MAX_NUM_REF + 1]; Frame* rpsCurrList1[MAX_NUM_REF + 1]; #if ENABLE_MULTIVIEW int numPocTotalCurr = numPocStCurr0 + numPocStCurr1 + numPocLtCurr + refPicSetInterLayer0.size() + refPicSetInterLayer1.size(); #else int numPocTotalCurr = numPocStCurr0 + numPocStCurr1 + numPocLtCurr; #endif #if ENABLE_SCC_EXT if (m_param->bEnableSCC) numPocTotalCurr++; #endif int cIdx = 0; for (i = 0; i < numPocStCurr0; i++, cIdx++) rpsCurrList0[cIdx] = refPicSetStCurr0[i]; #if ENABLE_MULTIVIEW if (m_param->numViews > 1) for (i = 0; i < refPicSetInterLayer0.size(); i++, cIdx++) rpsCurrList0[cIdx] = refPicSetInterLayer0.getPOC(m_poc, 0); #endif for (i = 0; i < numPocStCurr1; i++, cIdx++) rpsCurrList0[cIdx] = refPicSetStCurr1[i]; for (i = 0; i < numPocLtCurr; i++, cIdx++) rpsCurrList0[cIdx] = refPicSetLtCurr[i]; #if ENABLE_MULTIVIEW if (m_param->numViews > 1) for (i = 0; i < refPicSetInterLayer1.size(); i++, cIdx++) rpsCurrList0[cIdx] = refPicSetInterLayer1.getPOC(m_poc, 0); #endif #if ENABLE_SCC_EXT if (m_param->bEnableSCC) rpsCurrList0[cIdx++] = picList.getPOC(m_poc); #endif X265_CHECK(cIdx == numPocTotalCurr, "RPS index check fail\n"); if (m_sliceType == B_SLICE) { cIdx = 0; for (i = 0; i < numPocStCurr1; i++, cIdx++) rpsCurrList1[cIdx] = refPicSetStCurr1[i]; #if ENABLE_MULTIVIEW if (m_param->numViews > 1) for (i = 0; i < refPicSetInterLayer1.size(); i++, cIdx++) rpsCurrList1[cIdx] = refPicSetInterLayer1.getPOC(m_poc, 0); #endif for (i = 0; i < numPocStCurr0; i++, cIdx++) rpsCurrList1[cIdx] = refPicSetStCurr0[i]; for (i = 0; i < numPocLtCurr; i++, cIdx++) rpsCurrList1[cIdx] = refPicSetLtCurr[i]; #if ENABLE_MULTIVIEW if (m_param->numViews > 1) for (i = 0; i < refPicSetInterLayer0.size(); i++, cIdx++) rpsCurrList1[cIdx] = refPicSetInterLayer0.getPOC(m_poc, 0); #endif #if ENABLE_SCC_EXT if (m_param->bEnableSCC) rpsCurrList1[cIdx++] = picList.getPOC(m_poc); #endif X265_CHECK(cIdx == numPocTotalCurr, "RPS index check fail\n"); } for (int rIdx = 0; rIdx < m_numRefIdx[0]; rIdx++) { cIdx = rIdx % numPocTotalCurr; X265_CHECK(cIdx >= 0 && cIdx < numPocTotalCurr, "RPS index check fail\n"); m_refFrameList[0][rIdx] = rpsCurrList0[cIdx]; #if ENABLE_MULTIVIEW m_refFrameList[0][rIdx] = rpsCurrList0[cIdx]; #endif } #if ENABLE_SCC_EXT if (m_param->bEnableSCC && numPocTotalCurr > m_numRefIdx[0]) { m_refFrameList[0][m_numRefIdx[0] - 1] = picList.getPOC(m_poc); } #endif if (m_sliceType != B_SLICE) { m_numRefIdx[1] = 0; memset(m_refFrameList[1], 0, sizeof(m_refFrameList[1])); } else { for (int rIdx = 0; rIdx < m_numRefIdx[1]; rIdx++) { cIdx = rIdx % numPocTotalCurr; X265_CHECK(cIdx >= 0 && cIdx < numPocTotalCurr, "RPS index check fail\n"); m_refFrameList[1][rIdx] = rpsCurrList1[cIdx]; #if ENABLE_MULTIVIEW m_refFrameList[1][rIdx] = rpsCurrList1[cIdx]; #endif } } for (int dir = 0; dir < 2; dir++) for (int numRefIdx = 0; numRefIdx < m_numRefIdx[dir]; numRefIdx++) m_refPOCList[dir][numRefIdx] = m_refFrameList[dir][numRefIdx]->m_poc; } void Slice::disableWeights() { for (int l = 0; l < 2; l++) for (int i = 0; i < MAX_NUM_REF; i++) for (int yuv = 0; yuv < 3; yuv++) { WeightParam& wp = m_weightPredTable[l][i][yuv]; wp.wtPresent = 0; wp.log2WeightDenom = 0; wp.inputWeight = 1; wp.inputOffset = 0; } } #if ENABLE_SCC_EXT bool Slice::isOnlyCurrentPictureAsReference() const { if (m_sliceType == I_SLICE) { return true; } for (int i = 0; i < m_numRefIdx[0]; i++) { if (m_refFrameList[0][i]->m_poc != m_poc) { return false; } } for (int i = 0; i < m_numRefIdx[1]; i++) { if (m_refFrameList[1][i]->m_poc != m_poc) { return false; } } return true; } #endif /* Sorts the deltaPOC and Used by current values in the RPS based on the * deltaPOC values. deltaPOC values are sorted with -ve values before the +ve * values. -ve values are in decreasing order. +ve values are in increasing * order */ void RPS::sortDeltaPOC() { // sort in increasing order (smallest first) for (int j = 1; j < numberOfPictures; j++) { int dPOC = deltaPOC[j]; bool used = bUsed[j]; for (int k = j - 1; k >= 0; k--) { int temp = deltaPOC[k]; if (dPOC < temp) { deltaPOC[k + 1] = temp; bUsed[k + 1] = bUsed[k]; deltaPOC[k] = dPOC; bUsed[k] = used; } } } // flip the negative values to largest first int numNegPics = numberOfNegativePictures; for (int j = 0, k = numNegPics - 1; j < numNegPics >> 1; j++, k--) { int dPOC = deltaPOC[j]; bool used = bUsed[j]; deltaPOC[j] = deltaPOC[k]; bUsed[j] = bUsed[k]; deltaPOC[k] = dPOC; bUsed[k] = used; } } uint32_t Slice::realEndAddress(uint32_t endCUAddr) const { // Calculate end address uint32_t internalAddress = (endCUAddr - 1) % m_param->num4x4Partitions; uint32_t externalAddress = (endCUAddr - 1) / m_param->num4x4Partitions; uint32_t xmax = m_sps->picWidthInLumaSamples - (externalAddress % m_sps->numCuInWidth) * m_param->maxCUSize; uint32_t ymax = m_sps->picHeightInLumaSamples - (externalAddress / m_sps->numCuInWidth) * m_param->maxCUSize; while (g_zscanToPelX[internalAddress] >= xmax || g_zscanToPelY[internalAddress] >= ymax) internalAddress--; internalAddress++; if (internalAddress == m_param->num4x4Partitions) { internalAddress = 0; externalAddress++; } return externalAddress * m_param->num4x4Partitions + internalAddress; }