<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Fri, Oct 18, 2013 at 5:43 AM, Deepthi Devaki Akkoorath <span dir="ltr"><<a href="mailto:deepthidevaki@multicorewareinc.com" target="_blank">deepthidevaki@multicorewareinc.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote"><div><div class="h5">On Fri, Oct 18, 2013 at 5:22 AM, Steve Borho <span dir="ltr"><<a href="mailto:steve@borho.org" target="_blank">steve@borho.org</a>></span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote"><div>On Thu, Oct 17, 2013 at 5:39 AM,  <span dir="ltr"><<a href="mailto:deepthidevaki@multicorewareinc.com" target="_blank">deepthidevaki@multicorewareinc.com</a>></span> wrote:<br>


<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"># HG changeset patch<br>
# User Deepthi Devaki <<a href="mailto:deepthidevaki@multicorewareinc.com" target="_blank">deepthidevaki@multicorewareinc.com</a>><br>
# Date 1382006045 -19800<br>
# Node ID 677d71fd793959c7e98df56f99f0b02a89fe050d<br>
# Parent  fc9dbd798ac37ec1acc0596aa179f0deb586c092<br>
Lookahead: Implement wavefront parallel processing<br></blockquote><div><br></div></div><div>this looks good; I think you have the general idea down.  It can be simplified a great deal, comments below</div><div>
<div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">

diff -r fc9dbd798ac3 -r 677d71fd7939 source/common/wavefront.h<br>
--- a/source/common/wavefront.h Thu Oct 17 14:14:40 2013 +0530<br>
+++ b/source/common/wavefront.h Thu Oct 17 16:04:05 2013 +0530<br>
@@ -47,11 +47,6 @@<br>
<br>
     int m_numRows;<br>
<br>
-    // WaveFront's implementation of JobProvider::findJob. Consults<br>
-    // m_queuedBitmap and calls ProcessRow(row) for lowest numbered queued row<br>
-    // or returns false<br>
-    bool findJob();<br>
-<br>
 public:<br>
<br>
     WaveFront(ThreadPool *pool) : JobProvider(pool), m_queuedBitmap(0) {}<br>
@@ -69,6 +64,11 @@<br>
<br>
     void clearEnabledRowMask();<br>
<br>
+    // WaveFront's implementation of JobProvider::findJob. Consults<br>
+    // m_queuedBitmap and calls ProcessRow(row) for lowest numbered queued row<br>
+    // or returns false<br>
+    bool findJob();<br>
+<br></blockquote><div><br></div></div><div>I think this is unnecessary if you refer to your own findJob() method (this->findJob())</div><div><div> </div></div></div></div></div></blockquote><div><br></div>
</div></div><div>Do you mean to write separate findJob() for Lookahead? But then it will be a replica of Wavefront::findjob()</div></div></div></div></blockquote><div><br></div><div>I was confused and thought you were defining your own findJob(); disregard this comment</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div><div class="h5"><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">



     // Returns true if a row above curRow is available for processing.  The processRow()<br>
     // method may call this function periodically and voluntarily exit<br>
     bool checkHigherPriorityRow(int curRow);<br>
diff -r fc9dbd798ac3 -r 677d71fd7939 source/encoder/encoder.cpp<br>
--- a/source/encoder/encoder.cpp        Thu Oct 17 14:14:40 2013 +0530<br>
+++ b/source/encoder/encoder.cpp        Thu Oct 17 16:04:05 2013 +0530<br>
@@ -92,6 +92,7 @@<br>
         }<br>
     }<br>
     m_lookahead = new Lookahead(this);<br>
+    m_lookahead->setThreadPool(m_threadPool);<br>
     m_dpb = new DPB(this);<br>
     m_rateControl = new RateControl(this);<br>
 }<br>
@@ -144,6 +145,7 @@<br>
             m_frameEncoder[i].init(this, numRows);<br>
         }<br>
     }<br>
+    m_lookahead->init();<br>
 }<br>
<br>
 int Encoder::getStreamHeaders(NALUnitEBSP **nalunits)<br>
diff -r fc9dbd798ac3 -r 677d71fd7939 source/encoder/slicetype.cpp<br>
--- a/source/encoder/slicetype.cpp      Thu Oct 17 14:14:40 2013 +0530<br>
+++ b/source/encoder/slicetype.cpp      Thu Oct 17 16:04:05 2013 +0530<br>
@@ -62,29 +62,67 @@<br>
     dst.y = median(a.y, b.y, c.y);<br>
 }<br>
