<div dir="ltr">From 378b56a91aafc13dec3882e96905b8478d27a566 Mon Sep 17 00:00:00 2001<br>From: AnusuyaKumarasamy <<a href="mailto:anusuya.kumarasamy@multicorewareinc.com">anusuya.kumarasamy@multicorewareinc.com</a>><br>Date: Thu, 24 Oct 2024 12:46:40 +0530<br>Subject: [PATCH 02/10] Make use of halfpel and quarterpel source frames from<br> lookahead for mcstf<br><br>---<br> source/common/lowres.cpp         |  4 +-<br> source/common/temporalfilter.cpp | 76 ++++++++++++++++----------------<br> source/common/temporalfilter.h   |  8 ++--<br> source/encoder/encoder.cpp       | 18 ++------<br> 4 files changed, 50 insertions(+), 56 deletions(-)<br><br>diff --git a/source/common/lowres.cpp b/source/common/lowres.cpp<br>index 857414e91..14d1e03f4 100644<br>--- a/source/common/lowres.cpp<br>+++ b/source/common/lowres.cpp<br>@@ -162,7 +162,7 @@ bool Lowres::create(x265_param* param, PicYuv *origPic, uint32_t qgSize)<br>     lowresPlane[2] = buffer[2] + padoffset;<br>     lowresPlane[3] = buffer[3] + padoffset;<br> <br>-    if (bEnableHME)<br>+    if (bEnableHME || param->bEnableTemporalFilter)<br>     {<br>         intptr_t lumaStrideHalf = lumaStride / 2;<br>         if (lumaStrideHalf & 31)<br>@@ -375,7 +375,7 @@ void Lowres::init(PicYuv *origPic, int poc)<br>     extendPicBorder(lowresPlane[2], lumaStride, width, lines, origPic->m_lumaMarginX, origPic->m_lumaMarginY);<br>     extendPicBorder(lowresPlane[3], lumaStride, width, lines, origPic->m_lumaMarginX, origPic->m_lumaMarginY);<br>     <br>-    if (origPic->m_param->bEnableHME)<br>+    if (origPic->m_param->bEnableHME || origPic->m_param->bEnableTemporalFilter)<br>     {<br>         primitives.frameInitLowerRes(lowresPlane[0],<br>             lowerResPlane[0], lowerResPlane[1], lowerResPlane[2], lowerResPlane[3],<br>diff --git a/source/common/temporalfilter.cpp b/source/common/temporalfilter.cpp<br>index 5b75517ee..235379b63 100644<br>--- a/source/common/temporalfilter.cpp<br>+++ b/source/common/temporalfilter.cpp<br>@@ -192,7 +192,8 @@ fail:<br> }<br> <br> int TemporalFilter::motionErrorLumaSAD(<br>-    PicYuv *orig,<br>+    pixel* src,<br>+    int stride,<br>     PicYuv *buffer,<br>     int x,<br>     int y,<br>@@ -202,8 +203,8 @@ int TemporalFilter::motionErrorLumaSAD(<br>     int besterror)<br> {<br> <br>-    pixel* origOrigin = orig->m_picOrg[0];<br>-    intptr_t origStride = orig->m_stride;<br>+    pixel* origOrigin = src;<br>+    intptr_t origStride = stride;<br>     pixel *buffOrigin = buffer->m_picOrg[0];<br>     intptr_t buffStride = buffer->m_stride;<br>     int error = 0;// dx * 10 + dy * 10;<br>@@ -296,7 +297,8 @@ int TemporalFilter::motionErrorLumaSAD(<br> }<br> <br> int TemporalFilter::motionErrorLumaSSD(<br>-    PicYuv *orig,<br>+    pixel* src,<br>+    int stride,<br>     PicYuv *buffer,<br>     int x,<br>     int y,<br>@@ -306,8 +308,8 @@ int TemporalFilter::motionErrorLumaSSD(<br>     int besterror)<br> {<br> <br>-    pixel* origOrigin = orig->m_picOrg[0];<br>-    intptr_t origStride = orig->m_stride;<br>+    pixel* origOrigin = src;<br>+    intptr_t origStride = stride;<br>     pixel *buffOrigin = buffer->m_picOrg[0];<br>     intptr_t buffStride = buffer->m_stride;<br>     int error = 0;// dx * 10 + dy * 10;<br>@@ -646,7 +648,7 @@ void TemporalFilter::bilateralFilter(Frame* frame,<br>     }<br> }<br> <br>-void TemporalFilter::motionEstimationLuma(MV *mvs, uint32_t mvStride, PicYuv *orig, PicYuv *buffer, int blockSize,<br>+void TemporalFilter::motionEstimationLuma(MV *mvs, uint32_t mvStride, pixel* src,int stride, int height, int width, PicYuv *buffer, int blockSize,<br>     MV *previous, uint32_t prevMvStride, int factor)<br> {<br> <br>@@ -655,8 +657,8 @@ void TemporalFilter::motionEstimationLuma(MV *mvs, uint32_t mvStride, PicYuv *or<br> <br>     const int stepSize = blockSize;<br> <br>-    const int origWidth = orig->m_picWidth;<br>-    const int origHeight = orig->m_picHeight;<br>+    const int origWidth = width;<br>+    const int origHeight = height;<br> <br>     int error;<br> <br>@@ -664,8 +666,8 @@ void TemporalFilter::motionEstimationLuma(MV *mvs, uint32_t mvStride, PicYuv *or<br>     {<br>         for (int blockX = 0; blockX + blockSize <= origWidth; blockX += stepSize)<br>         {<br>-            const intptr_t pelOffset = blockY * orig->m_stride + blockX;<br>-            m_metld->me.setSourcePU(orig->m_picOrg[0], orig->m_stride, pelOffset, blockSize, blockSize, X265_HEX_SEARCH, 1);<br>+            const intptr_t pelOffset = blockY * stride + blockX;<br>+            m_metld->me.setSourcePU(src, stride, pelOffset, blockSize, blockSize, X265_HEX_SEARCH, 1);<br> <br> <br>             MV best(0, 0);<br>@@ -692,9 +694,9 @@ void TemporalFilter::motionEstimationLuma(MV *mvs, uint32_t mvStride, PicYuv *or<br>                             MV old = previous[mvIdx];<br> <br>                             if (m_useSADinME)<br>-                                error = motionErrorLumaSAD(orig, buffer, blockX, blockY, old.x * factor, old.y * factor, blockSize, leastError);<br>+                                error = motionErrorLumaSAD(src, stride, buffer, blockX, blockY, old.x * factor, old.y * factor, blockSize, leastError);<br>                             else<br>-                                error = motionErrorLumaSSD(orig, buffer, blockX, blockY, old.x * factor, old.y * factor, blockSize, leastError);<br>+                                error = motionErrorLumaSSD(src, stride, buffer, blockX, blockY, old.x * factor, old.y * factor, blockSize, leastError);<br> <br>                             if (error < leastError)<br>                             {<br>@@ -706,9 +708,9 @@ void TemporalFilter::motionEstimationLuma(MV *mvs, uint32_t mvStride, PicYuv *or<br>                 }<br> <br>                 if (m_useSADinME)<br>-                    error = motionErrorLumaSAD(orig, buffer, blockX, blockY, 0, 0, blockSize, leastError);<br>+                    error = motionErrorLumaSAD(src, stride, buffer, blockX, blockY, 0, 0, blockSize, leastError);<br>                 else<br>-                    error = motionErrorLumaSSD(orig, buffer, blockX, blockY, 0, 0, blockSize, leastError);<br>+                    error = motionErrorLumaSSD(src, stride, buffer, blockX, blockY, 0, 0, blockSize, leastError);<br> <br>                 if (error < leastError)<br>                 {<br>@@ -724,9 +726,9 @@ void TemporalFilter::motionEstimationLuma(MV *mvs, uint32_t mvStride, PicYuv *or<br>                 for (int x2 = prevBest.x / m_motionVectorFactor - range; x2 <= prevBest.x / m_motionVectorFactor + range; x2++)<br>                 {<br>                     if (m_useSADinME)<br>-                        error = motionErrorLumaSAD(orig, buffer, blockX, blockY, x2 * m_motionVectorFactor, y2 * m_motionVectorFactor, blockSize, leastError);<br>+                        error = motionErrorLumaSAD(src, stride, buffer, blockX, blockY, x2 * m_motionVectorFactor, y2 * m_motionVectorFactor, blockSize, leastError);<br>                     else<br>-                        error = motionErrorLumaSSD(orig, buffer, blockX, blockY, x2 * m_motionVectorFactor, y2 * m_motionVectorFactor, blockSize, leastError);<br>+                        error = motionErrorLumaSSD(src, stride, buffer, blockX, blockY, x2 * m_motionVectorFactor, y2 * m_motionVectorFactor, blockSize, leastError);<br>                     if (error < leastError)<br>                     {<br>                         best.set(x2 * m_motionVectorFactor, y2 * m_motionVectorFactor);<br>@@ -741,9 +743,9 @@ void TemporalFilter::motionEstimationLuma(MV *mvs, uint32_t mvStride, PicYuv *or<br>                 MV aboveMV = mvs[idx];<br> <br>                 if (m_useSADinME)<br>-                    error = motionErrorLumaSAD(orig, buffer, blockX, blockY, aboveMV.x, aboveMV.y, blockSize, leastError);<br>+                    error = motionErrorLumaSAD(src, stride, buffer, blockX, blockY, aboveMV.x, aboveMV.y, blockSize, leastError);<br>                 else<br>-                    error = motionErrorLumaSSD(orig, buffer, blockX, blockY, aboveMV.x, aboveMV.y, blockSize, leastError);<br>+                    error = motionErrorLumaSSD(src, stride, buffer, blockX, blockY, aboveMV.x, aboveMV.y, blockSize, leastError);<br> <br>                 if (error < leastError)<br>                 {<br>@@ -758,9 +760,9 @@ void TemporalFilter::motionEstimationLuma(MV *mvs, uint32_t mvStride, PicYuv *or<br>                 MV leftMV = mvs[idx];<br> <br>                 if (m_useSADinME)<br>-                    error = motionErrorLumaSAD(orig, buffer, blockX, blockY, leftMV.x, leftMV.y, blockSize, leastError);<br>+                    error = motionErrorLumaSAD(src, stride, buffer, blockX, blockY, leftMV.x, leftMV.y, blockSize, leastError);<br>                 else<br>-                    error = motionErrorLumaSSD(orig, buffer, blockX, blockY, leftMV.x, leftMV.y, blockSize, leastError);<br>+                    error = motionErrorLumaSSD(src, stride, buffer, blockX, blockY, leftMV.x, leftMV.y, blockSize, leastError);<br> <br>                 if (error < leastError)<br>                 {<br>@@ -775,7 +777,7 @@ void TemporalFilter::motionEstimationLuma(MV *mvs, uint32_t mvStride, PicYuv *or<br>             {<br>                 for (int y1 = 0; y1 < blockSize; y1++)<br>                 {<br>-                    avg = avg + *(orig->m_picOrg[0] + (blockX + x1 + orig->m_stride * (blockY + y1)));<br>+                    avg = avg + *(src + (blockX + x1 + stride * (blockY + y1)));<br>                 }<br>             }<br>             avg = avg / (blockSize * blockSize);<br>@@ -786,7 +788,7 @@ void TemporalFilter::motionEstimationLuma(MV *mvs, uint32_t mvStride, PicYuv *or<br>             {<br>                 for (int y1 = 0; y1 < blockSize; y1++)<br>                 {<br>-                    int pix = *(orig->m_picOrg[0] + (blockX + x1 + orig->m_stride * (blockY + y1)));<br>+                    int pix = *(src + (blockX + x1 + stride * (blockY + y1)));<br>                     variance = variance + (pix - avg) * (pix - avg);<br>                 }<br>             }<br>@@ -846,9 +848,9 @@ void TemporalFilter::motionEstimationLumaDoubleRes(MV *mvs, uint32_t mvStride, P<br>                             MV old = previous[mvIdx];<br> <br>                             if (m_useSADinME)<br>-                                error = motionErrorLumaSAD(orig, buffer, blockX, blockY, old.x * factor, old.y * factor, blockSize, leastError);<br>+                                error = motionErrorLumaSAD(orig->m_picOrg[0], orig->m_stride, buffer, blockX, blockY, old.x * factor, old.y * factor, blockSize, leastError);<br>                             else<br>-                                error = motionErrorLumaSSD(orig, buffer, blockX, blockY, old.x * factor, old.y * factor, blockSize, leastError);<br>+                                error = motionErrorLumaSSD(orig->m_picOrg[0], orig->m_stride, buffer, blockX, blockY, old.x * factor, old.y * factor, blockSize, leastError);<br> <br>                             if (error < leastError)<br>                             {<br>@@ -860,9 +862,9 @@ void TemporalFilter::motionEstimationLumaDoubleRes(MV *mvs, uint32_t mvStride, P<br>                 }<br> <br>                 if (m_useSADinME)<br>-                    error = motionErrorLumaSAD(orig, buffer, blockX, blockY, 0, 0, blockSize, leastError);<br>+                    error = motionErrorLumaSAD(orig->m_picOrg[0], orig->m_stride, buffer, blockX, blockY, 0, 0, blockSize, leastError);<br>                 else<br>-                    error = motionErrorLumaSSD(orig, buffer, blockX, blockY, 0, 0, blockSize, leastError);<br>+                    error = motionErrorLumaSSD(orig->m_picOrg[0], orig->m_stride, buffer, blockX, blockY, 0, 0, blockSize, leastError);<br> <br>                 if (error < leastError)<br>                 {<br>@@ -878,9 +880,9 @@ void TemporalFilter::motionEstimationLumaDoubleRes(MV *mvs, uint32_t mvStride, P<br>                 for (int x2 = prevBest.x / m_motionVectorFactor - range; x2 <= prevBest.x / m_motionVectorFactor + range; x2++)<br>                 {<br>                     if (m_useSADinME)<br>-                        error = motionErrorLumaSAD(orig, buffer, blockX, blockY, x2 * m_motionVectorFactor, y2 * m_motionVectorFactor, blockSize, leastError);<br>+                        error = motionErrorLumaSAD(orig->m_picOrg[0], orig->m_stride, buffer, blockX, blockY, x2 * m_motionVectorFactor, y2 * m_motionVectorFactor, blockSize, leastError);<br>                     else<br>-                        error = motionErrorLumaSSD(orig, buffer, blockX, blockY, x2 * m_motionVectorFactor, y2 * m_motionVectorFactor, blockSize, leastError);<br>+                        error = motionErrorLumaSSD(orig->m_picOrg[0], orig->m_stride, buffer, blockX, blockY, x2 * m_motionVectorFactor, y2 * m_motionVectorFactor, blockSize, leastError);<br> <br>                     if (error < leastError)<br>                     {<br>@@ -897,9 +899,9 @@ void TemporalFilter::motionEstimationLumaDoubleRes(MV *mvs, uint32_t mvStride, P<br>                 for (int x2 = prevBest.x - doubleRange; x2 <= prevBest.x + doubleRange; x2 += 4)<br>                 {<br>                     if (m_useSADinME)<br>-                        error = motionErrorLumaSAD(orig, buffer, blockX, blockY, x2, y2, blockSize, leastError);<br>+                        error = motionErrorLumaSAD(orig->m_picOrg[0], orig->m_stride, buffer, blockX, blockY, x2, y2, blockSize, leastError);<br>                     else<br>-                        error = motionErrorLumaSSD(orig, buffer, blockX, blockY, x2, y2, blockSize, leastError);<br>+                        error = motionErrorLumaSSD(orig->m_picOrg[0], orig->m_stride, buffer, blockX, blockY, x2, y2, blockSize, leastError);<br> <br>                     if (error < leastError)<br>                     {<br>@@ -916,9 +918,9 @@ void TemporalFilter::motionEstimationLumaDoubleRes(MV *mvs, uint32_t mvStride, P<br>                 for (int x2 = prevBest.x - doubleRange; x2 <= prevBest.x + doubleRange; x2++)<br>                 {<br>                     if (m_useSADinME)<br>-                        error = motionErrorLumaSAD(orig, buffer, blockX, blockY, x2, y2, blockSize, leastError);<br>+                        error = motionErrorLumaSAD(orig->m_picOrg[0], orig->m_stride, buffer, blockX, blockY, x2, y2, blockSize, leastError);<br>                     else<br>-                        error = motionErrorLumaSSD(orig, buffer, blockX, blockY, x2, y2, blockSize, leastError);<br>+                        error = motionErrorLumaSSD(orig->m_picOrg[0], orig->m_stride, buffer, blockX, blockY, x2, y2, blockSize, leastError);<br> <br>                     if (error < leastError)<br>                     {<br>@@ -935,9 +937,9 @@ void TemporalFilter::motionEstimationLumaDoubleRes(MV *mvs, uint32_t mvStride, P<br>                 MV aboveMV = mvs[idx];<br> <br>                 if (m_useSADinME)<br>-                    error = motionErrorLumaSAD(orig, buffer, blockX, blockY, aboveMV.x, aboveMV.y, blockSize, leastError);<br>+                    error = motionErrorLumaSAD(orig->m_picOrg[0], orig->m_stride, buffer, blockX, blockY, aboveMV.x, aboveMV.y, blockSize, leastError);<br>                 else<br>-                    error = motionErrorLumaSSD(orig, buffer, blockX, blockY, aboveMV.x, aboveMV.y, blockSize, leastError);<br>+                    error = motionErrorLumaSSD(orig->m_picOrg[0], orig->m_stride, buffer, blockX, blockY, aboveMV.x, aboveMV.y, blockSize, leastError);<br> <br>                 if (error < leastError)<br>                 {<br>@@ -952,9 +954,9 @@ void TemporalFilter::motionEstimationLumaDoubleRes(MV *mvs, uint32_t mvStride, P<br>                 MV leftMV = mvs[idx];<br> <br>                 if (m_useSADinME)<br>-                    error = motionErrorLumaSAD(orig, buffer, blockX, blockY, leftMV.x, leftMV.y, blockSize, leastError);<br>+                    error = motionErrorLumaSAD(orig->m_picOrg[0], orig->m_stride, buffer, blockX, blockY, leftMV.x, leftMV.y, blockSize, leastError);<br>                 else<br>-                    error = motionErrorLumaSSD(orig, buffer, blockX, blockY, leftMV.x, leftMV.y, blockSize, leastError);<br>+                    error = motionErrorLumaSSD(orig->m_picOrg[0], orig->m_stride, buffer, blockX, blockY, leftMV.x, leftMV.y, blockSize, leastError);<br> <br>                 if (error < leastError)<br>                 {<br>diff --git a/source/common/temporalfilter.h b/source/common/temporalfilter.h<br>index 723644633..ae60c77f8 100644<br>--- a/source/common/temporalfilter.h<br>+++ b/source/common/temporalfilter.h<br>@@ -152,13 +152,14 @@ namespace X265_NS {<br> <br>         void bilateralFilter(Frame* frame, TemporalFilterRefPicInfo* mctfRefList, double overallStrength);<br> <br>-        void motionEstimationLuma(MV *mvs, uint32_t mvStride, PicYuv *orig, PicYuv *buffer, int bs,<br>+        void motionEstimationLuma(MV *mvs, uint32_t mvStride, pixel* src, int stride, int height, int width, PicYuv *buffer, int bs,<br>             MV *previous = 0, uint32_t prevmvStride = 0, int factor = 1);<br> <br>         void motionEstimationLumaDoubleRes(MV *mvs, uint32_t mvStride, PicYuv *orig, PicYuv *buffer, int blockSize,<br>             MV *previous, uint32_t prevMvStride, int factor, int* minError);<br> <br>-        int motionErrorLumaSSD(PicYuv *orig,<br>+        int motionErrorLumaSSD(pixel* src,<br>+            int stride,<br>             PicYuv *buffer,<br>             int x,<br>             int y,<br>@@ -167,7 +168,8 @@ namespace X265_NS {<br>             int bs,<br>             int besterror = 8 * 8 * 1024 * 1024);<br> <br>-        int motionErrorLumaSAD(PicYuv *orig,<br>+        int motionErrorLumaSAD(pixel* src,<br>+            int stride,<br>             PicYuv *buffer,<br>             int x,<br>             int y,<br>diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp<br>index 5e715b713..58818379a 100644<br>--- a/source/encoder/encoder.cpp<br>+++ b/source/encoder/encoder.cpp<br>@@ -2507,16 +2507,6 @@ int Encoder::encode(const x265_picture* pic_in, x265_picture* pic_out)<br>                     return -1;<br>                 }<br> <br>-<br>-                if (!*frameEnc[0]->m_isSubSampled)<br>-                {<br>-                    primitives.frameSubSampleLuma((const pixel *)frameEnc[0]->m_fencPic->m_picOrg[0],frameEnc[0]->m_fencPicSubsampled2->m_picOrg[0], frameEnc[0]->m_fencPic->m_stride, frameEnc[0]->m_fencPicSubsampled2->m_stride, frameEnc[0]->m_fencPicSubsampled2->m_picWidth, frameEnc[0]->m_fencPicSubsampled2->m_picHeight);<br>-                    extendPicBorder(frameEnc[0]->m_fencPicSubsampled2->m_picOrg[0], frameEnc[0]->m_fencPicSubsampled2->m_stride, frameEnc[0]->m_fencPicSubsampled2->m_picWidth, frameEnc[0]->m_fencPicSubsampled2->m_picHeight, frameEnc[0]->m_fencPicSubsampled2->m_lumaMarginX, frameEnc[0]->m_fencPicSubsampled2->m_lumaMarginY);<br>-                    primitives.frameSubSampleLuma((const pixel *)frameEnc[0]->m_fencPicSubsampled2->m_picOrg[0],frameEnc[0]->m_fencPicSubsampled4->m_picOrg[0], frameEnc[0]->m_fencPicSubsampled2->m_stride, frameEnc[0]->m_fencPicSubsampled4->m_stride, frameEnc[0]->m_fencPicSubsampled4->m_picWidth, frameEnc[0]->m_fencPicSubsampled4->m_picHeight);<br>-                    extendPicBorder(frameEnc[0]->m_fencPicSubsampled4->m_picOrg[0], frameEnc[0]->m_fencPicSubsampled4->m_stride, frameEnc[0]->m_fencPicSubsampled4->m_picWidth, frameEnc[0]->m_fencPicSubsampled4->m_picHeight, frameEnc[0]->m_fencPicSubsampled4->m_lumaMarginX, frameEnc[0]->m_fencPicSubsampled4->m_lumaMarginY);<br>-                    *frameEnc[0]->m_isSubSampled = true;<br>-                }<br>-<br>                 for (uint8_t i = 1; i <= frameEnc[0]->m_mcstf->m_numRef; i++)<br>                 {<br>                     TemporalFilterRefPicInfo *ref = &curEncoder->m_mcstfRefList[i - 1];<br>@@ -2534,10 +2524,10 @@ int Encoder::encode(const x265_picture* pic_in, x265_picture* pic_out)<br>                 {<br>                     TemporalFilterRefPicInfo *ref = &curEncoder->m_mcstfRefList[i - 1];<br> <br>-                    curEncoder->m_frameEncTF->motionEstimationLuma(ref->mvs0, ref->mvsStride0, frameEnc[0]->m_fencPicSubsampled4, ref->picBufferSubSampled4, 16);<br>-                    curEncoder->m_frameEncTF->motionEstimationLuma(ref->mvs1, ref->mvsStride1, frameEnc[0]->m_fencPicSubsampled2, ref->picBufferSubSampled2, 16, ref->mvs0, ref->mvsStride0, 2);<br>-                    curEncoder->m_frameEncTF->motionEstimationLuma(ref->mvs2, ref->mvsStride2, frameEnc[0]->m_fencPic, ref->picBuffer, 16, ref->mvs1, ref->mvsStride1, 2);<br>-                    curEncoder->m_frameEncTF->motionEstimationLumaDoubleRes(ref->mvs,  ref->mvsStride, frameEnc[0]->m_fencPic, ref->picBuffer, 8, ref->mvs2, ref->mvsStride2, 1, ref->error);<br>+                    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, ref->picBufferSubSampled4, 16);<br>+                    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, ref->picBufferSubSampled2, 16, ref->mvs0, ref->mvsStride0, 2);<br>+                    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, 16, ref->mvs1, ref->mvsStride1, 2);<br>+                    curEncoder->m_frameEncTF->motionEstimationLumaDoubleRes(ref->mvs, ref->mvsStride, frameEnc[0]->m_fencPic, ref->picBuffer, 8, ref->mvs2, ref->mvsStride2, 1, ref->error);<br>                 }<br> <br>                 for (int i = 0; i < frameEnc[0]->m_mcstf->m_numRef; i++)<br>-- <br>2.36.0.windows.1<br><br></div>