[x265] [PATCH 04/10] shifted mcstf from encoder to lookahead

Anusuya Kumarasamy anusuya.kumarasamy at multicorewareinc.com
Mon Nov 11 14:14:21 UTC 2024


>From 679defdc97e93ed7597623045e8306fcdc29d916 Mon Sep 17 00:00:00 2001
From: AnusuyaKumarasamy <anusuya.kumarasamy at multicorewareinc.com>
Date: Thu, 24 Oct 2024 15:41:44 +0530
Subject: [PATCH 04/10] shifted mcstf from encoder to lookahead

---
 source/common/frame.cpp         |   3 +
 source/common/frame.h           |   1 +
 source/common/picyuv.cpp        |   4 +
 source/common/temporalfilter.h  |   2 +
 source/encoder/encoder.cpp      |  55 ++++++++------
 source/encoder/frameencoder.cpp |   2 +-
 source/encoder/slicetype.cpp    | 125 ++++++++++++++++++++++++++++++++
 source/encoder/slicetype.h      |   7 ++
 8 files changed, 175 insertions(+), 24 deletions(-)

diff --git a/source/common/frame.cpp b/source/common/frame.cpp
index 4c800e94e..80f341edf 100644
--- a/source/common/frame.cpp
+++ b/source/common/frame.cpp
@@ -94,6 +94,9 @@ bool Frame::create(x265_param *param, float* quantOffsets)
         m_mcstf->m_range = param->mcstfFrameRange;
         m_mcstf->init(param);

+        for (int i = 0; i < (m_mcstf->m_range << 1); i++)
+            m_mcstf->createRefPicInfo(&m_mcstfRefList[i], m_param);
+
         m_fencPicSubsampled2 = new PicYuv;
         m_fencPicSubsampled4 = new PicYuv;

diff --git a/source/common/frame.h b/source/common/frame.h
index 8d330026e..e85727deb 100644
--- a/source/common/frame.h
+++ b/source/common/frame.h
@@ -147,6 +147,7 @@ public:
     Frame*                 m_nextMCSTF;           // PicList doubly linked
list pointers
     Frame*                 m_prevMCSTF;
     int*                   m_isSubSampled;
+    TemporalFilterRefPicInfo
m_mcstfRefList[MAX_MCSTF_TEMPORAL_WINDOW_LENGTH];

     /*Vbv-End-Flag*/
     int vbvEndFlag;
diff --git a/source/common/picyuv.cpp b/source/common/picyuv.cpp
index a0190acc3..df8d666ea 100644
--- a/source/common/picyuv.cpp
+++ b/source/common/picyuv.cpp
@@ -154,6 +154,10 @@ bool PicYuv::createScaledPicYUV(x265_param* param,
uint8_t scaleFactor)
     m_param = param;
     m_picWidth = m_param->sourceWidth / scaleFactor;
     m_picHeight = m_param->sourceHeight / scaleFactor;
+    int maxBlocksInRow = (m_picWidth + X265_LOWRES_CU_SIZE - 1) >>
X265_LOWRES_CU_BITS;
+    int maxBlocksInCol = (m_picHeight + X265_LOWRES_CU_SIZE - 1) >>
X265_LOWRES_CU_BITS;
+    m_picWidth = maxBlocksInRow * X265_LOWRES_CU_SIZE;
+    m_picHeight = maxBlocksInCol * X265_LOWRES_CU_SIZE;

     m_picCsp = m_param->internalCsp;
     m_hChromaShift = CHROMA_H_SHIFT(m_picCsp);