<br>
-Lookahead::Lookahead(TEncCfg *_cfg)<br>
+Lookahead::Lookahead(TEncCfg *_cfg) : WaveFront(NULL)<br></blockquote><div><br></div></div><div>Pass the thread pool pointer as a second argument and initialize WaveFront with it; then you don't need the setThreadPool() method</div>

<div><div>
<div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
 {<br>
     this->cfg = _cfg;<br>
     numDecided = 0;<br>
     lastKeyframe = -cfg->param.keyframeMax;<br>
     lastNonB = NULL;<br>
-    predictions = (pixel*)X265_MALLOC(pixel, 35 * 8 * 8);<br>
-    me.setQP(X265_LOOKAHEAD_QP);<br>
-    me.setSearchMethod(X265_HEX_SEARCH);<br>
-    me.setSubpelRefine(1);<br>
     merange = 16;<br>
     widthInCU = ((cfg->param.sourceWidth / 2) + X265_LOWRES_CU_SIZE - 1) >> X265_LOWRES_CU_BITS;<br>
     heightInCU = ((cfg->param.sourceHeight / 2) + X265_LOWRES_CU_SIZE - 1) >> X265_LOWRES_CU_BITS;<br>
+<br>
+    lock = new Lock[heightInCU];<br>
+    rowme = new MotionEstimate[heightInCU];<br>
+<br>
+    active = (bool*)X265_MALLOC(bool, heightInCU);<br>
+    completed = (uint32_t*)X265_MALLOC(uint32_t, heightInCU);<br>
+    rowpredictions = (pixel**)X265_MALLOC(pixel*, heightInCU);<br>
+    rowcostEst = (int*)X265_MALLOC(int, heightInCU);<br>
+    rowcostIntra = (int*)X265_MALLOC(int, heightInCU);<br>
+    rowIntraMbs = (int*)X265_MALLOC(int, heightInCU);<br>
+    for (int i = 0; i < heightInCU; i++)<br>
+    {<br>
+        rowme[i].setQP(X265_LOOKAHEAD_QP);<br>
+        rowme[i].setSearchMethod(X265_HEX_SEARCH);<br>
+        rowme[i].setSubpelRefine(1);<br>
+        rowpredictions[i] = (pixel*)X265_MALLOC(pixel, 35 * 8 * 8);<br>
+        rowcostEst[i] = 0;<br>
+        rowcostIntra[i] = 0;<br>
+        rowIntraMbs[i] = 0;<br>
+    }<br></blockquote><div><br></div></div></div><div>This would be much cleaner as a per-row struct similar to CTURow (LookaheadRow?)</div><div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">



 }<br>
<br>
 Lookahead::~Lookahead()<br>
 {<br>
 }<br>
