<div dir="ltr"><div dir="ltr"><div>From 7c777cce9b374a31c999c960f1e794616987cb8f Mon Sep 17 00:00:00 2001</div><div>From: ashok2022 <<a href="mailto:ashok@multicorewareinc.com">ashok@multicorewareinc.com</a>></div><div>Date: Wed, 21 Sep 2022 17:48:38 +0530</div><div>Subject: [PATCH] Added functions related to mcstf feature</div><div><br></div><div>---</div><div> source/common/common.h    |   2 +</div><div> source/common/frame.cpp   |  64 ++++++++++++++++++++++++</div><div> source/common/frame.h     |  12 +++++</div><div> source/common/mv.h        |   2 +</div><div> source/common/piclist.cpp | 101 ++++++++++++++++++++++++++++++++++++++</div><div> source/common/piclist.h   |   7 +++</div><div> source/common/picyuv.cpp  |  52 ++++++++++++++++++++</div><div> source/common/picyuv.h    |   2 +</div><div> source/common/slice.h     |   1 +</div><div> 9 files changed, 243 insertions(+)</div><div><br></div><div>diff --git a/source/common/common.h b/source/common/common.h</div><div>index a245c7dae..982b03d89 100644</div><div>--- a/source/common/common.h</div><div>+++ b/source/common/common.h</div><div>@@ -342,6 +342,8 @@ typedef int16_t  coeff_t;      // transform coefficient</div><div> #define MAX_NUM_DYN_REFINE          (NUM_CU_DEPTH * X265_REFINE_INTER_LEVELS)</div><div> #define X265_BYTE 8</div><div> </div><div>+#define MAX_MCTF_TEMPORAL_WINDOW_LENGTH 8</div><div>+</div><div> namespace X265_NS {</div><div> </div><div> enum { SAO_NUM_OFFSET = 4 };</div><div>diff --git a/source/common/frame.cpp b/source/common/frame.cpp</div><div>index 255882a9d..0ce301bfa 100644</div><div>--- a/source/common/frame.cpp</div><div>+++ b/source/common/frame.cpp</div><div>@@ -64,12 +64,38 @@ Frame::Frame()</div><div>     m_edgeBitPlane = NULL;</div><div>     m_edgeBitPic = NULL;</div><div>     m_isInsideWindow = 0;</div><div>+</div><div>+    // mcstf</div><div>+    m_isSubSampled = NULL;</div><div>+    m_mcstf = NULL;</div><div>+    m_refPicCnt[0] = 0;</div><div>+    m_refPicCnt[1] = 0;</div><div>+    m_nextMCSTF = NULL;</div><div>+    m_prevMCSTF = NULL;</div><div>+</div><div> }</div><div> </div><div> bool Frame::create(x265_param *param, float* quantOffsets)</div><div> {</div><div>     m_fencPic = new PicYuv;</div><div>     m_param = param;</div><div>+</div><div>+    if (m_param->bEnableGopBasedTemporalFilter)</div><div>+    {</div><div>+        m_mcstf = new TemporalFilter;</div><div>+        m_mcstf->init(param);</div><div>+</div><div>+        m_fencPicSubsampled2 = new PicYuv;</div><div>+        m_fencPicSubsampled4 = new PicYuv;</div><div>+</div><div>+        if (!m_fencPicSubsampled2->createScaledPicYUV(param, 2))</div><div>+            return false;</div><div>+        if (!m_fencPicSubsampled4->createScaledPicYUV(param, 4))</div><div>+            return false;</div><div>+</div><div>+        CHECKED_MALLOC_ZERO(m_isSubSampled, int, 1);</div><div>+    }</div><div>+</div><div>     CHECKED_MALLOC_ZERO(m_rcData, RcStats, 1);</div><div> </div><div>     if (param->bCTUInfo)</div><div>@@ -151,6 +177,24 @@ fail:</div><div>     return false;</div><div> }</div><div> </div><div>+bool Frame::createSubSample()</div><div>+{</div><div>+</div><div>+    //m_param = param;</div><div>+</div><div>+    m_fencPicSubsampled2 = new PicYuv;</div><div>+    m_fencPicSubsampled4 = new PicYuv;</div><div>+</div><div>+    if (!m_fencPicSubsampled2->createScaledPicYUV(m_param, 2))</div><div>+        return false;</div><div>+    if (!m_fencPicSubsampled4->createScaledPicYUV(m_param, 4))</div><div>+        return false;</div><div>+    CHECKED_MALLOC_ZERO(m_isSubSampled, int, 1);</div><div>+    return true;</div><div>+fail:</div><div>+    return false;</div><div>+}</div><div>+</div><div> bool Frame::allocEncodeData(x265_param *param, const SPS& sps)</div><div> {</div><div>     m_encData = new FrameData;</div><div>@@ -207,6 +251,26 @@ void Frame::destroy()</div><div>         m_fencPic = NULL;</div><div>     }</div><div> </div><div>+    if (m_param->bEnableGopBasedTemporalFilter)</div><div>+    {</div><div>+</div><div>+        if (m_fencPicSubsampled2)</div><div>+        {</div><div>+            m_fencPicSubsampled2->destroy();</div><div>+            delete m_fencPicSubsampled2;</div><div>+            m_fencPicSubsampled2 = NULL;</div><div>+        }</div><div>+</div><div>+        if (m_fencPicSubsampled4)</div><div>+        {</div><div>+            m_fencPicSubsampled4->destroy();</div><div>+            delete m_fencPicSubsampled4;</div><div>+            m_fencPicSubsampled4 = NULL;</div><div>+        }</div><div>+        delete m_mcstf;</div><div>+        X265_FREE(m_isSubSampled);</div><div>+    }</div><div>+</div><div>     if (m_reconPic)</div><div>     {</div><div>         m_reconPic->destroy();</div><div>diff --git a/source/common/frame.h b/source/common/frame.h</div><div>index ac1185e81..b1dd00e21 100644</div><div>--- a/source/common/frame.h</div><div>+++ b/source/common/frame.h</div><div>@@ -28,6 +28,7 @@</div><div> #include "common.h"</div><div> #include "lowres.h"</div><div> #include "threading.h"</div><div>+#include "temporalfilter.h"</div><div> </div><div> namespace X265_NS {</div><div> // private namespace</div><div>@@ -84,6 +85,9 @@ public:</div><div> </div><div>     /* Data associated with x265_picture */</div><div>     PicYuv*                m_fencPic;</div><div>+    PicYuv*                m_fencPicSubsampled2;</div><div>+    PicYuv*                m_fencPicSubsampled4;</div><div>+</div><div>     int                    m_poc;</div><div>     int                    m_encodeOrder;</div><div>     int64_t                m_pts;                // user provided presentation time stamp</div><div>@@ -133,6 +137,13 @@ public:</div><div>     bool                   m_classifyFrame;</div><div>     int                    m_fieldNum;</div><div> </div><div>+    /*MCSTF*/</div><div>+    TemporalFilter*        m_mcstf;</div><div>+    int                    m_refPicCnt[2];</div><div>+    Frame*                 m_nextMCSTF;           // PicList doubly linked list pointers</div><div>+    Frame*                 m_prevMCSTF;</div><div>+    int*                   m_isSubSampled;</div><div>+</div><div>     /* aq-mode 4 : Gaussian, edge and theta frames for edge information */</div><div>     pixel*                 m_edgePic;</div><div>     pixel*                 m_gaussianPic;</div><div>@@ -147,6 +158,7 @@ public:</div><div>     Frame();</div><div> </div><div>     bool create(x265_param *param, float* quantOffsets);</div><div>+    bool createSubSample();</div><div>     bool allocEncodeData(x265_param *param, const SPS& sps);</div><div>     void reinit(const SPS& sps);</div><div>     void destroy();</div><div>diff --git a/source/common/mv.h b/source/common/mv.h</div><div>index 191090cb9..5a8872cdd 100644</div><div>--- a/source/common/mv.h</div><div>+++ b/source/common/mv.h</div><div>@@ -105,6 +105,8 @@ public:</div><div>     {</div><div>         return x >= _min.x && x <= _max.x && y >= _min.y && y <= _max.y;</div><div>     }</div><div>+</div><div>+    void set(int32_t _x, int32_t _y) { x = _x; y = _y; }</div><div> };</div><div> }</div><div> </div><div>diff --git a/source/common/piclist.cpp b/source/common/piclist.cpp</div><div>index 91929f101..275617f6f 100644</div><div>--- a/source/common/piclist.cpp</div><div>+++ b/source/common/piclist.cpp</div><div>@@ -45,6 +45,25 @@ void PicList::pushFront(Frame& curFrame)</div><div>     m_count++;</div><div> }</div><div> </div><div>+void PicList::pushFrontMCSTF(Frame& curFrame)</div><div>+{</div><div>+    X265_CHECK(!curFrame.m_nextMCSTF && !curFrame.m_nextMCSTF, "piclist: picture already in OPB list\n"); // ensure frame is not in a list</div><div>+    curFrame.m_nextMCSTF = m_start;</div><div>+    curFrame.m_prevMCSTF = NULL;</div><div>+</div><div>+    if (m_count)</div><div>+    {</div><div>+        m_start->m_prevMCSTF = &curFrame;</div><div>+        m_start = &curFrame;</div><div>+    }</div><div>+    else</div><div>+    {</div><div>+        m_start = m_end = &curFrame;</div><div>+    }</div><div>+    m_count++;</div><div>+</div><div>+}</div><div>+</div><div> void PicList::pushBack(Frame& curFrame)</div><div> {</div><div>     X265_CHECK(!curFrame.m_next && !curFrame.m_prev, "piclist: picture already in list\n"); // ensure frame is not in a list</div><div>@@ -63,6 +82,24 @@ void PicList::pushBack(Frame& curFrame)</div><div>     m_count++;</div><div> }</div><div> </div><div>+void PicList::pushBackMCSTF(Frame& curFrame)</div><div>+{</div><div>+    X265_CHECK(!curFrame.m_nextMCSTF && !curFrame.m_prevMCSTF, "piclist: picture already in OPB list\n"); // ensure frame is not in a list</div><div>+    curFrame.m_nextMCSTF = NULL;</div><div>+    curFrame.m_prevMCSTF = m_end;</div><div>+</div><div>+    if (m_count)</div><div>+    {</div><div>+        m_end->m_nextMCSTF = &curFrame;</div><div>+        m_end = &curFrame;</div><div>+    }</div><div>+    else</div><div>+    {</div><div>+        m_start = m_end = &curFrame;</div><div>+    }</div><div>+    m_count++;</div><div>+}</div><div>+</div><div> Frame *PicList::popFront()</div><div> {</div><div>     if (m_start)</div><div>@@ -94,6 +131,14 @@ Frame* PicList::getPOC(int poc)</div><div>     return curFrame;</div><div> }</div><div> </div><div>+Frame* PicList::getPOCMCSTF(int poc)</div><div>+{</div><div>+    Frame *curFrame = m_start;</div><div>+    while (curFrame && curFrame->m_poc != poc)</div><div>+        curFrame = curFrame->m_nextMCSTF;</div><div>+    return curFrame;</div><div>+}</div><div>+</div><div> Frame *PicList::popBack()</div><div> {</div><div>     if (m_end)</div><div>@@ -117,6 +162,29 @@ Frame *PicList::popBack()</div><div>         return NULL;</div><div> }</div><div> </div><div>+Frame *PicList::popBackMCSTF()</div><div>+{</div><div>+    if (m_end)</div><div>+    {</div><div>+        Frame* temp = m_end;</div><div>+        m_count--;</div><div>+</div><div>+        if (m_count)</div><div>+        {</div><div>+            m_end = m_end->m_prevMCSTF;</div><div>+            m_end->m_nextMCSTF = NULL;</div><div>+        }</div><div>+        else</div><div>+        {</div><div>+            m_start = m_end = NULL;</div><div>+        }</div><div>+        temp->m_nextMCSTF = temp->m_prevMCSTF = NULL;</div><div>+        return temp;</div><div>+    }</div><div>+    else</div><div>+        return NULL;</div><div>+}</div><div>+</div><div> Frame* PicList::getCurFrame(void)</div><div> {</div><div>     Frame *curFrame = m_start;</div><div>@@ -158,3 +226,36 @@ void PicList::remove(Frame& curFrame)</div><div> </div><div>     curFrame.m_next = curFrame.m_prev = NULL;</div><div> }</div><div>+</div><div>+void PicList::removeMCSTF(Frame& curFrame)</div><div>+{</div><div>+#if _DEBUG</div><div>+    Frame *tmp = m_start;</div><div>+    while (tmp && tmp != &curFrame)</div><div>+    {</div><div>+        tmp = tmp->m_nextMCSTF;</div><div>+    }</div><div>+</div><div>+    X265_CHECK(tmp == &curFrame, "framelist: pic being removed was not in list\n"); // verify pic is in this list</div><div>+#endif</div><div>+</div><div>+    m_count--;</div><div>+    if (m_count)</div><div>+    {</div><div>+        if (m_start == &curFrame)</div><div>+            m_start = curFrame.m_nextMCSTF;</div><div>+        if (m_end == &curFrame)</div><div>+            m_end = curFrame.m_prevMCSTF;</div><div>+</div><div>+        if (curFrame.m_nextMCSTF)</div><div>+            curFrame.m_nextMCSTF->m_prevMCSTF = curFrame.m_prevMCSTF;</div><div>+        if (curFrame.m_prevMCSTF)</div><div>+            curFrame.m_prevMCSTF->m_nextMCSTF = curFrame.m_nextMCSTF;</div><div>+    }</div><div>+    else</div><div>+    {</div><div>+        m_start = m_end = NULL;</div><div>+    }</div><div>+</div><div>+    curFrame.m_nextMCSTF = curFrame.m_prevMCSTF = NULL;</div><div>+}</div><div>diff --git a/source/common/piclist.h b/source/common/piclist.h</div><div>index e1d6e714a..45023c93b 100644</div><div>--- a/source/common/piclist.h</div><div>+++ b/source/common/piclist.h</div><div>@@ -49,24 +49,31 @@ public:</div><div> </div><div>     /** Push picture to end of the list */</div><div>     void pushBack(Frame& pic);</div><div>+    void pushBackMCSTF(Frame& pic);</div><div> </div><div>     /** Push picture to beginning of the list */</div><div>     void pushFront(Frame& pic);</div><div>+    void pushFrontMCSTF(Frame& pic);</div><div> </div><div>     /** Pop picture from end of the list */</div><div>     Frame* popBack();</div><div>+    Frame* popBackMCSTF();</div><div> </div><div>     /** Pop picture from beginning of the list */</div><div>     Frame* popFront();</div><div> </div><div>     /** Find frame with specified POC */</div><div>     Frame* getPOC(int poc);</div><div>+    /* Find next MCSTF frame with specified POC */</div><div>+    Frame* getPOCMCSTF(int poc);</div><div> </div><div>     /** Get the current Frame from the list **/</div><div>     Frame* getCurFrame(void);</div><div> </div><div>     /** Remove picture from list */</div><div>     void remove(Frame& pic);</div><div>+    /* Remove MCSTF picture from list */</div><div>+    void removeMCSTF(Frame& pic);</div><div> </div><div>     Frame* first()        { return m_start;   }</div><div> </div><div>diff --git a/source/common/picyuv.cpp b/source/common/picyuv.cpp</div><div>index e65dbdd46..2855356b5 100644</div><div>--- a/source/common/picyuv.cpp</div><div>+++ b/source/common/picyuv.cpp</div><div>@@ -125,6 +125,58 @@ fail:</div><div>     return false;</div><div> }</div><div> </div><div>+/*Copy pixels from the picture buffer of a frame to picture buffer of another frame*/</div><div>+void PicYuv::copyFromFrame(PicYuv* source)</div><div>+{</div><div>+    uint32_t numCuInHeight = (m_picHeight + m_param->maxCUSize - 1) / m_param->maxCUSize;</div><div>+</div><div>+    int maxHeight = numCuInHeight * m_param->maxCUSize;</div><div>+    memcpy(m_picBuf[0], source->m_picBuf[0], sizeof(pixel)* m_stride * (maxHeight + (m_lumaMarginY * 2)));</div><div>+    m_picOrg[0] = m_picBuf[0] + m_lumaMarginY * m_stride + m_lumaMarginX;</div><div>+</div><div>+    if (m_picCsp != X265_CSP_I400)</div><div>+    {</div><div>+        memcpy(m_picBuf[1], source->m_picBuf[1], sizeof(pixel)* m_strideC * ((maxHeight >> m_vChromaShift) + (m_chromaMarginY * 2)));</div><div>+        memcpy(m_picBuf[2], source->m_picBuf[2], sizeof(pixel)* m_strideC * ((maxHeight >> m_vChromaShift) + (m_chromaMarginY * 2)));</div><div>+</div><div>+        m_picOrg[1] = m_picBuf[1] + m_chromaMarginY * m_strideC + m_chromaMarginX;</div><div>+        m_picOrg[2] = m_picBuf[2] + m_chromaMarginY * m_strideC + m_chromaMarginX;</div><div>+    }</div><div>+    else</div><div>+    {</div><div>+        m_picBuf[1] = m_picBuf[2] = NULL;</div><div>+        m_picOrg[1] = m_picOrg[2] = NULL;</div><div>+    }</div><div>+}</div><div>+</div><div>+bool PicYuv::createScaledPicYUV(x265_param* param, uint8_t scaleFactor)</div><div>+{</div><div>+    m_param = param;</div><div>+    m_picWidth = m_param->sourceWidth / scaleFactor;</div><div>+    m_picHeight = m_param->sourceHeight / scaleFactor;</div><div>+</div><div>+    m_picCsp = m_param->internalCsp;</div><div>+    m_hChromaShift = CHROMA_H_SHIFT(m_picCsp);</div><div>+    m_vChromaShift = CHROMA_V_SHIFT(m_picCsp);</div><div>+</div><div>+    uint32_t numCuInWidth = (m_picWidth + param->maxCUSize - 1) / param->maxCUSize;</div><div>+    uint32_t numCuInHeight = (m_picHeight + param->maxCUSize - 1) / param->maxCUSize;</div><div>+</div><div>+    m_lumaMarginX = 32; // search margin for L0 and L1 ME in horizontal direction</div><div>+    m_lumaMarginY = 32; // search margin for L0 and L1 ME in vertical direction</div><div>+    m_stride = (numCuInWidth * param->maxCUSize) + (m_lumaMarginX << 1);</div><div>+</div><div>+    int maxHeight = numCuInHeight * param->maxCUSize;</div><div>+    CHECKED_MALLOC_ZERO(m_picBuf[0], pixel, m_stride * (maxHeight + (m_lumaMarginY * 2)));</div><div>+    m_picOrg[0] = m_picBuf[0] + m_lumaMarginY * m_stride + m_lumaMarginX;</div><div>+    m_picBuf[1] = m_picBuf[2] = NULL;</div><div>+    m_picOrg[1] = m_picOrg[2] = NULL;</div><div>+    return true;</div><div>+</div><div>+fail:</div><div>+    return false;</div><div>+}</div><div>+</div><div> int PicYuv::getLumaBufLen(uint32_t picWidth, uint32_t picHeight, uint32_t picCsp)</div><div> {</div><div>     m_picWidth = picWidth;</div><div>diff --git a/source/common/picyuv.h b/source/common/picyuv.h</div><div>index 0b53d354d..ba448567a 100644</div><div>--- a/source/common/picyuv.h</div><div>+++ b/source/common/picyuv.h</div><div>@@ -78,11 +78,13 @@ public:</div><div>     PicYuv();</div><div> </div><div>     bool  create(x265_param* param, bool picAlloc = true, pixel *pixelbuf = NULL);</div><div>+    bool  createScaledPicYUV(x265_param* param, uint8_t scaleFactor);</div><div>     bool  createOffsets(const SPS& sps);</div><div>     void  destroy();</div><div>     int   getLumaBufLen(uint32_t picWidth, uint32_t picHeight, uint32_t picCsp);</div><div> </div><div>     void  copyFromPicture(const x265_picture&, const x265_param& param, int padx, int pady);</div><div>+    void  copyFromFrame(PicYuv* source);</div><div> </div><div>     intptr_t getChromaAddrOffset(uint32_t ctuAddr, uint32_t absPartIdx) const { return m_cuOffsetC[ctuAddr] + m_buOffsetC[absPartIdx]; }</div><div> </div><div>diff --git a/source/common/slice.h b/source/common/slice.h</div><div>index 9a48d39c6..c5327c198 100644</div><div>--- a/source/common/slice.h</div><div>+++ b/source/common/slice.h</div><div>@@ -363,6 +363,7 @@ public:</div><div>     int         m_iNumRPSInSPS;</div><div>     const x265_param *m_param;</div><div>     int         m_fieldNum;</div><div>+    Frame*      m_mcstfRefFrameList[2][MAX_MCTF_TEMPORAL_WINDOW_LENGTH];</div><div> </div><div>     Slice()</div><div>     {</div><div>-- </div><div>2.34.1.windows.1</div><div><br></div><div><div dir="ltr" class="gmail_signature"><div dir="ltr"><div><i><font face="georgia, serif">Thanks and Regards,</font></i></div><div><i><font face="georgia, serif"><b>Snehaa.G</b><br>Video Codec Engineer,<br>Media & AI analytics<br><a href="https://multicorewareinc.com/" target="_blank"><img src="https://ci3.googleusercontent.com/mail-sig/AIorK4yEumXeQ2mgcFAR2us9INa7z3rCbl8ordut3fbdeIbuPv0n3EA75Or1rHs0neGaI0WM8mFPz1g"></a><br><span></span><span></span><br></font></i></div></div></div></div></div></div>