diff --git a/source/common/temporalfilter.h b/source/common/temporalfilter.h
index 9fe51da8c..1cd8028c7 100644
--- a/source/common/temporalfilter.h
+++ b/source/common/temporalfilter.h
@@ -105,6 +105,8 @@ namespace X265_NS {
         int*       error;
         int*       noise;
         int        poc;
+        pixel*     lowres;
+        pixel*     lowerRes;

         int16_t    origOffset;
         bool       isFilteredFrame;
diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp
index 0a0c09307..d75dcafd8 100644
--- a/source/encoder/encoder.cpp
+++ b/source/encoder/encoder.cpp
@@ -1415,6 +1415,15 @@ inline int enqueueRefFrame(FrameEncoder*
curframeEncoder, Frame* iterFrame, Fram
     dest->isFilteredFrame = isPreFiltered;
     dest->isSubsampled = iterFrame->m_isSubSampled;
     dest->origOffset = i;
+
+    TemporalFilterRefPicInfo* temp =
&curFrame->m_mcstfRefList[curFrame->m_mcstf->m_numRef];
+    temp->poc = iterFrame->m_poc;
+    temp->picBuffer = iterFrame->m_fencPic;
+    temp->lowres = iterFrame->m_lowres.lowresPlane[0];
+    temp->lowerRes = iterFrame->m_lowres.lowerResPlane[0];
+    temp->isFilteredFrame = isPreFiltered;
+    temp->origOffset = i;
+
     curFrame->m_mcstf->m_numRef++;

     return 1;
@@ -1443,12 +1452,12 @@ bool Encoder::generateMcstfRef(Frame* frameEnc,
FrameEncoder* currEncoder)
                         TemporalFilter* mcstf = frameEnc->m_mcstf;
                         while (mcstf->m_numRef)
                         {
-
 memset(currEncoder->m_mcstfRefList[mcstf->m_numRef].mvs0,  0, sizeof(MV) *
((mcstf->m_sourceWidth / 16) * (mcstf->m_sourceHeight / 16)));
-
 memset(currEncoder->m_mcstfRefList[mcstf->m_numRef].mvs1,  0, sizeof(MV) *
((mcstf->m_sourceWidth / 16) * (mcstf->m_sourceHeight / 16)));
-
 memset(currEncoder->m_mcstfRefList[mcstf->m_numRef].mvs2,  0, sizeof(MV) *
((mcstf->m_sourceWidth / 16) * (mcstf->m_sourceHeight / 16)));
-
 memset(currEncoder->m_mcstfRefList[mcstf->m_numRef].mvs,   0, sizeof(MV) *
((mcstf->m_sourceWidth /  4) * (mcstf->m_sourceHeight /  4)));
-
 memset(currEncoder->m_mcstfRefList[mcstf->m_numRef].noise, 0, sizeof(int)
* ((mcstf->m_sourceWidth / 4) * (mcstf->m_sourceHeight / 4)));
-
 memset(currEncoder->m_mcstfRefList[mcstf->m_numRef].error, 0, sizeof(int)
* ((mcstf->m_sourceWidth / 4) * (mcstf->m_sourceHeight / 4)));
+
 memset(frameEnc->m_mcstfRefList[mcstf->m_numRef].mvs0, 0, sizeof(MV) *
((mcstf->m_sourceWidth / 16) * (mcstf->m_sourceHeight / 16)));
+
 memset(frameEnc->m_mcstfRefList[mcstf->m_numRef].mvs1, 0, sizeof(MV) *
((mcstf->m_sourceWidth / 16) * (mcstf->m_sourceHeight / 16)));
+
 memset(frameEnc->m_mcstfRefList[mcstf->m_numRef].mvs2, 0, sizeof(MV) *
((mcstf->m_sourceWidth / 16) * (mcstf->m_sourceHeight / 16)));
+
 memset(frameEnc->m_mcstfRefList[mcstf->m_numRef].mvs, 0, sizeof(MV) *
((mcstf->m_sourceWidth / 4) * (mcstf->m_sourceHeight / 4)));
+
 memset(frameEnc->m_mcstfRefList[mcstf->m_numRef].noise, 0, sizeof(int) *
((mcstf->m_sourceWidth / 4) * (mcstf->m_sourceHeight / 4)));
+
 memset(frameEnc->m_mcstfRefList[mcstf->m_numRef].error, 0, sizeof(int) *
((mcstf->m_sourceWidth / 4) * (mcstf->m_sourceHeight / 4)));

                             mcstf->m_numRef--;
                         }
@@ -1513,7 +1522,7 @@ int Encoder::encode(const x265_picture* pic_in,
x265_picture* pic_out)
         m_dpb->recycleUnreferenced();

         if (m_param->bEnableTemporalFilter)
-            m_origPicBuffer->recycleOrigPicList();
+            m_lookahead->m_origPicBuf->recycleOrigPicList();
     }

     if ((pic_in && (!m_param->chunkEnd || (m_encodedFrameNum <
m_param->chunkEnd))) || (m_param->bEnableFrameDuplication && !pic_in &&
(read < written)))
@@ -1917,7 +1926,7 @@ int Encoder::encode(const x265_picture* pic_in,
x265_picture* pic_out)
                                 dupFrame->m_fencPic->m_cuOffsetC =
m_sps.cuOffsetC;
                                 dupFrame->m_fencPic->m_buOffsetC =
m_sps.buOffsetC;
                             }