<br>
+void Lookahead::init()<br>
+{<br>
+    if (!WaveFront::init(heightInCU))<br>
+    {<br>
+        m_pool = NULL;<br>
+    }<br>
+    memset((void*)completed, 0, heightInCU * sizeof(uint32_t));<br>
+    memset((void*)active, 0, heightInCU * sizeof(bool));<br></blockquote><div><br></div></div><div>these memsets are unnecessary</div><div><div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">



+}<br>
+<br>
 void Lookahead::destroy()<br>
 {<br>
-    if (predictions)<br>
-        X265_FREE(predictions);<br>
+    delete[] lock;<br>
+    delete[] rowme;<br>
+<br>
+    X265_FREE((void*)active);<br>
+    X265_FREE((void*)completed);<br>
+    for (int i = 0; i < heightInCU; i++)<br>
+    {<br>
+        X265_FREE(rowpredictions[i]);<br>
+    }<br>
+<br>
+    X265_FREE(rowpredictions);<br>
+    X265_FREE(rowcostEst);<br>
+    X265_FREE(rowcostIntra);<br>
+    X265_FREE(rowIntraMbs);<br>
<br>
     // these two queues will be empty, unless the encode was aborted<br>
     while (!inputQueue.empty())<br>
@@ -165,9 +203,12 @@<br>
 int Lookahead::estimateFrameCost(int p0, int p1, int b, bool bIntraPenalty)<br>
 {<br>
     int score = 0;<br>
-    bool bDoSearch[2];<br>
     Lowres *fenc = frames[b];<br>
<br>
+    curb = b;<br>
+    curp0 = p0;<br>
+    curp1 = p1;<br>
+<br>
     if (fenc->costEst[b - p0][p1 - b] >= 0 && fenc->rowSatds[b - p0][p1 - b][0] != -1)<br>
         score = fenc->costEst[b - p0][p1 - b];<br>
     else<br>
@@ -185,23 +226,58 @@<br>
          * predictors in the main encode.  This considerably improves MV<br>
          * prediction overall. */<br>
         // TODO: use lowres MVs as motion candidates in full-res search<br>
-        me.setSourcePlane(fenc->lowresPlane[0], fenc->lumaStride);<br>
-        for (int j = heightInCU - 1; j >= 0; j--)<br>
+<br>
+        for (int i = 0; i < heightInCU; i++)<br>
         {<br>
-            if (!fenc->bIntraCalculated)<br>
-                fenc->rowSatds[0][0][j] = 0;<br>
-            fenc->rowSatds[b - p0][p1 - b][j] = 0;<br>
+            rowme[i].setSourcePlane(fenc->lowresPlane[0], fenc->lumaStride);<br>
+        }<br>
<br>
-            for (int i = widthInCU - 1; i >= 0; i--)<br>
+        memset((void*)completed, 0, heightInCU * sizeof(uint32_t));<br>
+        memset((void*)active, 0, heightInCU * sizeof(bool));<br>
+        memset((void*)rowcostEst, 0, heightInCU * sizeof(int));<br>
+        memset((void*)rowcostIntra, 0, heightInCU * sizeof(int));<br>
+        memset((void*)rowIntraMbs, 0, heightInCU * sizeof(int));<br>
+        rowsCompleted = false;<br>
+<br>
+        if (m_pool && cfg->param.bEnableWavefront)<br></blockquote><div><br></div></div></div><div>checking bEnableWavefront is unnecessary here; we can always use wave-front lookahead scheduling so long as we have a thread pool.</div>


<div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+        {<br>
+            WaveFront::clearEnabledRowMask();<br></blockquote><div><br></div><div>We need another method which just sets the enabledRowMask to all 1s because it's only purpose is to track reference frame dependencies and we have none here.</div>

<div>
<div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+            WaveFront::enqueue();<br>
+<br>
+            for (int row = 0; row < heightInCU; row++)<br>
             {<br>
-                estimateCUCost(i, j, p0, p1, b, bDoSearch);<br>
+                enableRow(row);<br>
+                if (row == 0)<br>
+                    enqueueRow(0);<br>
+                else<br>
+                    m_pool->pokeIdleThread();<br>
+            }<br></blockquote><div><br></div></div><div>this whole loop is unnecessary (no frame dependencies), just use equeueRow(0)</div><div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">



+<br>
+            while (!rowsCompleted)<br>
+            {<br>
+                WaveFront::findJob();<br>
+            }<br>
+<br>
+            WaveFront::dequeue();<br>
+        }<br>
+        else<br>
+        {<br>
+            for (int row = 0; row < heightInCU; row++)<br>
+            {<br>
+                processRow(row);<br>
             }<br>
         }<br>
<br>
+        //Accumulate cost from each row<br></blockquote></div><div>nit: space after // </div><div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">



+        for (int row = 0; row < heightInCU; row++)<br>
+        {<br>
+            score += rowcostEst[row];<br>
+            fenc->costEst[0][0] += rowcostIntra[row];<br>
+            fenc->intraMbs[b - p0] += rowIntraMbs[row];<br></blockquote><div><br></div></div><div>score must be saved in fenc->costEst[b - p0][p1 - b];</div><div><div> </div></div></div></div></div></blockquote>
<div><br></div></div></div><div>Yes. It is stored later.</div><div><div class="h5"><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra">
<div class="gmail_quote">
<div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">

+        }<br>
+<br>
         fenc->bIntraCalculated = true;<br>
<br>
-        score = fenc->costEst[b - p0][p1 - b];<br>
-<br>
         if (b != p1)<br>
             score = (uint64_t)score * 100 / (130 + cfg->param.bFrameBias);<br>
<br>
@@ -218,7 +294,7 @@<br>
     return score;<br>
 }<br>
<br>
-void Lookahead::estimateCUCost(int cux, int cuy, int p0, int p1, int b, bool bDoSearch[2])<br>
+void Lookahead::estimateCUCost(int cux, int cuy, int p0, int p1, int b, bool bDoSearch[2], int row)<br></blockquote><div><br></div></div><div>perhaps this would be cleaner if it were a method of LookaheadRow</div><div> </div>


<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div><div>
 {<br>
     Lowres *fref0 = frames[p0];<br>
     Lowres *fref1 = frames[p1];<br>
@@ -233,7 +309,7 @@<br>
     const bool bFrameScoreCU = (cux > 0 && cux < widthInCU - 1 &&<br>
                                 cuy > 0 && cuy < heightInCU - 1) || widthInCU <= 2 || heightInCU <= 2;<br>
<br>
-    me.setSourcePU(pelOffset, cuSize, cuSize);<br>
+    rowme[row].setSourcePU(pelOffset, cuSize, cuSize);<br>
<br>
     MV(*fenc_mvs[2]) = { &fenc->lowresMvs[0][b - p0 - 1][cuXY],<br>
                          &fenc->lowresMvs[1][p1 - b - 1][cuXY] };<br>
@@ -241,7 +317,7 @@<br>
                             &fenc->lowresMvCosts[1][p1 - b - 1][cuXY] };<br>
<br>
     MV mvmin, mvmax;<br>
-    int bcost = me.COST_MAX;<br>
+    int bcost = rowme[row].COST_MAX;<br>
     int listused = 0;<br>
<br>
     // establish search bounds that don't cross extended frame boundaries<br>
@@ -286,7 +362,7 @@<br>
                 median_mv(mvp, mvc[0], mvc[1], mvc[2]);<br>
             }<br>
