[x265] [PATCH MV-HEVC 06/10] Fix hash mismatch and temporal mvp issue
Anusuya Kumarasamy
anusuya.kumarasamy at multicorewareinc.com
Tue Aug 6 10:49:27 UTC 2024
>From 9d58aa88fc522dede32a12cc5a66342a0c3ee298 Mon Sep 17 00:00:00 2001
From: AnusuyaKumarasamy <anusuya.kumarasamy at multicorewareinc.com>
Date: Fri, 12 Jul 2024 16:28:14 +0530
Subject: [PATCH] Fix hash mismatch and temporal mvp issue
---
source/common/cudata.cpp | 165 +++++++++++++++++++++++++++++-------
source/common/cudata.h | 4 +-
source/encoder/analysis.cpp | 2 +-
source/encoder/dpb.cpp | 24 +++++-
source/encoder/search.cpp | 6 +-
5 files changed, 165 insertions(+), 36 deletions(-)
diff --git a/source/common/cudata.cpp b/source/common/cudata.cpp
index 19281dee2..baa9be476 100644
--- a/source/common/cudata.cpp
+++ b/source/common/cudata.cpp
@@ -1712,28 +1712,61 @@ uint32_t CUData::getInterMergeCandidates(uint32_t
absPartIdx, uint32_t puIdx, MV
}
// Create the PMV list. Called for each reference index.
-int CUData::getPMV(InterNeighbourMV *neighbours, uint32_t picList,
uint32_t refIdx, MV* amvpCand, MV* pmv) const
+int CUData::getPMV(InterNeighbourMV* neighbours, uint32_t picList,
uint32_t refIdx, MV* amvpCand, MV* pmv, uint32_t puIdx, uint32_t
absPartIdx) const
{
MV directMV[MD_ABOVE_LEFT + 1];
MV indirectMV[MD_ABOVE_LEFT + 1];
bool validDirect[MD_ABOVE_LEFT + 1];
bool validIndirect[MD_ABOVE_LEFT + 1];
- // Left candidate.
- validDirect[MD_BELOW_LEFT] = getDirectPMV(directMV[MD_BELOW_LEFT],
neighbours + MD_BELOW_LEFT, picList, refIdx);
- validDirect[MD_LEFT] = getDirectPMV(directMV[MD_LEFT],
neighbours + MD_LEFT, picList, refIdx);
- // Top candidate.
- validDirect[MD_ABOVE_RIGHT] = getDirectPMV(directMV[MD_ABOVE_RIGHT],
neighbours + MD_ABOVE_RIGHT, picList, refIdx);
- validDirect[MD_ABOVE] = getDirectPMV(directMV[MD_ABOVE],
neighbours + MD_ABOVE, picList, refIdx);
- validDirect[MD_ABOVE_LEFT] = getDirectPMV(directMV[MD_ABOVE_LEFT],
neighbours + MD_ABOVE_LEFT, picList, refIdx);
-
- // Left candidate.
- validIndirect[MD_BELOW_LEFT] =
getIndirectPMV(indirectMV[MD_BELOW_LEFT], neighbours + MD_BELOW_LEFT,
picList, refIdx);
- validIndirect[MD_LEFT] = getIndirectPMV(indirectMV[MD_LEFT],
neighbours + MD_LEFT, picList, refIdx);
- // Top candidate.
- validIndirect[MD_ABOVE_RIGHT] =
getIndirectPMV(indirectMV[MD_ABOVE_RIGHT], neighbours + MD_ABOVE_RIGHT,
picList, refIdx);
- validIndirect[MD_ABOVE] = getIndirectPMV(indirectMV[MD_ABOVE],
neighbours + MD_ABOVE, picList, refIdx);
- validIndirect[MD_ABOVE_LEFT] =
getIndirectPMV(indirectMV[MD_ABOVE_LEFT], neighbours + MD_ABOVE_LEFT,
picList, refIdx);
+#if ENABLE_MULTIVIEW
+ if (m_slice->m_param->numViews > 1)
+ {
+ // Left candidate.
+ if ((neighbours + MD_BELOW_LEFT)->isAvailable || (neighbours +
MD_LEFT)->isAvailable)
+ {
+ validIndirect[MD_ABOVE_RIGHT] = validIndirect[MD_ABOVE] =
validIndirect[MD_ABOVE_LEFT] = false;
+
+ validDirect[MD_BELOW_LEFT] =
getDirectPMV(directMV[MD_BELOW_LEFT], neighbours + MD_BELOW_LEFT, picList,
refIdx);
+ validDirect[MD_LEFT] = getDirectPMV(directMV[MD_LEFT],
neighbours + MD_LEFT, picList, refIdx);
+
+ validIndirect[MD_BELOW_LEFT] =
getIndirectPMV(indirectMV[MD_BELOW_LEFT], neighbours + MD_BELOW_LEFT,
picList, refIdx);
+ validIndirect[MD_LEFT] = getIndirectPMV(indirectMV[MD_LEFT],
neighbours + MD_LEFT, picList, refIdx);
+ }
+
+ // Top candidate.
+ validDirect[MD_ABOVE_RIGHT] =
getDirectPMV(directMV[MD_ABOVE_RIGHT], neighbours + MD_ABOVE_RIGHT,
picList, refIdx);
+ validDirect[MD_ABOVE] = getDirectPMV(directMV[MD_ABOVE],
neighbours + MD_ABOVE, picList, refIdx);
+ validDirect[MD_ABOVE_LEFT] = getDirectPMV(directMV[MD_ABOVE_LEFT],
neighbours + MD_ABOVE_LEFT, picList, refIdx);
+
+ // Top candidate.
+ if (!((neighbours + MD_BELOW_LEFT)->isAvailable || (neighbours +
MD_LEFT)->isAvailable))
+ {
+ validDirect[MD_BELOW_LEFT] = validDirect[MD_LEFT] =
validIndirect[MD_BELOW_LEFT] = validIndirect[MD_LEFT] = false;
+ validIndirect[MD_ABOVE_RIGHT] =
getIndirectPMV(indirectMV[MD_ABOVE_RIGHT], neighbours + MD_ABOVE_RIGHT,
picList, refIdx);
+ validIndirect[MD_ABOVE] = getIndirectPMV(indirectMV[MD_ABOVE],
neighbours + MD_ABOVE, picList, refIdx);
+ validIndirect[MD_ABOVE_LEFT] =
getIndirectPMV(indirectMV[MD_ABOVE_LEFT], neighbours + MD_ABOVE_LEFT,
picList, refIdx);
+ }
+ }
+ else
+#endif
+ {
+ // Left candidate.
+ validDirect[MD_BELOW_LEFT] = getDirectPMV(directMV[MD_BELOW_LEFT],
neighbours + MD_BELOW_LEFT, picList, refIdx);
+ validDirect[MD_LEFT] = getDirectPMV(directMV[MD_LEFT], neighbours
+ MD_LEFT, picList, refIdx);
+ // Top candidate.
+ validDirect[MD_ABOVE_RIGHT] =
getDirectPMV(directMV[MD_ABOVE_RIGHT], neighbours + MD_ABOVE_RIGHT,
picList, refIdx);
+ validDirect[MD_ABOVE] = getDirectPMV(directMV[MD_ABOVE],
neighbours + MD_ABOVE, picList, refIdx);
+ validDirect[MD_ABOVE_LEFT] = getDirectPMV(directMV[MD_ABOVE_LEFT],
neighbours + MD_ABOVE_LEFT, picList, refIdx);
+
+ // Left candidate.
+ validIndirect[MD_BELOW_LEFT] =
getIndirectPMV(indirectMV[MD_BELOW_LEFT], neighbours + MD_BELOW_LEFT,
picList, refIdx);
+ validIndirect[MD_LEFT] = getIndirectPMV(indirectMV[MD_LEFT],
neighbours + MD_LEFT, picList, refIdx);
+ // Top candidate.
+ validIndirect[MD_ABOVE_RIGHT] =
getIndirectPMV(indirectMV[MD_ABOVE_RIGHT], neighbours + MD_ABOVE_RIGHT,
picList, refIdx);
+ validIndirect[MD_ABOVE] = getIndirectPMV(indirectMV[MD_ABOVE],
neighbours + MD_ABOVE, picList, refIdx);
+ validIndirect[MD_ABOVE_LEFT] =
getIndirectPMV(indirectMV[MD_ABOVE_LEFT], neighbours + MD_ABOVE_LEFT,
picList, refIdx);
+ }
int num = 0;
// Left predictor search
@@ -1781,22 +1814,75 @@ int CUData::getPMV(InterNeighbourMV *neighbours,
uint32_t picList, uint32_t refI
// Get the collocated candidate. At this step, either the first
candidate
// was found or its value is 0.
- if (m_slice->m_sps->bTemporalMVPEnabled && num < 2)
+#if ENABLE_MULTIVIEW
+ if (m_slice->m_param->numViews > 1)
+ {
+ if (m_slice->m_sps->bTemporalMVPEnabled && num < 2)
+ {
+ int refId = refIdx;
+ uint32_t absPartAddr = m_absIdxInCTU + absPartIdx;
+ uint32_t partIdxRB = deriveRightBottomIdx(puIdx);
+ bool isValid;
+
+ // co-located RightBottom temporal predictor (H)
+ int ctuIdx = -1;
+
+ // image boundary check
+ if (m_encData->getPicCTU(m_cuAddr)->m_cuPelX +
g_zscanToPelX[partIdxRB] + UNIT_SIZE <
m_slice->m_sps->picWidthInLumaSamples &&
+ m_encData->getPicCTU(m_cuAddr)->m_cuPelY +
g_zscanToPelY[partIdxRB] + UNIT_SIZE <
m_slice->m_sps->picHeightInLumaSamples)
+ {
+ uint32_t absPartIdxRB = g_zscanToRaster[partIdxRB];
+ uint32_t numUnits = s_numPartInCUSize;
+ bool bNotLastCol = lessThanCol(absPartIdxRB, numUnits -
1); // is not at the last column of CTU
+ bool bNotLastRow = lessThanRow(absPartIdxRB, numUnits -
1); // is not at the last row of CTU
+
+ if (bNotLastCol && bNotLastRow)
+ {
+ absPartAddr = g_rasterToZscan[absPartIdxRB +
RASTER_SIZE + 1];
+ ctuIdx = m_cuAddr;
+ }
+ else if (bNotLastCol)
+ absPartAddr = g_rasterToZscan[(absPartIdxRB + 1) &
(numUnits - 1)];
+ else if (bNotLastRow)
+ {
+ absPartAddr = g_rasterToZscan[absPartIdxRB +
RASTER_SIZE - numUnits + 1];
+ ctuIdx = m_cuAddr + 1;
+ }
+ else // is the right bottom corner of CTU
+ absPartAddr = 0;
+ }
+ if (ctuIdx >= 0 &&
getColMVP(neighbours[MD_COLLOCATED].mv[picList], refId, picList, ctuIdx,
absPartAddr))
+ pmv[numMvc++] = amvpCand[num++] =
neighbours[MD_COLLOCATED].mv[picList];
+ else
+ {
+ uint32_t partIdxCenter = deriveCenterIdx(puIdx);
+ uint32_t curCTUIdx = m_cuAddr;
+ if (getColMVP(neighbours[MD_COLLOCATED].mv[picList],
refId, picList, curCTUIdx, partIdxCenter))
+ pmv[numMvc++] = amvpCand[num++] =
neighbours[MD_COLLOCATED].mv[picList];
+ }
+ }
+ }
+ else
+#endif
{
- int tempRefIdx = neighbours[MD_COLLOCATED].refIdx[picList];
- if (tempRefIdx != -1)
+ if (m_slice->m_sps->bTemporalMVPEnabled && num < 2)
{
- uint32_t cuAddr = neighbours[MD_COLLOCATED].cuAddr[picList];
- const Frame* colPic =
m_slice->m_refFrameList[m_slice->isInterB() &&
!m_slice->m_colFromL0Flag][m_slice->m_colRefIdx];
- const CUData* colCU = colPic->m_encData->getPicCTU(cuAddr);
+ int tempRefIdx = neighbours[MD_COLLOCATED].refIdx[picList];
+ if (tempRefIdx != -1)
+ {
+ uint32_t cuAddr =
neighbours[MD_COLLOCATED].cuAddr[picList];
+ const Frame* colPic =
m_slice->m_refFrameList[m_slice->isInterB() &&
!m_slice->m_colFromL0Flag][m_slice->m_colRefIdx];
+ const CUData* colCU = colPic->m_encData->getPicCTU(cuAddr);
- // Scale the vector
- int colRefPOC = colCU->m_slice->m_refPOCList[tempRefIdx >>
4][tempRefIdx & 0xf];
- int colPOC = colCU->m_slice->m_poc;
+ // Scale the vector
+ int colRefPOC = colCU->m_slice->m_refPOCList[tempRefIdx >>
4][tempRefIdx & 0xf];
+ int colPOC = colCU->m_slice->m_poc;
- int curRefPOC = m_slice->m_refPOCList[picList][refIdx];
- int curPOC = m_slice->m_poc;
- pmv[numMvc++] = amvpCand[num++] =
scaleMvByPOCDist(neighbours[MD_COLLOCATED].mv[picList], curPOC, curRefPOC,
colPOC, colRefPOC);
+ int curRefPOC = m_slice->m_refPOCList[picList][refIdx];
+ int curPOC = m_slice->m_poc;
+
+ pmv[numMvc++] = amvpCand[num++] =
scaleMvByPOCDist(neighbours[MD_COLLOCATED].mv[picList], curPOC, curRefPOC,
colPOC, colRefPOC);
+ }
}
}
@@ -1822,7 +1908,7 @@ void CUData::getNeighbourMV(uint32_t puIdx, uint32_t
absPartIdx, InterNeighbourM
getInterNeighbourMV(neighbours + MD_ABOVE, partIdxRT, MD_ABOVE);
getInterNeighbourMV(neighbours + MD_ABOVE_LEFT, partIdxLT,
MD_ABOVE_LEFT);
- if (m_slice->m_sps->bTemporalMVPEnabled)
+ if (m_slice->m_sps->bTemporalMVPEnabled &&
!(m_slice->m_param->numViews > 1))
{
uint32_t absPartAddr = m_absIdxInCTU + absPartIdx;
uint32_t partIdxRB = deriveRightBottomIdx(puIdx);
@@ -1895,6 +1981,7 @@ void CUData::getInterNeighbourMV(InterNeighbourMV
*neighbour, uint32_t partUnitI
// Mark the PMV as unavailable.
for (int i = 0; i < 2; i++)
neighbour->refIdx[i] = -1;
+ neighbour->isAvailable = (tmpCU != NULL) && (tmpCU->isInter(idx));
return;
}
@@ -1905,6 +1992,7 @@ void CUData::getInterNeighbourMV(InterNeighbourMV
*neighbour, uint32_t partUnitI
// Get the reference idx.
neighbour->refIdx[i] = tmpCU->m_refIdx[i][idx];
+ neighbour->isAvailable = (tmpCU != NULL) && (tmpCU->isInter(idx));
}
}
@@ -1958,8 +2046,18 @@ bool CUData::getIndirectPMV(MV& outMV,
InterNeighbourMV *neighbours, uint32_t pi
int neibRefPOC = m_slice->m_refPOCList[picList][partRefIdx];
MV mvp = neighbours->mv[picList];
+#if ENABLE_MULTIVIEW
+ if ((curRefPOC == curPOC) == (neibRefPOC == curPOC))
+ {
+ if (curRefPOC == curPOC)
+ outMV = mvp;
+ if (!(curRefPOC == curPOC))
+ outMV = scaleMvByPOCDist(mvp, curPOC, curRefPOC,
neibPOC, neibRefPOC);
+#else
outMV = scaleMvByPOCDist(mvp, curPOC, curRefPOC, neibPOC,
neibRefPOC);
+#endif
return true;
+ }
}
}
return false;
@@ -1995,7 +2093,16 @@ bool CUData::getColMVP(MV& outMV, int& outRefIdx,
int picList, int cuAddr, int p
int curRefPOC = m_slice->m_refPOCList[picList][outRefIdx];
int curPOC = m_slice->m_poc;
+#if ENABLE_MULTIVIEW
+ if ((colPOC == colRefPOC) != (curPOC == curRefPOC))
+ return false;
+ else if (curRefPOC == curPOC)
+ outMV = colmv;
+ else if (!(curRefPOC == curPOC))
+ outMV = scaleMvByPOCDist(colmv, curPOC, curRefPOC, colPOC,
colRefPOC);
+#else
outMV = scaleMvByPOCDist(colmv, curPOC, curRefPOC, colPOC, colRefPOC);
+#endif;
return true;
}
diff --git a/source/common/cudata.h b/source/common/cudata.h
index 8397f0568..404e95714 100644
--- a/source/common/cudata.h
+++ b/source/common/cudata.h
@@ -107,6 +107,8 @@ struct InterNeighbourMV
// Collocated right bottom CU addr.
uint32_t cuAddr[2];
+ bool isAvailable;
+
// For spatial prediction, this field contains the reference index
// in each list (-1 if not available).
//
@@ -272,7 +274,7 @@ public:
int8_t getRefQP(uint32_t currAbsIdxInCTU) const;
uint32_t getInterMergeCandidates(uint32_t absPartIdx, uint32_t puIdx,
MVField (*candMvField)[2], uint8_t* candDir) const;
void clipMv(MV& outMV) const;
- int getPMV(InterNeighbourMV *neighbours, uint32_t reference_list,
uint32_t refIdx, MV* amvpCand, MV* pmv) const;
+ int getPMV(InterNeighbourMV* neighbours, uint32_t reference_list,
uint32_t refIdx, MV* amvpCand, MV* pmv, uint32_t puIdx = 0, uint32_t
absPartIdx = 0) const;
void getNeighbourMV(uint32_t puIdx, uint32_t absPartIdx,
InterNeighbourMV* neighbours) const;
void getIntraTUQtDepthRange(uint32_t tuDepthRange[2], uint32_t
absPartIdx) const;
void getInterTUQtDepthRange(uint32_t tuDepthRange[2], uint32_t
absPartIdx) const;
diff --git a/source/encoder/analysis.cpp b/source/encoder/analysis.cpp
index aabf386ca..1f1984707 100644
--- a/source/encoder/analysis.cpp
+++ b/source/encoder/analysis.cpp
@@ -2501,7 +2501,7 @@ void Analysis::recodeCU(const CUData& parentCTU,
const CUGeom& cuGeom, int32_t q
continue;
MV mvp;
- int numMvc =
mode.cu.getPMV(mode.interNeighbours, list, ref, mode.amvpCand[list][ref],
mvc);
+ int numMvc =
mode.cu.getPMV(mode.interNeighbours, list, ref, mode.amvpCand[list][ref],
mvc, part, pu.puAbsPartIdx);
mvp =
mode.amvpCand[list][ref][mode.cu.m_mvpIdx[list][pu.puAbsPartIdx]];
if (m_param->interRefine == 1)
{
diff --git a/source/encoder/dpb.cpp b/source/encoder/dpb.cpp
index 3b4934df5..a187e6657 100644
--- a/source/encoder/dpb.cpp
+++ b/source/encoder/dpb.cpp
@@ -287,9 +287,29 @@ void DPB::prepareEncode(Frame *newFrame)
/* TODO: the lookahead should be able to tell which reference
picture
* had the least motion residual. We should be able to use that
here to
* select a colocation reference list and index */
- slice->m_colFromL0Flag = false;
+
+ bool bLowDelay = true;
+ int iCurrPOC = slice->m_poc;
+ int iRefIdx = 0;
+
+ for (iRefIdx = 0; iRefIdx < slice->m_numRefIdx[0] && bLowDelay;
iRefIdx++)
+ {
+ if (slice->m_refPOCList[0][iRefIdx] > iCurrPOC)
+ {
+ bLowDelay = false;
+ }
+ }
+ for (iRefIdx = 0; iRefIdx < slice->m_numRefIdx[1] && bLowDelay;
iRefIdx++)
+ {
+ if (slice->m_refPOCList[1][iRefIdx] > iCurrPOC)
+ {
+ bLowDelay = false;
+ }
+ }
+
+ slice->m_bCheckLDC = bLowDelay;
+ slice->m_colFromL0Flag = bLowDelay;
slice->m_colRefIdx = 0;
- slice->m_bCheckLDC = false;
}
else
{
diff --git a/source/encoder/search.cpp b/source/encoder/search.cpp
index 3218f4a24..9dc5f90c5 100644
--- a/source/encoder/search.cpp
+++ b/source/encoder/search.cpp
@@ -2092,7 +2092,7 @@ void Search::singleMotionEstimation(Search& master,
Mode& interMode, const Predi
// 12 mv candidates including lowresMV
MV mvc[(MD_ABOVE_LEFT + 1) * 2 + 2];
- int numMvc = interMode.cu.getPMV(interMode.interNeighbours, list, ref,
interMode.amvpCand[list][ref], mvc);
+ int numMvc = interMode.cu.getPMV(interMode.interNeighbours, list, ref,
interMode.amvpCand[list][ref], mvc, 0, pu.puAbsPartIdx);
const MV* amvp = interMode.amvpCand[list][ref];
int mvpIdx = selectMVP(interMode.cu, pu, amvp, list, ref);
@@ -2246,7 +2246,7 @@ void Search::predInterSearch(Mode& interMode, const
CUGeom& cuGeom, bool bChroma
uint32_t bits = m_listSelBits[list] + MVP_IDX_BITS;
bits += getTUBits(ref, numRefIdx[list]);
- int numMvc = cu.getPMV(interMode.interNeighbours, list,
ref, interMode.amvpCand[list][ref], mvc);
+ int numMvc = cu.getPMV(interMode.interNeighbours, list,
ref, interMode.amvpCand[list][ref], mvc, puIdx, pu.puAbsPartIdx);
const MV* amvp = interMode.amvpCand[list][ref];
int mvpIdx = selectMVP(cu, pu, amvp, list, ref);
MV mvmin, mvmax, outmv, mvp;
@@ -2404,7 +2404,7 @@ void Search::predInterSearch(Mode& interMode, const
CUGeom& cuGeom, bool bChroma
uint32_t bits = m_listSelBits[list] + MVP_IDX_BITS;
bits += getTUBits(ref, numRefIdx[list]);
- int numMvc = cu.getPMV(interMode.interNeighbours,
list, ref, interMode.amvpCand[list][ref], mvc);
+ int numMvc = cu.getPMV(interMode.interNeighbours,
list, ref, interMode.amvpCand[list][ref], mvc, puIdx, pu.puAbsPartIdx);
const MV* amvp = interMode.amvpCand[list][ref];
int mvpIdx = selectMVP(cu, pu, amvp, list, ref);
--
2.36.0.windows.1
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20240806/cfa7db82/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0006-Fix-hash-mismatch-and-temporal-mvp-issue.patch
Type: application/x-patch
Size: 18046 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20240806/cfa7db82/attachment-0001.bin>
More information about the x265-devel
mailing list