-                            m_origPicBuffer->addEncPicture(dupFrame);
+
 m_lookahead->m_origPicBuf->addEncPicture(dupFrame);
                         }
                     }
                 }
@@ -1936,7 +1945,7 @@ int Encoder::encode(const x265_picture* pic_in,
x265_picture* pic_out)
             extendPicBorder(orig->m_picOrg[2], orig->m_strideC,
orig->m_picWidth >> orig->m_hChromaShift, orig->m_picHeight >>
orig->m_vChromaShift, orig->m_chromaMarginX, orig->m_chromaMarginY);

             //TODO: Add subsampling here if required
-            m_origPicBuffer->addPicture(inFrame[0]);
+            m_lookahead->m_origPicBuf->addPicture(inFrame[0]);;
         }

         m_lookahead->addPicture(*inFrame[0], sliceType);
@@ -2188,11 +2197,11 @@ int Encoder::encode(const x265_picture* pic_in,
x265_picture* pic_out)

                 if (m_param->bEnableTemporalFilter)
                 {
-                    Frame* curFrame =
m_origPicBuffer->m_mcstfPicList.getPOCMCSTF(outFrame->m_poc);
+                    Frame* curFrame =
m_lookahead->m_origPicBuf->m_mcstfPicList.getPOCMCSTF(outFrame->m_poc);
                     X265_CHECK(curFrame, "Outframe not found in DPB's
mcstfPicList");
                     curFrame->m_refPicCnt[0]--;
                     curFrame->m_refPicCnt[1]--;
-                    curFrame =
m_origPicBuffer->m_mcstfOrigPicList.getPOCMCSTF(outFrame->m_poc);
+                    curFrame =
m_lookahead->m_origPicBuf->m_mcstfOrigPicList.getPOCMCSTF(outFrame->m_poc);
                     X265_CHECK(curFrame, "Outframe not found in OPB's
mcstfOrigPicList");
                     curFrame->m_refPicCnt[1]--;
                 }
@@ -2203,7 +2212,7 @@ int Encoder::encode(const x265_picture* pic_in,
x265_picture* pic_out)
                     ATOMIC_DEC(&outFrame->m_countRefEncoders);
                     m_dpb->recycleUnreferenced();
                     if (m_param->bEnableTemporalFilter)
-                        m_origPicBuffer->recycleOrigPicList();
+                        m_lookahead->m_origPicBuf->recycleOrigPicList();
                 }
                 else
                     m_exportedPic[sLayer] = outFrame;
@@ -2448,9 +2457,9 @@ int Encoder::encode(const x265_picture* pic_in,
x265_picture* pic_out)

             if (m_param->bEnableTemporalFilter)
             {
-
 X265_CHECK(!m_origPicBuffer->m_mcstfOrigPicFreeList.empty(), "Frames not
available in Encoded OPB");
+
 X265_CHECK(!m_lookahead->m_origPicBuf->m_mcstfOrigPicFreeList.empty(),
"Frames not available in Encoded OPB");

-                Frame *dupFrame =
m_origPicBuffer->m_mcstfOrigPicFreeList.popBackMCSTF();
+                Frame* dupFrame =
m_lookahead->m_origPicBuf->m_mcstfOrigPicFreeList.popBackMCSTF();
                 dupFrame->m_fencPic->copyFromFrame(frameEnc[0]->m_fencPic);
                 dupFrame->m_poc = frameEnc[0]->m_poc;
                 dupFrame->m_encodeOrder = frameEnc[0]->m_encodeOrder;
@@ -2461,8 +2470,8 @@ int Encoder::encode(const x265_picture* pic_in,
x265_picture* pic_out)
                 if (m_param->totalFrames && (dupFrame->m_poc >=
(m_param->totalFrames - dupFrame->m_mcstf->m_range)))
                     dupFrame->m_refPicCnt[1] -= (uint8_t)(dupFrame->m_poc
+ dupFrame->m_mcstf->m_range - m_param->totalFrames + 1);

-                m_origPicBuffer->addEncPictureToPicList(dupFrame);
-                m_origPicBuffer->setOrigPicList(frameEnc[0], m_pocLast);
+
 m_lookahead->m_origPicBuf->addEncPictureToPicList(dupFrame);
+                m_lookahead->m_origPicBuf->setOrigPicList(frameEnc[0],
m_pocLast);
             }

             for (int layer = 0; layer < m_param->numLayers; layer++)
@@ -2510,18 +2519,18 @@ int Encoder::encode(const x265_picture* pic_in,
x265_picture* pic_out)

                 for (uint8_t i = 1; i <= frameEnc[0]->m_mcstf->m_numRef;
i++)
                 {
-                    TemporalFilterRefPicInfo *ref =
&curEncoder->m_mcstfRefList[i - 1];
-                    Frame* curFrame =
m_origPicBuffer->m_mcstfPicList.getPOCMCSTF(ref->poc);
+                    TemporalFilterRefPicInfo* ref =
&frameEnc[0]->m_mcstfRefList[i - 1];
+                    Frame* curFrame =
m_lookahead->m_origPicBuf->m_mcstfPicList.getPOCMCSTF(ref->poc);

-
 curEncoder->m_frameEncTF->motionEstimationLuma(ref->mvs0, ref->mvsStride0,
frameEnc[0]->m_lowres.lowerResPlane[0], (frameEnc[0]->m_lowres.lumaStride /
2), frameEnc[0]->m_fencPicSubsampled4->m_picHeight,
frameEnc[0]->m_fencPicSubsampled4->m_picWidth,
curFrame->m_lowres.lowerResPlane[0], 16);
-
 curEncoder->m_frameEncTF->motionEstimationLuma(ref->mvs1, ref->mvsStride1,
frameEnc[0]->m_lowres.lowresPlane[0], frameEnc[0]->m_lowres.lumaStride,
frameEnc[0]->m_fencPicSubsampled2->m_picHeight,
frameEnc[0]->m_fencPicSubsampled2->m_picWidth,
curFrame->m_lowres.lowresPlane[0], 16, ref->mvs0, ref->mvsStride0, 2);
-
 curEncoder->m_frameEncTF->motionEstimationLuma(ref->mvs2, ref->mvsStride2,
frameEnc[0]->m_fencPic->m_picOrg[0], frameEnc[0]->m_fencPic->m_stride,
frameEnc[0]->m_fencPic->m_picHeight, frameEnc[0]->m_fencPic->m_picWidth,
ref->picBuffer->m_picOrg[0], 16, ref->mvs1, ref->mvsStride1, 2);
-
 curEncoder->m_frameEncTF->motionEstimationLumaDoubleRes(ref->mvs,
ref->mvsStride, frameEnc[0]->m_fencPic, ref->picBuffer, 8, ref->mvs2,
ref->mvsStride2, 1, ref->error);
+                    //curFrame->m_mcstf->motionEstimationLuma(ref->mvs0,
ref->mvsStride0, frameEnc[0]->m_lowres.lowerResPlane[0],
(curFrame->m_lowres.lumaStride / 2), (curFrame->m_lowres.lines / 2),
(curFrame->m_lowres.width / 2), ref->lowerRes, 16);
+                    //curFrame->m_mcstf->motionEstimationLuma(ref->mvs1,
ref->mvsStride1, frameEnc[0]->m_lowres.lowresPlane[0],
(curFrame->m_lowres.lumaStride), (curFrame->m_lowres.lines),
(curFrame->m_lowres.width), ref->lowres, 16, ref->mvs0, ref->mvsStride0, 2);
+                    curFrame->m_mcstf->motionEstimationLuma(ref->mvs2,
ref->mvsStride2, frameEnc[0]->m_fencPic->m_picOrg[0],
curFrame->m_fencPic->m_stride, curFrame->m_fencPic->m_picHeight,
curFrame->m_fencPic->m_picWidth, ref->picBuffer->m_picOrg[0], 16,
ref->mvs1, ref->mvsStride1, 2);
+
 curFrame->m_mcstf->motionEstimationLumaDoubleRes(ref->mvs, ref->mvsStride,
frameEnc[0]->m_fencPic, ref->picBuffer, 8, ref->mvs2, ref->mvsStride2, 1,
ref->error);
                 }

                 for (int i = 0; i < frameEnc[0]->m_mcstf->m_numRef; i++)
                 {
-                    TemporalFilterRefPicInfo *ref =
&curEncoder->m_mcstfRefList[i];
+                    TemporalFilterRefPicInfo* ref =
&frameEnc[0]->m_mcstfRefList[i];
                     ref->slicetype =
m_lookahead->findSliceType(frameEnc[0]->m_poc + ref->origOffset);
                     Frame* dpbframePtr =
m_dpb->m_picList.getPOC(frameEnc[0]->m_poc + ref->origOffset, 0);
                     if (dpbframePtr != NULL)
diff --git a/source/encoder/frameencoder.cpp
b/source/encoder/frameencoder.cpp
index b6f2d6ed1..772810f3d 100644
--- a/source/encoder/frameencoder.cpp
+++ b/source/encoder/frameencoder.cpp
@@ -677,7 +677,7 @@ void FrameEncoder::compressFrame(int layer)
     if (m_param->bEnableTemporalFilter)
     {
         m_frameEncTF->m_QP = qp;
-        m_frameEncTF->bilateralFilter(m_frame[layer], m_mcstfRefList,
m_param->temporalFilterStrength);
+        m_frameEncTF->bilateralFilter(m_frame[layer],
m_frame[layer]->m_mcstfRefList, m_param->temporalFilterStrength);
     }

     if (m_nr)
diff --git a/source/encoder/slicetype.cpp b/source/encoder/slicetype.cpp
index 8bbac8244..19f6d8f53 100644
--- a/source/encoder/slicetype.cpp
+++ b/source/encoder/slicetype.cpp
@@ -991,6 +991,7 @@ Lookahead::Lookahead(x265_param *param, ThreadPool*
pool)
     m_isFadeIn = false;
     m_fadeCount = 0;
     m_fadeStart = -1;
+    m_origPicBuf = 0;

     /* Allow the strength to be adjusted via qcompress, since the two
concepts
      * are very similar. */
@@ -1126,6 +1127,9 @@ bool Lookahead::create()
         m_tld[i].init(m_8x8Width, m_8x8Height, m_8x8Blocks);
     m_scratch = X265_MALLOC(int, m_tld[0].widthInCU);

+    if (m_param->bEnableTemporalFilter)
+        m_origPicBuf = new OrigPicBuffer();
+
     return m_tld && m_scratch;
 }