<br>
-            *fenc_costs[i] = me.motionEstimate(i ? fref1 : fref0, mvmin, mvmax, mvp, numc, mvc, merange, *fenc_mvs[i]);<br>
+            *fenc_costs[i] = rowme[row].motionEstimate(i ? fref1 : fref0, mvmin, mvmax, mvp, numc, mvc, merange, *fenc_mvs[i]);<br>
             COPY2_IF_LT(bcost, *fenc_costs[i], listused, i + 1);<br>
         }<br>
         if (bBidir)<br>
@@ -388,23 +464,23 @@<br>
         int predsize = cuSize * cuSize;<br>
<br>
         // generate 35 intra predictions into tmp<br>
-        primitives.intra_pred_dc(pAbove0 + 1, pLeft0 + 1, predictions, cuSize, cuSize, (cuSize <= 16));<br>
+        primitives.intra_pred_dc(pAbove0 + 1, pLeft0 + 1, rowpredictions[row], cuSize, cuSize, (cuSize <= 16));<br>
         pixel *above = (cuSize >= 8) ? pAbove1 : pAbove0;<br>
         pixel *left  = (cuSize >= 8) ? pLeft1 : pLeft0;<br>
-        primitives.intra_pred_planar((pixel*)above + 1, (pixel*)left + 1, predictions + predsize, cuSize, cuSize);<br>
-        primitives.intra_pred_allangs[nLog2SizeMinus2](predictions + 2 * predsize, pAbove0, pLeft0, pAbove1, pLeft1, (cuSize <= 16));<br>
+        primitives.intra_pred_planar((pixel*)above + 1, (pixel*)left + 1, rowpredictions[row] + predsize, cuSize, cuSize);<br>
+        primitives.intra_pred_allangs[nLog2SizeMinus2](rowpredictions[row] + 2 * predsize, pAbove0, pLeft0, pAbove1, pLeft1, (cuSize <= 16));<br>
<br>
         // calculate 35 satd costs, keep least cost<br>
         ALIGN_VAR_32(pixel, buf_trans[32 * 32]);<br>
-        primitives.transpose[nLog2SizeMinus2](buf_trans, me.fenc, FENC_STRIDE);<br>
+        primitives.transpose[nLog2SizeMinus2](buf_trans, rowme[row].fenc, FENC_STRIDE);<br>
         pixelcmp_t satd = primitives.satd[PartitionFromSizes(cuSize, cuSize)];<br>
