<div dir="ltr"><div># HG changeset patch</div><div># User Vignesh Vijayakumar <<a href="mailto:vignesh@multicorewareinc.com">vignesh@multicorewareinc.com</a>></div><div># Date 1480313149 -19800</div><div>#      Mon Nov 28 11:35:49 2016 +0530</div><div># Node ID f8d523976ed61cada53c579d8145a815d21d08ed</div><div># Parent  5d95fbd53ca31747498c4bd661fa24f6ffd5a070</div><div>SEA motion search Implementation</div><div><br></div><div>diff -r 5d95fbd53ca3 -r f8d523976ed6 doc/reST/cli.rst</div><div>--- a/doc/reST/cli.rst<span class="gmail-Apple-tab-span" style="white-space:pre">     </span>Fri Nov 25 12:57:52 2016 +0530</div><div>+++ b/doc/reST/cli.rst<span class="gmail-Apple-tab-span" style="white-space:pre">   </span>Mon Nov 28 11:35:49 2016 +0530</div><div>@@ -964,13 +964,17 @@</div><div> <span class="gmail-Apple-tab-span" style="white-space:pre">   </span>encoder: a star-pattern search followed by an optional radix scan</div><div> <span class="gmail-Apple-tab-span" style="white-space:pre">    </span>followed by an optional star-search refinement. Full is an</div><div> <span class="gmail-Apple-tab-span" style="white-space:pre">   </span>exhaustive search; an order of magnitude slower than all other</div><div>-<span class="gmail-Apple-tab-span" style="white-space:pre">        </span>searches but not much better than umh or star.</div><div>+<span class="gmail-Apple-tab-span" style="white-space:pre">        </span>searches but not much better than umh or star. SEA is similar to</div><div>+<span class="gmail-Apple-tab-span" style="white-space:pre">      </span>FULL search; a three step motion search adopted from x264: DC </div><div>+<span class="gmail-Apple-tab-span" style="white-space:pre">       </span>calculation followed by ADS calculation followed by SAD of the</div><div>+<span class="gmail-Apple-tab-span" style="white-space:pre">        </span>passed motion vector candidates, hence faster than Full search. </div><div> </div><div> <span class="gmail-Apple-tab-span" style="white-space:pre">   </span>0. dia</div><div> <span class="gmail-Apple-tab-span" style="white-space:pre">       </span>1. hex **(default)**</div><div> <span class="gmail-Apple-tab-span" style="white-space:pre"> </span>2. umh</div><div> <span class="gmail-Apple-tab-span" style="white-space:pre">       </span>3. star</div><div>-<span class="gmail-Apple-tab-span" style="white-space:pre">       </span>4. full</div><div>+<span class="gmail-Apple-tab-span" style="white-space:pre">       </span>4. sea</div><div>+<span class="gmail-Apple-tab-span" style="white-space:pre">        </span>5. full</div><div> </div><div> .. option:: --subme, -m <0..7></div><div> </div><div>diff -r 5d95fbd53ca3 -r f8d523976ed6 source/common/common.h</div><div>--- a/source/common/common.h<span class="gmail-Apple-tab-span" style="white-space:pre">   </span>Fri Nov 25 12:57:52 2016 +0530</div><div>+++ b/source/common/common.h<span class="gmail-Apple-tab-span" style="white-space:pre">     </span>Mon Nov 28 11:35:49 2016 +0530</div><div>@@ -328,6 +328,8 @@</div><div> </div><div> #define PIXEL_MAX ((1 << X265_DEPTH) - 1)</div><div> </div><div>+#define INTEGRAL_PLANE_NUM          12 // 12 integral planes for 32x32, 32x24, 32x8, 24x32, 16x16, 16x12, 16x4, 12x16, 8x32, 8x8, 4x16 and 4x4.</div><div>+</div><div> namespace X265_NS {</div><div> </div><div> enum { SAO_NUM_OFFSET = 4 };</div><div>diff -r 5d95fbd53ca3 -r f8d523976ed6 source/common/framedata.cpp</div><div>--- a/source/common/framedata.cpp<span class="gmail-Apple-tab-span" style="white-space:pre">       </span>Fri Nov 25 12:57:52 2016 +0530</div><div>+++ b/source/common/framedata.cpp<span class="gmail-Apple-tab-span" style="white-space:pre">        </span>Mon Nov 28 11:35:49 2016 +0530</div><div>@@ -48,6 +48,12 @@</div><div>     CHECKED_MALLOC_ZERO(m_cuStat, RCStatCU, sps.numCUsInFrame);</div><div>     CHECKED_MALLOC(m_rowStat, RCStatRow, sps.numCuInHeight);</div><div>     reinit(sps);</div><div>+    </div><div>+    for (int i = 0; i < INTEGRAL_PLANE_NUM; i++)</div><div>+    {</div><div>+        m_meBuffer[i] = NULL;</div><div>+        m_meIntegral[i] = NULL;</div><div>+    }</div><div>     return true;</div><div> </div><div> fail:</div><div>@@ -70,4 +76,16 @@</div><div> </div><div>     X265_FREE(m_cuStat);</div><div>     X265_FREE(m_rowStat);</div><div>+</div><div>+    if (m_meBuffer)</div><div>+    {</div><div>+        for (int i = 0; i < INTEGRAL_PLANE_NUM; i++)</div><div>+        {</div><div>+            if (m_meBuffer[i] != NULL)</div><div>+            {</div><div>+                X265_FREE(m_meBuffer[i]);</div><div>+                m_meBuffer[i] = NULL;</div><div>+            }</div><div>+        }</div><div>+    }</div><div> }</div><div>diff -r 5d95fbd53ca3 -r f8d523976ed6 source/common/framedata.h</div><div>--- a/source/common/framedata.h<span class="gmail-Apple-tab-span" style="white-space:pre">      </span>Fri Nov 25 12:57:52 2016 +0530</div><div>+++ b/source/common/framedata.h<span class="gmail-Apple-tab-span" style="white-space:pre">  </span>Mon Nov 28 11:35:49 2016 +0530</div><div>@@ -151,6 +151,9 @@</div><div>     double         m_rateFactor; /* calculated based on the Frame QP */</div><div>     int            m_picCsp;</div><div> </div><div>+    uint32_t*              m_meIntegral[INTEGRAL_PLANE_NUM];       // 12 integral planes for 32x32, 32x24, 32x8, 24x32, 16x16, 16x12, 16x4, 12x16, 8x32, 8x8, 4x16 and 4x4.</div><div>+    uint32_t*              m_meBuffer[INTEGRAL_PLANE_NUM];</div><div>+</div><div>     FrameData();</div><div> </div><div>     bool create(const x265_param& param, const SPS& sps, int csp);</div><div>diff -r 5d95fbd53ca3 -r f8d523976ed6 source/common/param.cpp</div><div>--- a/source/common/param.cpp<span class="gmail-Apple-tab-span" style="white-space:pre">        </span>Fri Nov 25 12:57:52 2016 +0530</div><div>+++ b/source/common/param.cpp<span class="gmail-Apple-tab-span" style="white-space:pre">    </span>Mon Nov 28 11:35:49 2016 +0530</div><div>@@ -1092,8 +1092,8 @@</div><div>           "Frame rate numerator and denominator must be specified");</div><div>     CHECK(param->interlaceMode < 0 || param->interlaceMode > 2,</div><div>           "Interlace mode must be 0 (progressive) 1 (top-field first) or 2 (bottom field first)");</div><div>-    CHECK(param->searchMethod<0 || param->searchMethod> X265_FULL_SEARCH,</div><div>-          "Search method is not supported value (0:DIA 1:HEX 2:UMH 3:HM 5:FULL)");</div><div>+    CHECK(param->searchMethod < 0 || param->searchMethod > X265_FULL_SEARCH,</div><div>+          "Search method is not supported value (0:DIA 1:HEX 2:UMH 3:HM 4:SEA 5:FULL)");</div><div>     CHECK(param->searchRange < 0,</div><div>           "Search Range must be more than 0");</div><div>     CHECK(param->searchRange >= 32768,</div><div>@@ -1256,6 +1256,10 @@</div><div>         "qpmin exceeds supported range (0 to 69)");</div><div>     CHECK(param->log2MaxPocLsb < 4 || param->log2MaxPocLsb > 16,</div><div>         "Supported range for log2MaxPocLsb is 4 to 16");</div><div>+#if !X86_64</div><div>+    CHECK(param->searchMethod == X265_SEA && (param->sourceWidth > 840 || param->sourceHeight > 480),</div><div>+        "SEA motion search does not support resolutions greater than 480p in 32 bit build");</div><div>+#endif</div><div>     return check_failed;</div><div> }</div><div> </div><div>diff -r 5d95fbd53ca3 -r f8d523976ed6 source/common/pixel.cpp</div><div>--- a/source/common/pixel.cpp<span class="gmail-Apple-tab-span" style="white-space:pre">     </span>Fri Nov 25 12:57:52 2016 +0530</div><div>+++ b/source/common/pixel.cpp<span class="gmail-Apple-tab-span" style="white-space:pre">    </span>Mon Nov 28 11:35:49 2016 +0530</div><div>@@ -117,6 +117,52 @@</div><div>     }</div><div> }</div><div> </div><div>+template<int lx, int ly></div><div>+int ads_x4(int encDC[4], uint32_t *sums, int delta, uint16_t *costMvX, int16_t *mvs, int width, int thresh)</div><div>+{</div><div>+    int nmv = 0;</div><div>+    for (int16_t i = 0; i < width; i++, sums++)</div><div>+    {</div><div>+        int ads = abs(encDC[0] - long(sums[0]))</div><div>+            + abs(encDC[1] - long(sums[lx >> 1]))</div><div>+            + abs(encDC[2] - long(sums[delta]))</div><div>+            + abs(encDC[3] - long(sums[delta + (lx >> 1)]))</div><div>+            + costMvX[i];</div><div>+        if (ads < thresh)</div><div>+            mvs[nmv++] = i;</div><div>+    }</div><div>+    return nmv;</div><div>+}</div><div>+</div><div>+template<int lx, int ly></div><div>+int ads_x2(int encDC[2], uint32_t *sums, int delta, uint16_t *costMvX, int16_t *mvs, int width, int thresh)</div><div>+{</div><div>+    int nmv = 0;</div><div>+    for (int16_t i = 0; i < width; i++, sums++)</div><div>+    {</div><div>+        int ads = abs(encDC[0] - long(sums[0]))</div><div>+            + abs(encDC[1] - long(sums[delta]))</div><div>+            + costMvX[i];</div><div>+        if (ads < thresh)</div><div>+            mvs[nmv++] = i;</div><div>+    }</div><div>+    return nmv;</div><div>+}</div><div>+</div><div>+template<int lx, int ly></div><div>+int ads_x1(int encDC[1], uint32_t *sums, int, uint16_t *costMvX, int16_t *mvs, int width, int thresh)</div><div>+{</div><div>+    int nmv = 0;</div><div>+    for (int16_t i = 0; i < width; i++, sums++)</div><div>+    {</div><div>+        int ads = abs(encDC[0] - long(sums[0]))</div><div>+            + costMvX[i];</div><div>+        if (ads < thresh)</div><div>+            mvs[nmv++] = i;</div><div>+    }</div><div>+    return nmv;</div><div>+}</div><div>+</div><div> template<int lx, int ly, class T1, class T2></div><div> sse_t sse(const T1* pix1, intptr_t stride_pix1, const T2* pix2, intptr_t stride_pix2)</div><div> {</div><div>@@ -991,6 +1037,32 @@</div><div>     LUMA_PU(64, 16);</div><div>     LUMA_PU(16, 64);</div><div> </div><div>+    p.pu[LUMA_4x4].ads = ads_x1<4, 4>;</div><div>+    p.pu[LUMA_8x8].ads = ads_x1<8, 8>;</div><div>+    p.pu[LUMA_8x4].ads = ads_x2<8, 4>;</div><div>+    p.pu[LUMA_4x8].ads = ads_x2<4, 8>;</div><div>+    p.pu[LUMA_16x16].ads = ads_x4<16, 16>;</div><div>+    p.pu[LUMA_16x8].ads = ads_x2<16, 8>;</div><div>+    p.pu[LUMA_8x16].ads = ads_x2<8, 16>;</div><div>+    p.pu[LUMA_16x12].ads = ads_x1<16, 12>;</div><div>+    p.pu[LUMA_12x16].ads = ads_x1<12, 16>;</div><div>+    p.pu[LUMA_16x4].ads = ads_x1<16, 4>;</div><div>+    p.pu[LUMA_4x16].ads = ads_x1<4, 16>;</div><div>+    p.pu[LUMA_32x32].ads = ads_x4<32, 32>;</div><div>+    p.pu[LUMA_32x16].ads = ads_x2<32, 16>;</div><div>+    p.pu[LUMA_16x32].ads = ads_x2<16, 32>;</div><div>+    p.pu[LUMA_32x24].ads = ads_x4<32, 24>;</div><div>+    p.pu[LUMA_24x32].ads = ads_x4<24, 32>;</div><div>+    p.pu[LUMA_32x8].ads = ads_x4<32, 8>;</div><div>+    p.pu[LUMA_8x32].ads = ads_x4<8, 32>;</div><div>+    p.pu[LUMA_64x64].ads = ads_x4<64, 64>;</div><div>+    p.pu[LUMA_64x32].ads = ads_x2<64, 32>;</div><div>+    p.pu[LUMA_32x64].ads = ads_x2<32, 64>;</div><div>+    p.pu[LUMA_64x48].ads = ads_x4<64, 48>;</div><div>+    p.pu[LUMA_48x64].ads = ads_x4<48, 64>;</div><div>+    p.pu[LUMA_64x16].ads = ads_x4<64, 16>;</div><div>+    p.pu[LUMA_16x64].ads = ads_x4<16, 64>;</div><div>+</div><div>     p.pu[LUMA_4x4].satd   = satd_4x4;</div><div>     p.pu[LUMA_8x8].satd   = satd8<8, 8>;</div><div>     p.pu[LUMA_8x4].satd   = satd_8x4;</div><div>diff -r 5d95fbd53ca3 -r f8d523976ed6 source/common/primitives.h</div><div>--- a/source/common/primitives.h<span class="gmail-Apple-tab-span" style="white-space:pre">    </span>Fri Nov 25 12:57:52 2016 +0530</div><div>+++ b/source/common/primitives.h<span class="gmail-Apple-tab-span" style="white-space:pre"> </span>Mon Nov 28 11:35:49 2016 +0530</div><div>@@ -115,6 +115,7 @@</div><div> typedef sse_t (*pixel_sse_t)(const pixel* fenc, intptr_t fencstride, const pixel* fref, intptr_t frefstride); // fenc is aligned</div><div> typedef sse_t (*pixel_sse_ss_t)(const int16_t* fenc, intptr_t fencstride, const int16_t* fref, intptr_t frefstride);</div><div> typedef sse_t (*pixel_ssd_s_t)(const int16_t* fenc, intptr_t fencstride);</div><div>+typedef int(*pixelcmp_ads_t)(int encDC[], uint32_t *sums, int delta, uint16_t *costMvX, int16_t *mvs, int width, int thresh);</div><div> typedef void (*pixelcmp_x4_t)(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, const pixel* fref3, intptr_t frefstride, int32_t* res);</div><div> typedef void (*pixelcmp_x3_t)(const pixel* fenc, const pixel* fref0, const pixel* fref1, const pixel* fref2, intptr_t frefstride, int32_t* res);</div><div> typedef void (*blockfill_s_t)(int16_t* dst, intptr_t dstride, int16_t val);</div><div>@@ -217,6 +218,7 @@</div><div>         pixelcmp_t     sad;         // Sum of Absolute Differences</div><div>         pixelcmp_x3_t  sad_x3;      // Sum of Absolute Differences, 3 mv offsets at once</div><div>         pixelcmp_x4_t  sad_x4;      // Sum of Absolute Differences, 4 mv offsets at once</div><div>+        pixelcmp_ads_t ads;         // Absolute Differences sum</div><div>         pixelcmp_t     satd;        // Sum of Absolute Transformed Differences (4x4 Hadamard)</div><div> </div><div>         filter_pp_t    luma_hpp;    // 8-tap luma motion compensation interpolation filters</div><div>@@ -402,6 +404,22 @@</div><div>     return part;</div><div> }</div><div> </div><div>+/* Computes the size of the LumaPU for a given LumaPU enum */</div><div>+inline void sizesFromPartition(int part, int *width, int *height)</div><div>+{</div><div>+    X265_CHECK(part >= 0 && part <= 24, "Invalid part %d \n", part);</div><div>+    extern const uint8_t lumaPartitionMapTable[];</div><div>+    int index = 0;</div><div>+    for (int i = 0; i < 256;i++)</div><div>+        if (part == lumaPartitionMapTable[i])</div><div>+        {</div><div>+            index = i;</div><div>+            break;</div><div>+        }</div><div>+    *width = 4 * ((index >> 4) + 1);</div><div>+    *height = 4 * ((index % 16) + 1);</div><div>+}</div><div>+</div><div> inline int partitionFromLog2Size(int log2Size)</div><div> {</div><div>     X265_CHECK(2 <= log2Size && log2Size <= 6, "Invalid block size\n");</div><div>diff -r 5d95fbd53ca3 -r f8d523976ed6 source/common/yuv.cpp</div><div>--- a/source/common/yuv.cpp<span class="gmail-Apple-tab-span" style="white-space:pre">       </span>Fri Nov 25 12:57:52 2016 +0530</div><div>+++ b/source/common/yuv.cpp<span class="gmail-Apple-tab-span" style="white-space:pre">      </span>Mon Nov 28 11:35:49 2016 +0530</div><div>@@ -47,6 +47,11 @@</div><div>     m_size  = size;</div><div>     m_part = partitionFromSizes(size, size);</div><div> </div><div>+    for (int i = 0; i < 2; i++)</div><div>+        for (int j = 0; j < MAX_NUM_REF; j++)</div><div>+            for (int k = 0; k < INTEGRAL_PLANE_NUM; k++)</div><div>+                m_integral[i][j][k] = NULL;</div><div>+</div><div>     if (csp == X265_CSP_I400)</div><div>     {</div><div>         CHECKED_MALLOC(m_buf[0], pixel, size * size + 8);</div><div>diff -r 5d95fbd53ca3 -r f8d523976ed6 source/common/yuv.h</div><div>--- a/source/common/yuv.h<span class="gmail-Apple-tab-span" style="white-space:pre">       </span>Fri Nov 25 12:57:52 2016 +0530</div><div>+++ b/source/common/yuv.h<span class="gmail-Apple-tab-span" style="white-space:pre">        </span>Mon Nov 28 11:35:49 2016 +0530</div><div>@@ -48,6 +48,7 @@</div><div>     int      m_csp;</div><div>     int      m_hChromaShift;</div><div>     int      m_vChromaShift;</div><div>+    uint32_t *m_integral[2][MAX_NUM_REF][INTEGRAL_PLANE_NUM];</div><div> </div><div>     Yuv();</div><div> </div><div>diff -r 5d95fbd53ca3 -r f8d523976ed6 source/encoder/analysis.cpp</div><div>--- a/source/encoder/analysis.cpp<span class="gmail-Apple-tab-span" style="white-space:pre">      </span>Fri Nov 25 12:57:52 2016 +0530</div><div>+++ b/source/encoder/analysis.cpp<span class="gmail-Apple-tab-span" style="white-space:pre">        </span>Mon Nov 28 11:35:49 2016 +0530</div><div>@@ -943,6 +943,16 @@</div><div>     ModeDepth& md = m_modeDepth[depth];</div><div>     md.bestMode = NULL;</div><div> </div><div>+    if (m_param->searchMethod == X265_SEA)</div><div>+    {</div><div>+        int numPredDir = m_slice->isInterP() ? 1 : 2;</div><div>+        int offset = (int)(m_frame->m_reconPic->m_cuOffsetY[parentCTU.m_cuAddr] + m_frame->m_reconPic->m_buOffsetY[cuGeom.absPartIdx]);</div><div>+        for (int list = 0; list < numPredDir; list++)</div><div>+            for (int i = 0; i < m_frame->m_encData->m_slice->m_numRefIdx[list]; i++)</div><div>+                for (int planes = 0; planes < INTEGRAL_PLANE_NUM; planes++)</div><div>+                    m_modeDepth[depth].fencYuv.m_integral[list][i][planes] = m_frame->m_encData->m_slice->m_refFrameList[list][i]->m_encData->m_meIntegral[planes] + offset;</div><div>+    }</div><div>+</div><div>     PicYuv& reconPic = *m_frame->m_reconPic;</div><div> </div><div>     bool mightSplit = !(cuGeom.flags & CUGeom::LEAF);</div><div>@@ -1484,6 +1494,16 @@</div><div>     ModeDepth& md = m_modeDepth[depth];</div><div>     md.bestMode = NULL;</div><div> </div><div>+    if (m_param->searchMethod == X265_SEA)</div><div>+    {</div><div>+        int numPredDir = m_slice->isInterP() ? 1 : 2;</div><div>+        int offset = (int)(m_frame->m_reconPic->m_cuOffsetY[parentCTU.m_cuAddr] + m_frame->m_reconPic->m_buOffsetY[cuGeom.absPartIdx]);</div><div>+        for (int list = 0; list < numPredDir; list++)</div><div>+            for (int i = 0; i < m_frame->m_encData->m_slice->m_numRefIdx[list]; i++)</div><div>+                for (int planes = 0; planes < INTEGRAL_PLANE_NUM; planes++)</div><div>+                    m_modeDepth[depth].fencYuv.m_integral[list][i][planes] = m_frame->m_encData->m_slice->m_refFrameList[list][i]->m_encData->m_meIntegral[planes] + offset;</div><div>+    }</div><div>+</div><div>     bool mightSplit = !(cuGeom.flags & CUGeom::LEAF);</div><div>     bool mightNotSplit = !(cuGeom.flags & CUGeom::SPLIT_MANDATORY);</div><div>     bool skipRecursion = false;</div><div>diff -r 5d95fbd53ca3 -r f8d523976ed6 source/encoder/bitcost.cpp</div><div>--- a/source/encoder/bitcost.cpp<span class="gmail-Apple-tab-span" style="white-space:pre">    </span>Fri Nov 25 12:57:52 2016 +0530</div><div>+++ b/source/encoder/bitcost.cpp<span class="gmail-Apple-tab-span" style="white-space:pre"> </span>Mon Nov 28 11:35:49 2016 +0530</div><div>@@ -54,7 +54,22 @@</div><div>                 s_costs[qp][i] = s_costs[qp][-i] = (uint16_t)X265_MIN(s_bitsizes[i] * lambda + 0.5f, (1 << 15) - 1);</div><div>         }</div><div>     }</div><div>+    for (int j = 0; j < 4; j++)</div><div>+    {</div><div>+         if (!s_fpelMvCosts[qp][j])</div><div>+        {</div><div>+            s_fpelMvCosts[qp][j] = X265_MALLOC(uint16_t, BC_MAX_MV + 1) + (BC_MAX_MV >> 1);</div><div>+        }</div><div>+    }</div><div> </div><div>+    for (int j = 0; j < 4; j++)</div><div>+    {</div><div>+        for (int i = -(BC_MAX_MV >> 1); i < (BC_MAX_MV >> 1); i++)</div><div>+        {</div><div>+            s_fpelMvCosts[qp][j][i] = s_costs[qp][i * 4 + j];</div><div>+        }</div><div>+        m_fpelMvCosts[j] = s_fpelMvCosts[qp][j];</div><div>+    }</div><div>     m_cost = s_costs[qp];</div><div> }</div><div> </div><div>@@ -64,6 +79,8 @@</div><div> </div><div> uint16_t *BitCost::s_costs[BC_MAX_QP];</div><div> </div><div>+uint16_t* BitCost::s_fpelMvCosts[BC_MAX_QP][4];</div><div>+</div><div> float *BitCost::s_bitsizes;</div><div> </div><div> Lock BitCost::s_costCalcLock;</div><div>@@ -97,6 +114,17 @@</div><div>         }</div><div>     }</div><div> </div><div>+    for (int i = 0; i < BC_MAX_QP; i++)</div><div>+    {</div><div>+        if (s_fpelMvCosts[i][0])</div><div>+        {</div><div>+            for (int j = 0; j < 4; j++)</div><div>+            {</div><div>+                X265_FREE(s_fpelMvCosts[i][j] - (BC_MAX_MV >> 1));</div><div>+            }</div><div>+        }</div><div>+    }</div><div>+</div><div>     if (s_bitsizes)</div><div>     {</div><div>         X265_FREE(s_bitsizes - 2 * BC_MAX_MV);</div><div>diff -r 5d95fbd53ca3 -r f8d523976ed6 source/encoder/bitcost.h</div><div>--- a/source/encoder/bitcost.h<span class="gmail-Apple-tab-span" style="white-space:pre">        </span>Fri Nov 25 12:57:52 2016 +0530</div><div>+++ b/source/encoder/bitcost.h<span class="gmail-Apple-tab-span" style="white-space:pre">   </span>Mon Nov 28 11:35:49 2016 +0530</div><div>@@ -67,6 +67,8 @@</div><div> </div><div>     uint16_t *m_cost;</div><div> </div><div>+    uint16_t *m_fpelMvCosts[4];</div><div>+</div><div>     MV        m_mvp;</div><div> </div><div>     BitCost& operator =(const BitCost&);</div><div>@@ -84,6 +86,8 @@</div><div> </div><div>     static uint16_t *s_costs[BC_MAX_QP];</div><div> </div><div>+    static uint16_t *s_fpelMvCosts[BC_MAX_QP][4];</div><div>+</div><div>     static Lock s_costCalcLock;</div><div> </div><div>     static void CalculateLogs();</div><div>diff -r 5d95fbd53ca3 -r f8d523976ed6 source/encoder/dpb.cpp</div><div>--- a/source/encoder/dpb.cpp<span class="gmail-Apple-tab-span" style="white-space:pre">   </span>Fri Nov 25 12:57:52 2016 +0530</div><div>+++ b/source/encoder/dpb.cpp<span class="gmail-Apple-tab-span" style="white-space:pre">     </span>Mon Nov 28 11:35:49 2016 +0530</div><div>@@ -92,6 +92,19 @@</div><div>             m_freeList.pushBack(*curFrame);</div><div>             curFrame->m_encData->m_freeListNext = m_frameDataFreeList;</div><div>             m_frameDataFreeList = curFrame->m_encData;</div><div>+</div><div>+            if (curFrame->m_encData->m_meBuffer)</div><div>+            {</div><div>+                for (int i = 0; i < INTEGRAL_PLANE_NUM; i++)</div><div>+                {</div><div>+                    if (curFrame->m_encData->m_meBuffer[i] != NULL)</div><div>+                    {</div><div>+                        X265_FREE(curFrame->m_encData->m_meBuffer[i]);</div><div>+                        curFrame->m_encData->m_meBuffer[i] = NULL;</div><div>+                    }</div><div>+                }</div><div>+            }</div><div>+</div><div>             curFrame->m_encData = NULL;</div><div>             curFrame->m_reconPic = NULL;</div><div>         }</div><div>diff -r 5d95fbd53ca3 -r f8d523976ed6 source/encoder/encoder.cpp</div><div>--- a/source/encoder/encoder.cpp<span class="gmail-Apple-tab-span" style="white-space:pre">    </span>Fri Nov 25 12:57:52 2016 +0530</div><div>+++ b/source/encoder/encoder.cpp<span class="gmail-Apple-tab-span" style="white-space:pre"> </span>Mon Nov 28 11:35:49 2016 +0530</div><div>@@ -869,6 +869,25 @@</div><div>                 slice->m_endCUAddr = slice->realEndAddress(m_sps.numCUsInFrame * NUM_4x4_PARTITIONS);</div><div>             }</div><div> </div><div>+            if (m_param->searchMethod == X265_SEA && frameEnc->m_lowres.sliceType != X265_TYPE_B)</div><div>+            {</div><div>+                int padX = g_maxCUSize + 32;</div><div>+                int padY = g_maxCUSize + 16;</div><div>+                uint32_t numCuInHeight = (frameEnc->m_encData->m_reconPic->m_picHeight + g_maxCUSize - 1) / g_maxCUSize;</div><div>+                int maxHeight = numCuInHeight * g_maxCUSize;</div><div>+                for (int i = 0; i < INTEGRAL_PLANE_NUM; i++)</div><div>+                {</div><div>+                    frameEnc->m_encData->m_meBuffer[i] = X265_MALLOC(uint32_t, frameEnc->m_reconPic->m_stride * (maxHeight + (2 * padY)));</div><div>+                    if (frameEnc->m_encData->m_meBuffer[i])</div><div>+                    {</div><div>+                        memset(frameEnc->m_encData->m_meBuffer[i], 0, sizeof(uint32_t)* frameEnc->m_reconPic->m_stride * (maxHeight + (2 * padY)));</div><div>+                        frameEnc->m_encData->m_meIntegral[i] = frameEnc->m_encData->m_meBuffer[i] + frameEnc->m_encData->m_reconPic->m_stride * padY + padX;</div><div>+                    }</div><div>+                    else</div><div>+                        x265_log(m_param, X265_LOG_ERROR, "SEA motion search: POC %d Integral buffer[%d] unallocated\n", frameEnc->m_poc, i);</div><div>+                }</div><div>+            }</div><div>+</div><div>             if (m_param->bOptQpPPS && frameEnc->m_lowres.bKeyframe && m_param->bRepeatHeaders)</div><div>             {</div><div>                 ScopedLock qpLock(m_sliceQpLock);</div><div>diff -r 5d95fbd53ca3 -r f8d523976ed6 source/encoder/framefilter.cpp</div><div>--- a/source/encoder/framefilter.cpp<span class="gmail-Apple-tab-span" style="white-space:pre"> </span>Fri Nov 25 12:57:52 2016 +0530</div><div>+++ b/source/encoder/framefilter.cpp<span class="gmail-Apple-tab-span" style="white-space:pre">     </span>Mon Nov 28 11:35:49 2016 +0530</div><div>@@ -35,6 +35,109 @@</div><div> static uint64_t computeSSD(pixel *fenc, pixel *rec, intptr_t stride, uint32_t width, uint32_t height);</div><div> static float calculateSSIM(pixel *pix1, intptr_t stride1, pixel *pix2, intptr_t stride2, uint32_t width, uint32_t height, void *buf, uint32_t& cnt);</div><div> </div><div>+static void integral_init4h(uint32_t *sum, pixel *pix, intptr_t stride)</div><div>+{</div><div>+    int32_t v = pix[0] + pix[1] + pix[2] + pix[3];</div><div>+    for (int16_t x = 0; x < stride - 4; x++)</div><div>+    {</div><div>+        sum[x] = v + sum[x - stride];</div><div>+        v += pix[x + 4] - pix[x];</div><div>+    }</div><div>+}</div><div>+</div><div>+static void integral_init8h(uint32_t *sum, pixel *pix, intptr_t stride)</div><div>+{</div><div>+    int32_t v = pix[0] + pix[1] + pix[2] + pix[3] + pix[4] + pix[5] + pix[6] + pix[7];</div><div>+    for (int16_t x = 0; x < stride - 8; x++)</div><div>+    {</div><div>+        sum[x] = v + sum[x - stride];</div><div>+        v += pix[x + 8] - pix[x];</div><div>+    }</div><div>+}</div><div>+</div><div>+static void integral_init12h(uint32_t *sum, pixel *pix, intptr_t stride)</div><div>+{</div><div>+    int32_t v = pix[0] + pix[1] + pix[2] + pix[3] + pix[4] + pix[5] + pix[6] + pix[7] +</div><div>+        pix[8] + pix[9] + pix[10] + pix[11];</div><div>+    for (int16_t x = 0; x < stride - 12; x++)</div><div>+    {</div><div>+        sum[x] = v + sum[x - stride];</div><div>+        v += pix[x + 12] - pix[x];</div><div>+    }</div><div>+}</div><div>+</div><div>+static void integral_init16h(uint32_t *sum, pixel *pix, intptr_t stride)</div><div>+{</div><div>+    int32_t v = pix[0] + pix[1] + pix[2] + pix[3] + pix[4] + pix[5] + pix[6] + pix[7] +</div><div>+        pix[8] + pix[9] + pix[10] + pix[11] + pix[12] + pix[13] + pix[14] + pix[15];</div><div>+    for (int16_t x = 0; x < stride - 16; x++)</div><div>+    {</div><div>+        sum[x] = v + sum[x - stride];</div><div>+        v += pix[x + 16] - pix[x];</div><div>+    }</div><div>+}</div><div>+</div><div>+static void integral_init24h(uint32_t *sum, pixel *pix, intptr_t stride)</div><div>+{</div><div>+    int32_t v = pix[0] + pix[1] + pix[2] + pix[3] + pix[4] + pix[5] + pix[6] + pix[7] +</div><div>+        pix[8] + pix[9] + pix[10] + pix[11] + pix[12] + pix[13] + pix[14] + pix[15] +</div><div>+        pix[16] + pix[17] + pix[18] + pix[19] + pix[20] + pix[21] + pix[22] + pix[23];</div><div>+    for (int16_t x = 0; x < stride - 24; x++)</div><div>+    {</div><div>+        sum[x] = v + sum[x - stride];</div><div>+        v += pix[x + 24] - pix[x];</div><div>+    }</div><div>+}</div><div>+</div><div>+static void integral_init32h(uint32_t *sum, pixel *pix, intptr_t stride)</div><div>+{</div><div>+    int32_t v = pix[0] + pix[1] + pix[2] + pix[3] + pix[4] + pix[5] + pix[6] + pix[7] +</div><div>+        pix[8] + pix[9] + pix[10] + pix[11] + pix[12] + pix[13] + pix[14] + pix[15] +</div><div>+        pix[16] + pix[17] + pix[18] + pix[19] + pix[20] + pix[21] + pix[22] + pix[23] +</div><div>+        pix[24] + pix[25] + pix[26] + pix[27] + pix[28] + pix[29] + pix[30] + pix[31];</div><div>+    for (int16_t x = 0; x < stride - 32; x++)</div><div>+    {</div><div>+        sum[x] = v + sum[x - stride];</div><div>+        v += pix[x + 32] - pix[x];</div><div>+    }</div><div>+}</div><div>+</div><div>+static void integral_init4v(uint32_t *sum4, intptr_t stride)</div><div>+{</div><div>+    for (int x = 0; x < stride; x++)</div><div>+        sum4[x] = sum4[x + 4 * stride] - sum4[x];</div><div>+}</div><div>+</div><div>+static void integral_init8v(uint32_t *sum8, intptr_t stride)</div><div>+{</div><div>+    for (int x = 0; x < stride; x++)</div><div>+        sum8[x] = sum8[x + 8 * stride] - sum8[x];</div><div>+}</div><div>+</div><div>+static void integral_init12v(uint32_t *sum12, intptr_t stride)</div><div>+{</div><div>+    for (int x = 0; x < stride; x++)</div><div>+        sum12[x] = sum12[x + 12 * stride] - sum12[x];</div><div>+}</div><div>+</div><div>+static void integral_init16v(uint32_t *sum16, intptr_t stride)</div><div>+{</div><div>+    for (int x = 0; x < stride; x++)</div><div>+        sum16[x] = sum16[x + 16 * stride] - sum16[x];</div><div>+}</div><div>+</div><div>+static void integral_init24v(uint32_t *sum24, intptr_t stride)</div><div>+{</div><div>+    for (int x = 0; x < stride; x++)</div><div>+        sum24[x] = sum24[x + 24 * stride] - sum24[x];</div><div>+}</div><div>+</div><div>+static void integral_init32v(uint32_t *sum32, intptr_t stride)</div><div>+{</div><div>+    for (int x = 0; x < stride; x++)</div><div>+        sum32[x] = sum32[x + 32 * stride] - sum32[x];</div><div>+}</div><div>+</div><div> void FrameFilter::destroy()</div><div> {</div><div>     X265_FREE(m_ssimBuf);</div><div>@@ -65,6 +168,7 @@</div><div>     m_saoRowDelay = m_param->bEnableLoopFilter ? 1 : 0;</div><div>     m_lastHeight = (m_param->sourceHeight % g_maxCUSize) ? (m_param->sourceHeight % g_maxCUSize) : g_maxCUSize;</div><div>     m_lastWidth = (m_param->sourceWidth % g_maxCUSize) ? (m_param->sourceWidth % g_maxCUSize) : g_maxCUSize;</div><div>+    integralCompleted.set(0);</div><div> </div><div>     if (m_param->bEnableSsim)</div><div>         m_ssimBuf = X265_MALLOC(int, 8 * (m_param->sourceWidth / 4 + 3));</div><div>@@ -664,6 +768,107 @@</div><div>         }</div><div>     } // end of (m_param->maxSlices == 1)</div><div> </div><div>+    int lastRow = row == (int)m_frame->m_encData->m_slice->m_sps->numCuInHeight - 1;</div><div>+</div><div>+    /* generate integral planes for SEA motion search */</div><div>+    if (m_param->searchMethod == X265_SEA && m_frame->m_encData->m_meIntegral && m_frame->m_lowres.sliceType != X265_TYPE_B)</div><div>+    {</div><div>+        /* If WPP, other than first row, integral calculation for current row needs to wait till the</div><div>+        * integral for the previous row is computed */</div><div>+        if (m_param->bEnableWavefront && row)</div><div>+        {</div><div>+            while (m_parallelFilter[row - 1].m_frameFilter->integralCompleted.get() == 0)</div><div>+            {</div><div>+                m_parallelFilter[row - 1].m_frameFilter->integralCompleted.waitForChange(0);</div><div>+            }</div><div>+        }</div><div>+</div><div>+        int stride = (int)m_frame->m_reconPic->m_stride;</div><div>+        int padX = g_maxCUSize + 32;</div><div>+        int padY = g_maxCUSize + 16;</div><div>+        int numCuInHeight = m_frame->m_encData->m_slice->m_sps->numCuInHeight;</div><div>+        int maxHeight = numCuInHeight * g_maxCUSize;</div><div>+        int start = 0;</div><div>+</div><div>+        if (m_param->interlaceMode)</div><div>+            start = (row * g_maxCUSize >> 1);</div><div>+        else</div><div>+            start = row * g_maxCUSize;</div><div>+</div><div>+        int height = lastRow ? (maxHeight + g_maxCUSize * m_param->interlaceMode) : (((row + m_param->interlaceMode) * g_maxCUSize) + g_maxCUSize);</div><div>+</div><div>+        if (!row)</div><div>+        {</div><div>+            for (int i = 0; i < INTEGRAL_PLANE_NUM; i++)</div><div>+                memset(m_frame->m_encData->m_meIntegral[i] - padY * stride - padX, 0, stride * sizeof(uint32_t));</div><div>+            start = -padY;</div><div>+        }</div><div>+</div><div>+        if (lastRow)</div><div>+            height += padY - 1;</div><div>+</div><div>+        for (int y = start; y < height; y++)</div><div>+        {</div><div>+            pixel    *pix = m_frame->m_reconPic->m_picOrg[0] + y * stride - padX;</div><div>+            uint32_t *sum32x32 = m_frame->m_encData->m_meIntegral[0] + (y + 1) * stride - padX;</div><div>+            uint32_t *sum32x24 = m_frame->m_encData->m_meIntegral[1] + (y + 1) * stride - padX;</div><div>+            uint32_t *sum32x8 = m_frame->m_encData->m_meIntegral[2] + (y + 1) * stride - padX;</div><div>+            uint32_t *sum24x32 = m_frame->m_encData->m_meIntegral[3] + (y + 1) * stride - padX;</div><div>+            uint32_t *sum16x16 = m_frame->m_encData->m_meIntegral[4] + (y + 1) * stride - padX;</div><div>+            uint32_t *sum16x12 = m_frame->m_encData->m_meIntegral[5] + (y + 1) * stride - padX;</div><div>+            uint32_t *sum16x4 = m_frame->m_encData->m_meIntegral[6] + (y + 1) * stride - padX;</div><div>+            uint32_t *sum12x16 = m_frame->m_encData->m_meIntegral[7] + (y + 1) * stride - padX;</div><div>+            uint32_t *sum8x32 = m_frame->m_encData->m_meIntegral[8] + (y + 1) * stride - padX;</div><div>+            uint32_t *sum8x8 = m_frame->m_encData->m_meIntegral[9] + (y + 1) * stride - padX;</div><div>+            uint32_t *sum4x16 = m_frame->m_encData->m_meIntegral[10] + (y + 1) * stride - padX;</div><div>+            uint32_t *sum4x4 = m_frame->m_encData->m_meIntegral[11] + (y + 1) * stride - padX;</div><div>+</div><div>+            /*For width = 32 */</div><div>+            integral_init32h(sum32x32, pix, stride);</div><div>+            if (y >= 32 - padY)</div><div>+                integral_init32v(sum32x32 - 32 * stride, stride);</div><div>+            integral_init32h(sum32x24, pix, stride);</div><div>+            if (y >= 24 - padY)</div><div>+                integral_init24v(sum32x24 - 24 * stride, stride);</div><div>+            integral_init32h(sum32x8, pix, stride);</div><div>+            if (y >= 8 - padY)</div><div>+                integral_init8v(sum32x8 - 8 * stride, stride);</div><div>+            /*For width = 24 */</div><div>+            integral_init24h(sum24x32, pix, stride);</div><div>+            if (y >= 32 - padY)</div><div>+                integral_init32v(sum24x32 - 32 * stride, stride);</div><div>+            /*For width = 16 */</div><div>+            integral_init16h(sum16x16, pix, stride);</div><div>+            if (y >= 16 - padY)</div><div>+                integral_init16v(sum16x16 - 16 * stride, stride);</div><div>+            integral_init16h(sum16x12, pix, stride);</div><div>+            if (y >= 12 - padY)</div><div>+                integral_init12v(sum16x12 - 12 * stride, stride);</div><div>+            integral_init16h(sum16x4, pix, stride);</div><div>+            if (y >= 4 - padY)</div><div>+                integral_init4v(sum16x4 - 4 * stride, stride);</div><div>+            /*For width = 12 */</div><div>+            integral_init12h(sum12x16, pix, stride);</div><div>+            if (y >= 16 - padY)</div><div>+                integral_init16v(sum12x16 - 16 * stride, stride);</div><div>+            /*For width = 8 */</div><div>+            integral_init8h(sum8x32, pix, stride);</div><div>+            if (y >= 32 - padY)</div><div>+                integral_init32v(sum8x32 - 32 * stride, stride);</div><div>+            integral_init8h(sum8x8, pix, stride);</div><div>+            if (y >= 8 - padY)</div><div>+                integral_init8v(sum8x8 - 8 * stride, stride);</div><div>+            /*For width = 4 */</div><div>+            integral_init4h(sum4x16, pix, stride);</div><div>+            if (y >= 16 - padY)</div><div>+                integral_init16v(sum4x16 - 16 * stride, stride);</div><div>+            integral_init4h(sum4x4, pix, stride);</div><div>+            if (y >= 4 - padY)</div><div>+                integral_init4v(sum4x4 - 4 * stride, stride);</div><div>+        }</div><div>+        m_parallelFilter[row].m_frameFilter->integralCompleted.set(1);</div><div>+    }</div><div>+</div><div>     if (ATOMIC_INC(&m_frameEncoder->m_completionCount) == 2 * (int)m_frameEncoder->m_numRows)</div><div>     {</div><div>         m_frameEncoder->m_completionEvent.trigger();</div><div>diff -r 5d95fbd53ca3 -r f8d523976ed6 source/encoder/framefilter.h</div><div>--- a/source/encoder/framefilter.h<span class="gmail-Apple-tab-span" style="white-space:pre">      </span>Fri Nov 25 12:57:52 2016 +0530</div><div>+++ b/source/encoder/framefilter.h<span class="gmail-Apple-tab-span" style="white-space:pre">       </span>Mon Nov 28 11:35:49 2016 +0530</div><div>@@ -57,6 +57,8 @@</div><div>     int           m_lastHeight;</div><div>     int           m_lastWidth;</div><div>     </div><div>+    ThreadSafeInteger integralCompleted;     /* check if integral calculation is completed in this row */</div><div>+</div><div>     void*         m_ssimBuf;        /* Temp storage for ssim computation */</div><div> </div><div> #define MAX_PFILTER_CUS     (4) /* maximum CUs for every thread */</div><div>diff -r 5d95fbd53ca3 -r f8d523976ed6 source/encoder/motion.cpp</div><div>--- a/source/encoder/motion.cpp<span class="gmail-Apple-tab-span" style="white-space:pre">        </span>Fri Nov 25 12:57:52 2016 +0530</div><div>+++ b/source/encoder/motion.cpp<span class="gmail-Apple-tab-span" style="white-space:pre">  </span>Mon Nov 28 11:35:49 2016 +0530</div><div>@@ -109,6 +109,8 @@</div><div>     blockOffset = 0;</div><div>     bChromaSATD = false;</div><div>     chromaSatd = NULL;</div><div>+    for (int i = 0; i < INTEGRAL_PLANE_NUM; i++)</div><div>+        integral[i] = NULL;</div><div> }</div><div> </div><div> void MotionEstimate::init(int csp)</div><div>@@ -165,10 +167,12 @@</div><div>     partEnum = partitionFromSizes(pwidth, pheight);</div><div>     X265_CHECK(LUMA_4x4 != partEnum, "4x4 inter partition detected!\n");</div><div>     sad = primitives.pu[partEnum].sad;</div><div>+    ads = primitives.pu[partEnum].ads;</div><div>     satd = primitives.pu[partEnum].satd;</div><div>     sad_x3 = primitives.pu[partEnum].sad_x3;</div><div>     sad_x4 = primitives.pu[partEnum].sad_x4;</div><div> </div><div>+</div><div>     blockwidth = pwidth;</div><div>     blockOffset = offset;</div><div>     absPartIdx = ctuAddr = -1;</div><div>@@ -188,6 +192,7 @@</div><div>     partEnum = partitionFromSizes(pwidth, pheight);</div><div>     X265_CHECK(LUMA_4x4 != partEnum, "4x4 inter partition detected!\n");</div><div>     sad = primitives.pu[partEnum].sad;</div><div>+    ads = primitives.pu[partEnum].ads;</div><div>     satd = primitives.pu[partEnum].satd;</div><div>     sad_x3 = primitives.pu[partEnum].sad_x3;</div><div>     sad_x4 = primitives.pu[partEnum].sad_x4;</div><div>@@ -288,6 +293,21 @@</div><div>             COPY2_IF_LT(bcost, costs[3], bmv, omv + MV(m3x, m3y)); \</div><div>     }</div><div> </div><div>+#define COST_MV_X3_ABS( m0x, m0y, m1x, m1y, m2x, m2y )\</div><div>+{\</div><div>+    sad_x3(fenc, \</div><div>+    fref + (m0x) + (m0y) * stride, \</div><div>+    fref + (m1x) + (m1y) * stride, \</div><div>+    fref + (m2x) + (m2y) * stride, \</div><div>+    stride, costs); \</div><div>+    costs[0] += p_cost_mvx[(m0x) << 2]; /* no cost_mvy */\</div><div>+    costs[1] += p_cost_mvx[(m1x) << 2]; \</div><div>+    costs[2] += p_cost_mvx[(m2x) << 2]; \</div><div>+    COPY3_IF_LT(bcost, costs[0], bmv.x, m0x, bmv.y, m0y); \</div><div>+    COPY3_IF_LT(bcost, costs[1], bmv.x, m1x, bmv.y, m1y); \</div><div>+    COPY3_IF_LT(bcost, costs[2], bmv.x, m2x, bmv.y, m2y); \</div><div>+}</div><div>+</div><div> #define COST_MV_X4_DIR(m0x, m0y, m1x, m1y, m2x, m2y, m3x, m3y, costs) \</div><div>     { \</div><div>         pixel *pix_base = fref + bmv.x + bmv.y * stride; \</div><div>@@ -1078,6 +1098,161 @@</div><div>         break;</div><div>     }</div><div> </div><div>+    case X265_SEA:</div><div>+    {</div><div>+        // Successive Elimination Algorithm</div><div>+        const int16_t minX = X265_MAX(omv.x - (int16_t)merange, mvmin.x);</div><div>+        const int16_t minY = X265_MAX(omv.y - (int16_t)merange, mvmin.y);</div><div>+        const int16_t maxX = X265_MIN(omv.x + (int16_t)merange, mvmax.x);</div><div>+        const int16_t maxY = X265_MIN(omv.y + (int16_t)merange, mvmax.y);</div><div>+        const uint16_t *p_cost_mvx = m_cost_mvx - qmvp.x;</div><div>+        const uint16_t *p_cost_mvy = m_cost_mvy - qmvp.y;</div><div>+        int16_t* meScratchBuffer = NULL;</div><div>+        int scratchSize = merange * 2 + 4;</div><div>+        if (scratchSize)</div><div>+        {</div><div>+            meScratchBuffer = X265_MALLOC(int16_t, scratchSize);</div><div>+            memset(meScratchBuffer, 0, sizeof(int16_t)* scratchSize);</div><div>+        }</div><div>+</div><div>+        /* SEA is fastest in multiples of 4 */</div><div>+        int meRangeWidth = (maxX - minX + 3) & ~3;</div><div>+        int w = 0, h = 0;                    // Width and height of the PU</div><div>+        ALIGN_VAR_32(pixel, zero[64 * FENC_STRIDE]) = { 0 };</div><div>+        ALIGN_VAR_32(int, encDC[4]);</div><div>+        uint16_t *fpelCostMvX = m_fpelMvCosts[-qmvp.x & 3] + (-qmvp.x >> 2);</div><div>+        sizesFromPartition(partEnum, &w, &h);</div><div>+        int deltaX = (w <= 8) ? (w) : (w >> 1);</div><div>+        int deltaY = (h <= 8) ? (h) : (h >> 1);</div><div>+</div><div>+        /* Check if very small rectangular blocks which cannot be sub-divided anymore */</div><div>+        bool smallRectPartition = partEnum == LUMA_4x4 || partEnum == LUMA_16x12 ||</div><div>+            partEnum == LUMA_12x16 || partEnum == LUMA_16x4 || partEnum == LUMA_4x16;</div><div>+        /* Check if vertical partition */</div><div>+        bool verticalRect = partEnum == LUMA_32x64 || partEnum == LUMA_16x32 || partEnum == LUMA_8x16 ||</div><div>+            partEnum == LUMA_4x8;</div><div>+        /* Check if horizontal partition */</div><div>+        bool horizontalRect = partEnum == LUMA_64x32 || partEnum == LUMA_32x16 || partEnum == LUMA_16x8 ||</div><div>+            partEnum == LUMA_8x4;</div><div>+        /* Check if assymetric vertical partition */</div><div>+        bool assymetricVertical = partEnum == LUMA_12x16 || partEnum == LUMA_4x16 || partEnum == LUMA_24x32 ||</div><div>+            partEnum == LUMA_8x32 || partEnum == LUMA_48x64 || partEnum == LUMA_16x64;</div><div>+        /* Check if assymetric horizontal partition */</div><div>+        bool assymetricHorizontal = partEnum == LUMA_16x12 || partEnum == LUMA_16x4 || partEnum == LUMA_32x24 ||</div><div>+            partEnum == LUMA_32x8 || partEnum == LUMA_64x48 || partEnum == LUMA_64x16;</div><div>+</div><div>+        int tempPartEnum = 0;</div><div>+</div><div>+        /* If a vertical rectangular partition, it is horizontally split into two, for ads_x2() */</div><div>+        if (verticalRect)</div><div>+            tempPartEnum = partitionFromSizes(w, h >> 1);</div><div>+        /* If a horizontal rectangular partition, it is vertically split into two, for ads_x2() */</div><div>+        else if (horizontalRect)</div><div>+            tempPartEnum = partitionFromSizes(w >> 1, h);</div><div>+        /* We have integral planes introduced to account for assymetric partitions.</div><div>+         * Hence all assymetric partitions except those which cannot be split into legal sizes,</div><div>+         * are split into four for ads_x4() */</div><div>+        else if (assymetricVertical || assymetricHorizontal)</div><div>+            tempPartEnum = smallRectPartition ? partEnum : partitionFromSizes(w >> 1, h >> 1);</div><div>+        /* General case: Square partitions. All partitions with width > 8 are split into four</div><div>+         * for ads_x4(), for 4x4 and 8x8 we do ads_x1() */</div><div>+        else</div><div>+            tempPartEnum = (w <= 8) ? partEnum : partitionFromSizes(w >> 1, h >> 1);</div><div>+</div><div>+        /* Successive elimination by comparing DC before a full SAD,</div><div>+         * because sum(abs(diff)) >= abs(diff(sum)). */</div><div>+        primitives.pu[tempPartEnum].sad_x4(zero,</div><div>+                         fenc,</div><div>+                         fenc + deltaX,</div><div>+                         fenc + deltaY * FENC_STRIDE,</div><div>+                         fenc + deltaX + deltaY * FENC_STRIDE,</div><div>+                         FENC_STRIDE,</div><div>+                         encDC);</div><div>+</div><div>+        /* Assigning appropriate integral plane */</div><div>+        uint32_t *sumsBase = NULL;</div><div>+        switch (deltaX)</div><div>+        {</div><div>+            case 32: if (deltaY % 24 == 0)</div><div>+                         sumsBase = integral[1];</div><div>+                     else if (deltaY == 8)</div><div>+                         sumsBase = integral[2];</div><div>+                     else</div><div>+                         sumsBase = integral[0];</div><div>+               break;</div><div>+            case 24: sumsBase = integral[3];</div><div>+               break;</div><div>+            case 16: if (deltaY % 12 == 0)</div><div>+                         sumsBase = integral[5];</div><div>+                     else if (deltaY == 4)</div><div>+                         sumsBase = integral[6];</div><div>+                     else</div><div>+                         sumsBase = integral[4];</div><div>+               break;</div><div>+            case 12: sumsBase = integral[7];</div><div>+                break;</div><div>+            case 8: if (deltaY == 32)</div><div>+                        sumsBase = integral[8];</div><div>+                    else</div><div>+                        sumsBase = integral[9];</div><div>+                break;</div><div>+            case 4: if (deltaY == 16)</div><div>+                        sumsBase = integral[10];</div><div>+                    else</div><div>+                        sumsBase = integral[11];</div><div>+                break;</div><div>+            default: sumsBase = integral[11];</div><div>+                break;</div><div>+        }</div><div>+</div><div>+        if (partEnum == LUMA_64x64 || partEnum == LUMA_32x32 || partEnum == LUMA_16x16 ||</div><div>+            partEnum == LUMA_32x64 || partEnum == LUMA_16x32 || partEnum == LUMA_8x16 ||</div><div>+            partEnum == LUMA_4x8 || partEnum == LUMA_12x16 || partEnum == LUMA_4x16 ||</div><div>+            partEnum == LUMA_24x32 || partEnum == LUMA_8x32 || partEnum == LUMA_48x64 ||</div><div>+            partEnum == LUMA_16x64)</div><div>+            deltaY *= (int)stride;</div><div>+</div><div>+        if (verticalRect)</div><div>+            encDC[1] = encDC[2];</div><div>+</div><div>+        if (horizontalRect)</div><div>+            deltaY = deltaX;</div><div>+</div><div>+        /* ADS and SAD */</div><div>+        MV tmv;</div><div>+        for (tmv.y = minY; tmv.y <= maxY; tmv.y++)</div><div>+        {</div><div>+            int i, xn;</div><div>+            int ycost = p_cost_mvy[tmv.y] << 2;</div><div>+            if (bcost <= ycost)</div><div>+                continue;</div><div>+            bcost -= ycost;</div><div>+</div><div>+            /* ADS_4 for 16x16, 32x32, 64x64, 24x32, 32x24, 48x64, 64x48, 32x8, 8x32, 64x16, 16x64 partitions</div><div>+             * ADS_1 for 4x4, 8x8, 16x4, 4x16, 16x12, 12x16 partitions</div><div>+             * ADS_2 for all other rectangular partitions */</div><div>+            xn = ads(encDC,</div><div>+                    sumsBase + minX + tmv.y * stride,</div><div>+                    deltaY,</div><div>+                    fpelCostMvX + minX,</div><div>+                    meScratchBuffer,</div><div>+                    meRangeWidth,</div><div>+                    bcost);</div><div>+</div><div>+            for (i = 0; i < xn - 2; i += 3)</div><div>+                COST_MV_X3_ABS(minX + meScratchBuffer[i], tmv.y,</div><div>+                             minX + meScratchBuffer[i + 1], tmv.y,</div><div>+                             minX + meScratchBuffer[i + 2], tmv.y);</div><div>+</div><div>+            bcost += ycost;</div><div>+            for (; i < xn; i++)</div><div>+                COST_MV(minX + meScratchBuffer[i], tmv.y);</div><div>+        }</div><div>+        if (meScratchBuffer)</div><div>+            x265_free(meScratchBuffer);</div><div>+        break;</div><div>+    }</div><div>+</div><div>     case X265_FULL_SEARCH:</div><div>     {</div><div>         // dead slow exhaustive search, but at least it uses sad_x4()</div><div>diff -r 5d95fbd53ca3 -r f8d523976ed6 source/encoder/motion.h</div><div>--- a/source/encoder/motion.h<span class="gmail-Apple-tab-span" style="white-space:pre">   </span>Fri Nov 25 12:57:52 2016 +0530</div><div>+++ b/source/encoder/motion.h<span class="gmail-Apple-tab-span" style="white-space:pre">    </span>Mon Nov 28 11:35:49 2016 +0530</div><div>@@ -52,6 +52,7 @@</div><div>     pixelcmp_t sad;</div><div>     pixelcmp_x3_t sad_x3;</div><div>     pixelcmp_x4_t sad_x4;</div><div>+    pixelcmp_ads_t ads;</div><div>     pixelcmp_t satd;</div><div>     pixelcmp_t chromaSatd;</div><div> </div><div>@@ -61,6 +62,7 @@</div><div> </div><div>     static const int COST_MAX = 1 << 28;</div><div> </div><div>+    uint32_t* integral[INTEGRAL_PLANE_NUM];</div><div>     Yuv fencPUYuv;</div><div>     int partEnum;</div><div>     bool bChromaSATD;</div><div>diff -r 5d95fbd53ca3 -r f8d523976ed6 source/encoder/search.cpp</div><div>--- a/source/encoder/search.cpp<span class="gmail-Apple-tab-span" style="white-space:pre">        </span>Fri Nov 25 12:57:52 2016 +0530</div><div>+++ b/source/encoder/search.cpp<span class="gmail-Apple-tab-span" style="white-space:pre">  </span>Mon Nov 28 11:35:49 2016 +0530</div><div>@@ -2243,7 +2243,13 @@</div><div>                         if (lmv.notZero())</div><div>                             mvc[numMvc++] = lmv;</div><div>                     }</div><div>-</div><div>+                    if (m_param->searchMethod == X265_SEA)</div><div>+                    {</div><div>+                        int puX = puIdx & 1;</div><div>+                        int puY = puIdx >> 1;</div><div>+                        for (int planes = 0; planes < INTEGRAL_PLANE_NUM; planes++)</div><div>+                            m_me.integral[planes] = interMode.fencYuv->m_integral[list][ref][planes] + puX * pu.width + puY * pu.height * m_slice->m_refFrameList[list][ref]->m_reconPic->m_stride;</div><div>+                    }</div><div>                     setSearchRange(cu, mvp, m_param->searchRange, mvmin, mvmax);</div><div>                     int satdCost = m_me.motionEstimate(&slice->m_mref[list][ref], mvmin, mvmax, mvp, numMvc, mvc, m_param->searchRange, outmv, </div><div>                       m_param->bSourceReferenceEstimation ? m_slice->m_refFrameList[list][ref]->m_fencPic->getLumaAddr(0) : 0);</div><div>diff -r 5d95fbd53ca3 -r f8d523976ed6 source/test/regression-tests.txt</div><div>--- a/source/test/regression-tests.txt<span class="gmail-Apple-tab-span" style="white-space:pre">   </span>Fri Nov 25 12:57:52 2016 +0530</div><div>+++ b/source/test/regression-tests.txt<span class="gmail-Apple-tab-span" style="white-space:pre">   </span>Mon Nov 28 11:35:49 2016 +0530</div><div>@@ -149,4 +149,7 @@</div><div> CrowdRun_1920x1080_50_10bit_422.yuv,--preset faster --interlace tff</div><div> CrowdRun_1920x1080_50_10bit_422.yuv,--preset fast --interlace bff</div><div> </div><div>+#SEA Implementation Test</div><div>+silent_cif_420.y4m,--preset veryslow --me 4</div><div>+big_buck_bunny_360p24.y4m,--preset superfast --me 4</div><div> # vim: tw=200</div><div>diff -r 5d95fbd53ca3 -r f8d523976ed6 source/x265.h</div><div>--- a/source/x265.h<span class="gmail-Apple-tab-span" style="white-space:pre">        </span>Fri Nov 25 12:57:52 2016 +0530</div><div>+++ b/source/x265.h<span class="gmail-Apple-tab-span" style="white-space:pre">      </span>Mon Nov 28 11:35:49 2016 +0530</div><div>@@ -290,6 +290,7 @@</div><div>     X265_HEX_SEARCH,</div><div>     X265_UMH_SEARCH,</div><div>     X265_STAR_SEARCH,</div><div>+    X265_SEA,</div><div>     X265_FULL_SEARCH</div><div> } X265_ME_METHODS;</div><div> </div><div>@@ -464,7 +465,7 @@</div><div> } x265_stats;</div><div> </div><div> /* String values accepted by x265_param_parse() (and CLI) for various parameters */</div><div>-static const char * const x265_motion_est_names[] = { "dia", "hex", "umh", "star", "full", 0 };</div><div>+static const char * const x265_motion_est_names[] = { "dia", "hex", "umh", "star", "sea", "full", 0 };</div><div> static const char * const x265_source_csp_names[] = { "i400", "i420", "i422", "i444", "nv12", "nv16", 0 };</div><div> static const char * const x265_video_format_names[] = { "component", "pal", "ntsc", "secam", "mac", "undef", 0 };</div><div> static const char * const x265_fullrange_names[] = { "limited", "full", 0 };</div><div>@@ -910,9 +911,9 @@</div><div>     /* Limit modes analyzed for each CU using cost metrics from the 4 sub-CUs */</div><div>     uint32_t limitModes;</div><div> </div><div>-    /* ME search method (DIA, HEX, UMH, STAR, FULL). The search patterns</div><div>+    /* ME search method (DIA, HEX, UMH, STAR, SEA, FULL). The search patterns</div><div>      * (methods) are sorted in increasing complexity, with diamond being the</div><div>-     * simplest and fastest and full being the slowest.  DIA, HEX, and UMH were</div><div>+     * simplest and fastest and full being the slowest.  DIA, HEX, UMH and SEA were</div><div>      * adapted from x264 directly. STAR is an adaption of the HEVC reference</div><div>      * encoder's three step search, while full is a naive exhaustive search. The</div><div>      * default is the star search, it has a good balance of performance and</div>
</div>