@@ -1165,6 +1169,9 @@ void Lookahead::destroy()
         delete curFrame;
     }

+    if (m_param->bEnableTemporalFilter)
+        delete m_origPicBuf;
+
     X265_FREE(m_scratch);
     delete [] m_tld;
     if (m_param->lookaheadThreads > 0)
@@ -1787,6 +1794,108 @@ void Lookahead::compCostBref(Lowres **frames, int
start, int end, int num)
     }
 }

+void Lookahead::estimatelowresmotion(Frame* curframe)
+{
+
+    for (int i = 1; i <= curframe->m_mcstf->m_numRef; i++)
+    {
+        TemporalFilterRefPicInfo * ref = &curframe->m_mcstfRefList[i - 1];
+
+        curframe->m_mcstf->motionEstimationLuma(ref->mvs0,
ref->mvsStride0, curframe->m_lowres.lowerResPlane[0],
(curframe->m_lowres.lumaStride / 2), (curframe->m_lowres.lines / 2),
(curframe->m_lowres.width / 2), ref->lowerRes, 16);
+        curframe->m_mcstf->motionEstimationLuma(ref->mvs1,
ref->mvsStride1, curframe->m_lowres.lowresPlane[0],
(curframe->m_lowres.lumaStride), (curframe->m_lowres.lines),
(curframe->m_lowres.width), ref->lowres, 16, ref->mvs0, ref->mvsStride0, 2);
+        //curframe->m_mcstf->motionEstimationLuma(ref->mvs2,
ref->mvsStride2, curframe->m_fencPic->m_picOrg[0],
curframe->m_fencPic->m_stride, curframe->m_fencPic->m_picHeight,
curframe->m_fencPic->m_picWidth, ref->picBuffer->m_picOrg[0], 16,
ref->mvs1, ref->mvsStride1, 2);
+        //curframe->m_mcstf->motionEstimationLumaDoubleRes(ref->mvs,
ref->mvsStride, curframe->m_fencPic, ref->picBuffer, 8, ref->mvs2,
ref->mvsStride2, 1, ref->error);
+    }
+
+}
+
+inline int enqueueRefFrame(Frame* iterFrame, Frame* curFrame, bool
isPreFiltered, int16_t i)
+{
+    TemporalFilterRefPicInfo * temp =
&curFrame->m_mcstfRefList[curFrame->m_mcstf->m_numRef];
+    temp->poc = iterFrame->m_poc;
+    temp->picBuffer = iterFrame->m_fencPic;
+    temp->lowres = iterFrame->m_lowres.lowresPlane[0];
+    temp->lowerRes = iterFrame->m_lowres.lowerResPlane[0];
+    temp->isFilteredFrame = isPreFiltered;
+    temp->isSubsampled = iterFrame->m_isSubSampled;
+    temp->origOffset = i;
+    curFrame->m_mcstf->m_numRef++;
+
+     return 1;
+}
+
+bool Lookahead::isFilterThisframe(uint8_t sliceTypeConfig, int
curSliceType)
+{
+    uint8_t newSliceType = 0;
+    switch (curSliceType)
+    {
+        case 1: newSliceType |= 1 << 0;
+               break;
+        case 2: newSliceType |= 1 << 0;
+               break;
+        case 3: newSliceType |= 1 << 1;
+               break;
+        case 4: newSliceType |= 1 << 2;
+               break;
+        case 5: newSliceType |= 1 << 3;
+               break;
+        default: return 0;
+    }
+     return ((sliceTypeConfig & newSliceType) != 0);
+}
+
+bool Lookahead::generatemcstf(Frame * frameEnc, PicList refPic, int
poclast)
+ {
+     frameEnc->m_mcstf->m_numRef = 0;
+
+    for (int iterPOC = (frameEnc->m_poc - frameEnc->m_mcstf->m_range);
+            iterPOC <= (frameEnc->m_poc + frameEnc->m_mcstf->m_range);
iterPOC++)
+    {
+         bool isFound = false;
+        if (iterPOC != frameEnc->m_poc)
+        {
+                //search for the reference frame in the Original Picture
Buffer
+            if (!isFound)
+                {
+                for (int j = 0; j < (2 * frameEnc->m_mcstf->m_range); j++)
+                {
+                    if (iterPOC < 0)
+                         continue;
+                    if (iterPOC >= poclast)
+                         {
+
+                    TemporalFilter * mcstf = frameEnc->m_mcstf;
+                    while (mcstf->m_numRef)
+                    {
+
 memset(frameEnc->m_mcstfRefList[mcstf->m_numRef].mvs0, 0, sizeof(MV) *
((mcstf->m_sourceWidth / 16) * (mcstf->m_sourceHeight / 16)));
+
 memset(frameEnc->m_mcstfRefList[mcstf->m_numRef].mvs1, 0, sizeof(MV) *
((mcstf->m_sourceWidth / 16) * (mcstf->m_sourceHeight / 16)));
+
 memset(frameEnc->m_mcstfRefList[mcstf->m_numRef].mvs2, 0, sizeof(MV) *
((mcstf->m_sourceWidth / 16) * (mcstf->m_sourceHeight / 16)));
+
 memset(frameEnc->m_mcstfRefList[mcstf->m_numRef].mvs, 0, sizeof(MV) *
((mcstf->m_sourceWidth / 4) * (mcstf->m_sourceHeight / 4)));
+
 memset(frameEnc->m_mcstfRefList[mcstf->m_numRef].noise, 0, sizeof(int) *
((mcstf->m_sourceWidth / 4) * (mcstf->m_sourceHeight / 4)));
+
 memset(frameEnc->m_mcstfRefList[mcstf->m_numRef].error, 0, sizeof(int) *
((mcstf->m_sourceWidth / 4) * (mcstf->m_sourceHeight / 4)));
+
+                        mcstf->m_numRef--;
+                    }
+
+                    break;
+                    }
+                    Frame * iterFrame = refPic.getPOCMCSTF(iterPOC);
+                    if (iterFrame->m_poc == iterPOC)
+                    {
+                        if (!enqueueRefFrame(iterFrame, frameEnc, false,
(int16_t)(iterPOC - frameEnc->m_poc)))
+                        {
+                            return false;
+                        };
+                        break;
+                    }
+                }
+            }
+        }
+    }
+
+    return true;
+}
+
 /* called by API thread or worker thread with inputQueueLock acquired */
 void Lookahead::slicetypeDecide()
 {
@@ -2047,6 +2156,22 @@ void Lookahead::slicetypeDecide()
         }
     }