-        int icost = me.COST_MAX, cost;<br>
+        int icost = rowme[row].COST_MAX, cost;<br>
         for (UInt mode = 0; mode < 35; mode++)<br>
         {<br>
             if ((mode >= 2) && (mode < 18))<br>
-                cost = satd(buf_trans, cuSize, &predictions[mode * predsize], cuSize);<br>
+                cost = satd(buf_trans, cuSize, &rowpredictions[row][mode * predsize], cuSize);<br>
             else<br>
-                cost = satd(me.fenc, FENC_STRIDE, &predictions[mode * predsize], cuSize);<br>
+                cost = satd(rowme[row].fenc, FENC_STRIDE, &rowpredictions[row][mode * predsize], cuSize);<br>
             if (cost < icost)<br>
                 icost = cost;<br>
         }<br>
@@ -412,14 +488,14 @@<br>
         // TOOD: i_icost += intra_penalty + lowres_penalty;<br>
         fenc->intraCost[cuXY] = icost;<br>
         fenc->rowSatds[0][0][cuy] += icost;<br>
-        if (bFrameScoreCU) fenc->costEst[0][0] += icost;<br>
+        if (bFrameScoreCU) rowcostIntra[row] += icost;<br>
     }<br>
<br>
     if (!bBidir)<br>
     {<br>
         if (fenc->intraCost[cuXY] < bcost)<br>
         {<br>
-            if (bFrameScoreCU) fenc->intraMbs[b - p0]++;<br>
+            if (bFrameScoreCU) rowIntraMbs[row]++;<br>
             bcost = fenc->intraCost[cuXY];<br>
             listused = 0;<br>
         }<br>
@@ -429,7 +505,7 @@<br>
     if (p0 != p1)<br>
     {<br>
         fenc->rowSatds[b - p0][p1 - b][cuy] += bcost;<br>
-        if (bFrameScoreCU) fenc->costEst[b - p0][p1 - b] += bcost;<br>
+        if (bFrameScoreCU) rowcostEst[row] += bcost;<br>
     }<br>
     fenc->lowresCosts[b - p0][p1 - b][cuXY] = (uint16_t)(X265_MIN(bcost, LOWRES_COST_MASK) | (listused << LOWRES_COST_SHIFT));<br>
 }<br>
@@ -547,6 +623,7 @@<br>
             {<br>
                 frames[i + 1] = &list[i]->m_lowres;<br>
             }<br>
+<br>
             if (IS_X265_TYPE_I(frames[bframes + 1]->sliceType))<br>
                 p0 = bframes + 1;<br>
             else // P<br>
@@ -914,7 +991,7 @@<br>
 {<br>
     char paths[2][X265_LOOKAHEAD_MAX + 1];<br>
     int num_paths = X265_MIN(cfg->param.bframes + 1, length);<br>
-    int best_cost = me.COST_MAX;<br>
+    int best_cost = rowme[0].COST_MAX;<br>
     int idx = 0;<br>
<br>
     /* Iterate over all currently possible paths */<br>
@@ -993,3 +1070,41 @@<br>
<br>
     return cost;<br>
 }<br>
+<br>
+void Lookahead::processRow(int row)<br>
+{<br>
+    int realrow = heightInCU - 1 - row;<br>
+    Lowres *fenc = frames[curb];<br>
+<br>
+    if (!fenc->bIntraCalculated)<br>
+        fenc->rowSatds[0][0][realrow] = 0;<br>
+    fenc->rowSatds[curb - curp0][curp1 - curb][realrow] = 0;<br>
+    for (int i = widthInCU - 1 - completed[row]; i >= 0; i--) //Go backwards<br>
+    {<br>
+        estimateCUCost(i, realrow, curp0, curp1, curb, bDoSearch, row);<br>
+        completed[row]++;<br>
+<br>
+        if (completed[row] >= 2 && row < heightInCU - 1)<br>
+        {<br>
+            ScopedLock below(lock[row + 1]);<br>
+            if (active[row + 1] == false &&<br>
+                completed[row + 1] + 2 <= completed[row])<br>
+            {<br>
+                active[row + 1] = true;<br>
+                enqueueRow(row + 1);<br>
+            }<br>
+        }<br>
+<br>
+        ScopedLock self(lock[row]);<br>
+        if (row > 0 && (int32_t)completed[row] < widthInCU - 1 && completed[row - 1] < completed[row] + 2)<br>
+        {<br>
+            active[row] = false;<br>
+            return;<br>
+        }<br>
+    }<br>
+<br>
+    if (row == heightInCU - 1)<br>
+    {<br>
+        rowsCompleted = true;<br>
+    }<br>
+}<br>
diff -r fc9dbd798ac3 -r 677d71fd7939 source/encoder/slicetype.h<br>
--- a/source/encoder/slicetype.h        Thu Oct 17 14:14:40 2013 +0530<br>
+++ b/source/encoder/slicetype.h        Thu Oct 17 16:04:05 2013 +0530<br>
@@ -26,7 +26,7 @@<br>
<br>
 #include "motion.h"<br>
 #include "piclist.h"<br>