+    Frame* frameEnc = m_inputQueue.first();
+    for (int i = 0; i < m_inputQueue.size(); i++)
+    {
+        if (m_param->bEnableTemporalFilter &&
isFilterThisframe(frameEnc->m_mcstf->m_sliceTypeConfig,
frameEnc->m_lowres.sliceType))
+        {
+            if (!generatemcstf(frameEnc, m_origPicBuf->m_mcstfPicList,
m_inputQueue.last()->m_poc))
+            {
+                x265_log(m_param, X265_LOG_ERROR, "Failed to initialize
MCSTFReferencePicInfo at POC %d\n", frameEnc->m_poc);
+                fflush(stderr);
+            }
+
+            estimatelowresmotion(frameEnc);
+        }
+         frameEnc = frameEnc->m_next;
+    }
+
     if (m_param->bEnableTemporalSubLayers > 2)
     {
         //Split the partial mini GOP into sub mini GOPs when temporal sub
layers are enabled
diff --git a/source/encoder/slicetype.h b/source/encoder/slicetype.h
index f4184e4e2..214e295b7 100644
--- a/source/encoder/slicetype.h
+++ b/source/encoder/slicetype.h
@@ -30,6 +30,7 @@
 #include "motion.h"
 #include "piclist.h"
 #include "threadpool.h"
+#include "temporalfilter.h"

 namespace X265_NS {
 // private namespace
@@ -202,6 +203,8 @@ public:

     int8_t                  m_gopId;

+    OrigPicBuffer*          m_origPicBuf;
+
     Lookahead(x265_param *param, ThreadPool *pool);
 #if DETAILED_CU_STATS
     int64_t       m_slicetypeDecideElapsedTime;
@@ -224,6 +227,10 @@ public:
     void    getEstimatedPictureCost(Frame *pic);
     void    setLookaheadQueue();
     int     findSliceType(int poc);
+    void    estimatelowresmotion(Frame* frame);
+    bool    generatemcstf(Frame * frame, PicList refPic, int poclast);
+    bool    isFilterThisframe(uint8_t sliceTypeConfig, int curSliceType);
+

 protected:

-- 
2.36.0.windows.1
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20241111/a256aa9a/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0004-shifted-mcstf-from-encoder-to-lookahead.patch
Type: application/octet-stream
Size: 22070 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20241111/a256aa9a/attachment-0001.obj>


More information about the x265-devel mailing list