-#include "common.h"<br>
+#include "wavefront.h"<br>
<br>
 namespace x265 {<br>
 // private namespace<br>
@@ -35,11 +35,9 @@<br>
 class TComPic;<br>
 class TEncCfg;<br>
<br>
-struct Lookahead<br>
+struct Lookahead : public WaveFront<br>
 {<br>
-    MotionEstimate   me;<br>
     TEncCfg         *cfg;<br>
-    pixel           *predictions;   // buffer for 35 intra predictions<br>
     Lowres          *frames[X265_LOOKAHEAD_MAX];<br>
     Lowres          *lastNonB;<br>
     int              merange;<br>
@@ -51,9 +49,24 @@<br>
     PicList inputQueue;  // input pictures in order received<br>
     PicList outputQueue; // pictures to be encoded, in encode order<br>
<br>
+    bool bDoSearch[2];<br>
+    int curb, curp0, curp1;<br>
+    bool rowsCompleted;<br>
+<br>
+    //For wavefront parallelism<br>
+    Lock*                lock;<br>
+    volatile bool*       active;<br>
+    volatile uint32_t*   completed;<br>
+    pixel**              rowpredictions;    // buffer for 35 intra predictions<br>
+    MotionEstimate*      rowme;<br>
+    int*                 rowcostEst;<br>
+    int*                 rowcostIntra;<br>
+    int*                 rowIntraMbs;<br>
+<br>
     Lookahead(TEncCfg *);<br>
     ~Lookahead();<br>
<br>
+    void init();<br>
     void addPicture(TComPic*, int sliceType);<br>
     void flush();<br>
     void destroy();<br>
@@ -61,13 +74,15 @@<br>
     int getEstimatedPictureCost(TComPic *pic);<br>
<br>
     int estimateFrameCost(int p0, int p1, int b, bool bIntraPenalty);<br>
-    void estimateCUCost(int cux, int cuy, int p0, int p1, int b, bool bDoSearch[2]);<br>
+    void estimateCUCost(int cux, int cuy, int p0, int p1, int b, bool bDoSearch[2], int row);<br>
<br>
     void slicetypeAnalyse(bool bKeyframe);<br>
     int scenecut(int p0, int p1, bool bRealScenecut, int numFrames, int maxSearch);<br>
     int scenecutInternal(int p0, int p1, bool bRealScenecut);<br>
     void slicetypePath(int length, char(*best_paths)[X265_LOOKAHEAD_MAX + 1]);<br>
     int slicetypePathCost(char *path, int threshold);<br>
+<br>
+    void processRow(int row);<br>
 };<br>
 }<br>
<br></div></div>
_______________________________________________<br>
x265-devel mailing list<br>
<a href="mailto:x265-devel@videolan.org" target="_blank">x265-devel@videolan.org</a><br>
<a href="https://mailman.videolan.org/listinfo/x265-devel" target="_blank">https://mailman.videolan.org/listinfo/x265-devel</a><span><font color="#888888"><br>
</font></span></blockquote></div><span><font color="#888888"><br><br clear="all"><div><br></div>-- <br>Steve Borho
</font></span></div></div>
<br>_______________________________________________<br>
x265-devel mailing list<br>
<a href="mailto:x265-devel@videolan.org" target="_blank">x265-devel@videolan.org</a><br>
<a href="https://mailman.videolan.org/listinfo/x265-devel" target="_blank">https://mailman.videolan.org/listinfo/x265-devel</a><br>
<br></blockquote></div></div></div><br></div></div>
<br>_______________________________________________<br>
x265-devel mailing list<br>
<a href="mailto:x265-devel@videolan.org">x265-devel@videolan.org</a><br>
<a href="https://mailman.videolan.org/listinfo/x265-devel" target="_blank">https://mailman.videolan.org/listinfo/x265-devel</a><br>
<br></blockquote></div><br><br clear="all"><div><br></div>-- <br>Steve Borho
</div></div>