Ticket #84: InterSearch.cpp

File InterSearch.cpp, 177.4 KB (added by yuwenhe, 6 years ago)

bug fix in "AFFINE_ENC_BUGFIX"

Line 
1/* The copyright in this software is being made available under the BSD
2 * License, included below. This software may be subject to other third party
3 * and contributor rights, including patent rights, and no such rights are
4 * granted under this license.
5 *
6 * Copyright (c) 2010-2018, ITU/ISO/IEC
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
11 *
12 *  * Redistributions of source code must retain the above copyright notice,
13 *    this list of conditions and the following disclaimer.
14 *  * Redistributions in binary form must reproduce the above copyright notice,
15 *    this list of conditions and the following disclaimer in the documentation
16 *    and/or other materials provided with the distribution.
17 *  * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
18 *    be used to endorse or promote products derived from this software without
19 *    specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
31 * THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34/** \file     EncSearch.cpp
35 *  \brief    encoder inter search class
36 */
37
38#include "InterSearch.h"
39
40
41#include "CommonLib/CommonDef.h"
42#include "CommonLib/Rom.h"
43#include "CommonLib/MotionInfo.h"
44#include "CommonLib/Picture.h"
45#include "CommonLib/UnitTools.h"
46#include "CommonLib/dtrace_next.h"
47#include "CommonLib/dtrace_buffer.h"
48#if JEM_TOOLS
49#include "CommonLib/BilateralFilter.h"
50#endif
51
52#include "EncModeCtrl.h"
53#include "EncLib.h"
54
55#include <math.h>
56#include <limits>
57
58
59 //! \ingroup EncoderLib
60 //! \{
61
62static const Mv s_acMvRefineH[9] =
63{
64  Mv(  0,  0 ), // 0
65  Mv(  0, -1 ), // 1
66  Mv(  0,  1 ), // 2
67  Mv( -1,  0 ), // 3
68  Mv(  1,  0 ), // 4
69  Mv( -1, -1 ), // 5
70  Mv(  1, -1 ), // 6
71  Mv( -1,  1 ), // 7
72  Mv(  1,  1 )  // 8
73};
74
75static const Mv s_acMvRefineQ[9] =
76{
77  Mv(  0,  0 ), // 0
78  Mv(  0, -1 ), // 1
79  Mv(  0,  1 ), // 2
80  Mv( -1, -1 ), // 5
81  Mv(  1, -1 ), // 6
82  Mv( -1,  0 ), // 3
83  Mv(  1,  0 ), // 4
84  Mv( -1,  1 ), // 7
85  Mv(  1,  1 )  // 8
86};
87
88
89InterSearch::InterSearch()
90  : m_modeCtrl                    (nullptr)
91  , m_pSplitCS                    (nullptr)
92  , m_pFullCS                     (nullptr)
93  , m_pcEncCfg                    (nullptr)
94  , m_pcTrQuant                   (nullptr)
95#if JEM_TOOLS
96  , m_bilateralFilter             (nullptr)
97#endif
98  , m_iSearchRange                (0)
99  , m_bipredSearchRange           (0)
100  , m_motionEstimationSearchMethod(MESEARCH_FULL)
101  , m_CABACEstimator              (nullptr)
102  , m_CtxCache                    (nullptr)
103  , m_pTempPel                    (nullptr)
104  , m_isInitialized               (false)
105{
106  for (int i=0; i<MAX_NUM_REF_LIST_ADAPT_SR; i++)
107  {
108    memset (m_aaiAdaptSR[i], 0, MAX_IDX_ADAPT_SR * sizeof (int));
109  }
110  for (int i=0; i<AMVP_MAX_NUM_CANDS+1; i++)
111  {
112    memset (m_auiMVPIdxCost[i], 0, (AMVP_MAX_NUM_CANDS+1) * sizeof (uint32_t) );
113  }
114
115  setWpScalingDistParam( -1, REF_PIC_LIST_X, nullptr );
116}
117
118
119void InterSearch::destroy()
120{
121  CHECK(!m_isInitialized, "Not initialized");
122  if ( m_pTempPel )
123  {
124    delete [] m_pTempPel;
125    m_pTempPel = NULL;
126  }
127
128  m_pSplitCS = m_pFullCS = nullptr;
129
130  m_pSaveCS = nullptr;
131
132  for(uint32_t i = 0; i < NUM_REF_PIC_LIST_01; i++)
133  {
134    m_tmpPredStorage[i].destroy();
135  }
136  m_tmpStorageLCU.destroy();
137  m_tmpAffiStorage.destroy();
138
139  if ( m_tmpAffiError != NULL )
140  {
141    delete[] m_tmpAffiError;
142  }
143  if ( m_tmpAffiDeri[0] != NULL )
144  {
145    delete[] m_tmpAffiDeri[0];
146  }
147  if ( m_tmpAffiDeri[1] != NULL )
148  {
149    delete[] m_tmpAffiDeri[1];
150  }
151#if JEM_TOOLS
152  m_obmcOrgMod.destroy();
153#endif
154  m_isInitialized = false;
155}
156
157void InterSearch::setTempBuffers( CodingStructure ****pSplitCS, CodingStructure ****pFullCS, CodingStructure **pSaveCS )
158{
159  m_pSplitCS = pSplitCS;
160  m_pFullCS  = pFullCS;
161  m_pSaveCS  = pSaveCS;
162}
163
164#if ENABLE_SPLIT_PARALLELISM
165void InterSearch::copyState( const InterSearch& other )
166{
167  if( !m_pcEncCfg->getQTBT() )
168  {
169    memcpy( m_integerMv2Nx2N, other.m_integerMv2Nx2N, sizeof( m_integerMv2Nx2N ) );
170  }
171
172  memcpy( m_aaiAdaptSR, other.m_aaiAdaptSR, sizeof( m_aaiAdaptSR ) );
173}
174#endif
175
176InterSearch::~InterSearch()
177{
178  if (m_isInitialized)
179  {
180    destroy();
181  }
182}
183
184void InterSearch::init( EncCfg*        pcEncCfg,
185                        TrQuant*       pcTrQuant,
186#if JEM_TOOLS
187                        BilateralFilter*
188                                       bilateralFilter,
189#endif
190                        int            iSearchRange,
191                        int            bipredSearchRange,
192                        MESearchMethod motionEstimationSearchMethod,
193                        const uint32_t     maxCUWidth,
194                        const uint32_t     maxCUHeight,
195                        const uint32_t     maxTotalCUDepth,
196                        RdCost*        pcRdCost,
197                        CABACWriter*   CABACEstimator,
198                        CtxCache*      ctxCache
199)
200{
201  CHECK(m_isInitialized, "Already initialized");
202  m_pcEncCfg                     = pcEncCfg;
203  m_pcTrQuant                    = pcTrQuant;
204#if JEM_TOOLS
205  m_bilateralFilter              = bilateralFilter;
206#endif
207  m_iSearchRange                 = iSearchRange;
208  m_bipredSearchRange            = bipredSearchRange;
209  m_motionEstimationSearchMethod = motionEstimationSearchMethod;
210  m_CABACEstimator               = CABACEstimator;
211  m_CtxCache                     = ctxCache;
212
213  for( uint32_t iDir = 0; iDir < MAX_NUM_REF_LIST_ADAPT_SR; iDir++ )
214  {
215    for( uint32_t iRefIdx = 0; iRefIdx < MAX_IDX_ADAPT_SR; iRefIdx++ )
216    {
217      m_aaiAdaptSR[iDir][iRefIdx] = iSearchRange;
218    }
219  }
220
221  // initialize motion cost
222  for( int iNum = 0; iNum < AMVP_MAX_NUM_CANDS + 1; iNum++ )
223  {
224    for( int iIdx = 0; iIdx < AMVP_MAX_NUM_CANDS; iIdx++ )
225    {
226      if( iIdx < iNum )
227      {
228        m_auiMVPIdxCost[iIdx][iNum] = xGetMvpIdxBits( iIdx, iNum );
229      }
230      else
231      {
232#if DISTORTION_TYPE_BUGFIX
233        m_auiMVPIdxCost[iIdx][iNum] = MAX_UINT;
234#else
235        m_auiMVPIdxCost[iIdx][iNum] = MAX_INT;
236#endif
237      }
238    }
239  }
240
241  const ChromaFormat cform = pcEncCfg->getChromaFormatIdc();
242  InterPrediction::init( pcRdCost, cform );
243
244  for( uint32_t i = 0; i < NUM_REF_PIC_LIST_01; i++ )
245  {
246    m_tmpPredStorage[i].create( UnitArea( cform, Area( 0, 0, MAX_CU_SIZE, MAX_CU_SIZE ) ) );
247  }
248  m_tmpStorageLCU.create( UnitArea( cform, Area( 0, 0, MAX_CU_SIZE, MAX_CU_SIZE ) ) );
249  m_tmpAffiStorage.create( UnitArea( cform, Area( 0, 0, MAX_CU_SIZE, MAX_CU_SIZE ) ) );
250#if JVET_K0367_AFFINE_FIX_POINT
251  m_tmpAffiError = new Pel[MAX_CU_SIZE * MAX_CU_SIZE];
252  m_tmpAffiDeri[0] = new int[MAX_CU_SIZE * MAX_CU_SIZE];
253  m_tmpAffiDeri[1] = new int[MAX_CU_SIZE * MAX_CU_SIZE];
254#else
255  m_tmpAffiError   = new int   [MAX_CU_SIZE * MAX_CU_SIZE];
256  m_tmpAffiDeri[0] = new double[MAX_CU_SIZE * MAX_CU_SIZE];
257  m_tmpAffiDeri[1] = new double[MAX_CU_SIZE * MAX_CU_SIZE];
258#endif
259#if JEM_TOOLS
260  m_obmcOrgMod.create( UnitArea( cform, Area( 0, 0, MAX_CU_SIZE, MAX_CU_SIZE ) ) );
261#endif
262  m_pTempPel = new Pel[maxCUWidth*maxCUHeight];
263
264  m_isInitialized = true;
265}
266
267
268inline void InterSearch::xTZSearchHelp( IntTZSearchStruct& rcStruct, const int iSearchX, const int iSearchY, const uint8_t ucPointNr, const uint32_t uiDistance )
269{
270  Distortion  uiSad = 0;
271
272//  CHECK(!( !( rcStruct.searchRange.left > iSearchX || rcStruct.searchRange.right < iSearchX || rcStruct.searchRange.top > iSearchY || rcStruct.searchRange.bottom < iSearchY )), "Unspecified error");
273
274  const Pel* const  piRefSrch = rcStruct.piRefY + iSearchY * rcStruct.iRefStride + iSearchX;
275
276  m_cDistParam.cur.buf = piRefSrch;
277
278  if( 1 == rcStruct.subShiftMode )
279  {
280    // motion cost
281#if JVET_K0357_AMVR
282    Distortion uiBitCost = m_pcRdCost->getCostOfVectorWithPredictor( iSearchX, iSearchY, rcStruct.imvShift );
283#else
284    Distortion uiBitCost = m_pcRdCost->getCostOfVectorWithPredictor( iSearchX, iSearchY );
285#endif
286
287    // Skip search if bit cost is already larger than best SAD
288    if (uiBitCost < rcStruct.uiBestSad)
289    {
290      Distortion uiTempSad = m_cDistParam.distFunc( m_cDistParam );
291
292      if((uiTempSad + uiBitCost) < rcStruct.uiBestSad)
293      {
294        // it's not supposed that any member of DistParams is manipulated beside cur.buf
295        int subShift = m_cDistParam.subShift;
296        const Pel* pOrgCpy = m_cDistParam.org.buf;
297        uiSad += uiTempSad >> m_cDistParam.subShift;
298
299        while( m_cDistParam.subShift > 0 )
300        {
301          int isubShift           = m_cDistParam.subShift -1;
302          m_cDistParam.org.buf = rcStruct.pcPatternKey->buf + (rcStruct.pcPatternKey->stride << isubShift);
303          m_cDistParam.cur.buf = piRefSrch + (rcStruct.iRefStride << isubShift);
304          uiTempSad            = m_cDistParam.distFunc( m_cDistParam );
305          uiSad               += uiTempSad >> m_cDistParam.subShift;
306
307          if(((uiSad << isubShift) + uiBitCost) > rcStruct.uiBestSad)
308          {
309            break;
310          }
311
312          m_cDistParam.subShift--;
313        }
314
315        if(m_cDistParam.subShift == 0)
316        {
317          uiSad += uiBitCost;
318
319          if( uiSad < rcStruct.uiBestSad )
320          {
321            rcStruct.uiBestSad      = uiSad;
322            rcStruct.iBestX         = iSearchX;
323            rcStruct.iBestY         = iSearchY;
324            rcStruct.uiBestDistance = uiDistance;
325            rcStruct.uiBestRound    = 0;
326            rcStruct.ucPointNr      = ucPointNr;
327            m_cDistParam.maximumDistortionForEarlyExit = uiSad;
328          }
329        }
330
331        // restore org ptr
332        m_cDistParam.org.buf  = pOrgCpy;
333        m_cDistParam.subShift = subShift;
334      }
335    }
336  }
337  else
338  {
339    uiSad = m_cDistParam.distFunc( m_cDistParam );
340
341    // only add motion cost if uiSad is smaller than best. Otherwise pointless
342    // to add motion cost.
343    if( uiSad < rcStruct.uiBestSad )
344    {
345      // motion cost
346#if JVET_K0357_AMVR
347      uiSad += m_pcRdCost->getCostOfVectorWithPredictor( iSearchX, iSearchY, rcStruct.imvShift );
348#else
349      uiSad += m_pcRdCost->getCostOfVectorWithPredictor( iSearchX, iSearchY );
350#endif
351
352      if( uiSad < rcStruct.uiBestSad )
353      {
354        rcStruct.uiBestSad      = uiSad;
355        rcStruct.iBestX         = iSearchX;
356        rcStruct.iBestY         = iSearchY;
357        rcStruct.uiBestDistance = uiDistance;
358        rcStruct.uiBestRound    = 0;
359        rcStruct.ucPointNr      = ucPointNr;
360        m_cDistParam.maximumDistortionForEarlyExit = uiSad;
361      }
362    }
363  }
364}
365
366
367
368inline void InterSearch::xTZ2PointSearch( IntTZSearchStruct& rcStruct )
369{
370  const SearchRange& sr = rcStruct.searchRange;
371
372  static const int xOffset[2][9] = { {  0, -1, -1,  0, -1, +1, -1, -1, +1 }, {  0,  0, +1, +1, -1, +1,  0, +1,  0 } };
373  static const int yOffset[2][9] = { {  0,  0, -1, -1, +1, -1,  0, +1,  0 }, {  0, -1, -1,  0, -1, +1, +1, +1, +1 } };
374
375  // 2 point search,                   //   1 2 3
376  // check only the 2 untested points  //   4 0 5
377  // around the start point            //   6 7 8
378  const int iX1 = rcStruct.iBestX + xOffset[0][rcStruct.ucPointNr];
379  const int iX2 = rcStruct.iBestX + xOffset[1][rcStruct.ucPointNr];
380
381  const int iY1 = rcStruct.iBestY + yOffset[0][rcStruct.ucPointNr];
382  const int iY2 = rcStruct.iBestY + yOffset[1][rcStruct.ucPointNr];
383
384  if( iX1 >= sr.left && iX1 <= sr.right && iY1 >= sr.top && iY1 <= sr.bottom )
385  {
386    xTZSearchHelp( rcStruct, iX1, iY1, 0, 2 );
387  }
388
389  if( iX2 >= sr.left && iX2 <= sr.right && iY2 >= sr.top && iY2 <= sr.bottom )
390  {
391    xTZSearchHelp( rcStruct, iX2, iY2, 0, 2 );
392  }
393}
394
395
396inline void InterSearch::xTZ8PointSquareSearch( IntTZSearchStruct& rcStruct, const int iStartX, const int iStartY, const int iDist )
397{
398  const SearchRange& sr = rcStruct.searchRange;
399  // 8 point search,                   //   1 2 3
400  // search around the start point     //   4 0 5
401  // with the required  distance       //   6 7 8
402  CHECK( iDist == 0 , "Invalid distance");
403  const int iTop        = iStartY - iDist;
404  const int iBottom     = iStartY + iDist;
405  const int iLeft       = iStartX - iDist;
406  const int iRight      = iStartX + iDist;
407  rcStruct.uiBestRound += 1;
408
409  if ( iTop >= sr.top ) // check top
410  {
411    if ( iLeft >= sr.left ) // check top left
412    {
413      xTZSearchHelp( rcStruct, iLeft, iTop, 1, iDist );
414    }
415    // top middle
416    xTZSearchHelp( rcStruct, iStartX, iTop, 2, iDist );
417
418    if ( iRight <= sr.right ) // check top right
419    {
420      xTZSearchHelp( rcStruct, iRight, iTop, 3, iDist );
421    }
422  } // check top
423  if ( iLeft >= sr.left ) // check middle left
424  {
425    xTZSearchHelp( rcStruct, iLeft, iStartY, 4, iDist );
426  }
427  if ( iRight <= sr.right ) // check middle right
428  {
429    xTZSearchHelp( rcStruct, iRight, iStartY, 5, iDist );
430  }
431  if ( iBottom <= sr.bottom ) // check bottom
432  {
433    if ( iLeft >= sr.left ) // check bottom left
434    {
435      xTZSearchHelp( rcStruct, iLeft, iBottom, 6, iDist );
436    }
437    // check bottom middle
438    xTZSearchHelp( rcStruct, iStartX, iBottom, 7, iDist );
439
440    if ( iRight <= sr.right ) // check bottom right
441    {
442      xTZSearchHelp( rcStruct, iRight, iBottom, 8, iDist );
443    }
444  } // check bottom
445}
446
447
448
449
450inline void InterSearch::xTZ8PointDiamondSearch( IntTZSearchStruct& rcStruct,
451                                                 const int iStartX,
452                                                 const int iStartY,
453                                                 const int iDist,
454                                                 const bool bCheckCornersAtDist1 )
455{
456  const SearchRange& sr = rcStruct.searchRange;
457  // 8 point search,                   //   1 2 3
458  // search around the start point     //   4 0 5
459  // with the required  distance       //   6 7 8
460  CHECK( iDist == 0, "Invalid distance" );
461  const int iTop        = iStartY - iDist;
462  const int iBottom     = iStartY + iDist;
463  const int iLeft       = iStartX - iDist;
464  const int iRight      = iStartX + iDist;
465  rcStruct.uiBestRound += 1;
466
467  if ( iDist == 1 )
468  {
469    if ( iTop >= sr.top ) // check top
470    {
471      if (bCheckCornersAtDist1)
472      {
473        if ( iLeft >= sr.left) // check top-left
474        {
475          xTZSearchHelp( rcStruct, iLeft, iTop, 1, iDist );
476        }
477        xTZSearchHelp( rcStruct, iStartX, iTop, 2, iDist );
478        if ( iRight <= sr.right ) // check middle right
479        {
480          xTZSearchHelp( rcStruct, iRight, iTop, 3, iDist );
481        }
482      }
483      else
484      {
485        xTZSearchHelp( rcStruct, iStartX, iTop, 2, iDist );
486      }
487    }
488    if ( iLeft >= sr.left ) // check middle left
489    {
490      xTZSearchHelp( rcStruct, iLeft, iStartY, 4, iDist );
491    }
492    if ( iRight <= sr.right ) // check middle right
493    {
494      xTZSearchHelp( rcStruct, iRight, iStartY, 5, iDist );
495    }
496    if ( iBottom <= sr.bottom ) // check bottom
497    {
498      if (bCheckCornersAtDist1)
499      {
500        if ( iLeft >= sr.left) // check top-left
501        {
502          xTZSearchHelp( rcStruct, iLeft, iBottom, 6, iDist );
503        }
504        xTZSearchHelp( rcStruct, iStartX, iBottom, 7, iDist );
505        if ( iRight <= sr.right ) // check middle right
506        {
507          xTZSearchHelp( rcStruct, iRight, iBottom, 8, iDist );
508        }
509      }
510      else
511      {
512        xTZSearchHelp( rcStruct, iStartX, iBottom, 7, iDist );
513      }
514    }
515  }
516  else
517  {
518    if ( iDist <= 8 )
519    {
520      const int iTop_2      = iStartY - (iDist>>1);
521      const int iBottom_2   = iStartY + (iDist>>1);
522      const int iLeft_2     = iStartX - (iDist>>1);
523      const int iRight_2    = iStartX + (iDist>>1);
524
525      if (  iTop >= sr.top && iLeft >= sr.left &&
526           iRight <= sr.right && iBottom <= sr.bottom ) // check border
527      {
528        xTZSearchHelp( rcStruct, iStartX,  iTop,      2, iDist    );
529        xTZSearchHelp( rcStruct, iLeft_2,  iTop_2,    1, iDist>>1 );
530        xTZSearchHelp( rcStruct, iRight_2, iTop_2,    3, iDist>>1 );
531        xTZSearchHelp( rcStruct, iLeft,    iStartY,   4, iDist    );
532        xTZSearchHelp( rcStruct, iRight,   iStartY,   5, iDist    );
533        xTZSearchHelp( rcStruct, iLeft_2,  iBottom_2, 6, iDist>>1 );
534        xTZSearchHelp( rcStruct, iRight_2, iBottom_2, 8, iDist>>1 );
535        xTZSearchHelp( rcStruct, iStartX,  iBottom,   7, iDist    );
536      }
537      else // check border
538      {
539        if ( iTop >= sr.top ) // check top
540        {
541          xTZSearchHelp( rcStruct, iStartX, iTop, 2, iDist );
542        }
543        if ( iTop_2 >= sr.top ) // check half top
544        {
545          if ( iLeft_2 >= sr.left ) // check half left
546          {
547            xTZSearchHelp( rcStruct, iLeft_2, iTop_2, 1, (iDist>>1) );
548          }
549          if ( iRight_2 <= sr.right ) // check half right
550          {
551            xTZSearchHelp( rcStruct, iRight_2, iTop_2, 3, (iDist>>1) );
552          }
553        } // check half top
554        if ( iLeft >= sr.left ) // check left
555        {
556          xTZSearchHelp( rcStruct, iLeft, iStartY, 4, iDist );
557        }
558        if ( iRight <= sr.right ) // check right
559        {
560          xTZSearchHelp( rcStruct, iRight, iStartY, 5, iDist );
561        }
562        if ( iBottom_2 <= sr.bottom ) // check half bottom
563        {
564          if ( iLeft_2 >= sr.left ) // check half left
565          {
566            xTZSearchHelp( rcStruct, iLeft_2, iBottom_2, 6, (iDist>>1) );
567          }
568          if ( iRight_2 <= sr.right ) // check half right
569          {
570            xTZSearchHelp( rcStruct, iRight_2, iBottom_2, 8, (iDist>>1) );
571          }
572        } // check half bottom
573        if ( iBottom <= sr.bottom ) // check bottom
574        {
575          xTZSearchHelp( rcStruct, iStartX, iBottom, 7, iDist );
576        }
577      } // check border
578    }
579    else // iDist > 8
580    {
581      if ( iTop >= sr.top && iLeft >= sr.left &&
582           iRight <= sr.right && iBottom <= sr.bottom ) // check border
583      {
584        xTZSearchHelp( rcStruct, iStartX, iTop,    0, iDist );
585        xTZSearchHelp( rcStruct, iLeft,   iStartY, 0, iDist );
586        xTZSearchHelp( rcStruct, iRight,  iStartY, 0, iDist );
587        xTZSearchHelp( rcStruct, iStartX, iBottom, 0, iDist );
588        for ( int index = 1; index < 4; index++ )
589        {
590          const int iPosYT = iTop    + ((iDist>>2) * index);
591          const int iPosYB = iBottom - ((iDist>>2) * index);
592          const int iPosXL = iStartX - ((iDist>>2) * index);
593          const int iPosXR = iStartX + ((iDist>>2) * index);
594          xTZSearchHelp( rcStruct, iPosXL, iPosYT, 0, iDist );
595          xTZSearchHelp( rcStruct, iPosXR, iPosYT, 0, iDist );
596          xTZSearchHelp( rcStruct, iPosXL, iPosYB, 0, iDist );
597          xTZSearchHelp( rcStruct, iPosXR, iPosYB, 0, iDist );
598        }
599      }
600      else // check border
601      {
602        if ( iTop >= sr.top ) // check top
603        {
604          xTZSearchHelp( rcStruct, iStartX, iTop, 0, iDist );
605        }
606        if ( iLeft >= sr.left ) // check left
607        {
608          xTZSearchHelp( rcStruct, iLeft, iStartY, 0, iDist );
609        }
610        if ( iRight <= sr.right ) // check right
611        {
612          xTZSearchHelp( rcStruct, iRight, iStartY, 0, iDist );
613        }
614        if ( iBottom <= sr.bottom ) // check bottom
615        {
616          xTZSearchHelp( rcStruct, iStartX, iBottom, 0, iDist );
617        }
618        for ( int index = 1; index < 4; index++ )
619        {
620          const int iPosYT = iTop    + ((iDist>>2) * index);
621          const int iPosYB = iBottom - ((iDist>>2) * index);
622          const int iPosXL = iStartX - ((iDist>>2) * index);
623          const int iPosXR = iStartX + ((iDist>>2) * index);
624
625          if ( iPosYT >= sr.top ) // check top
626          {
627            if ( iPosXL >= sr.left ) // check left
628            {
629              xTZSearchHelp( rcStruct, iPosXL, iPosYT, 0, iDist );
630            }
631            if ( iPosXR <= sr.right ) // check right
632            {
633              xTZSearchHelp( rcStruct, iPosXR, iPosYT, 0, iDist );
634            }
635          } // check top
636          if ( iPosYB <= sr.bottom ) // check bottom
637          {
638            if ( iPosXL >= sr.left ) // check left
639            {
640              xTZSearchHelp( rcStruct, iPosXL, iPosYB, 0, iDist );
641            }
642            if ( iPosXR <= sr.right ) // check right
643            {
644              xTZSearchHelp( rcStruct, iPosXR, iPosYB, 0, iDist );
645            }
646          } // check bottom
647        } // for ...
648      } // check border
649    } // iDist <= 8
650  } // iDist == 1
651}
652
653Distortion InterSearch::xPatternRefinement( const CPelBuf* pcPatternKey,
654                                            Mv baseRefMv,
655                                            int iFrac, Mv& rcMvFrac,
656                                            bool bAllowUseOfHadamard )
657{
658  Distortion  uiDist;
659  Distortion  uiDistBest  = std::numeric_limits<Distortion>::max();
660  uint32_t        uiDirecBest = 0;
661
662  Pel*  piRefPos;
663  int iRefStride = pcPatternKey->width + 1;
664  m_pcRdCost->setDistParam( m_cDistParam, *pcPatternKey, m_filteredBlock[0][0][0], iRefStride, m_lumaClpRng.bd, COMPONENT_Y, 0, 1, m_pcEncCfg->getUseHADME() && bAllowUseOfHadamard );
665
666  const Mv* pcMvRefine = (iFrac == 2 ? s_acMvRefineH : s_acMvRefineQ);
667  for (uint32_t i = 0; i < 9; i++)
668  {
669    Mv cMvTest = pcMvRefine[i];
670    cMvTest += baseRefMv;
671
672    int horVal = cMvTest.getHor() * iFrac;
673    int verVal = cMvTest.getVer() * iFrac;
674    piRefPos = m_filteredBlock[verVal & 3][horVal & 3][0];
675
676    if (horVal == 2 && (verVal & 1) == 0)
677    {
678      piRefPos += 1;
679    }
680    if ((horVal & 1) == 0 && verVal == 2)
681    {
682      piRefPos += iRefStride;
683    }
684    cMvTest = pcMvRefine[i];
685    cMvTest += rcMvFrac;
686
687
688    m_cDistParam.cur.buf   = piRefPos;
689    uiDist = m_cDistParam.distFunc( m_cDistParam );
690#if JVET_K0357_AMVR
691    uiDist += m_pcRdCost->getCostOfVectorWithPredictor( cMvTest.getHor(), cMvTest.getVer(), 0 );
692#else
693    uiDist += m_pcRdCost->getCostOfVectorWithPredictor( cMvTest.getHor(), cMvTest.getVer() );
694#endif
695
696    if ( uiDist < uiDistBest )
697    {
698      uiDistBest  = uiDist;
699      uiDirecBest = i;
700      m_cDistParam.maximumDistortionForEarlyExit = uiDist;
701    }
702  }
703
704  rcMvFrac = pcMvRefine[uiDirecBest];
705
706  return uiDistBest;
707}
708
709Distortion InterSearch::xGetInterPredictionError( PredictionUnit& pu, PelUnitBuf& origBuf, const RefPicList &eRefPicList )
710{
711  PelUnitBuf predBuf = m_tmpStorageLCU.getBuf( UnitAreaRelative(*pu.cu, pu) );
712
713  motionCompensation( pu, predBuf, eRefPicList );
714
715  DistParam cDistParam;
716  cDistParam.applyWeight = false;
717
718  m_pcRdCost->setDistParam( cDistParam, origBuf.Y(), predBuf.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, m_pcEncCfg->getUseHADME() && !pu.cu->transQuantBypass );
719
720  return (Distortion)cDistParam.distFunc( cDistParam );
721}
722
723//! estimation of best merge coding
724void InterSearch::xMergeEstimation( PredictionUnit& pu, PelUnitBuf& origBuf, int iPUIdx, uint32_t& uiMergeIdx, Distortion& ruiCost, MergeCtx &mergeCtx )
725{
726  PartSize partSize = pu.cu->partSize;
727
728  if ( pu.cs->pps->getLog2ParallelMergeLevelMinus2() && partSize != SIZE_2Nx2N && pu.cu->lumaSize().width <= 8 )
729  {
730    if ( iPUIdx == 0 )
731    {
732      UnitArea unitArea = pu;
733
734      pu.UnitArea::operator=( *pu.cu );
735      pu.cu->partSize = SIZE_2Nx2N;
736
737      PU::getInterMergeCandidates( pu, mergeCtx );
738
739      pu.UnitArea::operator=( unitArea );
740      pu.cu->partSize = partSize;
741    }
742  }
743  else
744  {
745    PU::getInterMergeCandidates( pu, mergeCtx );
746  }
747
748  PU::restrictBiPredMergeCands( pu, mergeCtx );
749
750  ruiCost = std::numeric_limits<Distortion>::max();
751  for( uint32_t uiMergeCand = 0; uiMergeCand < mergeCtx.numValidMergeCand; ++uiMergeCand )
752  {
753    mergeCtx.setMergeInfo( pu, uiMergeCand );
754
755    PU::spanMotionInfo( pu, mergeCtx );
756
757    Distortion uiCostCand = xGetInterPredictionError( pu, origBuf );
758    uint32_t       uiBitsCand = uiMergeCand + 1;
759
760    if( uiMergeCand == m_pcEncCfg->getMaxNumMergeCand() - 1 )
761    {
762      uiBitsCand--;
763    }
764    uiCostCand = uiCostCand + m_pcRdCost->getCost( uiBitsCand );
765    if ( uiCostCand < ruiCost )
766    {
767      ruiCost    = uiCostCand;
768      uiMergeIdx = uiMergeCand;
769    }
770  }
771}
772
773#if JEM_TOOLS
774void InterSearch::xFRUCMrgEstimation( PredictionUnit& pu, PelUnitBuf& origBuf, Distortion& ruiMinCost, uint8_t& ruhFRUCMode, MergeCtx &mrgCtx )
775{
776  ruiMinCost = std::numeric_limits<Distortion>::max();
777
778  CHECK( pu.mergeFlag == 0, "merge flag must be set" );
779  const uint8_t uhFRUCME[2] = { FRUC_MERGE_BILATERALMV , FRUC_MERGE_TEMPLATE };
780
781  for( int nME = 0 ; nME < 2 ; nME++ )
782  {
783    pu.frucMrgMode = uhFRUCME[nME];
784    pu.mergeType   = MRG_TYPE_FRUC;
785
786    bool bAvailable = deriveFRUCMV( pu );
787    if( bAvailable )
788    {
789      Distortion uiCostCand = xGetInterPredictionError( pu, origBuf );
790
791      uint32_t uiBitsCand = 1;
792#if DISTORTION_TYPE_BUGFIX
793      Distortion uiCost = uiCostCand + m_pcRdCost->getCost(uiBitsCand);
794#else
795      uint32_t uiCost = uiCostCand + m_pcRdCost->getCost( uiBitsCand );
796#endif
797
798      if( uiCost < ruiMinCost )
799      {
800        ruiMinCost = uiCost;
801        ruhFRUCMode = uhFRUCME[nME];
802
803        if( ruhFRUCMode == FRUC_MERGE_BILATERALMV )
804        {
805          CHECK( mrgCtx.subPuFrucMiBuf.area() == 0 || !mrgCtx.subPuFrucMiBuf.buf, "Buffer not initialized" );
806          mrgCtx.subPuFrucMiBuf.fill( MotionInfo() );
807
808          mrgCtx.subPuFrucMiBuf.copyFrom( pu.getMotionBuf() );
809        }
810      }
811    }
812  }
813}
814#endif
815
816//! search of the best candidate for inter prediction
817void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner)
818{
819  CodingStructure& cs = *cu.cs;
820
821  AMVPInfo     amvp[2];
822  Mv           cMvSrchRngLT;
823  Mv           cMvSrchRngRB;
824
825  Mv           cMvZero;
826
827  Mv           cMv[2];
828  Mv           cMvBi[2];
829  Mv           cMvTemp[2][33];
830#if JEM_TOOLS || JVET_K_AFFINE
831  Mv           cMvHevcTemp[2][33];
832#endif
833  int          iNumPredDir = cs.slice->isInterP() ? 1 : 2;
834
835  Mv           cMvPred[2][33];
836
837  Mv           cMvPredBi[2][33];
838  int          aaiMvpIdxBi[2][33];
839
840  int          aaiMvpIdx[2][33];
841  int          aaiMvpNum[2][33];
842
843  AMVPInfo     aacAMVPInfo[2][33];
844
845  int          iRefIdx[2]={0,0}; //If un-initialized, may cause SEGV in bi-directional prediction iterative stage.
846  int          iRefIdxBi[2];
847
848  uint32_t         uiMbBits[3] = {1, 1, 0};
849
850  uint32_t         uiLastMode = 0;
851#if JEM_TOOLS || JVET_K_AFFINE
852  uint32_t         uiLastModeTemp = 0;
853#endif
854  int          iRefStart, iRefEnd;
855
856  int          bestBiPRefIdxL1 = 0;
857  int          bestBiPMvpL1    = 0;
858  Distortion   biPDistTemp     = std::numeric_limits<Distortion>::max();
859
860  MergeCtx     mergeCtx;
861
862  // Loop over Prediction Units
863  CHECK(!cu.firstPU, "CU does not contain any PUs");
864  uint32_t         puIdx = 0;
865  auto &pu = *cu.firstPU;
866
867  {
868    // motion estimation only evaluates luma component
869    m_maxCompIDToPred = MAX_NUM_COMPONENT;
870//    m_maxCompIDToPred = COMPONENT_Y;
871
872    CHECK(pu.cu != &cu, "PU is contained in another CU");
873
874#if JEM_TOOLS
875    if( cu.cs->sps->getSpsNext().getUseSubPuMvp() )
876    {
877      Size bufSize = g_miScaling.scale( pu.lumaSize() );
878      mergeCtx.subPuMvpMiBuf    = MotionBuf( m_SubPuMiBuf,    bufSize );
879      mergeCtx.subPuMvpExtMiBuf = MotionBuf( m_SubPuExtMiBuf, bufSize );
880    }
881
882    if( cu.cs->sps->getSpsNext().getUseFRUCMrgMode() )
883    {
884      Size bufSize = g_miScaling.scale( pu.lumaSize() );
885      mergeCtx.subPuFrucMiBuf   = MotionBuf( m_SubPuFrucBuf,  bufSize );
886    }
887#endif
888#if !JEM_TOOLS && JVET_K0346
889    if (cu.cs->sps->getSpsNext().getUseSubPuMvp())
890    {
891      Size bufSize = g_miScaling.scale(pu.lumaSize());
892      mergeCtx.subPuMvpMiBuf = MotionBuf(m_SubPuMiBuf, bufSize);
893    }
894#endif
895
896    PU::spanMotionInfo( pu );
897#if JEM_TOOLS
898    PelUnitBuf obmcOrgBuf = m_obmcOrgMod.subBuf( UnitAreaRelative( pu, pu ) );
899    obmcOrgBuf.copyFrom( pu.cs->getOrgBuf( pu ) );
900    //consider OBMC in motion estimation
901    subBlockOBMC( pu, &obmcOrgBuf, true );
902
903    Distortion   uiHevcCost   = std::numeric_limits<Distortion>::max();
904    Distortion   uiAffineCost = std::numeric_limits<Distortion>::max();
905#endif
906#if !JEM_TOOLS && JVET_K_AFFINE
907    Distortion   uiHevcCost = std::numeric_limits<Distortion>::max();
908    Distortion   uiAffineCost = std::numeric_limits<Distortion>::max();
909#endif
910    Distortion   uiCost[2] = { std::numeric_limits<Distortion>::max(), std::numeric_limits<Distortion>::max() };
911    Distortion   uiCostBi  =   std::numeric_limits<Distortion>::max();
912    Distortion   uiCostTemp;
913
914    uint32_t         uiBits[3];
915    uint32_t         uiBitsTemp;
916    Distortion   bestBiPDist = std::numeric_limits<Distortion>::max();
917
918    Distortion   uiCostTempL0[MAX_NUM_REF];
919    for (int iNumRef=0; iNumRef < MAX_NUM_REF; iNumRef++)
920    {
921      uiCostTempL0[iNumRef] = std::numeric_limits<Distortion>::max();
922    }
923    uint32_t         uiBitsTempL0[MAX_NUM_REF];
924
925    Mv           mvValidList1;
926    int          refIdxValidList1 = 0;
927    uint32_t         bitsValidList1   = MAX_UINT;
928    Distortion   costValidList1   = std::numeric_limits<Distortion>::max();
929
930#if JEM_TOOLS
931    PelUnitBuf origBuf = cu.obmcFlag ? obmcOrgBuf.subBuf( UnitAreaRelative( cu, pu ) ) : pu.cs->getOrgBuf( pu );
932#else
933    PelUnitBuf origBuf = pu.cs->getOrgBuf( pu );
934#endif
935
936    xGetBlkBits( cu.partSize, cs.slice->isInterP(), puIdx, uiLastMode, uiMbBits );
937
938    m_pcRdCost->selectMotionLambda( cu.transQuantBypass );
939
940#if !JVET_K0220_ENC_CTRL
941    bool bFastSkipBi = false;
942    if( auto slsCtrl = dynamic_cast< SaveLoadEncInfoCtrl* >( m_modeCtrl ) )
943    {
944      bFastSkipBi = ( LOAD_ENC_INFO == slsCtrl->getSaveLoadTag( pu ) && 3 != slsCtrl->getSaveLoadInterDir( pu ) );
945    }
946
947#endif
948#if JEM_TOOLS || JVET_K_AFFINE
949#if !JVET_K0220_ENC_CTRL
950    bool bFastSkipAffine = false;
951    if( pu.cs->sps->getSpsNext().getUseQTBT() && m_pcEncCfg->getUseSaveLoadEncInfo() )
952    {
953      SaveLoadEncInfoCtrl* modeCtrl = dynamic_cast<SaveLoadEncInfoCtrl*>( m_modeCtrl );
954      bFastSkipAffine = modeCtrl && LOAD_ENC_INFO == modeCtrl->getSaveLoadTag( pu ) && !modeCtrl->getSaveLoadAffineFlag( pu );
955    }
956#endif
957#endif
958#if JVET_K0357_AMVR
959    unsigned imvShift = pu.cu->imv << 1;
960#endif
961      //  Uni-directional prediction
962      for ( int iRefList = 0; iRefList < iNumPredDir; iRefList++ )
963      {
964        RefPicList  eRefPicList = ( iRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
965
966        for ( int iRefIdxTemp = 0; iRefIdxTemp < cs.slice->getNumRefIdx(eRefPicList); iRefIdxTemp++ )
967        {
968          uiBitsTemp = uiMbBits[iRefList];
969          if ( cs.slice->getNumRefIdx(eRefPicList) > 1 )
970          {
971            uiBitsTemp += iRefIdxTemp+1;
972            if ( iRefIdxTemp == cs.slice->getNumRefIdx(eRefPicList)-1 )
973            {
974              uiBitsTemp--;
975            }
976          }
977          xEstimateMvPredAMVP( pu, origBuf, eRefPicList, iRefIdxTemp, cMvPred[iRefList][iRefIdxTemp], amvp[eRefPicList], false, &biPDistTemp);
978
979          aaiMvpIdx[iRefList][iRefIdxTemp] = pu.mvpIdx[eRefPicList];
980          aaiMvpNum[iRefList][iRefIdxTemp] = pu.mvpNum[eRefPicList];
981
982          if(cs.slice->getMvdL1ZeroFlag() && iRefList==1 && biPDistTemp < bestBiPDist)
983          {
984            bestBiPDist = biPDistTemp;
985            bestBiPMvpL1 = aaiMvpIdx[iRefList][iRefIdxTemp];
986            bestBiPRefIdxL1 = iRefIdxTemp;
987          }
988
989          uiBitsTemp += m_auiMVPIdxCost[aaiMvpIdx[iRefList][iRefIdxTemp]][AMVP_MAX_NUM_CANDS];
990
991          if ( m_pcEncCfg->getFastMEForGenBLowDelayEnabled() && iRefList == 1 )    // list 1
992          {
993            if ( cs.slice->getList1IdxToList0Idx( iRefIdxTemp ) >= 0 )
994            {
995              cMvTemp[1][iRefIdxTemp] = cMvTemp[0][cs.slice->getList1IdxToList0Idx( iRefIdxTemp )];
996              uiCostTemp = uiCostTempL0[cs.slice->getList1IdxToList0Idx( iRefIdxTemp )];
997              /*first subtract the bit-rate part of the cost of the other list*/
998              uiCostTemp -= m_pcRdCost->getCost( uiBitsTempL0[cs.slice->getList1IdxToList0Idx( iRefIdxTemp )] );
999              /*correct the bit-rate part of the current ref*/
1000              m_pcRdCost->setPredictor  ( cMvPred[iRefList][iRefIdxTemp] );
1001#if JVET_K0357_AMVR
1002              uiBitsTemp += m_pcRdCost->getBitsOfVectorWithPredictor( cMvTemp[1][iRefIdxTemp].getHor(), cMvTemp[1][iRefIdxTemp].getVer(), imvShift );
1003#else
1004              uiBitsTemp += m_pcRdCost->getBitsOfVectorWithPredictor( cMvTemp[1][iRefIdxTemp].getHor(), cMvTemp[1][iRefIdxTemp].getVer() );
1005#endif
1006              /*calculate the correct cost*/
1007              uiCostTemp += m_pcRdCost->getCost( uiBitsTemp );
1008            }
1009            else
1010            {
1011              xMotionEstimation( pu, origBuf, eRefPicList, cMvPred[iRefList][iRefIdxTemp], iRefIdxTemp, cMvTemp[iRefList][iRefIdxTemp], aaiMvpIdx[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp, amvp[eRefPicList] );
1012            }
1013          }
1014          else
1015          {
1016            xMotionEstimation( pu, origBuf, eRefPicList, cMvPred[iRefList][iRefIdxTemp], iRefIdxTemp, cMvTemp[iRefList][iRefIdxTemp], aaiMvpIdx[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp, amvp[eRefPicList] );
1017          }
1018          xCopyAMVPInfo( &amvp[eRefPicList], &aacAMVPInfo[iRefList][iRefIdxTemp]); // must always be done ( also when AMVP_MODE = AM_NONE )
1019#if JVET_K0357_AMVR
1020          xCheckBestMVP( eRefPicList, cMvTemp[iRefList][iRefIdxTemp], cMvPred[iRefList][iRefIdxTemp], aaiMvpIdx[iRefList][iRefIdxTemp], amvp[eRefPicList], uiBitsTemp, uiCostTemp, pu.cu->imv );
1021#else
1022          xCheckBestMVP( eRefPicList, cMvTemp[iRefList][iRefIdxTemp], cMvPred[iRefList][iRefIdxTemp], aaiMvpIdx[iRefList][iRefIdxTemp], amvp[eRefPicList], uiBitsTemp, uiCostTemp );
1023#endif
1024
1025          if ( iRefList == 0 )
1026          {
1027            uiCostTempL0[iRefIdxTemp] = uiCostTemp;
1028            uiBitsTempL0[iRefIdxTemp] = uiBitsTemp;
1029          }
1030          if ( uiCostTemp < uiCost[iRefList] )
1031          {
1032            uiCost[iRefList] = uiCostTemp;
1033            uiBits[iRefList] = uiBitsTemp; // storing for bi-prediction
1034
1035            // set motion
1036            cMv    [iRefList] = cMvTemp[iRefList][iRefIdxTemp];
1037            iRefIdx[iRefList] = iRefIdxTemp;
1038          }
1039
1040          if ( iRefList == 1 && uiCostTemp < costValidList1 && cs.slice->getList1IdxToList0Idx( iRefIdxTemp ) < 0 )
1041          {
1042            costValidList1 = uiCostTemp;
1043            bitsValidList1 = uiBitsTemp;
1044
1045            // set motion
1046            mvValidList1     = cMvTemp[iRefList][iRefIdxTemp];
1047            refIdxValidList1 = iRefIdxTemp;
1048          }
1049        }
1050      }
1051
1052#if JVET_K0220_ENC_CTRL
1053      if (cu.Y().width > 8 && cu.Y().height > 8 && cu.partSize == SIZE_2Nx2N && cu.slice->getSPS()->getSpsNext().getUseAffine() 
1054#if JEM_TOOLS
1055        && !cu.LICFlag
1056#endif
1057#if JVET_K0357_AMVR
1058        && cu.imv == 0
1059#endif
1060        )
1061#else
1062      if (cu.Y().width > 8 && cu.Y().height > 8 && cu.partSize == SIZE_2Nx2N && cu.slice->getSPS()->getSpsNext().getUseAffine() 
1063#if JEM_TOOLS
1064        && !cu.LICFlag
1065#endif
1066#if JVET_K0357_AMVR
1067        && cu.imv == 0
1068#endif
1069        && !bFastSkipAffine)
1070#endif
1071      {
1072        ::memcpy( cMvHevcTemp, cMvTemp, sizeof( cMvTemp ) );
1073      }
1074#if !JEM_TOOLS && JVET_K_AFFINE
1075#if JVET_K0220_ENC_CTRL
1076      if ( cu.Y().width > 8 && cu.Y().height > 8 && cu.partSize == SIZE_2Nx2N && cu.slice->getSPS()->getSpsNext().getUseAffine() )
1077#else
1078      if ( cu.Y().width > 8 && cu.Y().height > 8 && cu.partSize == SIZE_2Nx2N && cu.slice->getSPS()->getSpsNext().getUseAffine() && !bFastSkipAffine )
1079#endif
1080      {
1081        ::memcpy( cMvHevcTemp, cMvTemp, sizeof( cMvTemp ) );
1082      }
1083#endif
1084      //  Bi-predictive Motion estimation
1085#if JVET_K0220_ENC_CTRL
1086      if( ( cs.slice->isInterB() ) && ( PU::isBipredRestriction( pu ) == false ) )
1087#else
1088      if ( (cs.slice->isInterB()) && ( PU::isBipredRestriction(pu) == false)  && !bFastSkipBi )
1089#endif
1090      {
1091        cMvBi[0] = cMv[0];
1092        cMvBi[1] = cMv[1];
1093        iRefIdxBi[0] = iRefIdx[0];
1094        iRefIdxBi[1] = iRefIdx[1];
1095
1096        ::memcpy( cMvPredBi,   cMvPred,   sizeof( cMvPred   ) );
1097        ::memcpy( aaiMvpIdxBi, aaiMvpIdx, sizeof( aaiMvpIdx ) );
1098
1099        uint32_t uiMotBits[2];
1100
1101        if(cs.slice->getMvdL1ZeroFlag())
1102        {
1103          xCopyAMVPInfo(&aacAMVPInfo[1][bestBiPRefIdxL1], &amvp[REF_PIC_LIST_1]);
1104          aaiMvpIdxBi[1][bestBiPRefIdxL1] = bestBiPMvpL1;
1105          cMvPredBi  [1][bestBiPRefIdxL1] = amvp[REF_PIC_LIST_1].mvCand[bestBiPMvpL1];
1106
1107          cMvBi    [1] = cMvPredBi[1][bestBiPRefIdxL1];
1108          iRefIdxBi[1] = bestBiPRefIdxL1;
1109          pu.mv    [REF_PIC_LIST_1] = cMvBi[1];
1110          pu.refIdx[REF_PIC_LIST_1] = iRefIdxBi[1];
1111          pu.mvpIdx[REF_PIC_LIST_1] = bestBiPMvpL1;
1112
1113          PelUnitBuf predBufTmp = m_tmpPredStorage[REF_PIC_LIST_1].getBuf( UnitAreaRelative(cu, pu) );
1114          motionCompensation( pu, predBufTmp, REF_PIC_LIST_1 );
1115
1116          uiMotBits[0] = uiBits[0] - uiMbBits[0];
1117          uiMotBits[1] = uiMbBits[1];
1118
1119          if ( cs.slice->getNumRefIdx(REF_PIC_LIST_1) > 1 )
1120          {
1121            uiMotBits[1] += bestBiPRefIdxL1 + 1;
1122            if ( bestBiPRefIdxL1 == cs.slice->getNumRefIdx(REF_PIC_LIST_1)-1 )
1123            {
1124              uiMotBits[1]--;
1125            }
1126          }
1127
1128          uiMotBits[1] += m_auiMVPIdxCost[aaiMvpIdxBi[1][bestBiPRefIdxL1]][AMVP_MAX_NUM_CANDS];
1129
1130          uiBits[2] = uiMbBits[2] + uiMotBits[0] + uiMotBits[1];
1131
1132          cMvTemp[1][bestBiPRefIdxL1] = cMvBi[1];
1133        }
1134        else
1135        {
1136          uiMotBits[0] = uiBits[0] - uiMbBits[0];
1137          uiMotBits[1] = uiBits[1] - uiMbBits[1];
1138          uiBits[2] = uiMbBits[2] + uiMotBits[0] + uiMotBits[1];
1139        }
1140
1141        // 4-times iteration (default)
1142        int iNumIter = 4;
1143
1144        // fast encoder setting: only one iteration
1145        if ( m_pcEncCfg->getFastInterSearchMode()==FASTINTERSEARCH_MODE1 || m_pcEncCfg->getFastInterSearchMode()==FASTINTERSEARCH_MODE2 || cs.slice->getMvdL1ZeroFlag() )
1146        {
1147          iNumIter = 1;
1148        }
1149
1150        for ( int iIter = 0; iIter < iNumIter; iIter++ )
1151        {
1152          int         iRefList    = iIter % 2;
1153
1154          if ( m_pcEncCfg->getFastInterSearchMode()==FASTINTERSEARCH_MODE1 || m_pcEncCfg->getFastInterSearchMode()==FASTINTERSEARCH_MODE2 )
1155          {
1156            if( uiCost[0] <= uiCost[1] )
1157            {
1158              iRefList = 1;
1159            }
1160            else
1161            {
1162              iRefList = 0;
1163            }
1164          }
1165          else if ( iIter == 0 )
1166          {
1167            iRefList = 0;
1168          }
1169          if ( iIter == 0 && !cs.slice->getMvdL1ZeroFlag())
1170          {
1171            pu.mv    [1 - iRefList] = cMv    [1 - iRefList];
1172            pu.refIdx[1 - iRefList] = iRefIdx[1 - iRefList];
1173
1174            PelUnitBuf predBufTmp = m_tmpPredStorage[1 - iRefList].getBuf( UnitAreaRelative(cu, pu) );
1175            motionCompensation( pu, predBufTmp, RefPicList(1 - iRefList) );
1176          }
1177
1178          RefPicList  eRefPicList = ( iRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
1179
1180          if(cs.slice->getMvdL1ZeroFlag())
1181          {
1182            iRefList = 0;
1183            eRefPicList = REF_PIC_LIST_0;
1184          }
1185
1186          bool bChanged = false;
1187
1188          iRefStart = 0;
1189          iRefEnd   = cs.slice->getNumRefIdx(eRefPicList)-1;
1190
1191          for ( int iRefIdxTemp = iRefStart; iRefIdxTemp <= iRefEnd; iRefIdxTemp++ )
1192          {
1193            uiBitsTemp = uiMbBits[2] + uiMotBits[1-iRefList];
1194            if ( cs.slice->getNumRefIdx(eRefPicList) > 1 )
1195            {
1196              uiBitsTemp += iRefIdxTemp+1;
1197              if ( iRefIdxTemp == cs.slice->getNumRefIdx(eRefPicList)-1 )
1198              {
1199                uiBitsTemp--;
1200              }
1201            }
1202            uiBitsTemp += m_auiMVPIdxCost[aaiMvpIdxBi[iRefList][iRefIdxTemp]][AMVP_MAX_NUM_CANDS];
1203
1204            // call ME
1205            xCopyAMVPInfo(&aacAMVPInfo[iRefList][iRefIdxTemp], &amvp[eRefPicList] );
1206            xMotionEstimation ( pu, origBuf, eRefPicList, cMvPredBi[iRefList][iRefIdxTemp], iRefIdxTemp, cMvTemp[iRefList][iRefIdxTemp], aaiMvpIdxBi[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp, amvp[eRefPicList], true );
1207#if JVET_K0357_AMVR
1208            xCheckBestMVP( eRefPicList, cMvTemp[iRefList][iRefIdxTemp], cMvPredBi[iRefList][iRefIdxTemp], aaiMvpIdxBi[iRefList][iRefIdxTemp], amvp[eRefPicList], uiBitsTemp, uiCostTemp, pu.cu->imv);
1209#else
1210            xCheckBestMVP( eRefPicList, cMvTemp[iRefList][iRefIdxTemp], cMvPredBi[iRefList][iRefIdxTemp], aaiMvpIdxBi[iRefList][iRefIdxTemp], amvp[eRefPicList], uiBitsTemp, uiCostTemp);
1211#endif
1212            if ( uiCostTemp < uiCostBi )
1213            {
1214              bChanged = true;
1215
1216              cMvBi[iRefList]     = cMvTemp[iRefList][iRefIdxTemp];
1217              iRefIdxBi[iRefList] = iRefIdxTemp;
1218
1219              uiCostBi            = uiCostTemp;
1220              uiMotBits[iRefList] = uiBitsTemp - uiMbBits[2] - uiMotBits[1-iRefList];
1221              uiBits[2]           = uiBitsTemp;
1222
1223              if(iNumIter!=1)
1224              {
1225                //  Set motion
1226                pu.mv    [eRefPicList] = cMvBi    [iRefList];
1227                pu.refIdx[eRefPicList] = iRefIdxBi[iRefList];
1228
1229                PelUnitBuf predBufTmp = m_tmpPredStorage[iRefList].getBuf( UnitAreaRelative(cu, pu) );
1230                motionCompensation( pu, predBufTmp, eRefPicList );
1231              }
1232            }
1233          } // for loop-iRefIdxTemp
1234
1235          if ( !bChanged )
1236          {
1237            if ( uiCostBi <= uiCost[0] && uiCostBi <= uiCost[1] )
1238            {
1239              xCopyAMVPInfo(&aacAMVPInfo[0][iRefIdxBi[0]], &amvp[REF_PIC_LIST_0]);
1240#if JVET_K0357_AMVR
1241              xCheckBestMVP( REF_PIC_LIST_0, cMvBi[0], cMvPredBi[0][iRefIdxBi[0]], aaiMvpIdxBi[0][iRefIdxBi[0]], amvp[eRefPicList], uiBits[2], uiCostBi, pu.cu->imv);
1242#else
1243              xCheckBestMVP( REF_PIC_LIST_0, cMvBi[0], cMvPredBi[0][iRefIdxBi[0]], aaiMvpIdxBi[0][iRefIdxBi[0]], amvp[eRefPicList], uiBits[2], uiCostBi);
1244#endif
1245              if(!cs.slice->getMvdL1ZeroFlag())
1246              {
1247                xCopyAMVPInfo(&aacAMVPInfo[1][iRefIdxBi[1]], &amvp[REF_PIC_LIST_1]);
1248#if JVET_K0357_AMVR
1249                xCheckBestMVP( REF_PIC_LIST_1, cMvBi[1], cMvPredBi[1][iRefIdxBi[1]], aaiMvpIdxBi[1][iRefIdxBi[1]], amvp[eRefPicList], uiBits[2], uiCostBi, pu.cu->imv);
1250#else
1251                xCheckBestMVP( REF_PIC_LIST_1, cMvBi[1], cMvPredBi[1][iRefIdxBi[1]], aaiMvpIdxBi[1][iRefIdxBi[1]], amvp[eRefPicList], uiBits[2], uiCostBi);
1252#endif
1253              }
1254            }
1255            break;
1256          }
1257        } // for loop-iter
1258      } // if (B_SLICE)
1259
1260
1261
1262      //  Clear Motion Field
1263    pu.mv    [REF_PIC_LIST_0] = Mv();
1264    pu.mv    [REF_PIC_LIST_1] = Mv();
1265    pu.mvd   [REF_PIC_LIST_0] = cMvZero;
1266    pu.mvd   [REF_PIC_LIST_1] = cMvZero;
1267    pu.refIdx[REF_PIC_LIST_0] = NOT_VALID;
1268    pu.refIdx[REF_PIC_LIST_1] = NOT_VALID;
1269    pu.mvpIdx[REF_PIC_LIST_0] = NOT_VALID;
1270    pu.mvpIdx[REF_PIC_LIST_1] = NOT_VALID;
1271    pu.mvpNum[REF_PIC_LIST_0] = NOT_VALID;
1272    pu.mvpNum[REF_PIC_LIST_1] = NOT_VALID;
1273
1274
1275    uint32_t uiMEBits = 0;
1276
1277    // Set Motion Field
1278
1279    cMv    [1] = mvValidList1;
1280    iRefIdx[1] = refIdxValidList1;
1281    uiBits [1] = bitsValidList1;
1282    uiCost [1] = costValidList1;
1283
1284#if JEM_TOOLS || JVET_K_AFFINE
1285      uiLastModeTemp = uiLastMode;
1286#endif
1287      if ( uiCostBi <= uiCost[0] && uiCostBi <= uiCost[1])
1288      {
1289        uiLastMode = 2;
1290        pu.mv    [REF_PIC_LIST_0] = cMvBi[0];
1291        pu.mv    [REF_PIC_LIST_1] = cMvBi[1];
1292        pu.mvd   [REF_PIC_LIST_0] = cMvBi[0] - cMvPredBi[0][iRefIdxBi[0]];
1293        pu.mvd   [REF_PIC_LIST_1] = cMvBi[1] - cMvPredBi[1][iRefIdxBi[1]];
1294        pu.refIdx[REF_PIC_LIST_0] = iRefIdxBi[0];
1295        pu.refIdx[REF_PIC_LIST_1] = iRefIdxBi[1];
1296        pu.mvpIdx[REF_PIC_LIST_0] = aaiMvpIdxBi[0][iRefIdxBi[0]];
1297        pu.mvpIdx[REF_PIC_LIST_1] = aaiMvpIdxBi[1][iRefIdxBi[1]];
1298        pu.mvpNum[REF_PIC_LIST_0] = aaiMvpNum[0][iRefIdxBi[0]];
1299        pu.mvpNum[REF_PIC_LIST_1] = aaiMvpNum[1][iRefIdxBi[1]];
1300        pu.interDir = 3;
1301
1302        uiMEBits = uiBits[2];
1303      }
1304      else if ( uiCost[0] <= uiCost[1] )
1305      {
1306        uiLastMode = 0;
1307        pu.mv    [REF_PIC_LIST_0] = cMv[0];
1308        pu.mvd   [REF_PIC_LIST_0] = cMv[0] - cMvPred[0][iRefIdx[0]];
1309        pu.refIdx[REF_PIC_LIST_0] = iRefIdx[0];
1310        pu.mvpIdx[REF_PIC_LIST_0] = aaiMvpIdx[0][iRefIdx[0]];
1311        pu.mvpNum[REF_PIC_LIST_0] = aaiMvpNum[0][iRefIdx[0]];
1312        pu.interDir = 1;
1313
1314        uiMEBits = uiBits[0];
1315      }
1316      else
1317      {
1318        uiLastMode = 1;
1319        pu.mv    [REF_PIC_LIST_1] = cMv[1];
1320        pu.mvd   [REF_PIC_LIST_1] = cMv[1] - cMvPred[1][iRefIdx[1]];
1321        pu.refIdx[REF_PIC_LIST_1] = iRefIdx[1];
1322        pu.mvpIdx[REF_PIC_LIST_1] = aaiMvpIdx[1][iRefIdx[1]];
1323        pu.mvpNum[REF_PIC_LIST_1] = aaiMvpNum[1][iRefIdx[1]];
1324        pu.interDir = 2;
1325
1326        uiMEBits = uiBits[1];
1327      }
1328
1329    if ( cu.partSize != SIZE_2Nx2N )
1330    {
1331      uint32_t uiMRGIndex    = 0;
1332
1333      // calculate ME cost
1334      Distortion uiMEError = xGetInterPredictionError( pu, origBuf );
1335      Distortion uiMECost = uiMEError + m_pcRdCost->getCost( uiMEBits );
1336      // save ME result.
1337      InterPredictionData savedPU = pu;
1338
1339      // find Merge result
1340      Distortion uiMRGCost = std::numeric_limits<Distortion>::max();
1341
1342      pu.initData();
1343      xMergeEstimation( pu, origBuf, puIdx, uiMRGIndex, uiMRGCost, mergeCtx );
1344
1345#if JEM_TOOLS
1346      Distortion uiFRUCMrgCost = std::numeric_limits<Distortion>::max();
1347      uint8_t uhFRUCMode = 0;
1348      if( pu.cs->slice->getSPS()->getSpsNext().getUseFRUCMrgMode() )
1349      {
1350        xFRUCMrgEstimation( pu, origBuf, uiFRUCMrgCost, uhFRUCMode, mergeCtx );
1351      }
1352
1353      if( uiMRGCost < uiMECost || uiFRUCMrgCost < uiMECost )
1354      {
1355        if( uiMRGCost <= uiFRUCMrgCost )
1356        {
1357          // set Merge result
1358          mergeCtx.setMergeInfo( pu, uiMRGIndex );
1359          pu.frucMrgMode = FRUC_MERGE_OFF;
1360        }
1361        else
1362        {
1363          pu.frucMrgMode = uhFRUCMode;
1364          if( pu.frucMrgMode == FRUC_MERGE_BILATERALMV )
1365          {
1366            pu.mergeType = MRG_TYPE_FRUC_SET;
1367            PU::spanMotionInfo( pu, mergeCtx );
1368            pu.mergeType = MRG_TYPE_FRUC;
1369          }
1370        }
1371      }
1372#else
1373      if( uiMRGCost < uiMECost )
1374      {
1375        // set Merge result
1376        mergeCtx.setMergeInfo( pu, uiMRGIndex );
1377      }
1378#endif
1379      else
1380      {
1381        pu = savedPU;
1382      }
1383#if JEM_TOOLS || JVET_K_AFFINE
1384      uiHevcCost = ( uiMRGCost < uiMECost ) ? uiMRGCost : uiMECost;
1385#endif
1386    }
1387#if JEM_TOOLS || JVET_K_AFFINE
1388    if( cu.cs->pcv->only2Nx2N || cu.partSize == SIZE_2Nx2N )
1389    {
1390      uiHevcCost = ( uiCostBi <= uiCost[0] && uiCostBi <= uiCost[1] ) ? uiCostBi : ( ( uiCost[0] <= uiCost[1] ) ? uiCost[0] : uiCost[1] );
1391    }
1392#endif
1393    CHECK( !( !cu.cs->pcv->only2Nx2N || cu.partSize == SIZE_2Nx2N ), "Unexpected part size for QTBT." );
1394#if JEM_TOOLS || JVET_K_AFFINE
1395#if JEM_TOOLS
1396#if JVET_K0220_ENC_CTRL
1397#if JVET_K0357_AMVR
1398    if (cu.Y().width > 8 && cu.Y().height > 8 && cu.partSize == SIZE_2Nx2N && cu.slice->getSPS()->getSpsNext().getUseAffine() && !cu.LICFlag && cu.imv == 0)
1399#else
1400    if (cu.Y().width > 8 && cu.Y().height > 8 && cu.partSize == SIZE_2Nx2N && cu.slice->getSPS()->getSpsNext().getUseAffine() && !cu.LICFlag)
1401#endif
1402#else
1403#if JVET_K0357_AMVR
1404    if (cu.Y().width > 8 && cu.Y().height > 8 && cu.partSize == SIZE_2Nx2N && cu.slice->getSPS()->getSpsNext().getUseAffine() && !cu.LICFlag && cu.imv == 0 && !bFastSkipAffine)
1405#else
1406    if (cu.Y().width > 8 && cu.Y().height > 8 && cu.partSize == SIZE_2Nx2N && cu.slice->getSPS()->getSpsNext().getUseAffine() && !cu.LICFlag && !bFastSkipAffine)
1407#endif
1408#endif
1409#else
1410#if JVET_K0220_ENC_CTRL
1411#if JVET_K0357_AMVR
1412    if (cu.Y().width > 8 && cu.Y().height > 8 && cu.partSize == SIZE_2Nx2N && cu.slice->getSPS()->getSpsNext().getUseAffine() && cu.imv == 0)
1413#else
1414    if (cu.Y().width > 8 && cu.Y().height > 8 && cu.partSize == SIZE_2Nx2N && cu.slice->getSPS()->getSpsNext().getUseAffine())
1415#endif
1416#else
1417#if JVET_K0357_AMVR
1418    if (cu.Y().width > 8 && cu.Y().height > 8 && cu.partSize == SIZE_2Nx2N && cu.slice->getSPS()->getSpsNext().getUseAffine() && cu.imv == 0 && !bFastSkipAffine)
1419#else
1420    if (cu.Y().width > 8 && cu.Y().height > 8 && cu.partSize == SIZE_2Nx2N && cu.slice->getSPS()->getSpsNext().getUseAffine() && !bFastSkipAffine)
1421#endif
1422#endif
1423#endif
1424    {
1425      // save normal hevc result
1426      uint32_t uiMRGIndex = pu.mergeIdx;
1427      bool bMergeFlag = pu.mergeFlag;
1428      uint32_t uiInterDir = pu.interDir;
1429
1430      Mv cMvd[2];
1431      uint32_t uiMvpIdx[2], uiMvpNum[2];
1432      uiMvpIdx[0] = pu.mvpIdx[REF_PIC_LIST_0];
1433      uiMvpIdx[1] = pu.mvpIdx[REF_PIC_LIST_1];
1434      uiMvpNum[0] = pu.mvpNum[REF_PIC_LIST_0];
1435      uiMvpNum[1] = pu.mvpNum[REF_PIC_LIST_1];
1436      cMvd[0]     = pu.mvd[REF_PIC_LIST_0];
1437      cMvd[1]     = pu.mvd[REF_PIC_LIST_1];
1438
1439      MvField cHevcMvField[2];
1440      cHevcMvField[0].setMvField( pu.mv[REF_PIC_LIST_0], pu.refIdx[REF_PIC_LIST_0] );
1441      cHevcMvField[1].setMvField( pu.mv[REF_PIC_LIST_1], pu.refIdx[REF_PIC_LIST_1] );
1442
1443      // do affine ME & Merge
1444#if JVET_K0185_AFFINE_6PARA_ENC
1445      cu.affineType = AFFINEMODEL_4PARAM;
1446      Mv acMvAffine4Para[2][33][3];
1447      int refIdx4Para[2] = { -1, -1 };
1448
1449#if JVET_K0220_ENC_CTRL
1450      xPredAffineInterSearch( pu, origBuf, puIdx, uiLastModeTemp, uiAffineCost, cMvHevcTemp, acMvAffine4Para, refIdx4Para );
1451#else
1452      xPredAffineInterSearch( pu, origBuf, puIdx, uiLastModeTemp, uiAffineCost, cMvHevcTemp, bFastSkipBi, acMvAffine4Para, refIdx4Para );
1453#endif
1454      if ( cu.slice->getSPS()->getSpsNext().getUseAffineType() )
1455      {
1456        if ( uiAffineCost < uiHevcCost * 1.05 ) ///< condition for 6 parameter affine ME
1457        {
1458          // save 4 parameter results
1459          Mv bestMv[2][3], bestMvd[2][3];
1460          int bestMvpIdx[2], bestMvpNum[2], bestRefIdx[2];
1461          uint8_t bestInterDir;
1462
1463          bestInterDir = pu.interDir;
1464          bestRefIdx[0] = pu.refIdx[0];
1465          bestRefIdx[1] = pu.refIdx[1];
1466          bestMvpIdx[0] = pu.mvpIdx[0];
1467          bestMvpIdx[1] = pu.mvpIdx[1];
1468          bestMvpNum[0] = pu.mvpNum[0];
1469          bestMvpNum[1] = pu.mvpNum[1];
1470
1471          const CMotionBuf &mb = pu.getMotionBuf();
1472          for ( int refList = 0; refList < 2; refList++ )
1473          {
1474            bestMv[refList][0] = mb.at( 0, 0 ).mv[refList];
1475            bestMv[refList][1] = mb.at( mb.width - 1, 0 ).mv[refList];
1476            bestMv[refList][2] = mb.at( 0, mb.height - 1 ).mv[refList];
1477
1478            bestMvd[refList][0] = pu.mvdAffi[refList][0];
1479            bestMvd[refList][1] = pu.mvdAffi[refList][1];
1480            bestMvd[refList][2] = pu.mvdAffi[refList][2];
1481          }
1482
1483          refIdx4Para[0] = bestRefIdx[0];
1484          refIdx4Para[1] = bestRefIdx[1];
1485
1486          Distortion uiAffine6Cost = std::numeric_limits<Distortion>::max();
1487          cu.affineType = AFFINEMODEL_6PARAM;
1488#if JVET_K0220_ENC_CTRL
1489          xPredAffineInterSearch( pu, origBuf, puIdx, uiLastModeTemp, uiAffine6Cost, cMvHevcTemp, acMvAffine4Para, refIdx4Para );
1490#else
1491          xPredAffineInterSearch( pu, origBuf, puIdx, uiLastModeTemp, uiAffine6Cost, cMvHevcTemp, bFastSkipBi, acMvAffine4Para, refIdx4Para );
1492#endif
1493
1494          // reset to 4 parameter affine inter mode
1495          if ( uiAffineCost <= uiAffine6Cost )
1496          {
1497            cu.affineType = AFFINEMODEL_4PARAM;
1498            pu.interDir = bestInterDir;
1499            pu.refIdx[0] = bestRefIdx[0];
1500            pu.refIdx[1] = bestRefIdx[1];
1501            pu.mvpIdx[0] = bestMvpIdx[0];
1502            pu.mvpIdx[1] = bestMvpIdx[1];
1503            pu.mvpNum[0] = bestMvpNum[0];
1504            pu.mvpNum[1] = bestMvpNum[1];
1505
1506            for ( int verIdx = 0; verIdx < 3; verIdx++ )
1507            {
1508              pu.mvdAffi[REF_PIC_LIST_0][verIdx] = bestMvd[0][verIdx];
1509              pu.mvdAffi[REF_PIC_LIST_1][verIdx] = bestMvd[1][verIdx];
1510            }
1511
1512            PU::setAllAffineMv( pu, bestMv[0][0], bestMv[0][1], bestMv[0][2], REF_PIC_LIST_0 );
1513            PU::setAllAffineMv( pu, bestMv[1][0], bestMv[1][1], bestMv[1][2], REF_PIC_LIST_1 );
1514          }
1515          else
1516          {
1517            uiAffineCost = uiAffine6Cost;
1518          }
1519        }
1520
1521        uiAffineCost += m_pcRdCost->getCost( 1 ); // add one bit for affine_type
1522      }
1523#else
1524#if JVET_K0220_ENC_CTRL
1525      xPredAffineInterSearch( pu, origBuf, puIdx, uiLastModeTemp, uiAffineCost, cMvHevcTemp );
1526#else
1527      xPredAffineInterSearch( pu, origBuf, puIdx, uiLastModeTemp, uiAffineCost, cMvHevcTemp, bFastSkipBi );
1528#endif
1529#endif
1530
1531      if ( uiHevcCost <= uiAffineCost )
1532      {
1533        // set hevc me result
1534        cu.affine = false;
1535        pu.mergeFlag = bMergeFlag;
1536        pu.mergeIdx = uiMRGIndex;
1537        pu.interDir = uiInterDir;
1538        pu.mv    [REF_PIC_LIST_0] = cHevcMvField[0].mv;
1539        pu.refIdx[REF_PIC_LIST_0] = cHevcMvField[0].refIdx;
1540        pu.mv    [REF_PIC_LIST_1] = cHevcMvField[1].mv;
1541        pu.refIdx[REF_PIC_LIST_1] = cHevcMvField[1].refIdx;
1542        pu.mvpIdx[REF_PIC_LIST_0] = uiMvpIdx[0];
1543        pu.mvpIdx[REF_PIC_LIST_1] = uiMvpIdx[1];
1544        pu.mvpNum[REF_PIC_LIST_0] = uiMvpNum[0];
1545        pu.mvpNum[REF_PIC_LIST_1] = uiMvpNum[1];
1546        pu.mvd[REF_PIC_LIST_0] = cMvd[0];
1547        pu.mvd[REF_PIC_LIST_1] = cMvd[1];
1548      }
1549      else
1550      {
1551        CHECK( !cu.affine, "Wrong." );
1552        uiLastMode = uiLastModeTemp;
1553      }
1554    }
1555#endif
1556    m_maxCompIDToPred = MAX_NUM_COMPONENT;
1557
1558#if JEM_TOOLS
1559    if( pu.frucMrgMode == FRUC_MERGE_OFF )
1560#endif
1561    {
1562      PU::spanMotionInfo( pu, mergeCtx );
1563    }
1564
1565    //  MC
1566    PelUnitBuf predBuf = pu.cs->getPredBuf(pu);
1567    motionCompensation( pu, predBuf, REF_PIC_LIST_X );
1568    puIdx++;
1569  }
1570
1571  setWpScalingDistParam( -1, REF_PIC_LIST_X, cu.cs->slice );
1572
1573  return;
1574}
1575
1576
1577
1578
1579// AMVP
1580void InterSearch::xEstimateMvPredAMVP( PredictionUnit& pu, PelUnitBuf& origBuf, RefPicList eRefPicList, int iRefIdx, Mv& rcMvPred, AMVPInfo& rAMVPInfo, bool bFilled, Distortion* puiDistBiP )
1581{
1582  Mv         cBestMv;
1583  int        iBestIdx   = 0;
1584  Distortion uiBestCost = std::numeric_limits<Distortion>::max();
1585  int        i;
1586
1587  AMVPInfo*  pcAMVPInfo = &rAMVPInfo;
1588
1589  // Fill the MV Candidates
1590  if (!bFilled)
1591  {
1592#if JEM_TOOLS
1593    PU::fillMvpCand( pu, eRefPicList, iRefIdx, *pcAMVPInfo, this );
1594#else
1595    PU::fillMvpCand( pu, eRefPicList, iRefIdx, *pcAMVPInfo );
1596#endif
1597  }
1598
1599  // initialize Mvp index & Mvp
1600  iBestIdx = 0;
1601  cBestMv  = pcAMVPInfo->mvCand[0];
1602
1603  PelUnitBuf predBuf = m_tmpStorageLCU.getBuf( UnitAreaRelative(*pu.cu, pu) );
1604
1605  //-- Check Minimum Cost.
1606  for( i = 0 ; i < pcAMVPInfo->numCand; i++)
1607  {
1608    Distortion uiTmpCost = xGetTemplateCost( pu, origBuf, predBuf, pcAMVPInfo->mvCand[i], i, AMVP_MAX_NUM_CANDS, eRefPicList, iRefIdx );
1609    if( uiBestCost > uiTmpCost )
1610    {
1611      uiBestCost     = uiTmpCost;
1612      cBestMv        = pcAMVPInfo->mvCand[i];
1613      iBestIdx       = i;
1614      (*puiDistBiP)  = uiTmpCost;
1615    }
1616  }
1617
1618  // Setting Best MVP
1619  rcMvPred = cBestMv;
1620  pu.mvpIdx[eRefPicList] = iBestIdx;
1621  pu.mvpNum[eRefPicList] = pcAMVPInfo->numCand;
1622
1623  return;
1624}
1625
1626uint32_t InterSearch::xGetMvpIdxBits(int iIdx, int iNum)
1627{
1628  CHECK(iIdx < 0 || iNum < 0 || iIdx >= iNum, "Invalid parameters");
1629
1630  if (iNum == 1)
1631  {
1632    return 0;
1633  }
1634
1635  uint32_t uiLength = 1;
1636  int iTemp = iIdx;
1637  if ( iTemp == 0 )
1638  {
1639    return uiLength;
1640  }
1641
1642  bool bCodeLast = ( iNum-1 > iTemp );
1643
1644  uiLength += (iTemp-1);
1645
1646  if( bCodeLast )
1647  {
1648    uiLength++;
1649  }
1650
1651  return uiLength;
1652}
1653
1654void InterSearch::xGetBlkBits( PartSize eCUMode, bool bPSlice, int iPartIdx, uint32_t uiLastMode, uint32_t uiBlkBit[3])
1655{
1656  if ( eCUMode == SIZE_2Nx2N )
1657  {
1658    uiBlkBit[0] = (! bPSlice) ? 3 : 1;
1659    uiBlkBit[1] = 3;
1660    uiBlkBit[2] = 5;
1661  }
1662  else
1663  {
1664    THROW("Wrong part size!");
1665  }
1666}
1667
1668void InterSearch::xCopyAMVPInfo (AMVPInfo* pSrc, AMVPInfo* pDst)
1669{
1670  pDst->numCand = pSrc->numCand;
1671  for (int i = 0; i < pSrc->numCand; i++)
1672  {
1673    pDst->mvCand[i] = pSrc->mvCand[i];
1674  }
1675}
1676
1677#if JVET_K0357_AMVR
1678void InterSearch::xCheckBestMVP ( RefPicList eRefPicList, Mv cMv, Mv& rcMvPred, int& riMVPIdx, AMVPInfo& amvpInfo, uint32_t& ruiBits, Distortion& ruiCost, const uint8_t imv )
1679#else
1680void InterSearch::xCheckBestMVP ( RefPicList eRefPicList, Mv cMv, Mv& rcMvPred, int& riMVPIdx, AMVPInfo& amvpInfo, uint32_t& ruiBits, Distortion& ruiCost )
1681#endif
1682{
1683#if JVET_K0357_AMVR
1684  if( imv > 0 )
1685  {
1686    return;
1687  }
1688  unsigned imvshift = imv << 1;
1689#endif
1690
1691  AMVPInfo* pcAMVPInfo = &amvpInfo;
1692
1693  CHECK(pcAMVPInfo->mvCand[riMVPIdx] != rcMvPred, "Invalid MV prediction candidate");
1694
1695  if (pcAMVPInfo->numCand < 2)
1696  {
1697    return;
1698  }
1699
1700  m_pcRdCost->setCostScale ( 0    );
1701
1702  int iBestMVPIdx = riMVPIdx;
1703
1704  m_pcRdCost->setPredictor( rcMvPred );
1705#if JVET_K0357_AMVR
1706  int iOrgMvBits = m_pcRdCost->getBitsOfVectorWithPredictor(cMv.getHor(), cMv.getVer(), imvshift);
1707#else
1708  int iOrgMvBits = m_pcRdCost->getBitsOfVectorWithPredictor(cMv.getHor(), cMv.getVer());
1709#endif
1710  iOrgMvBits += m_auiMVPIdxCost[riMVPIdx][AMVP_MAX_NUM_CANDS];
1711  int iBestMvBits = iOrgMvBits;
1712
1713  for (int iMVPIdx = 0; iMVPIdx < pcAMVPInfo->numCand; iMVPIdx++)
1714  {
1715    if (iMVPIdx == riMVPIdx)
1716    {
1717      continue;
1718    }
1719
1720    m_pcRdCost->setPredictor( pcAMVPInfo->mvCand[iMVPIdx] );
1721#if JVET_K0357_AMVR
1722    int iMvBits = m_pcRdCost->getBitsOfVectorWithPredictor(cMv.getHor(), cMv.getVer(), imvshift);
1723#else
1724    int iMvBits = m_pcRdCost->getBitsOfVectorWithPredictor(cMv.getHor(), cMv.getVer());
1725#endif
1726    iMvBits += m_auiMVPIdxCost[iMVPIdx][AMVP_MAX_NUM_CANDS];
1727
1728    if (iMvBits < iBestMvBits)
1729    {
1730      iBestMvBits = iMvBits;
1731      iBestMVPIdx = iMVPIdx;
1732    }
1733  }
1734
1735  if (iBestMVPIdx != riMVPIdx)  //if changed
1736  {
1737    rcMvPred = pcAMVPInfo->mvCand[iBestMVPIdx];
1738
1739    riMVPIdx = iBestMVPIdx;
1740    uint32_t uiOrgBits = ruiBits;
1741    ruiBits = uiOrgBits - iOrgMvBits + iBestMvBits;
1742    ruiCost = (ruiCost - m_pcRdCost->getCost( uiOrgBits ))  + m_pcRdCost->getCost( ruiBits );
1743  }
1744}
1745
1746
1747Distortion InterSearch::xGetTemplateCost( const PredictionUnit& pu,
1748                                          PelUnitBuf& origBuf,
1749                                          PelUnitBuf& predBuf,
1750                                          Mv          cMvCand,
1751                                          int         iMVPIdx,
1752                                          int         iMVPNum,
1753                                          RefPicList  eRefPicList,
1754                                          int         iRefIdx
1755)
1756{
1757  Distortion uiCost = std::numeric_limits<Distortion>::max();
1758
1759  const Picture* picRef = pu.cu->slice->getRefPic( eRefPicList, iRefIdx );
1760
1761  clipMv( cMvCand, pu.cu->lumaPos(), *pu.cs->sps );
1762
1763
1764  // prediction pattern
1765#if JEM_TOOLS
1766  const bool bi = !pu.cu->LICFlag && pu.cu->slice->testWeightPred() && pu.cu->slice->getSliceType()==P_SLICE;
1767#else
1768  const bool bi = pu.cu->slice->testWeightPred() && pu.cu->slice->getSliceType()==P_SLICE;
1769#endif
1770
1771
1772  xPredInterBlk( COMPONENT_Y, pu, picRef, cMvCand, predBuf, bi, pu.cu->slice->clpRng( COMPONENT_Y )
1773#if JEM_TOOLS
1774                , false, false, FRUC_MERGE_OFF, true
1775#endif
1776                );
1777
1778
1779  if ( bi )
1780  {
1781    xWeightedPredictionUni( pu, predBuf, eRefPicList, predBuf, iRefIdx, m_maxCompIDToPred );
1782  }
1783
1784  // calc distortion
1785
1786  uiCost  = m_pcRdCost->getDistPart( origBuf.Y(), predBuf.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, DF_SAD );
1787  uiCost += m_pcRdCost->getCost( m_auiMVPIdxCost[iMVPIdx][iMVPNum] );
1788
1789  return uiCost;
1790}
1791
1792#if JEM_TOOLS || JVET_K_AFFINE
1793Distortion InterSearch::xGetAffineTemplateCost( PredictionUnit& pu, PelUnitBuf& origBuf, PelUnitBuf& predBuf, Mv acMvCand[3], int iMVPIdx, int iMVPNum, RefPicList eRefPicList, int iRefIdx )
1794{
1795  Distortion uiCost = std::numeric_limits<Distortion>::max();
1796
1797  const Picture* picRef = pu.cu->slice->getRefPic( eRefPicList, iRefIdx );
1798
1799  // prediction pattern
1800  const bool bi = pu.cu->slice->testWeightPred() && pu.cu->slice->getSliceType()==P_SLICE;
1801  xPredAffineBlk( COMPONENT_Y, pu, picRef, acMvCand, predBuf, bi, pu.cu->slice->clpRng( COMPONENT_Y ) );
1802  if( bi )
1803  {
1804    xWeightedPredictionUni( pu, predBuf, eRefPicList, predBuf, iRefIdx, m_maxCompIDToPred );
1805  }
1806
1807  // calc distortion
1808
1809  uiCost  = m_pcRdCost->getDistPart( origBuf.Y(), predBuf.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, DF_SAD );
1810  uiCost += m_pcRdCost->getCost( m_auiMVPIdxCost[iMVPIdx][iMVPNum] );
1811  DTRACE( g_trace_ctx, D_COMMON, " (%d) affineTemplateCost=%d\n", DTRACE_GET_COUNTER(g_trace_ctx,D_COMMON), uiCost );
1812  return uiCost;
1813}
1814#endif
1815
1816void InterSearch::xMotionEstimation(PredictionUnit& pu, PelUnitBuf& origBuf, RefPicList eRefPicList, Mv& rcMvPred, int iRefIdxPred, Mv& rcMv, int& riMVPIdx, uint32_t& ruiBits, Distortion& ruiCost, const AMVPInfo& amvpInfo, bool bBi)
1817{
1818  Mv cMvHalf, cMvQter;
1819
1820  CHECK(eRefPicList >= MAX_NUM_REF_LIST_ADAPT_SR || iRefIdxPred>=int(MAX_IDX_ADAPT_SR), "Invalid reference picture list");
1821  m_iSearchRange = m_aaiAdaptSR[eRefPicList][iRefIdxPred];
1822
1823  int    iSrchRng   = (bBi ? m_bipredSearchRange : m_iSearchRange);
1824  double fWeight    = 1.0;
1825
1826  PelUnitBuf  origBufTmp = m_tmpStorageLCU.getBuf( UnitAreaRelative(*pu.cu, pu) );
1827  PelUnitBuf* pBuf       = &origBuf;
1828
1829  if(bBi) // Bi-predictive ME
1830  {
1831    // NOTE: Other buf contains predicted signal from another direction
1832    PelUnitBuf otherBuf = m_tmpPredStorage[1 - (int)eRefPicList].getBuf( UnitAreaRelative(*pu.cu, pu ));
1833    origBufTmp.copyFrom(origBuf);
1834    origBufTmp.removeHighFreq(otherBuf, m_pcEncCfg->getClipForBiPredMeEnabled(), pu.cu->slice->clpRngs() );
1835
1836    pBuf = &origBufTmp;
1837
1838    fWeight = 0.5;
1839  }
1840  m_cDistParam.isBiPred = bBi;
1841#if JEM_TOOLS
1842  m_cDistParam.useMR    = pu.cu->LICFlag;
1843#endif
1844
1845  //  Search key pattern initialization
1846  CPelBuf  tmpPattern   = pBuf->Y();
1847  CPelBuf* pcPatternKey = &tmpPattern;
1848
1849  m_lumaClpRng = pu.cs->slice->clpRng( COMPONENT_Y );
1850
1851  CPelBuf buf = pu.cu->slice->getRefPic(eRefPicList, iRefIdxPred)->getRecoBuf(pu.blocks[COMPONENT_Y]);
1852
1853  IntTZSearchStruct cStruct;
1854  cStruct.pcPatternKey  = pcPatternKey;
1855  cStruct.iRefStride    = buf.stride;
1856  cStruct.piRefY        = buf.buf;
1857#if JVET_K0357_AMVR
1858  cStruct.imvShift      = pu.cu->imv << 1;
1859#endif
1860  auto blkCache = dynamic_cast<CacheBlkInfoCtrl*>( m_modeCtrl );
1861
1862  bool bQTBTMV  = false;
1863  bool bQTBTMV2 = false;
1864  Mv cIntMv;
1865  if( !bBi )
1866  {
1867    bool bValid = blkCache && blkCache->getMv( pu, eRefPicList, iRefIdxPred, cIntMv );
1868    if( bValid )
1869    {
1870      bQTBTMV2 = true;
1871      cIntMv <<= 2;
1872    }
1873  }
1874
1875
1876  m_pcRdCost->setPredictor( rcMvPred );
1877
1878  m_pcRdCost->setCostScale(2);
1879
1880#if JEM_TOOLS
1881  if( pu.cu->LICFlag )
1882  {
1883    m_cDistParam.applyWeight = false;
1884  }
1885  else
1886#endif
1887  {
1888    setWpScalingDistParam(iRefIdxPred, eRefPicList, pu.cu->slice);
1889  }
1890
1891  //  Do integer search
1892  if( ( m_motionEstimationSearchMethod == MESEARCH_FULL ) || bBi || bQTBTMV )
1893  {
1894    if( !bQTBTMV )
1895    {
1896      xSetSearchRange( pu, ( bBi ? rcMv : rcMvPred ), iSrchRng, cStruct.searchRange );
1897    }
1898    cStruct.subShiftMode = m_pcEncCfg->getFastInterSearchMode() == FASTINTERSEARCH_MODE1 || m_pcEncCfg->getFastInterSearchMode() == FASTINTERSEARCH_MODE3 ? 2 : 0;
1899    xPatternSearch( cStruct, rcMv, ruiCost);
1900  }
1901  else if( bQTBTMV2 )
1902  {
1903    rcMv = cIntMv;
1904
1905    cStruct.subShiftMode = ( !m_pcEncCfg->getRestrictMESampling() && m_pcEncCfg->getMotionEstimationSearchMethod() == MESEARCH_SELECTIVE ) ? 1 :
1906                            ( m_pcEncCfg->getFastInterSearchMode() == FASTINTERSEARCH_MODE1 || m_pcEncCfg->getFastInterSearchMode() == FASTINTERSEARCH_MODE3 ) ? 2 : 0;
1907    xTZSearch( pu, cStruct, rcMv, ruiCost, NULL, false, true );
1908  }
1909  else
1910  {
1911    cStruct.subShiftMode = ( !m_pcEncCfg->getRestrictMESampling() && m_pcEncCfg->getMotionEstimationSearchMethod() == MESEARCH_SELECTIVE ) ? 1 :
1912                            ( m_pcEncCfg->getFastInterSearchMode() == FASTINTERSEARCH_MODE1 || m_pcEncCfg->getFastInterSearchMode() == FASTINTERSEARCH_MODE3 ) ? 2 : 0;
1913    rcMv = rcMvPred;
1914    const Mv *pIntegerMv2Nx2NPred = 0;
1915    if( !pu.cs->pcv->only2Nx2N && ( pu.cu->partSize != SIZE_2Nx2N || pu.cu->qtDepth != 0 ) )
1916    {
1917      pIntegerMv2Nx2NPred = &( m_integerMv2Nx2N[eRefPicList][iRefIdxPred] );
1918    }
1919    xPatternSearchFast( pu, cStruct, rcMv, ruiCost, pIntegerMv2Nx2NPred );
1920    if( blkCache )
1921    {
1922      blkCache->setMv( pu.cs->area, eRefPicList, iRefIdxPred, rcMv );
1923    }
1924    else if( pu.cu->partSize == SIZE_2Nx2N )
1925    {
1926      m_integerMv2Nx2N[eRefPicList][iRefIdxPred] = rcMv;
1927    }
1928  }
1929
1930#if JEM_TOOLS
1931  DTRACE( g_trace_ctx, D_ME, "%d %d %d :MECostFPel<L%d,%d>: %d,%d,%dx%d,%2d: %d", DTRACE_GET_COUNTER( g_trace_ctx, D_ME ), pu.cu->slice->getPOC(), pu.cu->imv, (int)eRefPicList, (int)bBi, pu.Y().x, pu.Y().y, pu.Y().width, pu.Y().height, pu.cu->partSize, ruiCost );
1932#else
1933  DTRACE( g_trace_ctx, D_ME, "%d %d %d :MECostFPel<L%d,%d>: %d,%d,%dx%d,%2d: %d", DTRACE_GET_COUNTER( g_trace_ctx, D_ME ), pu.cu->slice->getPOC(), 0, ( int ) eRefPicList, ( int ) bBi, pu.Y().x, pu.Y().y, pu.Y().width, pu.Y().height, pu.cu->partSize, ruiCost );
1934#endif
1935  // sub-pel refinement for sub-pel resolution
1936#if JVET_K0357_AMVR
1937  if( pu.cu->imv == 0 )
1938#endif
1939  {
1940    xPatternSearchFracDIF( pu, eRefPicList, iRefIdxPred, cStruct, rcMv, cMvHalf, cMvQter, ruiCost );
1941    m_pcRdCost->setCostScale( 0 );
1942    rcMv <<= 2;
1943    rcMv  += ( cMvHalf <<= 1 );
1944    rcMv  += cMvQter;
1945#if JVET_K0357_AMVR
1946    uint32_t uiMvBits = m_pcRdCost->getBitsOfVectorWithPredictor( rcMv.getHor(), rcMv.getVer(), cStruct.imvShift );
1947#else
1948    uint32_t uiMvBits = m_pcRdCost->getBitsOfVectorWithPredictor( rcMv.getHor(), rcMv.getVer() );
1949#endif
1950    ruiBits += uiMvBits;
1951    ruiCost = ( Distortion ) ( floor( fWeight * ( ( double ) ruiCost - ( double ) m_pcRdCost->getCost( uiMvBits ) ) ) + ( double ) m_pcRdCost->getCost( ruiBits ) );
1952  }
1953#if JVET_K0357_AMVR
1954  else // integer refinement for integer-pel and 4-pel resolution
1955  {
1956    xPatternSearchIntRefine( pu, cStruct, rcMv, rcMvPred, riMVPIdx, ruiBits, ruiCost, amvpInfo, fWeight);
1957  }
1958  DTRACE( g_trace_ctx, D_ME, "   MECost<L%d,%d>: %6d (%d)  MV:%d,%d\n", ( int ) eRefPicList, ( int ) bBi, ruiCost, ruiBits, rcMv.getHor() << ( pu.cs->sps->getSpsNext().getUseHighPrecMv() ? 2 : 0 ), rcMv.getVer() << ( pu.cs->sps->getSpsNext().getUseHighPrecMv() ? 2 : 0 ) );
1959#else
1960  DTRACE( g_trace_ctx, D_ME, "   MECost<L%d,%d>: %6d (%d)  MV:%d,%d\n", ( int ) eRefPicList, ( int ) bBi, ruiCost, ruiBits, rcMv.getHor(), rcMv.getVer() );
1961#endif
1962}
1963
1964
1965
1966void InterSearch::xSetSearchRange ( const PredictionUnit& pu,
1967                                    const Mv& cMvPred,
1968                                    const int iSrchRng,
1969                                    SearchRange& sr )
1970{
1971#if JEM_TOOLS || JVET_K0346 || JVET_K_AFFINE
1972  const int iMvShift = cMvPred.highPrec ? 4 : 2;
1973#else
1974  const int iMvShift = 2;
1975#endif
1976  Mv cFPMvPred = cMvPred;
1977  clipMv( cFPMvPred, pu.cu->lumaPos(), *pu.cs->sps );
1978
1979#if JEM_TOOLS || JVET_K0346 || JVET_K_AFFINE
1980  Mv mvTL( cFPMvPred.getHor() - ( iSrchRng << iMvShift ), cFPMvPred.getVer() - ( iSrchRng << iMvShift ), cFPMvPred.highPrec );
1981  Mv mvBR( cFPMvPred.getHor() + ( iSrchRng << iMvShift ), cFPMvPred.getVer() + ( iSrchRng << iMvShift ), cFPMvPred.highPrec );
1982#else
1983  Mv mvTL( cFPMvPred.getHor() - ( iSrchRng << iMvShift ), cFPMvPred.getVer() - ( iSrchRng << iMvShift ) );
1984  Mv mvBR( cFPMvPred.getHor() + ( iSrchRng << iMvShift ), cFPMvPred.getVer() + ( iSrchRng << iMvShift ) );
1985#endif
1986
1987  clipMv( mvTL, pu.cu->lumaPos(), *pu.cs->sps );
1988  clipMv( mvBR, pu.cu->lumaPos(), *pu.cs->sps );
1989
1990  mvTL.divideByPowerOf2( iMvShift );
1991  mvBR.divideByPowerOf2( iMvShift );
1992
1993  sr.left   = mvTL.hor;
1994  sr.top    = mvTL.ver;
1995  sr.right  = mvBR.hor;
1996  sr.bottom = mvBR.ver;
1997}
1998
1999
2000void InterSearch::xPatternSearch( IntTZSearchStruct&    cStruct,
2001                                  Mv&            rcMv,
2002                                  Distortion&    ruiSAD )
2003{
2004  Distortion  uiSad;
2005  Distortion  uiSadBest = std::numeric_limits<Distortion>::max();
2006  int         iBestX = 0;
2007  int         iBestY = 0;
2008
2009  //-- jclee for using the SAD function pointer
2010  m_pcRdCost->setDistParam( m_cDistParam, *cStruct.pcPatternKey, cStruct.piRefY, cStruct.iRefStride, m_lumaClpRng.bd, COMPONENT_Y, cStruct.subShiftMode );
2011
2012  const SearchRange& sr = cStruct.searchRange;
2013
2014  const Pel* piRef = cStruct.piRefY + (sr.top * cStruct.iRefStride);
2015  for ( int y = sr.top; y <= sr.bottom; y++ )
2016  {
2017    for ( int x = sr.left; x <= sr.right; x++ )
2018    {
2019      //  find min. distortion position
2020      m_cDistParam.cur.buf = piRef + x;
2021
2022      uiSad = m_cDistParam.distFunc( m_cDistParam );
2023
2024      // motion cost
2025#if JVET_K0357_AMVR
2026      uiSad += m_pcRdCost->getCostOfVectorWithPredictor( x, y, cStruct.imvShift );
2027#else
2028      uiSad += m_pcRdCost->getCostOfVectorWithPredictor( x, y );
2029#endif
2030
2031      if ( uiSad < uiSadBest )
2032      {
2033        uiSadBest = uiSad;
2034        iBestX    = x;
2035        iBestY    = y;
2036        m_cDistParam.maximumDistortionForEarlyExit = uiSad;
2037      }
2038    }
2039    piRef += cStruct.iRefStride;
2040  }
2041
2042#if JEM_TOOLS || JVET_K0346 || JVET_K_AFFINE
2043  CHECK( rcMv.highPrec, "Unexpected high precision MV." );
2044#endif
2045  rcMv.set( iBestX, iBestY );
2046
2047  cStruct.uiBestSad = uiSadBest; // th for testing
2048#if JVET_K0357_AMVR
2049  ruiSAD = uiSadBest - m_pcRdCost->getCostOfVectorWithPredictor( iBestX, iBestY, cStruct.imvShift );
2050#else
2051  ruiSAD = uiSadBest - m_pcRdCost->getCostOfVectorWithPredictor( iBestX, iBestY );
2052#endif
2053  return;
2054}
2055
2056
2057void InterSearch::xPatternSearchFast( const PredictionUnit& pu,
2058                                      IntTZSearchStruct&    cStruct,
2059                                      Mv&                   rcMv,
2060                                      Distortion&           ruiSAD,
2061                                      const Mv* const       pIntegerMv2Nx2NPred )
2062{
2063  switch ( m_motionEstimationSearchMethod )
2064  {
2065  case MESEARCH_DIAMOND:
2066    xTZSearch         ( pu, cStruct, rcMv, ruiSAD, pIntegerMv2Nx2NPred, false );
2067    break;
2068
2069  case MESEARCH_SELECTIVE:
2070    xTZSearchSelective( pu, cStruct, rcMv, ruiSAD, pIntegerMv2Nx2NPred );
2071    break;
2072
2073  case MESEARCH_DIAMOND_ENHANCED:
2074    xTZSearch         ( pu, cStruct, rcMv, ruiSAD, pIntegerMv2Nx2NPred, true );
2075    break;
2076
2077  case MESEARCH_FULL: // shouldn't get here.
2078  default:
2079    break;
2080  }
2081}
2082
2083
2084void InterSearch::xTZSearch( const PredictionUnit& pu,
2085                             IntTZSearchStruct&    cStruct,
2086                             Mv&                   rcMv,
2087                             Distortion&           ruiSAD,
2088                             const Mv* const       pIntegerMv2Nx2NPred,
2089                             const bool            bExtendedSettings,
2090                             const bool            bFastSettings)
2091{
2092  const bool bUseRasterInFastMode                    = true; //toggle this to further reduce runtime
2093
2094  const bool bUseAdaptiveRaster                      = bExtendedSettings;
2095  const int  iRaster                                 = (bFastSettings && bUseRasterInFastMode) ? 8 : 5;
2096  const bool bTestZeroVector                         = true && !bFastSettings;
2097  const bool bTestZeroVectorStart                    = bExtendedSettings;
2098  const bool bTestZeroVectorStop                     = false;
2099  const bool bFirstSearchDiamond                     = true;  // 1 = xTZ8PointDiamondSearch   0 = xTZ8PointSquareSearch
2100  const bool bFirstCornersForDiamondDist1            = bExtendedSettings;
2101  const bool bFirstSearchStop                        = m_pcEncCfg->getFastMEAssumingSmootherMVEnabled();
2102  const uint32_t uiFirstSearchRounds                     = bFastSettings ? (bUseRasterInFastMode?3:2) : 3;     // first search stop X rounds after best match (must be >=1)
2103  const bool bEnableRasterSearch                     = bFastSettings ? bUseRasterInFastMode : true;
2104  const bool bAlwaysRasterSearch                     = bExtendedSettings;  // true: BETTER but factor 2 slower
2105  const bool bRasterRefinementEnable                 = false; // enable either raster refinement or star refinement
2106  const bool bRasterRefinementDiamond                = false; // 1 = xTZ8PointDiamondSearch   0 = xTZ8PointSquareSearch
2107  const bool bRasterRefinementCornersForDiamondDist1 = bExtendedSettings;
2108  const bool bStarRefinementEnable                   = true;  // enable either star refinement or raster refinement
2109  const bool bStarRefinementDiamond                  = true;  // 1 = xTZ8PointDiamondSearch   0 = xTZ8PointSquareSearch
2110  const bool bStarRefinementCornersForDiamondDist1   = bExtendedSettings;
2111  const bool bStarRefinementStop                     = false || bFastSettings;
2112  const uint32_t uiStarRefinementRounds                  = 2;  // star refinement stop X rounds after best match (must be >=1)
2113  const bool bNewZeroNeighbourhoodTest               = bExtendedSettings;
2114
2115  int iSearchRange = m_iSearchRange;
2116
2117  clipMv( rcMv, pu.cu->lumaPos(), *pu.cs->sps );
2118  rcMv.divideByPowerOf2(2);
2119
2120  // init TZSearchStruct
2121#if DISTORTION_TYPE_BUGFIX
2122  cStruct.uiBestSad = std::numeric_limits<Distortion>::max();
2123#else
2124  cStruct.uiBestSad   = MAX_UINT;
2125#endif
2126
2127  //
2128  m_cDistParam.maximumDistortionForEarlyExit = cStruct.uiBestSad;
2129  m_pcRdCost->setDistParam( m_cDistParam, *cStruct.pcPatternKey, cStruct.piRefY, cStruct.iRefStride, m_lumaClpRng.bd, COMPONENT_Y, cStruct.subShiftMode );
2130
2131  // distortion
2132
2133
2134  // set rcMv (Median predictor) as start point and as best point
2135  xTZSearchHelp( cStruct, rcMv.getHor(), rcMv.getVer(), 0, 0 );
2136
2137  // test whether zero Mv is better start point than Median predictor
2138  if ( bTestZeroVector )
2139  {
2140    if ((rcMv.getHor() != 0 || rcMv.getVer() != 0) &&
2141      (0 != cStruct.iBestX || 0 != cStruct.iBestY))
2142    {
2143      // only test 0-vector if not obviously previously tested.
2144      xTZSearchHelp( cStruct, 0, 0, 0, 0 );
2145    }
2146  }
2147
2148  SearchRange& sr = cStruct.searchRange;
2149
2150  if (pIntegerMv2Nx2NPred != 0)
2151  {
2152    Mv integerMv2Nx2NPred = *pIntegerMv2Nx2NPred;
2153    integerMv2Nx2NPred <<= 2;
2154    clipMv( integerMv2Nx2NPred, pu.cu->lumaPos(), *pu.cs->sps );
2155    integerMv2Nx2NPred.divideByPowerOf2(2);
2156
2157    if ((rcMv != integerMv2Nx2NPred) &&
2158      (integerMv2Nx2NPred.getHor() != cStruct.iBestX || integerMv2Nx2NPred.getVer() != cStruct.iBestY))
2159    {
2160      // only test integerMv2Nx2NPred if not obviously previously tested.
2161      xTZSearchHelp( cStruct, integerMv2Nx2NPred.getHor(), integerMv2Nx2NPred.getVer(), 0, 0);
2162    }
2163  }
2164  {
2165    // set search range
2166    Mv currBestMv(cStruct.iBestX, cStruct.iBestY );
2167    currBestMv <<= 2;
2168    xSetSearchRange( pu, currBestMv, m_iSearchRange>>(bFastSettings?1:0), sr );
2169  }
2170
2171  // start search
2172  int  iDist = 0;
2173  int  iStartX = cStruct.iBestX;
2174  int  iStartY = cStruct.iBestY;
2175
2176  const bool bBestCandidateZero = (cStruct.iBestX == 0) && (cStruct.iBestY == 0);
2177
2178  // first search around best position up to now.
2179  // The following works as a "subsampled/log" window search around the best candidate
2180  for ( iDist = 1; iDist <= iSearchRange; iDist*=2 )
2181  {
2182    if ( bFirstSearchDiamond == 1 )
2183    {
2184      xTZ8PointDiamondSearch ( cStruct, iStartX, iStartY, iDist, bFirstCornersForDiamondDist1 );
2185    }
2186    else
2187    {
2188      xTZ8PointSquareSearch  ( cStruct, iStartX, iStartY, iDist );
2189    }
2190
2191    if ( bFirstSearchStop && ( cStruct.uiBestRound >= uiFirstSearchRounds ) ) // stop criterion
2192    {
2193      break;
2194    }
2195  }
2196
2197  if (!bNewZeroNeighbourhoodTest)
2198  {
2199    // test whether zero Mv is a better start point than Median predictor
2200    if ( bTestZeroVectorStart && ((cStruct.iBestX != 0) || (cStruct.iBestY != 0)) )
2201    {
2202      xTZSearchHelp( cStruct, 0, 0, 0, 0 );
2203      if ( (cStruct.iBestX == 0) && (cStruct.iBestY == 0) )
2204      {
2205        // test its neighborhood
2206        for ( iDist = 1; iDist <= iSearchRange; iDist*=2 )
2207        {
2208          xTZ8PointDiamondSearch( cStruct, 0, 0, iDist, false );
2209          if ( bTestZeroVectorStop && (cStruct.uiBestRound > 0) ) // stop criterion
2210          {
2211            break;
2212          }
2213        }
2214      }
2215    }
2216  }
2217  else
2218  {
2219    // Test also zero neighbourhood but with half the range
2220    // It was reported that the original (above) search scheme using bTestZeroVectorStart did not
2221    // make sense since one would have already checked the zero candidate earlier
2222    // and thus the conditions for that test would have not been satisfied
2223    if (bTestZeroVectorStart == true && bBestCandidateZero != true)
2224    {
2225      for ( iDist = 1; iDist <= (iSearchRange >> 1); iDist*=2 )
2226      {
2227        xTZ8PointDiamondSearch( cStruct, 0, 0, iDist, false );
2228        if ( bTestZeroVectorStop && (cStruct.uiBestRound > 2) ) // stop criterion
2229        {
2230          break;
2231        }
2232      }
2233    }
2234  }
2235
2236  // calculate only 2 missing points instead 8 points if cStruct.uiBestDistance == 1
2237  if ( cStruct.uiBestDistance == 1 )
2238  {
2239    cStruct.uiBestDistance = 0;
2240    xTZ2PointSearch( cStruct );
2241  }
2242
2243  // raster search if distance is too big
2244  if (bUseAdaptiveRaster)
2245  {
2246    int iWindowSize     = iRaster;
2247    SearchRange localsr = sr;
2248
2249    if (!(bEnableRasterSearch && ( ((int)(cStruct.uiBestDistance) >= iRaster))))
2250    {
2251      iWindowSize ++;
2252      localsr.left   /= 2;
2253      localsr.right  /= 2;
2254      localsr.top    /= 2;
2255      localsr.bottom /= 2;
2256    }
2257    cStruct.uiBestDistance = iWindowSize;
2258    for ( iStartY = localsr.top; iStartY <= localsr.bottom; iStartY += iWindowSize )
2259    {
2260      for ( iStartX = localsr.left; iStartX <= localsr.right; iStartX += iWindowSize )
2261      {
2262        xTZSearchHelp( cStruct, iStartX, iStartY, 0, iWindowSize );
2263      }
2264    }
2265  }
2266  else
2267  {
2268    if ( bEnableRasterSearch && ( ((int)(cStruct.uiBestDistance) >= iRaster) || bAlwaysRasterSearch ) )
2269    {
2270      cStruct.uiBestDistance = iRaster;
2271      for ( iStartY = sr.top; iStartY <= sr.bottom; iStartY += iRaster )
2272      {
2273        for ( iStartX = sr.left; iStartX <= sr.right; iStartX += iRaster )
2274        {
2275          xTZSearchHelp( cStruct, iStartX, iStartY, 0, iRaster );
2276        }
2277      }
2278    }
2279  }
2280
2281  // raster refinement
2282
2283  if ( bRasterRefinementEnable && cStruct.uiBestDistance > 0 )
2284  {
2285    while ( cStruct.uiBestDistance > 0 )
2286    {
2287      iStartX = cStruct.iBestX;
2288      iStartY = cStruct.iBestY;
2289      if ( cStruct.uiBestDistance > 1 )
2290      {
2291        iDist = cStruct.uiBestDistance >>= 1;
2292        if ( bRasterRefinementDiamond == 1 )
2293        {
2294          xTZ8PointDiamondSearch ( cStruct, iStartX, iStartY, iDist, bRasterRefinementCornersForDiamondDist1 );
2295        }
2296        else
2297        {
2298          xTZ8PointSquareSearch  ( cStruct, iStartX, iStartY, iDist );
2299        }
2300      }
2301
2302      // calculate only 2 missing points instead 8 points if cStruct.uiBestDistance == 1
2303      if ( cStruct.uiBestDistance == 1 )
2304      {
2305        cStruct.uiBestDistance = 0;
2306        if ( cStruct.ucPointNr != 0 )
2307        {
2308          xTZ2PointSearch( cStruct );
2309        }
2310      }
2311    }
2312  }
2313
2314  // star refinement
2315  if ( bStarRefinementEnable && cStruct.uiBestDistance > 0 )
2316  {
2317    while ( cStruct.uiBestDistance > 0 )
2318    {
2319      iStartX = cStruct.iBestX;
2320      iStartY = cStruct.iBestY;
2321      cStruct.uiBestDistance = 0;
2322      cStruct.ucPointNr = 0;
2323      for ( iDist = 1; iDist < iSearchRange + 1; iDist*=2 )
2324      {
2325        if ( bStarRefinementDiamond == 1 )
2326        {
2327          xTZ8PointDiamondSearch ( cStruct, iStartX, iStartY, iDist, bStarRefinementCornersForDiamondDist1 );
2328        }
2329        else
2330        {
2331          xTZ8PointSquareSearch  ( cStruct, iStartX, iStartY, iDist );
2332        }
2333        if ( bStarRefinementStop && (cStruct.uiBestRound >= uiStarRefinementRounds) ) // stop criterion
2334        {
2335          break;
2336        }
2337      }
2338
2339      // calculate only 2 missing points instead 8 points if cStrukt.uiBestDistance == 1
2340      if ( cStruct.uiBestDistance == 1 )
2341      {
2342        cStruct.uiBestDistance = 0;
2343        if ( cStruct.ucPointNr != 0 )
2344        {
2345          xTZ2PointSearch( cStruct );
2346        }
2347      }
2348    }
2349  }
2350
2351  // write out best match
2352#if JEM_TOOLS || JVET_K0346 || JVET_K_AFFINE
2353  CHECK( rcMv.highPrec, "Unexpected high precision MV." );
2354#endif
2355  rcMv.set( cStruct.iBestX, cStruct.iBestY );
2356#if JVET_K0357_AMVR
2357  ruiSAD = cStruct.uiBestSad - m_pcRdCost->getCostOfVectorWithPredictor( cStruct.iBestX, cStruct.iBestY, cStruct.imvShift );
2358#else
2359  ruiSAD = cStruct.uiBestSad - m_pcRdCost->getCostOfVectorWithPredictor( cStruct.iBestX, cStruct.iBestY );
2360#endif
2361}
2362
2363
2364void InterSearch::xTZSearchSelective( const PredictionUnit& pu,
2365                                      IntTZSearchStruct&    cStruct,
2366                                      Mv                    &rcMv,
2367                                      Distortion            &ruiSAD,
2368                                      const Mv* const       pIntegerMv2Nx2NPred )
2369{
2370  const bool bTestZeroVector          = true;
2371  const bool bEnableRasterSearch      = true;
2372  const bool bAlwaysRasterSearch      = false;  // 1: BETTER but factor 15x slower
2373  const bool bStarRefinementEnable    = true;   // enable either star refinement or raster refinement
2374  const bool bStarRefinementDiamond   = true;   // 1 = xTZ8PointDiamondSearch   0 = xTZ8PointSquareSearch
2375  const bool bStarRefinementStop      = false;
2376  const uint32_t uiStarRefinementRounds   = 2;  // star refinement stop X rounds after best match (must be >=1)
2377  const int  iSearchRange             = m_iSearchRange;
2378  const int  iSearchRangeInitial      = m_iSearchRange >> 2;
2379  const int  uiSearchStep             = 4;
2380  const int  iMVDistThresh            = 8;
2381
2382  int   iStartX                 = 0;
2383  int   iStartY                 = 0;
2384  int   iDist                   = 0;
2385
2386  clipMv( rcMv, pu.cu->lumaPos(), *pu.cs->sps );
2387
2388  rcMv.divideByPowerOf2(2);
2389
2390  // init TZSearchStruct
2391#if DISTORTION_TYPE_BUGFIX
2392  cStruct.uiBestSad = std::numeric_limits<Distortion>::max();
2393#else
2394  cStruct.uiBestSad = MAX_UINT;
2395#endif
2396  cStruct.iBestX = 0;
2397  cStruct.iBestY = 0;
2398
2399  m_cDistParam.maximumDistortionForEarlyExit = cStruct.uiBestSad;
2400  m_pcRdCost->setDistParam( m_cDistParam, *cStruct.pcPatternKey, cStruct.piRefY, cStruct.iRefStride, m_lumaClpRng.bd, COMPONENT_Y, cStruct.subShiftMode );
2401
2402
2403  // set rcMv (Median predictor) as start point and as best point
2404  xTZSearchHelp( cStruct, rcMv.getHor(), rcMv.getVer(), 0, 0 );
2405
2406  // test whether zero Mv is better start point than Median predictor
2407  if ( bTestZeroVector )
2408  {
2409    xTZSearchHelp( cStruct, 0, 0, 0, 0 );
2410  }
2411
2412  SearchRange& sr = cStruct.searchRange;
2413
2414  if ( pIntegerMv2Nx2NPred != 0 )
2415  {
2416    Mv integerMv2Nx2NPred = *pIntegerMv2Nx2NPred;
2417    integerMv2Nx2NPred <<= 2;
2418    clipMv( integerMv2Nx2NPred, pu.cu->lumaPos(), *pu.cs->sps );
2419    integerMv2Nx2NPred.divideByPowerOf2(2);
2420
2421    xTZSearchHelp( cStruct, integerMv2Nx2NPred.getHor(), integerMv2Nx2NPred.getVer(), 0, 0);
2422
2423  }
2424  {
2425    // set search range
2426    Mv currBestMv(cStruct.iBestX, cStruct.iBestY );
2427    currBestMv <<= 2;
2428    xSetSearchRange( pu, currBestMv, m_iSearchRange, sr );
2429  }
2430
2431  // Initial search
2432  int iBestX = cStruct.iBestX;
2433  int iBestY = cStruct.iBestY;
2434  int iFirstSrchRngHorLeft    = ((iBestX - iSearchRangeInitial) > sr.left)   ? (iBestX - iSearchRangeInitial) : sr.left;
2435  int iFirstSrchRngVerTop     = ((iBestY - iSearchRangeInitial) > sr.top)    ? (iBestY - iSearchRangeInitial) : sr.top;
2436  int iFirstSrchRngHorRight   = ((iBestX + iSearchRangeInitial) < sr.right)  ? (iBestX + iSearchRangeInitial) : sr.right;
2437  int iFirstSrchRngVerBottom  = ((iBestY + iSearchRangeInitial) < sr.bottom) ? (iBestY + iSearchRangeInitial) : sr.bottom;
2438
2439  for ( iStartY = iFirstSrchRngVerTop; iStartY <= iFirstSrchRngVerBottom; iStartY += uiSearchStep )
2440  {
2441    for ( iStartX = iFirstSrchRngHorLeft; iStartX <= iFirstSrchRngHorRight; iStartX += uiSearchStep )
2442    {
2443      xTZSearchHelp( cStruct, iStartX, iStartY, 0, 0 );
2444      xTZ8PointDiamondSearch ( cStruct, iStartX, iStartY, 1, false );
2445      xTZ8PointDiamondSearch ( cStruct, iStartX, iStartY, 2, false );
2446    }
2447  }
2448
2449  int iMaxMVDistToPred = (abs(cStruct.iBestX - iBestX) > iMVDistThresh || abs(cStruct.iBestY - iBestY) > iMVDistThresh);
2450
2451  //full search with early exit if MV is distant from predictors
2452  if ( bEnableRasterSearch && (iMaxMVDistToPred || bAlwaysRasterSearch) )
2453  {
2454    for ( iStartY = sr.top; iStartY <= sr.bottom; iStartY += 1 )
2455    {
2456      for ( iStartX = sr.left; iStartX <= sr.right; iStartX += 1 )
2457      {
2458        xTZSearchHelp( cStruct, iStartX, iStartY, 0, 1 );
2459      }
2460    }
2461  }
2462  //Smaller MV, refine around predictor
2463  else if ( bStarRefinementEnable && cStruct.uiBestDistance > 0 )
2464  {
2465    // start refinement
2466    while ( cStruct.uiBestDistance > 0 )
2467    {
2468      iStartX = cStruct.iBestX;
2469      iStartY = cStruct.iBestY;
2470      cStruct.uiBestDistance = 0;
2471      cStruct.ucPointNr = 0;
2472      for ( iDist = 1; iDist < iSearchRange + 1; iDist*=2 )
2473      {
2474        if ( bStarRefinementDiamond == 1 )
2475        {
2476          xTZ8PointDiamondSearch ( cStruct, iStartX, iStartY, iDist, false );
2477        }
2478        else
2479        {
2480          xTZ8PointSquareSearch  ( cStruct, iStartX, iStartY, iDist );
2481        }
2482        if ( bStarRefinementStop && (cStruct.uiBestRound >= uiStarRefinementRounds) ) // stop criterion
2483        {
2484          break;
2485        }
2486      }
2487
2488      // calculate only 2 missing points instead 8 points if cStrukt.uiBestDistance == 1
2489      if ( cStruct.uiBestDistance == 1 )
2490      {
2491        cStruct.uiBestDistance = 0;
2492        if ( cStruct.ucPointNr != 0 )
2493        {
2494          xTZ2PointSearch( cStruct );
2495        }
2496      }
2497    }
2498  }
2499
2500  // write out best match
2501#if JEM_TOOLS || JVET_K0346 || JVET_K_AFFINE
2502  CHECK( rcMv.highPrec, "Unexpected high precision MV." );
2503#endif
2504  rcMv.set( cStruct.iBestX, cStruct.iBestY );
2505#if JVET_K0357_AMVR
2506  ruiSAD = cStruct.uiBestSad - m_pcRdCost->getCostOfVectorWithPredictor( cStruct.iBestX, cStruct.iBestY, cStruct.imvShift );
2507#else
2508  ruiSAD = cStruct.uiBestSad - m_pcRdCost->getCostOfVectorWithPredictor( cStruct.iBestX, cStruct.iBestY );
2509#endif
2510}
2511
2512#if JVET_K0357_AMVR
2513void InterSearch::xPatternSearchIntRefine(PredictionUnit& pu, IntTZSearchStruct&  cStruct, Mv& rcMv, Mv& rcMvPred, int& riMVPIdx, uint32_t& ruiBits, Distortion& ruiCost, const AMVPInfo& amvpInfo, double fWeight)
2514{
2515
2516  CHECK( pu.cu->imv == 0,                       "xPatternSearchIntRefine(): IMV not used.");
2517  CHECK( amvpInfo.mvCand[riMVPIdx] != rcMvPred, "xPatternSearchIntRefine(): MvPred issue.");
2518
2519  const SPS &sps = *pu.cs->sps;
2520  m_pcRdCost->setDistParam( m_cDistParam, *cStruct.pcPatternKey, cStruct.piRefY, cStruct.iRefStride, m_lumaClpRng.bd, COMPONENT_Y, 0, 1, m_pcEncCfg->getUseHADME() && !pu.cu->transQuantBypass );
2521
2522  // input MV rcMV has integer resolution
2523  // -> shift it to QPEL
2524  rcMv <<= 2;
2525  // -> set MV scale for cost calculation to QPEL (0)
2526  m_pcRdCost->setCostScale ( 0 );
2527
2528  Distortion  uiDist, uiSATD = 0;
2529  Distortion  uiBestDist  = std::numeric_limits<Distortion>::max();
2530  // subtract old MVP costs because costs for all newly tested MVPs are added in here
2531  ruiBits -= m_auiMVPIdxCost[riMVPIdx][AMVP_MAX_NUM_CANDS];
2532
2533  Mv cBestMv = rcMv;
2534  Mv cBaseMvd[2];
2535  int iBestBits = 0;
2536  int iBestMVPIdx = riMVPIdx;
2537  int testPos[9][2] = { { 0, 0}, { -1, -1},{ -1, 0},{ -1, 1},{ 0, -1},{ 0, 1},{ 1, -1},{ 1, 0},{ 1, 1} };
2538
2539
2540  cBaseMvd[0] = (rcMv - amvpInfo.mvCand[0]);
2541  cBaseMvd[1] = (rcMv - amvpInfo.mvCand[1]);
2542  CHECK( (cBaseMvd[0].getHor() & 0x03) != 0 || (cBaseMvd[0].getVer() & 0x03) != 0 , "xPatternSearchIntRefine(): AMVP cand 0 Mvd issue.");
2543  CHECK( (cBaseMvd[1].getHor() & 0x03) != 0 || (cBaseMvd[1].getVer() & 0x03) != 0 , "xPatternSearchIntRefine(): AMVP cand 1 Mvd issue.");
2544
2545  roundMV(cBaseMvd[0], cStruct.imvShift);
2546  roundMV(cBaseMvd[1], cStruct.imvShift);
2547
2548  int mvOffset = 1 << cStruct.imvShift;
2549
2550  // test best integer position and all 8 neighboring positions
2551  for (int pos = 0; pos < 9; pos ++)
2552  {
2553    Mv cTestMv[2];
2554    // test both AMVP candidates for each position
2555    for (int iMVPIdx = 0; iMVPIdx < amvpInfo.numCand; iMVPIdx++)
2556    {
2557      cTestMv[iMVPIdx].set(testPos[pos][0]*mvOffset, testPos[pos][1]*mvOffset);
2558      cTestMv[iMVPIdx] += cBaseMvd[iMVPIdx];
2559      cTestMv[iMVPIdx] += amvpInfo.mvCand[iMVPIdx];
2560
2561      if ( iMVPIdx == 0 || cTestMv[0] != cTestMv[1])
2562      {
2563        Mv cTempMV = cTestMv[iMVPIdx];
2564        clipMv(cTempMV, pu.cu->lumaPos(), sps);
2565
2566        m_cDistParam.cur.buf = cStruct.piRefY  + cStruct.iRefStride * (cTempMV.getVer() >>  2) + (cTempMV.getHor() >> 2);
2567        uiDist = uiSATD = (Distortion) (m_cDistParam.distFunc( m_cDistParam ) * fWeight);
2568      }
2569      else
2570      {
2571        uiDist = uiSATD;
2572      }
2573
2574      int iMvBits = m_auiMVPIdxCost[iMVPIdx][AMVP_MAX_NUM_CANDS];
2575      m_pcRdCost->setPredictor( amvpInfo.mvCand[iMVPIdx] );
2576      iMvBits += m_pcRdCost->getBitsOfVectorWithPredictor( cTestMv[iMVPIdx].getHor(), cTestMv[iMVPIdx].getVer(), cStruct.imvShift );
2577      uiDist += m_pcRdCost->getCostOfVectorWithPredictor( cTestMv[iMVPIdx].getHor(), cTestMv[iMVPIdx].getVer(), cStruct.imvShift );
2578
2579      if (uiDist < uiBestDist)
2580      {
2581        uiBestDist = uiDist;
2582        cBestMv = cTestMv[iMVPIdx];
2583        iBestMVPIdx = iMVPIdx;
2584        iBestBits = iMvBits;
2585      }
2586    }
2587  }
2588
2589  rcMv = cBestMv;
2590  rcMvPred = amvpInfo.mvCand[iBestMVPIdx];
2591  riMVPIdx = iBestMVPIdx;
2592  m_pcRdCost->setPredictor( rcMvPred );
2593
2594  ruiBits += iBestBits;
2595  // taken from JEM 5.0
2596  // verify since it makes no sence to subtract Lamda*(Rmvd+Rmvpidx) from D+Lamda(Rmvd)
2597  // this would take the rate for the MVP idx out of the cost calculation
2598  // however this rate is always 1 so impact is small
2599  ruiCost = uiBestDist - m_pcRdCost->getCost(iBestBits) + m_pcRdCost->getCost(ruiBits);
2600  // taken from JEM 5.0
2601  // verify since it makes no sense to add rate for MVDs twicce
2602  ruiBits += m_pcRdCost->getBitsOfVectorWithPredictor(rcMv.getHor(), rcMv.getVer(), cStruct.imvShift);
2603
2604  return;
2605}
2606#endif
2607
2608void InterSearch::xPatternSearchFracDIF(
2609  const PredictionUnit& pu,
2610  RefPicList            eRefPicList,
2611  int                   iRefIdx,
2612  IntTZSearchStruct&    cStruct,
2613  const Mv&             rcMvInt,
2614  Mv&                   rcMvHalf,
2615  Mv&                   rcMvQter,
2616  Distortion&           ruiCost
2617)
2618{
2619  const bool bIsLosslessCoded = pu.cu->transQuantBypass;
2620
2621  //  Reference pattern initialization (integer scale)
2622  int         iOffset    = rcMvInt.getHor() + rcMvInt.getVer() * cStruct.iRefStride;
2623  CPelBuf cPatternRoi(cStruct.piRefY + iOffset, cStruct.iRefStride, *cStruct.pcPatternKey);
2624
2625
2626#if JVET_K0357_AMVR
2627  if( cStruct.imvShift )
2628  {
2629    m_pcRdCost->setDistParam( m_cDistParam, *cStruct.pcPatternKey, cStruct.piRefY + iOffset, cStruct.iRefStride, m_lumaClpRng.bd, COMPONENT_Y, 0, 1, m_pcEncCfg->getUseHADME() && !bIsLosslessCoded );
2630    ruiCost = m_cDistParam.distFunc( m_cDistParam );
2631    ruiCost += m_pcRdCost->getCostOfVectorWithPredictor( rcMvInt.getHor(), rcMvInt.getVer(), cStruct.imvShift );
2632    return;
2633  }
2634#endif
2635
2636  //  Half-pel refinement
2637  m_pcRdCost->setCostScale(1);
2638  xExtDIFUpSamplingH ( &cPatternRoi );
2639
2640  rcMvHalf = rcMvInt;   rcMvHalf <<= 1;    // for mv-cost
2641  Mv baseRefMv(0, 0);
2642  ruiCost = xPatternRefinement(cStruct.pcPatternKey, baseRefMv, 2, rcMvHalf, !bIsLosslessCoded);
2643
2644  //  quarter-pel refinement
2645  m_pcRdCost->setCostScale( 0 );
2646  xExtDIFUpSamplingQ ( &cPatternRoi, rcMvHalf );
2647  baseRefMv = rcMvHalf;
2648  baseRefMv <<= 1;
2649
2650  rcMvQter = rcMvInt;    rcMvQter <<= 1;    // for mv-cost
2651  rcMvQter += rcMvHalf;  rcMvQter <<= 1;
2652  ruiCost = xPatternRefinement( cStruct.pcPatternKey, baseRefMv, 1, rcMvQter, !bIsLosslessCoded );
2653}
2654
2655#if JEM_TOOLS || JVET_K_AFFINE
2656
2657void InterSearch::xPredAffineInterSearch( PredictionUnit&       pu,
2658                                          PelUnitBuf&           origBuf,
2659                                          int                   puIdx,
2660                                          uint32_t&                 lastMode,
2661                                          Distortion&           affineCost,
2662#if JVET_K0220_ENC_CTRL
2663                                          Mv                    hevcMv[2][33]
2664#else
2665                                          Mv                    hevcMv[2][33],
2666                                          bool                  bFastSkipBi
2667#endif
2668#if JVET_K0185_AFFINE_6PARA_ENC
2669                                        , Mv                    mvAffine4Para[2][33][3]
2670                                        , int                   refIdx4Para[2]
2671#endif
2672                                         )
2673{
2674  const Slice &slice = *pu.cu->slice;
2675
2676  affineCost = std::numeric_limits<Distortion>::max();
2677
2678  Mv        cMvZero;
2679  Mv        aacMv[2][3];
2680  Mv        cMvBi[2][3];
2681  Mv        cMvTemp[2][33][3];
2682
2683  int       iNumPredDir = slice.isInterP() ? 1 : 2;
2684
2685  int mvNum = 2;
2686#if JVET_K0185_AFFINE_6PARA_ENC
2687  mvNum = pu.cu->affineType ? 3 : 2;
2688#endif
2689
2690  // Mvp
2691  Mv        cMvPred[2][33][3];
2692  Mv        cMvPredBi[2][33][3];
2693  int       aaiMvpIdxBi[2][33];
2694  int       aaiMvpIdx[2][33];
2695  int       aaiMvpNum[2][33];
2696
2697  AffineAMVPInfo aacAffineAMVPInfo[2][33];
2698  AffineAMVPInfo affiAMVPInfoTemp[2];
2699
2700  int           iRefIdx[2]={0,0}; // If un-initialized, may cause SEGV in bi-directional prediction iterative stage.
2701  int           iRefIdxBi[2];
2702
2703  uint32_t          uiMbBits[3] = {1, 1, 0};
2704
2705  int           iRefStart, iRefEnd;
2706
2707  PartSize      ePartSize = pu.cu->partSize;
2708
2709  int           bestBiPRefIdxL1 = 0;
2710  int           bestBiPMvpL1 = 0;
2711#if DISTORTION_TYPE_BUGFIX
2712  Distortion biPDistTemp = std::numeric_limits<Distortion>::max();
2713#else
2714  uint32_t          biPDistTemp = MAX_INT;
2715#endif
2716
2717  Distortion    uiCost[2] = { std::numeric_limits<Distortion>::max(), std::numeric_limits<Distortion>::max() };
2718  Distortion    uiCostBi  = std::numeric_limits<Distortion>::max();
2719  Distortion    uiCostTemp;
2720
2721  uint32_t          uiBits[3];
2722  uint32_t          uiBitsTemp;
2723  Distortion    bestBiPDist = std::numeric_limits<Distortion>::max();
2724
2725  Distortion    uiCostTempL0[MAX_NUM_REF];
2726  for (int iNumRef=0; iNumRef < MAX_NUM_REF; iNumRef++)
2727  {
2728    uiCostTempL0[iNumRef] = std::numeric_limits<Distortion>::max();
2729  }
2730#if DISTORTION_TYPE_BUGFIX
2731  uint32_t uiBitsTempL0[MAX_NUM_REF];
2732#else
2733  Distortion    uiBitsTempL0[MAX_NUM_REF];
2734#endif
2735
2736  Mv            mvValidList1[4];
2737  int           refIdxValidList1 = 0;
2738  uint32_t          bitsValidList1 = MAX_UINT;
2739#if DISTORTION_TYPE_BUGFIX
2740  Distortion costValidList1 = std::numeric_limits<Distortion>::max();
2741#else
2742  uint32_t          costValidList1 = MAX_UINT;
2743#endif
2744  Mv            mvHevc[3];
2745
2746  xGetBlkBits( ePartSize, slice.isInterP(), puIdx, lastMode, uiMbBits);
2747
2748  pu.cu->affine = true;
2749  pu.mergeFlag = false;
2750
2751  // Uni-directional prediction
2752  for ( int iRefList = 0; iRefList < iNumPredDir; iRefList++ )
2753  {
2754    RefPicList  eRefPicList = ( iRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
2755
2756    for ( int iRefIdxTemp = 0; iRefIdxTemp < slice.getNumRefIdx(eRefPicList); iRefIdxTemp++ )
2757    {
2758      // Get RefIdx bits
2759      uiBitsTemp = uiMbBits[iRefList];
2760      if ( slice.getNumRefIdx(eRefPicList) > 1 )
2761      {
2762        uiBitsTemp += iRefIdxTemp+1;
2763        if ( iRefIdxTemp == slice.getNumRefIdx(eRefPicList)-1 )
2764        {
2765          uiBitsTemp--;
2766        }
2767      }
2768
2769      // Do Affine AMVP
2770      xEstimateAffineAMVP( pu, affiAMVPInfoTemp[eRefPicList], origBuf, eRefPicList, iRefIdxTemp, cMvPred[iRefList][iRefIdxTemp], &biPDistTemp );
2771      aaiMvpIdx[iRefList][iRefIdxTemp] = pu.mvpIdx[eRefPicList];
2772      aaiMvpNum[iRefList][iRefIdxTemp] = pu.mvpNum[eRefPicList];;
2773#if JVET_K0185_AFFINE_6PARA_ENC // reuse refidx of 4-para
2774      if ( pu.cu->affineType == AFFINEMODEL_6PARAM && refIdx4Para[iRefList] != iRefIdxTemp )
2775      {
2776        xCopyAffineAMVPInfo( affiAMVPInfoTemp[eRefPicList], aacAffineAMVPInfo[iRefList][iRefIdxTemp] );
2777        continue;
2778      }
2779#endif
2780
2781      // set hevc ME result as start search position when it is best than mvp
2782      for ( int i=0; i<3; i++ )
2783      {
2784        mvHevc[i] = hevcMv[iRefList][iRefIdxTemp];
2785      }
2786      PelUnitBuf predBuf = m_tmpStorageLCU.getBuf( UnitAreaRelative(*pu.cu, pu) );
2787
2788#if DISTORTION_TYPE_BUGFIX
2789      Distortion uiCandCost = xGetAffineTemplateCost(pu, origBuf, predBuf, mvHevc, aaiMvpIdx[iRefList][iRefIdxTemp],
2790                                                     AMVP_MAX_NUM_CANDS, eRefPicList, iRefIdxTemp);
2791#else
2792      uint32_t uiCandCost = xGetAffineTemplateCost( pu, origBuf, predBuf, mvHevc, aaiMvpIdx[iRefList][iRefIdxTemp], AMVP_MAX_NUM_CANDS, eRefPicList, iRefIdxTemp );
2793#endif
2794#if JVET_K0185_AFFINE_6PARA_ENC // use 4-parameter results as start point
2795      if ( pu.cu->affineType == AFFINEMODEL_6PARAM )
2796      {
2797        Mv mvFour[3];
2798        mvFour[0] = mvAffine4Para[iRefList][iRefIdxTemp][0];
2799        mvFour[1] = mvAffine4Para[iRefList][iRefIdxTemp][1];
2800
2801        int shift = MAX_CU_DEPTH;
2802        int vx2 = (mvFour[0].getHor() << shift) - ((mvFour[1].getVer() - mvFour[0].getVer()) << (shift + g_aucLog2[pu.lheight()] - g_aucLog2[pu.lwidth()]));
2803        int vy2 = (mvFour[0].getVer() << shift) + ((mvFour[1].getHor() - mvFour[0].getHor()) << (shift + g_aucLog2[pu.lheight()] - g_aucLog2[pu.lwidth()]));
2804        vx2 >>= shift;
2805        vy2 >>= shift;
2806        mvFour[2] = Mv( vx2, vy2, true );
2807        mvFour[2].roundMV2SignalPrecision();
2808
2809        Distortion uiCandCostInherit = xGetAffineTemplateCost( pu, origBuf, predBuf, mvFour, aaiMvpIdx[iRefList][iRefIdxTemp], AMVP_MAX_NUM_CANDS, eRefPicList, iRefIdxTemp );
2810        if ( uiCandCostInherit < uiCandCost )
2811        {
2812          uiCandCost = uiCandCostInherit;
2813          for ( int i = 0; i < 3; i++ )
2814          {
2815            mvHevc[i] = mvFour[i];
2816          }
2817        }
2818      }
2819#endif
2820
2821      if ( uiCandCost < biPDistTemp )
2822      {
2823        ::memcpy( cMvTemp[iRefList][iRefIdxTemp], mvHevc, sizeof(Mv)*3 );
2824      }
2825      else
2826      {
2827        ::memcpy( cMvTemp[iRefList][iRefIdxTemp], cMvPred[iRefList][iRefIdxTemp], sizeof(Mv)*3 );
2828      }
2829
2830      // GPB list 1, save the best MvpIdx, RefIdx and Cost
2831      if ( slice.getMvdL1ZeroFlag() && iRefList==1 && biPDistTemp < bestBiPDist )
2832      {
2833        bestBiPDist = biPDistTemp;
2834        bestBiPMvpL1 = aaiMvpIdx[iRefList][iRefIdxTemp];
2835        bestBiPRefIdxL1 = iRefIdxTemp;
2836      }
2837
2838      // Update bits
2839      uiBitsTemp += m_auiMVPIdxCost[aaiMvpIdx[iRefList][iRefIdxTemp]][AMVP_MAX_NUM_CANDS];
2840
2841      if ( m_pcEncCfg->getFastMEForGenBLowDelayEnabled() && iRefList == 1 )   // list 1
2842      {
2843#if JVET_K0185_AFFINE_6PARA_ENC
2844        if ( slice.getList1IdxToList0Idx( iRefIdxTemp ) >= 0 && (pu.cu->affineType != AFFINEMODEL_6PARAM || slice.getList1IdxToList0Idx( iRefIdxTemp ) == refIdx4Para[0]) )
2845#else
2846        if ( slice.getList1IdxToList0Idx( iRefIdxTemp ) >= 0 )
2847#endif
2848        {
2849          int iList1ToList0Idx = slice.getList1IdxToList0Idx( iRefIdxTemp );
2850          ::memcpy( cMvTemp[1][iRefIdxTemp], cMvTemp[0][iList1ToList0Idx], sizeof(Mv)*3 );
2851          uiCostTemp = uiCostTempL0[iList1ToList0Idx];
2852
2853          uiCostTemp -= m_pcRdCost->getCost( uiBitsTempL0[iList1ToList0Idx] );
2854          for (int iVerIdx = 0; iVerIdx < mvNum; iVerIdx++)
2855          {
2856            m_pcRdCost->setPredictor( cMvPred[iRefList][iRefIdxTemp][iVerIdx] );
2857            const int shift = cMvTemp[1][iRefIdxTemp][iVerIdx].highPrec ? VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE : 0;
2858#if JVET_K0337_AFFINE_MVD_PREDICTION
2859            Mv secondPred;
2860            if ( iVerIdx != 0 )
2861            {
2862              secondPred = cMvPred[iRefList][iRefIdxTemp][iVerIdx] + (cMvTemp[1][iRefIdxTemp][0] - cMvPred[1][iRefIdxTemp][0]);
2863              m_pcRdCost->setPredictor( secondPred );
2864            }
2865#endif
2866#if JVET_K0357_AMVR
2867            uiBitsTemp += m_pcRdCost->getBitsOfVectorWithPredictor( cMvTemp[1][iRefIdxTemp][iVerIdx].getHor()>>shift, cMvTemp[1][iRefIdxTemp][iVerIdx].getVer()>>shift, 0 );
2868#else
2869            uiBitsTemp += m_pcRdCost->getBitsOfVectorWithPredictor( cMvTemp[1][iRefIdxTemp][iVerIdx].getHor() >> shift, cMvTemp[1][iRefIdxTemp][iVerIdx].getVer() >> shift );
2870#endif
2871          }
2872          /*calculate the correct cost*/
2873          uiCostTemp += m_pcRdCost->getCost( uiBitsTemp );
2874          DTRACE( g_trace_ctx, D_COMMON, " (%d) uiCostTemp=%d\n", DTRACE_GET_COUNTER(g_trace_ctx,D_COMMON), uiCostTemp );
2875        }
2876        else
2877        {
2878          xAffineMotionEstimation( pu, origBuf, eRefPicList, cMvPred[iRefList][iRefIdxTemp], iRefIdxTemp, cMvTemp[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp );
2879        }
2880      }
2881      else
2882      {
2883        xAffineMotionEstimation( pu, origBuf, eRefPicList, cMvPred[iRefList][iRefIdxTemp], iRefIdxTemp, cMvTemp[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp );
2884      }
2885
2886      // Set best AMVP Index
2887      xCopyAffineAMVPInfo( affiAMVPInfoTemp[eRefPicList], aacAffineAMVPInfo[iRefList][iRefIdxTemp] );
2888      xCheckBestAffineMVP( pu, affiAMVPInfoTemp[eRefPicList], eRefPicList, cMvTemp[iRefList][iRefIdxTemp], cMvPred[iRefList][iRefIdxTemp], aaiMvpIdx[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp );
2889
2890      if ( iRefList == 0 )
2891      {
2892        uiCostTempL0[iRefIdxTemp] = uiCostTemp;
2893        uiBitsTempL0[iRefIdxTemp] = uiBitsTemp;
2894      }
2895      DTRACE( g_trace_ctx, D_COMMON, " (%d) uiCostTemp=%d, uiCost[iRefList]=%d\n", DTRACE_GET_COUNTER(g_trace_ctx,D_COMMON), uiCostTemp, uiCost[iRefList] );
2896      if ( uiCostTemp < uiCost[iRefList] )
2897      {
2898        uiCost[iRefList] = uiCostTemp;
2899        uiBits[iRefList] = uiBitsTemp; // storing for bi-prediction
2900
2901        // set best motion
2902        ::memcpy( aacMv[iRefList], cMvTemp[iRefList][iRefIdxTemp], sizeof(Mv) * 3 );
2903        iRefIdx[iRefList] = iRefIdxTemp;
2904      }
2905
2906      if ( iRefList == 1 && uiCostTemp < costValidList1 && slice.getList1IdxToList0Idx( iRefIdxTemp ) < 0 )
2907      {
2908        costValidList1 = uiCostTemp;
2909        bitsValidList1 = uiBitsTemp;
2910
2911        // set motion
2912        memcpy( mvValidList1, cMvTemp[iRefList][iRefIdxTemp], sizeof(Mv)*3 );
2913        refIdxValidList1 = iRefIdxTemp;
2914      }
2915    } // End refIdx loop
2916  } // end Uni-prediction
2917
2918#if JVET_K0185_AFFINE_6PARA_ENC // save 4-parameter UNI-ME results
2919  if ( pu.cu->affineType == AFFINEMODEL_4PARAM )
2920  {
2921    ::memcpy( mvAffine4Para, cMvTemp, sizeof( cMvTemp ) );
2922  }
2923#endif
2924
2925  // Bi-directional prediction
2926#if JVET_K0220_ENC_CTRL
2927  if ( slice.isInterB() && !PU::isBipredRestriction(pu) )
2928#else
2929  if ( slice.isInterB() && !PU::isBipredRestriction(pu) && !bFastSkipBi )
2930#endif
2931  {
2932    // Set as best list0 and list1
2933    iRefIdxBi[0] = iRefIdx[0];
2934    iRefIdxBi[1] = iRefIdx[1];
2935
2936    ::memcpy( cMvBi,       aacMv,     sizeof(aacMv)     );
2937    ::memcpy( cMvPredBi,   cMvPred,   sizeof(cMvPred)   );
2938    ::memcpy( aaiMvpIdxBi, aaiMvpIdx, sizeof(aaiMvpIdx) );
2939
2940    uint32_t uiMotBits[2];
2941
2942    if ( slice.getMvdL1ZeroFlag() ) // GPB, list 1 only use Mvp
2943    {
2944      xCopyAffineAMVPInfo( aacAffineAMVPInfo[1][bestBiPRefIdxL1], affiAMVPInfoTemp[REF_PIC_LIST_1] );
2945      pu.mvpIdx[REF_PIC_LIST_1] = bestBiPMvpL1;
2946      aaiMvpIdxBi[1][bestBiPRefIdxL1] = bestBiPMvpL1;
2947
2948      // Set Mv for list1
2949      Mv pcMvTemp[3] = { affiAMVPInfoTemp[REF_PIC_LIST_1].mvCandLT[bestBiPMvpL1],
2950                         affiAMVPInfoTemp[REF_PIC_LIST_1].mvCandRT[bestBiPMvpL1],
2951                         affiAMVPInfoTemp[REF_PIC_LIST_1].mvCandLB[bestBiPMvpL1] };
2952      ::memcpy( cMvPredBi[1][bestBiPRefIdxL1], pcMvTemp, sizeof(Mv)*3 );
2953      ::memcpy( cMvBi[1],                      pcMvTemp, sizeof(Mv)*3 );
2954      ::memcpy( cMvTemp[1][bestBiPRefIdxL1],   pcMvTemp, sizeof(Mv)*3 );
2955      iRefIdxBi[1] = bestBiPRefIdxL1;
2956
2957      // Get list1 prediction block
2958      PU::setAllAffineMv( pu, cMvBi[1][0], cMvBi[1][1], cMvBi[1][2], REF_PIC_LIST_1 );
2959      pu.refIdx[REF_PIC_LIST_1] = iRefIdxBi[1];
2960
2961      PelUnitBuf predBufTmp = m_tmpPredStorage[REF_PIC_LIST_1].getBuf( UnitAreaRelative(*pu.cu, pu) );
2962      motionCompensation( pu, predBufTmp, REF_PIC_LIST_1 );
2963
2964      // Update bits
2965      uiMotBits[0] = uiBits[0] - uiMbBits[0];
2966      uiMotBits[1] = uiMbBits[1];
2967
2968      if( slice.getNumRefIdx(REF_PIC_LIST_1) > 1 )
2969      {
2970        uiMotBits[1] += bestBiPRefIdxL1+1;
2971        if( bestBiPRefIdxL1 == slice.getNumRefIdx(REF_PIC_LIST_1)-1 )
2972        {
2973          uiMotBits[1]--;
2974        }
2975      }
2976      uiMotBits[1] += m_auiMVPIdxCost[aaiMvpIdxBi[1][bestBiPRefIdxL1]][AMVP_MAX_NUM_CANDS];
2977      uiBits[2] = uiMbBits[2] + uiMotBits[0] + uiMotBits[1];
2978    }
2979    else
2980    {
2981      uiMotBits[0] = uiBits[0] - uiMbBits[0];
2982      uiMotBits[1] = uiBits[1] - uiMbBits[1];
2983      uiBits[2] = uiMbBits[2] + uiMotBits[0] + uiMotBits[1];
2984    }
2985
2986    // 4-times iteration (default)
2987    int iNumIter = 4;
2988    // fast encoder setting or GPB: only one iteration
2989    if ( m_pcEncCfg->getFastInterSearchMode()==FASTINTERSEARCH_MODE1 || m_pcEncCfg->getFastInterSearchMode()==FASTINTERSEARCH_MODE2 || slice.getMvdL1ZeroFlag() )
2990    {
2991      iNumIter = 1;
2992    }
2993
2994    for ( int iIter = 0; iIter < iNumIter; iIter++ )
2995    {
2996      // Set RefList
2997      int iRefList = iIter % 2;
2998      if ( m_pcEncCfg->getFastInterSearchMode()==FASTINTERSEARCH_MODE1 || m_pcEncCfg->getFastInterSearchMode()==FASTINTERSEARCH_MODE2 )
2999      {
3000        if( uiCost[0] <= uiCost[1] )
3001        {
3002          iRefList = 1;
3003        }
3004        else
3005        {
3006          iRefList = 0;
3007        }
3008      }
3009      else if ( iIter == 0 )
3010      {
3011        iRefList = 0;
3012      }
3013
3014      // First iterate, get prediction block of opposite direction
3015      if( iIter == 0 && !slice.getMvdL1ZeroFlag() )
3016      {
3017        PU::setAllAffineMv( pu, aacMv[1-iRefList][0], aacMv[1-iRefList][1], aacMv[1-iRefList][2], RefPicList(1-iRefList) );
3018        pu.refIdx[1-iRefList] = iRefIdx[1-iRefList];
3019
3020        PelUnitBuf predBufTmp = m_tmpPredStorage[1 - iRefList].getBuf( UnitAreaRelative(*pu.cu, pu) );
3021        motionCompensation( pu, predBufTmp, RefPicList(1 - iRefList) );
3022      }
3023
3024      RefPicList eRefPicList = ( iRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
3025
3026      if ( slice.getMvdL1ZeroFlag() ) // GPB, fix List 1, search List 0
3027      {
3028        iRefList = 0;
3029        eRefPicList = REF_PIC_LIST_0;
3030      }
3031
3032      bool bChanged = false;
3033
3034      iRefStart = 0;
3035      iRefEnd   = slice.getNumRefIdx(eRefPicList) - 1;
3036
3037      for ( int iRefIdxTemp = iRefStart; iRefIdxTemp <= iRefEnd; iRefIdxTemp++ )
3038      {
3039#if JVET_K0185_AFFINE_6PARA_ENC // reuse refidx of 4-para
3040        if ( pu.cu->affineType == AFFINEMODEL_6PARAM && refIdx4Para[iRefList] != iRefIdxTemp )
3041        {
3042          continue;
3043        }
3044#endif
3045
3046        // update bits
3047        uiBitsTemp = uiMbBits[2] + uiMotBits[1-iRefList];
3048        if( slice.getNumRefIdx(eRefPicList) > 1 )
3049        {
3050          uiBitsTemp += iRefIdxTemp+1;
3051          if ( iRefIdxTemp == slice.getNumRefIdx(eRefPicList)-1 )
3052          {
3053            uiBitsTemp--;
3054          }
3055        }
3056        uiBitsTemp += m_auiMVPIdxCost[aaiMvpIdxBi[iRefList][iRefIdxTemp]][AMVP_MAX_NUM_CANDS];
3057
3058        // call Affine ME
3059        xAffineMotionEstimation( pu, origBuf, eRefPicList, cMvPredBi[iRefList][iRefIdxTemp], iRefIdxTemp, cMvTemp[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp, true );
3060        xCopyAffineAMVPInfo( aacAffineAMVPInfo[iRefList][iRefIdxTemp], affiAMVPInfoTemp[eRefPicList] );
3061        xCheckBestAffineMVP( pu, affiAMVPInfoTemp[eRefPicList], eRefPicList, cMvTemp[iRefList][iRefIdxTemp], cMvPredBi[iRefList][iRefIdxTemp], aaiMvpIdxBi[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp );
3062
3063        if ( uiCostTemp < uiCostBi )
3064        {
3065          bChanged = true;
3066          ::memcpy( cMvBi[iRefList], cMvTemp[iRefList][iRefIdxTemp], sizeof(Mv)*3 );
3067          iRefIdxBi[iRefList] = iRefIdxTemp;
3068
3069          uiCostBi            = uiCostTemp;
3070          uiMotBits[iRefList] = uiBitsTemp - uiMbBits[2] - uiMotBits[1-iRefList];
3071          uiBits[2]           = uiBitsTemp;
3072
3073          if ( iNumIter != 1 ) // MC for next iter
3074          {
3075            //  Set motion
3076            PU::setAllAffineMv( pu, cMvBi[iRefList][0], cMvBi[iRefList][1], cMvBi[iRefList][2], eRefPicList );
3077            pu.refIdx[eRefPicList] = iRefIdxBi[eRefPicList];
3078            PelUnitBuf predBufTmp = m_tmpPredStorage[iRefList].getBuf( UnitAreaRelative(*pu.cu, pu) );
3079            motionCompensation( pu, predBufTmp, eRefPicList );
3080          }
3081        }
3082      } // for loop-iRefIdxTemp
3083
3084      if ( !bChanged )
3085      {
3086        if ( uiCostBi <= uiCost[0] && uiCostBi <= uiCost[1] )
3087        {
3088          xCopyAffineAMVPInfo( aacAffineAMVPInfo[0][iRefIdxBi[0]], affiAMVPInfoTemp[REF_PIC_LIST_0] );
3089          xCheckBestAffineMVP( pu, affiAMVPInfoTemp[REF_PIC_LIST_0], REF_PIC_LIST_0, cMvBi[0], cMvPredBi[0][iRefIdxBi[0]], aaiMvpIdxBi[0][iRefIdxBi[0]], uiBits[2], uiCostBi );
3090
3091          if ( !slice.getMvdL1ZeroFlag() )
3092          {
3093            xCopyAffineAMVPInfo( aacAffineAMVPInfo[1][iRefIdxBi[1]], affiAMVPInfoTemp[REF_PIC_LIST_1] );
3094            xCheckBestAffineMVP( pu, affiAMVPInfoTemp[REF_PIC_LIST_1], REF_PIC_LIST_1, cMvBi[1], cMvPredBi[1][iRefIdxBi[1]], aaiMvpIdxBi[1][iRefIdxBi[1]], uiBits[2], uiCostBi );
3095          }
3096        }
3097        break;
3098      }
3099    } // for loop-iter
3100  } // if (B_SLICE)
3101
3102  pu.mv    [REF_PIC_LIST_0] = Mv();
3103  pu.mv    [REF_PIC_LIST_1] = Mv();
3104  pu.mvd   [REF_PIC_LIST_0] = cMvZero;
3105  pu.mvd   [REF_PIC_LIST_1] = cMvZero;
3106  pu.refIdx[REF_PIC_LIST_0] = NOT_VALID;
3107  pu.refIdx[REF_PIC_LIST_1] = NOT_VALID;
3108  pu.mvpIdx[REF_PIC_LIST_0] = NOT_VALID;
3109  pu.mvpIdx[REF_PIC_LIST_1] = NOT_VALID;
3110  pu.mvpNum[REF_PIC_LIST_0] = NOT_VALID;
3111  pu.mvpNum[REF_PIC_LIST_1] = NOT_VALID;
3112
3113  for ( int verIdx = 0; verIdx < 3; verIdx++ )
3114  {
3115    pu.mvdAffi[REF_PIC_LIST_0][verIdx] = cMvZero;
3116    pu.mvdAffi[REF_PIC_LIST_1][verIdx] = cMvZero;
3117  }
3118
3119  // Set Motion Field
3120  memcpy( aacMv[1], mvValidList1, sizeof(Mv)*3 );
3121  iRefIdx[1] = refIdxValidList1;
3122  uiBits[1]  = bitsValidList1;
3123  uiCost[1]  = costValidList1;
3124
3125  // Affine ME result set
3126  if ( uiCostBi <= uiCost[0] && uiCostBi <= uiCost[1] ) // Bi
3127  {
3128    lastMode = 2;
3129    affineCost = uiCostBi;
3130
3131    PU::setAllAffineMv( pu, cMvBi[0][0], cMvBi[0][1], cMvBi[0][2], REF_PIC_LIST_0 );
3132    PU::setAllAffineMv( pu, cMvBi[1][0], cMvBi[1][1], cMvBi[1][2], REF_PIC_LIST_1 );
3133    pu.refIdx[REF_PIC_LIST_0] = iRefIdxBi[0];
3134    pu.refIdx[REF_PIC_LIST_1] = iRefIdxBi[1];
3135
3136    for ( int verIdx = 0; verIdx < mvNum; verIdx++ )
3137    {
3138      pu.mvdAffi[REF_PIC_LIST_0][verIdx] = cMvBi[0][verIdx] - cMvPredBi[0][iRefIdxBi[0]][verIdx];
3139      pu.mvdAffi[REF_PIC_LIST_1][verIdx] = cMvBi[1][verIdx] - cMvPredBi[1][iRefIdxBi[1]][verIdx];
3140#if JVET_K0337_AFFINE_MVD_PREDICTION
3141      if ( verIdx != 0 )
3142      {
3143        pu.mvdAffi[0][verIdx] = pu.mvdAffi[0][verIdx] - pu.mvdAffi[0][0];
3144        pu.mvdAffi[1][verIdx] = pu.mvdAffi[1][verIdx] - pu.mvdAffi[1][0];
3145      }
3146#endif
3147    }
3148
3149    pu.interDir = 3;
3150
3151    pu.mvpIdx[REF_PIC_LIST_0] = aaiMvpIdxBi[0][iRefIdxBi[0]];
3152    pu.mvpNum[REF_PIC_LIST_0] = aaiMvpNum[0][iRefIdxBi[0]];
3153    pu.mvpIdx[REF_PIC_LIST_1] = aaiMvpIdxBi[1][iRefIdxBi[1]];
3154    pu.mvpNum[REF_PIC_LIST_1] = aaiMvpNum[1][iRefIdxBi[1]];
3155  }
3156  else if ( uiCost[0] <= uiCost[1] ) // List 0
3157  {
3158    lastMode = 0;
3159    affineCost = uiCost[0];
3160
3161    PU::setAllAffineMv( pu, aacMv[0][0], aacMv[0][1], aacMv[0][2], REF_PIC_LIST_0 );
3162    pu.refIdx[REF_PIC_LIST_0] = iRefIdx[0];
3163
3164    for ( int verIdx = 0; verIdx < mvNum; verIdx++ )
3165    {
3166      pu.mvdAffi[REF_PIC_LIST_0][verIdx] = aacMv[0][verIdx] - cMvPred[0][iRefIdx[0]][verIdx];
3167#if JVET_K0337_AFFINE_MVD_PREDICTION
3168      if ( verIdx != 0 )
3169      {
3170        pu.mvdAffi[0][verIdx] = pu.mvdAffi[0][verIdx] - pu.mvdAffi[0][0];
3171      }
3172#endif
3173    }
3174    pu.interDir = 1;
3175
3176    pu.mvpIdx[REF_PIC_LIST_0] = aaiMvpIdx[0][iRefIdx[0]];
3177    pu.mvpNum[REF_PIC_LIST_0] = aaiMvpNum[0][iRefIdx[0]];
3178  }
3179  else
3180  {
3181    lastMode = 1;
3182    affineCost = uiCost[1];
3183
3184    PU::setAllAffineMv( pu, aacMv[1][0], aacMv[1][1], aacMv[1][2], REF_PIC_LIST_1 );
3185    pu.refIdx[REF_PIC_LIST_1] = iRefIdx[1];
3186
3187    for ( int verIdx = 0; verIdx < mvNum; verIdx++ )
3188    {
3189      pu.mvdAffi[REF_PIC_LIST_1][verIdx] = aacMv[1][verIdx] - cMvPred[1][iRefIdx[1]][verIdx];
3190#if JVET_K0337_AFFINE_MVD_PREDICTION
3191      if ( verIdx != 0 )
3192      {
3193        pu.mvdAffi[1][verIdx] = pu.mvdAffi[1][verIdx] - pu.mvdAffi[1][0];
3194      }
3195#endif
3196    }
3197    pu.interDir = 2;
3198
3199    pu.mvpIdx[REF_PIC_LIST_1] = aaiMvpIdx[1][iRefIdx[1]];
3200    pu.mvpNum[REF_PIC_LIST_1] = aaiMvpNum[1][iRefIdx[1]];
3201  }
3202}
3203
3204void solveEqual( double** dEqualCoeff, int iOrder, double* dAffinePara )
3205{
3206#if JVET_K_AFFINE_BUG_FIXES
3207  for ( int k = 0; k < iOrder; k++ )
3208  {
3209    dAffinePara[k] = 0.;
3210  }
3211#endif
3212
3213  // row echelon
3214  for ( int i = 1; i < iOrder; i++ )
3215  {
3216    // find column max
3217    double temp = fabs(dEqualCoeff[i][i-1]);
3218    int tempIdx = i;
3219    for ( int j = i+1; j < iOrder+1; j++ )
3220    {
3221      if ( fabs(dEqualCoeff[j][i-1]) > temp )
3222      {
3223        temp = fabs(dEqualCoeff[j][i-1]);
3224        tempIdx = j;
3225      }
3226    }
3227
3228    // swap line
3229    if ( tempIdx != i )
3230    {
3231      for ( int j = 0; j < iOrder+1; j++ )
3232      {
3233        dEqualCoeff[0][j] = dEqualCoeff[i][j];
3234        dEqualCoeff[i][j] = dEqualCoeff[tempIdx][j];
3235        dEqualCoeff[tempIdx][j] = dEqualCoeff[0][j];
3236      }
3237    }
3238
3239    // elimination first column
3240#if JVET_K_AFFINE_BUG_FIXES
3241    if ( dEqualCoeff[i][i - 1] == 0. )
3242    {
3243      return;
3244    }
3245#endif
3246    for ( int j = i+1; j < iOrder+1; j++ )
3247    {
3248      for ( int k = i; k < iOrder+1; k++ )
3249      {
3250        dEqualCoeff[j][k] = dEqualCoeff[j][k] - dEqualCoeff[i][k] * dEqualCoeff[j][i-1] / dEqualCoeff[i][i-1];
3251      }
3252    }
3253  }
3254
3255#if JVET_K_AFFINE_BUG_FIXES
3256  if ( dEqualCoeff[iOrder][iOrder - 1] == 0. )
3257  {
3258    return;
3259  }
3260#endif
3261  dAffinePara[iOrder-1] = dEqualCoeff[iOrder][iOrder] / dEqualCoeff[iOrder][iOrder-1];
3262  for ( int i = iOrder-2; i >= 0; i-- )
3263  {
3264#if JVET_K_AFFINE_BUG_FIXES
3265    if ( dEqualCoeff[i + 1][i] == 0. )
3266    {
3267      for ( int k = 0; k < iOrder; k++ )
3268      {
3269        dAffinePara[k] = 0.;
3270      }
3271      return;
3272    }
3273#endif
3274    double temp = 0;
3275    for ( int j = i+1; j < iOrder; j++ )
3276    {
3277      temp += dEqualCoeff[i+1][j] * dAffinePara[j];
3278    }
3279    dAffinePara[i] = ( dEqualCoeff[i+1][iOrder] - temp ) / dEqualCoeff[i+1][i];
3280  }
3281}
3282
3283void InterSearch::xCheckBestAffineMVP( PredictionUnit &pu, AffineAMVPInfo &affineAMVPInfo, RefPicList eRefPicList, Mv acMv[3], Mv acMvPred[3], int& riMVPIdx, uint32_t& ruiBits, Distortion& ruiCost )
3284{
3285  if ( affineAMVPInfo.numCand < 2 )
3286  {
3287    return;
3288  }
3289
3290#if JVET_K0185_AFFINE_6PARA_ENC
3291  int mvNum = pu.cu->affineType ? 3 : 2;
3292#endif
3293
3294  m_pcRdCost->selectMotionLambda( pu.cu->transQuantBypass );
3295  m_pcRdCost->setCostScale ( 0 );
3296
3297  int iBestMVPIdx = riMVPIdx;
3298
3299  // Get origin MV bits
3300  int iOrgMvBits = 0;
3301#if JVET_K0185_AFFINE_6PARA_ENC
3302  for ( int iVerIdx = 0; iVerIdx < mvNum; iVerIdx++ )
3303#else
3304  for ( int iVerIdx=0; iVerIdx<2; iVerIdx++ )
3305#endif
3306  {
3307    m_pcRdCost->setPredictor ( acMvPred[iVerIdx] );
3308    const int shift = acMv[iVerIdx].highPrec ? VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE : 0;
3309
3310#if JVET_K0337_AFFINE_MVD_PREDICTION
3311    Mv secondPred;
3312    if ( iVerIdx != 0 )
3313    {
3314      secondPred = acMvPred[iVerIdx] + (acMv[0] - acMvPred[0]);
3315      m_pcRdCost->setPredictor( secondPred );
3316    }
3317#endif
3318#if JVET_K0357_AMVR
3319    iOrgMvBits += m_pcRdCost->getBitsOfVectorWithPredictor( acMv[iVerIdx].getHor()>>shift, acMv[iVerIdx].getVer()>>shift, 0 );
3320#else
3321    iOrgMvBits += m_pcRdCost->getBitsOfVectorWithPredictor( acMv[iVerIdx].getHor() >> shift, acMv[iVerIdx].getVer() >> shift );
3322#endif
3323  }
3324  iOrgMvBits += m_auiMVPIdxCost[riMVPIdx][AMVP_MAX_NUM_CANDS];
3325
3326  int iBestMvBits = iOrgMvBits;
3327  for (int iMVPIdx = 0; iMVPIdx < affineAMVPInfo.numCand; iMVPIdx++)
3328  {
3329    if (iMVPIdx == riMVPIdx)
3330    {
3331      continue;
3332    }
3333
3334    int iMvBits = 0;
3335#if JVET_K0185_AFFINE_6PARA_ENC
3336    for ( int iVerIdx = 0; iVerIdx < mvNum; iVerIdx++ )
3337#else
3338    for ( int iVerIdx=0; iVerIdx<2; iVerIdx++ )
3339#endif
3340    {
3341#if JVET_K0185_AFFINE_6PARA_ENC
3342      m_pcRdCost->setPredictor( iVerIdx == 2 ? affineAMVPInfo.mvCandLB[iMVPIdx] :
3343        (iVerIdx == 1 ? affineAMVPInfo.mvCandRT[iMVPIdx] : affineAMVPInfo.mvCandLT[iMVPIdx]) );
3344#else
3345      m_pcRdCost->setPredictor ( iVerIdx ? affineAMVPInfo.mvCandRT[iMVPIdx] : affineAMVPInfo.mvCandLT[iMVPIdx] );
3346#endif
3347      const int shift = acMv[iVerIdx].highPrec ? VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE : 0;
3348
3349#if JVET_K0337_AFFINE_MVD_PREDICTION
3350      Mv secondPred;
3351      if ( iVerIdx != 0 )
3352      {
3353#if JVET_K0185_AFFINE_6PARA_ENC
3354#if AFFINE_ENC_BUGFIX
3355        secondPred = (iVerIdx == 1 ? affineAMVPInfo.mvCandRT[iMVPIdx] : affineAMVPInfo.mvCandLB[iMVPIdx]) + (acMv[0] - affineAMVPInfo.mvCandLT[iMVPIdx]);
3356#else
3357        secondPred = (iVerIdx == 1 ? affineAMVPInfo.mvCandRT[iMVPIdx] : affineAMVPInfo.mvCandLT[iMVPIdx]) + (acMv[0] - affineAMVPInfo.mvCandLT[iMVPIdx]);
3358#endif
3359#else
3360        secondPred = affineAMVPInfo.mvCandRT[iMVPIdx] + (acMv[0] - affineAMVPInfo.mvCandLT[iMVPIdx]);
3361#endif
3362        m_pcRdCost->setPredictor( secondPred );
3363      }
3364#endif
3365#if JVET_K0357_AMVR
3366      iMvBits += m_pcRdCost->getBitsOfVectorWithPredictor( acMv[iVerIdx].getHor()>>shift, acMv[iVerIdx].getVer()>>shift, 0 );
3367#else
3368      iMvBits += m_pcRdCost->getBitsOfVectorWithPredictor( acMv[iVerIdx].getHor() >> shift, acMv[iVerIdx].getVer() >> shift );
3369#endif
3370    }
3371    iMvBits += m_auiMVPIdxCost[iMVPIdx][AMVP_MAX_NUM_CANDS];
3372
3373    if (iMvBits < iBestMvBits)
3374    {
3375      iBestMvBits = iMvBits;
3376      iBestMVPIdx = iMVPIdx;
3377    }
3378  }
3379
3380  if (iBestMVPIdx != riMVPIdx)  // if changed
3381  {
3382    acMvPred[0] = affineAMVPInfo.mvCandLT[iBestMVPIdx];
3383    acMvPred[1] = affineAMVPInfo.mvCandRT[iBestMVPIdx];
3384    acMvPred[2] = affineAMVPInfo.mvCandLB[iBestMVPIdx];
3385    riMVPIdx = iBestMVPIdx;
3386    uint32_t uiOrgBits = ruiBits;
3387    ruiBits = uiOrgBits - iOrgMvBits + iBestMvBits;
3388    ruiCost = (ruiCost - m_pcRdCost->getCost( uiOrgBits )) + m_pcRdCost->getCost( ruiBits );
3389  }
3390}
3391
3392void InterSearch::xAffineMotionEstimation( PredictionUnit& pu,
3393                                           PelUnitBuf&     origBuf,
3394                                           RefPicList      eRefPicList,
3395                                           Mv              acMvPred[3],
3396                                           int             iRefIdxPred,
3397                                           Mv              acMv[3],
3398                                           uint32_t&           ruiBits,
3399                                           Distortion&     ruiCost,
3400                                           bool            bBi )
3401{
3402  const int width  = pu.Y().width;
3403  const int height = pu.Y().height;
3404
3405  const Picture* refPic = pu.cu->slice->getRefPic(eRefPicList, iRefIdxPred);
3406
3407  // Set Origin YUV: pcYuv
3408  PelUnitBuf*   pBuf = &origBuf;
3409  double        fWeight       = 1.0;
3410
3411  PelUnitBuf  origBufTmp = m_tmpStorageLCU.getBuf( UnitAreaRelative( *pu.cu, pu ) );
3412
3413  // if Bi, set to ( 2 * Org - ListX )
3414  if ( bBi )
3415  {
3416    // NOTE: Other buf contains predicted signal from another direction
3417    PelUnitBuf otherBuf = m_tmpPredStorage[1 - (int)eRefPicList].getBuf( UnitAreaRelative( *pu.cu, pu ) );
3418    origBufTmp.copyFrom(origBuf);
3419    origBufTmp.removeHighFreq(otherBuf, m_pcEncCfg->getClipForBiPredMeEnabled(), pu.cu->slice->clpRngs());
3420    pBuf = &origBufTmp;
3421
3422    fWeight = 0.5;
3423  }
3424
3425  // pred YUV
3426  PelUnitBuf  predBuf = m_tmpAffiStorage.getBuf( UnitAreaRelative(*pu.cu, pu) );
3427
3428  // Set start Mv position, use input mv as started search mv
3429  Mv acMvTemp[3];
3430  ::memcpy( acMvTemp, acMv, sizeof(Mv)*3 );
3431  acMvTemp[0].setHighPrec();
3432  acMvTemp[1].setHighPrec();
3433  acMvTemp[2].setHighPrec();
3434
3435  // Set delta mv
3436  // malloc buffer
3437#if JVET_K0185_AFFINE_6PARA_ENC
3438  int iParaNum = pu.cu->affineType ? 7 : 5;
3439  int affineParaNum = iParaNum - 1;
3440  int mvNum = pu.cu->affineType ? 3 : 2;
3441#else
3442  static const int iParaNum = 5;
3443#endif
3444  double **pdEqualCoeff;
3445  pdEqualCoeff = new double *[iParaNum];
3446  for ( int i = 0; i < iParaNum; i++ )
3447  {
3448    pdEqualCoeff[i] = new double[iParaNum];
3449  }
3450
3451#if JVET_K0367_AFFINE_FIX_POINT
3452  int64_t  i64EqualCoeff[7][7];
3453  Pel    *piError = m_tmpAffiError;
3454  int    *pdDerivate[2];
3455#else
3456  int    *piError = m_tmpAffiError;
3457  double *pdDerivate[2];
3458#endif
3459  pdDerivate[0] = m_tmpAffiDeri[0];
3460  pdDerivate[1] = m_tmpAffiDeri[1];
3461
3462  Distortion uiCostBest = std::numeric_limits<Distortion>::max();
3463  uint32_t uiBitsBest = 0;
3464
3465  // do motion compensation with origin mv
3466  clipMv( acMvTemp[0], pu.cu->lumaPos(), *pu.cs->sps );
3467  clipMv( acMvTemp[1], pu.cu->lumaPos(), *pu.cs->sps );
3468#if JVET_K0185_AFFINE_6PARA_ENC
3469  if ( pu.cu->affineType == AFFINEMODEL_6PARAM )
3470  {
3471    clipMv( acMvTemp[2], pu.cu->lumaPos(), *pu.cs->sps );
3472  }
3473#endif
3474#if !JVET_K_AFFINE_BUG_FIXES
3475  int vx2 =  - ( acMvTemp[1].getVer() - acMvTemp[0].getVer() ) * height / width + acMvTemp[0].getHor();
3476  int vy2 =    ( acMvTemp[1].getHor() - acMvTemp[0].getHor() ) * height / width + acMvTemp[0].getVer();
3477  acMvTemp[2] = Mv( vx2, vy2, true );
3478  clipMv( acMvTemp[2], pu.cu->lumaPos(), *pu.cs->sps );
3479#endif
3480  xPredAffineBlk( COMPONENT_Y, pu, refPic, acMvTemp, predBuf, false, pu.cs->slice->clpRng( COMPONENT_Y ) );
3481
3482  // get error
3483  uiCostBest = m_pcRdCost->getDistPart( predBuf.Y(), pBuf->Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, DF_HAD );
3484
3485  // get cost with mv
3486  m_pcRdCost->setCostScale(0);
3487  uiBitsBest = ruiBits;
3488  DTRACE( g_trace_ctx, D_COMMON, " (%d) xx uiBitsBest=%d\n", DTRACE_GET_COUNTER(g_trace_ctx,D_COMMON), uiBitsBest );
3489#if JVET_K0185_AFFINE_6PARA_ENC
3490  for ( int i = 0; i < mvNum; i++ )
3491#else
3492  for ( int i=0; i<2; i++ )
3493#endif
3494  {
3495    DTRACE( g_trace_ctx, D_COMMON, "#mvPredForBits=(%d,%d) \n", acMvPred[i].getHor(), acMvPred[i].getVer() );
3496    m_pcRdCost->setPredictor( acMvPred[i] );
3497    DTRACE( g_trace_ctx, D_COMMON, "#mvForBits=(%d,%d) \n", acMvTemp[i].getHor(), acMvTemp[i].getVer() );
3498
3499    const int shift = acMvTemp[i].highPrec ? VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE : 0;
3500#if JVET_K0337_AFFINE_MVD_PREDICTION
3501    Mv secondPred;
3502    if ( i != 0 )
3503    {
3504      secondPred = acMvPred[i] + (acMvTemp[0] - acMvPred[0]);
3505      m_pcRdCost->setPredictor( secondPred );
3506    }
3507#endif
3508#if JVET_K0357_AMVR
3509    uiBitsBest += m_pcRdCost->getBitsOfVectorWithPredictor( acMvTemp[i].getHor()>>shift, acMvTemp[i].getVer()>>shift, 0 );
3510#else
3511    uiBitsBest += m_pcRdCost->getBitsOfVectorWithPredictor( acMvTemp[i].getHor() >> shift, acMvTemp[i].getVer() >> shift );
3512#endif
3513    DTRACE( g_trace_ctx, D_COMMON, " (%d) yy uiBitsBest=%d\n", DTRACE_GET_COUNTER(g_trace_ctx,D_COMMON), uiBitsBest );
3514  }
3515  uiCostBest = (Distortion)( floor( fWeight * (double)uiCostBest ) + (double)m_pcRdCost->getCost( uiBitsBest ) );
3516
3517  DTRACE( g_trace_ctx, D_COMMON, " (%d) uiBitsBest=%d, uiCostBest=%d\n", DTRACE_GET_COUNTER(g_trace_ctx,D_COMMON), uiBitsBest, uiCostBest );
3518
3519  ::memcpy( acMv, acMvTemp, sizeof(Mv) * 3 );
3520
3521  const int bufStride = pBuf->Y().stride;
3522  const int predBufStride = predBuf.Y().stride;
3523
3524#if JVET_K0185_AFFINE_6PARA_ENC
3525  int iIterTime;
3526  if ( pu.cu->affineType == AFFINEMODEL_6PARAM )
3527  {
3528    iIterTime = bBi ? 3 : 4;
3529  }
3530  else
3531  {
3532    iIterTime = bBi ? 3 : 5;
3533  }
3534
3535  if ( !pu.cu->cs->sps->getSpsNext().getUseAffineType() )
3536  {
3537    iIterTime = bBi ? 5 : 7;
3538  }
3539#else
3540  int iIterTime = bBi ? 5 : 7;
3541#endif
3542  for ( int iter=0; iter<iIterTime; iter++ )    // iterate loop
3543  {
3544    /*********************************************************************************
3545     *                         use gradient to update mv
3546     *********************************************************************************/
3547    // get Error Matrix
3548    Pel* pOrg  = pBuf->Y().buf;
3549    Pel* pPred = predBuf.Y().buf;
3550    for ( int j=0; j< height; j++ )
3551    {
3552      for ( int i=0; i< width; i++ )
3553      {
3554        piError[i + j * width] = pOrg[i] - pPred[i];
3555      }
3556      pOrg  += bufStride;
3557      pPred += predBufStride;
3558    }
3559
3560    // sobel x direction
3561    // -1 0 1
3562    // -2 0 2
3563    // -1 0 1
3564    pPred = predBuf.Y().buf;
3565#if JVET_K0367_AFFINE_FIX_POINT
3566    m_HorizontalSobelFilter( pPred, predBufStride, pdDerivate[0], width, width, height );
3567#else
3568    for ( int j = 1; j < height-1; j++ )
3569    {
3570      for ( int k = 1; k < width-1; k++ )
3571      {
3572        int iCenter = j*predBufStride + k;
3573        pdDerivate[0][j*width + k] = (double)( pPred[iCenter + 1 - predBufStride] - pPred[iCenter - 1 - predBufStride]
3574                                                  + ( pPred[iCenter + 1] << 1 )      - ( pPred[iCenter - 1] << 1 )
3575                                                  + pPred[iCenter + 1 + predBufStride] - pPred[iCenter - 1 + predBufStride] ) / 8 ;
3576      }
3577      pdDerivate[0][ j*width ]             = pdDerivate[0][ j*width + 1 ];
3578      pdDerivate[0][ j*width + width - 1 ] = pdDerivate[0][ j*width + width - 2 ];
3579    }
3580
3581    pdDerivate[0][0]                        = pdDerivate[0][width+1];
3582    pdDerivate[0][width-1]                  = pdDerivate[0][width+width-2];
3583    pdDerivate[0][(height-1)*width]         = pdDerivate[0][(height-2)*width+1];
3584    pdDerivate[0][(height-1)*width+width-1] = pdDerivate[0][(height-2)*width+width-2];
3585
3586    for ( int j = 1; j < width - 1; j++ )
3587    {
3588      pdDerivate[0][j] = pdDerivate[0][width+j];
3589      pdDerivate[0][(height-1)*width+j] = pdDerivate[0][(height-2)*width+j];
3590    }
3591#endif
3592
3593    // sobel y direction
3594    // -1 -2 -1
3595    //  0  0  0
3596    //  1  2  1
3597#if JVET_K0367_AFFINE_FIX_POINT
3598    m_VerticalSobelFilter( pPred, predBufStride, pdDerivate[1], width, width, height );
3599#else
3600    for ( int k=1; k < width-1; k++ )
3601    {
3602      for ( int j = 1; j < height-1; j++ )
3603      {
3604        int iCenter = j*predBufStride + k;
3605        pdDerivate[1][j*width + k] = (double)( pPred[iCenter + predBufStride - 1]    -   pPred[iCenter - predBufStride - 1]
3606                                           + ( pPred[iCenter + predBufStride] << 1 ) - ( pPred[iCenter - predBufStride] << 1 )
3607                                           +   pPred[iCenter + predBufStride + 1]    -   pPred[iCenter - predBufStride + 1] ) / 8;
3608      }
3609      pdDerivate[1][k] = pdDerivate[1][ width + k ];
3610      pdDerivate[1][ (height - 1) * width + k ] = pdDerivate[1][ (height - 2) * width + k ];
3611    }
3612
3613    pdDerivate[1][0]           = pdDerivate[1][width+1];
3614    pdDerivate[1][width-1] = pdDerivate[1][width + width-2];
3615    pdDerivate[1][(height-1)*width]         = pdDerivate[1][(height-2)*width+1];
3616    pdDerivate[1][(height-1)*width+width-1] = pdDerivate[1][(height-2)*width+(width-2)];
3617
3618    for ( int j=1; j < height-1; j++ )
3619    {
3620      pdDerivate[1][j*width] = pdDerivate[1][j*width+1];
3621      pdDerivate[1][j*width+width-1] = pdDerivate[1][j*width+width-2];
3622    }
3623#endif
3624
3625    // solve delta x and y
3626#if JVET_K0367_AFFINE_FIX_POINT
3627    for ( int row = 0; row < iParaNum; row++ )
3628    {
3629      memset( &i64EqualCoeff[row][0], 0, iParaNum * sizeof( int64_t ) );
3630    }
3631
3632    m_EqualCoeffComputer( piError, width, pdDerivate, width, i64EqualCoeff, width, height
3633#if JVET_K0185_AFFINE_6PARA_ENC
3634      , (pu.cu->affineType == AFFINEMODEL_6PARAM)
3635#else
3636      , false
3637#endif
3638    );
3639
3640    for ( int row = 0; row < iParaNum; row++ )
3641    {
3642      for ( int i = 0; i < iParaNum; i++ )
3643      {
3644        pdEqualCoeff[row][i] = (double)i64EqualCoeff[row][i];
3645      }
3646    }
3647#else
3648    for ( int m = 0; m != iParaNum; m++ )
3649    {
3650      for ( int n = 0; n != iParaNum; n++ )
3651      {
3652        pdEqualCoeff[m][n] = 0.0;
3653      }
3654    }
3655
3656    for ( int j = 0; j != height; j++ )
3657    {
3658      for ( int k = 0; k != width; k++ )
3659      {
3660        int iIdx = j * width + k;
3661#if JVET_K0185_AFFINE_6PARA_ENC
3662        double dC[6];
3663        if ( pu.cu->affineType )
3664        {
3665          dC[0] = pdDerivate[0][iIdx];
3666          dC[1] = k * pdDerivate[0][iIdx];
3667          dC[2] = pdDerivate[1][iIdx];
3668          dC[3] = k * pdDerivate[1][iIdx];
3669          dC[4] = j * pdDerivate[0][iIdx];
3670          dC[5] = j * pdDerivate[1][iIdx];
3671        }
3672        else
3673        {
3674          dC[0] = pdDerivate[0][iIdx];
3675          dC[1] = k * pdDerivate[0][iIdx] + j * pdDerivate[1][iIdx];
3676          dC[2] = pdDerivate[1][iIdx];
3677          dC[3] = j * pdDerivate[0][iIdx] - k * pdDerivate[1][iIdx];
3678        }
3679
3680        for ( int col = 0; col < affineParaNum; col++ )
3681        {
3682          for ( int row = 0; row < affineParaNum; row++ )
3683          {
3684            pdEqualCoeff[col + 1][row] += dC[col] * dC[row];
3685          }
3686          pdEqualCoeff[col + 1][affineParaNum] += (double)(piError[iIdx] * dC[col]);
3687        }
3688#else
3689        double dC[4];
3690        dC[0] = pdDerivate[0][iIdx];
3691        dC[1] = k * pdDerivate[0][iIdx] + j * pdDerivate[1][iIdx];
3692        dC[2] = pdDerivate[1][iIdx];
3693        dC[3] = j * pdDerivate[0][iIdx] - k * pdDerivate[1][iIdx];
3694
3695        for ( int col=0; col<4; col++ )
3696        {
3697          for ( int row=0; row<4; row++ )
3698          {
3699            pdEqualCoeff[col+1][row] += dC[col] * dC[row];
3700          }
3701          pdEqualCoeff[col+1][4] += (double)( piError[iIdx] * dC[col] );
3702        }
3703#endif
3704      }
3705    }
3706#endif
3707
3708#if JVET_K0185_AFFINE_6PARA_ENC
3709    double dAffinePara[6];
3710    double dDeltaMv[6];
3711    Mv acDeltaMv[3];
3712
3713    solveEqual( pdEqualCoeff, affineParaNum, dAffinePara );
3714
3715    // convert to delta mv
3716    dDeltaMv[0] = dAffinePara[0];
3717    dDeltaMv[2] = dAffinePara[2];
3718    if ( pu.cu->affineType == AFFINEMODEL_6PARAM )
3719    {
3720      dDeltaMv[1] = dAffinePara[1] * width + dAffinePara[0];
3721      dDeltaMv[3] = dAffinePara[3] * width + dAffinePara[2];
3722      dDeltaMv[4] = dAffinePara[4] * height + dAffinePara[0];
3723      dDeltaMv[5] = dAffinePara[5] * height + dAffinePara[2];
3724    }
3725    else
3726    {
3727      dDeltaMv[1] = dAffinePara[1] * width + dAffinePara[0];
3728      dDeltaMv[3] = -dAffinePara[3] * width + dAffinePara[2];
3729    }
3730
3731    acDeltaMv[0] = Mv( (int)(dDeltaMv[0] * 4 + SIGN( dDeltaMv[0] ) * 0.5) << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE, (int)(dDeltaMv[2] * 4 + SIGN( dDeltaMv[2] ) * 0.5) << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE, true );
3732    acDeltaMv[1] = Mv( (int)(dDeltaMv[1] * 4 + SIGN( dDeltaMv[1] ) * 0.5) << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE, (int)(dDeltaMv[3] * 4 + SIGN( dDeltaMv[3] ) * 0.5) << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE, true );
3733
3734    if ( pu.cu->affineType == AFFINEMODEL_6PARAM )
3735    {
3736      acDeltaMv[2] = Mv( (int)(dDeltaMv[4] * 4 + SIGN( dDeltaMv[4] ) * 0.5) << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE, (int)(dDeltaMv[5] * 4 + SIGN( dDeltaMv[5] ) * 0.5) << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE, true );
3737    }
3738#else
3739    double dAffinePara[4];
3740    solveEqual( pdEqualCoeff, 4, dAffinePara );
3741
3742    // convert to delta mv
3743    double dDeltaMv[4];
3744    dDeltaMv[0] = dAffinePara[0];
3745    dDeltaMv[2] = dAffinePara[2];
3746
3747    dDeltaMv[1] =   dAffinePara[1] * width + dAffinePara[0];
3748    dDeltaMv[3] = - dAffinePara[3] * width + dAffinePara[2];
3749
3750    Mv acDeltaMv[3];
3751    acDeltaMv[0] = Mv( (int)(dDeltaMv[0] * 4 + SIGN(dDeltaMv[0]) * 0.5 ) << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE, (int)(dDeltaMv[2] * 4 + SIGN(dDeltaMv[2]) * 0.5 ) << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE, true );
3752    acDeltaMv[1] = Mv( (int)(dDeltaMv[1] * 4 + SIGN(dDeltaMv[1]) * 0.5 ) << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE, (int)(dDeltaMv[3] * 4 + SIGN(dDeltaMv[3]) * 0.5 ) << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE, true );
3753#endif
3754
3755    bool bAllZero = false;
3756#if JVET_K0185_AFFINE_6PARA_ENC
3757    for ( int i = 0; i < mvNum; i++ )
3758#else
3759    for ( int i=0; i<2; i++ )
3760#endif
3761    {
3762      if ( acDeltaMv[i].getHor() != 0 || acDeltaMv[i].getVer() != 0 )
3763      {
3764        bAllZero = false;
3765        break;
3766      }
3767      bAllZero = true;
3768    }
3769
3770    if ( bAllZero )
3771      break;
3772
3773    // do motion compensation with updated mv
3774#if JVET_K0185_AFFINE_6PARA_ENC
3775    for ( int i = 0; i < mvNum; i++ )
3776#else
3777    for ( int i=0; i<2; i++ )
3778#endif
3779    {
3780      acMvTemp[i] += acDeltaMv[i];
3781#if JVET_K_AFFINE_BUG_FIXES
3782      acMvTemp[i].hor = Clip3( -32768, 32767, acMvTemp[i].hor );
3783      acMvTemp[i].ver = Clip3( -32768, 32767, acMvTemp[i].ver );
3784      acMvTemp[i].roundMV2SignalPrecision();
3785#endif
3786      clipMv(acMvTemp[i], pu.cu->lumaPos(), *pu.cs->sps);
3787    }
3788#if !JVET_K_AFFINE_BUG_FIXES
3789    int vx2, vy2;
3790    vx2 =  - ( acMvTemp[1].getVer() - acMvTemp[0].getVer() ) * height / width + acMvTemp[0].getHor();
3791    vy2 =    ( acMvTemp[1].getHor() - acMvTemp[0].getHor() ) * height / width + acMvTemp[0].getVer();
3792    acMvTemp[2].set( vx2, vy2 );
3793    clipMv(acMvTemp[2], pu.cu->lumaPos(), *pu.cs->sps);
3794#endif
3795    xPredAffineBlk( COMPONENT_Y, pu, refPic, acMvTemp, predBuf, false, pu.cu->slice->clpRng( COMPONENT_Y ) );
3796
3797    // get error
3798    Distortion uiCostTemp = m_pcRdCost->getDistPart( predBuf.Y(), pBuf->Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, DF_HAD );
3799    DTRACE( g_trace_ctx, D_COMMON, " (%d) uiCostTemp=%d\n", DTRACE_GET_COUNTER(g_trace_ctx,D_COMMON), uiCostTemp );
3800
3801    // get cost with mv
3802    m_pcRdCost->setCostScale(0);
3803    uint32_t uiBitsTemp = ruiBits;
3804#if JVET_K0185_AFFINE_6PARA_ENC
3805    for ( int i = 0; i < mvNum; i++ )
3806#else
3807    for ( int i=0; i<2; i++ )
3808#endif
3809    {
3810      m_pcRdCost->setPredictor( acMvPred[i] );
3811      const int shift = acMvTemp[i].highPrec ? VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE : 0;
3812#if JVET_K0337_AFFINE_MVD_PREDICTION
3813      Mv secondPred;
3814      if ( i != 0 )
3815      {
3816        secondPred = acMvPred[i] + (acMvTemp[0] - acMvPred[0]);
3817        m_pcRdCost->setPredictor( secondPred );
3818      }
3819#endif
3820#if JVET_K0357_AMVR
3821      uiBitsTemp += m_pcRdCost->getBitsOfVectorWithPredictor( acMvTemp[i].getHor()>>shift, acMvTemp[i].getVer()>>shift, 0 );
3822#else
3823      uiBitsTemp += m_pcRdCost->getBitsOfVectorWithPredictor( acMvTemp[i].getHor() >> shift, acMvTemp[i].getVer() >> shift );
3824#endif
3825    }
3826
3827    uiCostTemp = (Distortion)( floor( fWeight * (double)uiCostTemp ) + (double)m_pcRdCost->getCost( uiBitsTemp ) );
3828
3829    // store best cost and mv
3830    if ( uiCostTemp < uiCostBest )
3831    {
3832      uiCostBest = uiCostTemp;
3833      uiBitsBest = uiBitsTemp;
3834      memcpy( acMv, acMvTemp, sizeof(Mv) * 3 );
3835    }
3836  }
3837
3838  // free buffer
3839  for ( int i=0; i<iParaNum; i++ )
3840    delete []pdEqualCoeff[i];
3841  delete []pdEqualCoeff;
3842
3843  ruiBits = uiBitsBest;
3844  ruiCost = uiCostBest;
3845  DTRACE( g_trace_ctx, D_COMMON, " (%d) uiBitsBest=%d, uiCostBest=%d\n", DTRACE_GET_COUNTER(g_trace_ctx,D_COMMON), uiBitsBest, uiCostBest );
3846
3847}
3848
3849void InterSearch::xEstimateAffineAMVP( PredictionUnit&  pu,
3850                                       AffineAMVPInfo&  affineAMVPInfo,
3851                                       PelUnitBuf&      origBuf,
3852                                       RefPicList       eRefPicList,
3853                                       int              iRefIdx,
3854                                       Mv               acMvPred[3],
3855                                       Distortion*      puiDistBiP )
3856{
3857  Mv         bestMvLT, bestMvRT, bestMvLB;
3858  int        iBestIdx = 0;
3859  Distortion uiBestCost = std::numeric_limits<Distortion>::max();
3860
3861  // Fill the MV Candidates
3862  PU::fillAffineMvpCand( pu, eRefPicList, iRefIdx, affineAMVPInfo );
3863  CHECK( affineAMVPInfo.numCand == 0, "Assertion failed." );
3864
3865  PelUnitBuf predBuf = m_tmpStorageLCU.getBuf( UnitAreaRelative(*pu.cu, pu) );
3866
3867  // initialize Mvp index & Mvp
3868  iBestIdx = 0;
3869  for( int i = 0 ; i < affineAMVPInfo.numCand; i++ )
3870  {
3871    Mv mv[3] = { affineAMVPInfo.mvCandLT[i], affineAMVPInfo.mvCandRT[i], affineAMVPInfo.mvCandLB[i] };
3872    Mv mvTrace[3] = { affineAMVPInfo.mvCandLT[i], affineAMVPInfo.mvCandRT[i], affineAMVPInfo.mvCandLB[i] };
3873    mvTrace[0].setHighPrec();
3874    mvTrace[1].setHighPrec();
3875    mvTrace[2].setHighPrec();
3876
3877    Distortion uiTmpCost = xGetAffineTemplateCost( pu, origBuf, predBuf, mv, i, AMVP_MAX_NUM_CANDS, eRefPicList, iRefIdx );
3878
3879    if ( uiBestCost > uiTmpCost )
3880    {
3881      uiBestCost = uiTmpCost;
3882      bestMvLT = affineAMVPInfo.mvCandLT[i];
3883      bestMvRT = affineAMVPInfo.mvCandRT[i];
3884      bestMvLB = affineAMVPInfo.mvCandLB[i];
3885      iBestIdx  = i;
3886      *puiDistBiP = uiTmpCost;
3887    }
3888  }
3889
3890  // Setting Best MVP
3891  acMvPred[0] = bestMvLT;
3892  acMvPred[1] = bestMvRT;
3893  acMvPred[2] = bestMvLB;
3894
3895  pu.mvpIdx[eRefPicList] = iBestIdx;
3896  pu.mvpNum[eRefPicList] = affineAMVPInfo.numCand;
3897  DTRACE( g_trace_ctx, D_COMMON, "#estAffi=%d \n", affineAMVPInfo.numCand );
3898}
3899
3900void InterSearch::xCopyAffineAMVPInfo (AffineAMVPInfo& src, AffineAMVPInfo& dst)
3901{
3902  dst.numCand = src.numCand;
3903  DTRACE( g_trace_ctx, D_COMMON, " (%d) #copyAffi=%d \n", DTRACE_GET_COUNTER( g_trace_ctx, D_COMMON ), src.numCand );
3904  ::memcpy( dst.mvCandLT, src.mvCandLT, sizeof(Mv)*src.numCand );
3905  ::memcpy( dst.mvCandRT, src.mvCandRT, sizeof(Mv)*src.numCand );
3906  ::memcpy( dst.mvCandLB, src.mvCandLB, sizeof(Mv)*src.numCand );
3907}
3908#endif
3909
3910
3911/**
3912* \brief Generate half-sample interpolated block
3913*
3914* \param pattern Reference picture ROI
3915* \param biPred    Flag indicating whether block is for biprediction
3916*/
3917void InterSearch::xExtDIFUpSamplingH( CPelBuf* pattern )
3918{
3919  const ClpRng& clpRng = m_lumaClpRng;
3920  int width      = pattern->width;
3921  int height     = pattern->height;
3922  int srcStride  = pattern->stride;
3923
3924  int intStride = width + 1;
3925  int dstStride = width + 1;
3926  Pel *intPtr;
3927  Pel *dstPtr;
3928  int filterSize = NTAPS_LUMA;
3929  int halfFilterSize = (filterSize>>1);
3930  const Pel *srcPtr = pattern->buf - halfFilterSize*srcStride - 1;
3931
3932  const ChromaFormat chFmt = m_currChromaFormat;
3933
3934#if JEM_TOOLS || JVET_K0346 || JVET_K_AFFINE
3935  m_if.filterHor(COMPONENT_Y, srcPtr, srcStride, m_filteredBlockTmp[0][0], intStride, width + 1, height + filterSize, 0 << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE, false, chFmt, clpRng);
3936  m_if.filterHor(COMPONENT_Y, srcPtr, srcStride, m_filteredBlockTmp[2][0], intStride, width + 1, height + filterSize, 2 << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE, false, chFmt, clpRng);
3937
3938  intPtr = m_filteredBlockTmp[0][0] + halfFilterSize * intStride + 1;
3939  dstPtr = m_filteredBlock[0][0][0];
3940  m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width + 0, height + 0, 0 << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE, false, true, chFmt, clpRng);
3941
3942  intPtr = m_filteredBlockTmp[0][0] + (halfFilterSize - 1) * intStride + 1;
3943  dstPtr = m_filteredBlock[2][0][0];
3944  m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width + 0, height + 1, 2 << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE, false, true, chFmt, clpRng);
3945
3946  intPtr = m_filteredBlockTmp[2][0] + halfFilterSize * intStride;
3947  dstPtr = m_filteredBlock[0][2][0];
3948  m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width + 1, height + 0, 0 << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE, false, true, chFmt, clpRng);
3949
3950  intPtr = m_filteredBlockTmp[2][0] + (halfFilterSize - 1) * intStride;
3951  dstPtr = m_filteredBlock[2][2][0];
3952  m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width + 1, height + 1, 2 << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE, false, true, chFmt, clpRng);
3953#else
3954  m_if.filterHor(COMPONENT_Y, srcPtr, srcStride, m_filteredBlockTmp[0][0], intStride, width + 1, height + filterSize, 0, false, chFmt, clpRng);
3955  m_if.filterHor(COMPONENT_Y, srcPtr, srcStride, m_filteredBlockTmp[2][0], intStride, width + 1, height + filterSize, 2, false, chFmt, clpRng);
3956
3957  intPtr = m_filteredBlockTmp[0][0] + halfFilterSize * intStride + 1;
3958  dstPtr = m_filteredBlock[0][0][0];
3959  m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width + 0, height + 0, 0, false, true, chFmt, clpRng);
3960
3961  intPtr = m_filteredBlockTmp[0][0] + (halfFilterSize - 1) * intStride + 1;
3962  dstPtr = m_filteredBlock[2][0][0];
3963  m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width + 0, height + 1, 2, false, true, chFmt, clpRng);
3964
3965  intPtr = m_filteredBlockTmp[2][0] + halfFilterSize * intStride;
3966  dstPtr = m_filteredBlock[0][2][0];
3967  m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width + 1, height + 0, 0, false, true, chFmt, clpRng);
3968
3969  intPtr = m_filteredBlockTmp[2][0] + (halfFilterSize - 1) * intStride;
3970  dstPtr = m_filteredBlock[2][2][0];
3971  m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width + 1, height + 1, 2, false, true, chFmt, clpRng);
3972#endif
3973}
3974
3975
3976
3977
3978
3979/**
3980* \brief Generate quarter-sample interpolated blocks
3981*
3982* \param pattern    Reference picture ROI
3983* \param halfPelRef Half-pel mv
3984* \param biPred     Flag indicating whether block is for biprediction
3985*/
3986void InterSearch::xExtDIFUpSamplingQ( CPelBuf* pattern, Mv halfPelRef )
3987{
3988  const ClpRng& clpRng = m_lumaClpRng;
3989  int width      = pattern->width;
3990  int height     = pattern->height;
3991  int srcStride  = pattern->stride;
3992
3993  Pel const* srcPtr;
3994  int intStride = width + 1;
3995  int dstStride = width + 1;
3996  Pel *intPtr;
3997  Pel *dstPtr;
3998  int filterSize = NTAPS_LUMA;
3999
4000  int halfFilterSize = (filterSize>>1);
4001
4002  int extHeight = (halfPelRef.getVer() == 0) ? height + filterSize : height + filterSize-1;
4003
4004  const ChromaFormat chFmt = m_currChromaFormat;
4005
4006  // Horizontal filter 1/4
4007  srcPtr = pattern->buf - halfFilterSize * srcStride - 1;
4008  intPtr = m_filteredBlockTmp[1][0];
4009  if (halfPelRef.getVer() > 0)
4010  {
4011    srcPtr += srcStride;
4012  }
4013  if (halfPelRef.getHor() >= 0)
4014  {
4015    srcPtr += 1;
4016  }
4017#if JEM_TOOLS || JVET_K0346 || JVET_K_AFFINE
4018  m_if.filterHor(COMPONENT_Y, srcPtr, srcStride, intPtr, intStride, width, extHeight, 1 << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE, false, chFmt, clpRng);
4019#else
4020  m_if.filterHor(COMPONENT_Y, srcPtr, srcStride, intPtr, intStride, width, extHeight, 1, false, chFmt, clpRng);
4021#endif
4022
4023  // Horizontal filter 3/4
4024  srcPtr = pattern->buf - halfFilterSize*srcStride - 1;
4025  intPtr = m_filteredBlockTmp[3][0];
4026  if (halfPelRef.getVer() > 0)
4027  {
4028    srcPtr += srcStride;
4029  }
4030  if (halfPelRef.getHor() > 0)
4031  {
4032    srcPtr += 1;
4033  }
4034#if JEM_TOOLS || JVET_K0346 || JVET_K_AFFINE
4035  m_if.filterHor(COMPONENT_Y, srcPtr, srcStride, intPtr, intStride, width, extHeight, 3 << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE, false, chFmt, clpRng);
4036#else
4037  m_if.filterHor(COMPONENT_Y, srcPtr, srcStride, intPtr, intStride, width, extHeight, 3, false, chFmt, clpRng);
4038#endif
4039
4040  // Generate @ 1,1
4041  intPtr = m_filteredBlockTmp[1][0] + (halfFilterSize-1) * intStride;
4042  dstPtr = m_filteredBlock[1][1][0];
4043  if (halfPelRef.getVer() == 0)
4044  {
4045    intPtr += intStride;
4046  }
4047#if JEM_TOOLS || JVET_K0346 || JVET_K_AFFINE
4048  m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 1 << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE, false, true, chFmt, clpRng);
4049#else
4050  m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 1, false, true, chFmt, clpRng);
4051#endif
4052
4053  // Generate @ 3,1
4054  intPtr = m_filteredBlockTmp[1][0] + (halfFilterSize-1) * intStride;
4055  dstPtr = m_filteredBlock[3][1][0];
4056#if JEM_TOOLS || JVET_K0346 || JVET_K_AFFINE
4057  m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 3 << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE, false, true, chFmt, clpRng);
4058#else
4059  m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 3, false, true, chFmt, clpRng);
4060#endif
4061
4062  if (halfPelRef.getVer() != 0)
4063  {
4064    // Generate @ 2,1
4065    intPtr = m_filteredBlockTmp[1][0] + (halfFilterSize - 1) * intStride;
4066    dstPtr = m_filteredBlock[2][1][0];
4067    if (halfPelRef.getVer() == 0)
4068    {
4069      intPtr += intStride;
4070    }
4071#if JEM_TOOLS || JVET_K0346 || JVET_K_AFFINE
4072    m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 2 << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE, false, true, chFmt, clpRng);
4073#else
4074    m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 2, false, true, chFmt, clpRng);
4075#endif
4076
4077    // Generate @ 2,3
4078    intPtr = m_filteredBlockTmp[3][0] + (halfFilterSize - 1) * intStride;
4079    dstPtr = m_filteredBlock[2][3][0];
4080    if (halfPelRef.getVer() == 0)
4081    {
4082      intPtr += intStride;
4083    }
4084#if JEM_TOOLS || JVET_K0346 || JVET_K_AFFINE
4085    m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 2 << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE, false, true, chFmt, clpRng);
4086#else
4087    m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 2, false, true, chFmt, clpRng);
4088#endif
4089  }
4090  else
4091  {
4092    // Generate @ 0,1
4093    intPtr = m_filteredBlockTmp[1][0] + halfFilterSize * intStride;
4094    dstPtr = m_filteredBlock[0][1][0];
4095#if JEM_TOOLS || JVET_K0346 || JVET_K_AFFINE
4096    m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 0 << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE, false, true, chFmt, clpRng);
4097#else
4098    m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 0, false, true, chFmt, clpRng);
4099#endif
4100
4101    // Generate @ 0,3
4102    intPtr = m_filteredBlockTmp[3][0] + halfFilterSize * intStride;
4103    dstPtr = m_filteredBlock[0][3][0];
4104#if JEM_TOOLS || JVET_K0346 || JVET_K_AFFINE
4105    m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 0 << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE, false, true, chFmt, clpRng);
4106#else
4107    m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 0, false, true, chFmt, clpRng);
4108#endif
4109  }
4110
4111  if (halfPelRef.getHor() != 0)
4112  {
4113    // Generate @ 1,2
4114    intPtr = m_filteredBlockTmp[2][0] + (halfFilterSize - 1) * intStride;
4115    dstPtr = m_filteredBlock[1][2][0];
4116    if (halfPelRef.getHor() > 0)
4117    {
4118      intPtr += 1;
4119    }
4120    if (halfPelRef.getVer() >= 0)
4121    {
4122      intPtr += intStride;
4123    }
4124#if JEM_TOOLS || JVET_K0346 || JVET_K_AFFINE
4125    m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 1 << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE, false, true, chFmt, clpRng);
4126#else
4127    m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 1, false, true, chFmt, clpRng);
4128#endif
4129
4130    // Generate @ 3,2
4131    intPtr = m_filteredBlockTmp[2][0] + (halfFilterSize - 1) * intStride;
4132    dstPtr = m_filteredBlock[3][2][0];
4133    if (halfPelRef.getHor() > 0)
4134    {
4135      intPtr += 1;
4136    }
4137    if (halfPelRef.getVer() > 0)
4138    {
4139      intPtr += intStride;
4140    }
4141#if JEM_TOOLS || JVET_K0346 || JVET_K_AFFINE
4142    m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 3 << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE, false, true, chFmt, clpRng);
4143#else
4144    m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 3, false, true, chFmt, clpRng);
4145#endif
4146  }
4147  else
4148  {
4149    // Generate @ 1,0
4150    intPtr = m_filteredBlockTmp[0][0] + (halfFilterSize - 1) * intStride + 1;
4151    dstPtr = m_filteredBlock[1][0][0];
4152    if (halfPelRef.getVer() >= 0)
4153    {
4154      intPtr += intStride;
4155    }
4156#if JEM_TOOLS || JVET_K0346 || JVET_K_AFFINE
4157    m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 1 << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE, false, true, chFmt, clpRng);
4158#else
4159    m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 1, false, true, chFmt, clpRng);
4160#endif
4161
4162    // Generate @ 3,0
4163    intPtr = m_filteredBlockTmp[0][0] + (halfFilterSize - 1) * intStride + 1;
4164    dstPtr = m_filteredBlock[3][0][0];
4165    if (halfPelRef.getVer() > 0)
4166    {
4167      intPtr += intStride;
4168    }
4169#if JEM_TOOLS || JVET_K0346 || JVET_K_AFFINE
4170    m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 3 << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE, false, true, chFmt, clpRng);
4171#else
4172    m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 3, false, true, chFmt, clpRng);
4173#endif
4174  }
4175
4176  // Generate @ 1,3
4177  intPtr = m_filteredBlockTmp[3][0] + (halfFilterSize - 1) * intStride;
4178  dstPtr = m_filteredBlock[1][3][0];
4179  if (halfPelRef.getVer() == 0)
4180  {
4181    intPtr += intStride;
4182  }
4183#if JEM_TOOLS || JVET_K0346 || JVET_K_AFFINE
4184  m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 1 << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE, false, true, chFmt, clpRng);
4185#else
4186  m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 1, false, true, chFmt, clpRng);
4187#endif
4188
4189  // Generate @ 3,3
4190  intPtr = m_filteredBlockTmp[3][0] + (halfFilterSize - 1) * intStride;
4191  dstPtr = m_filteredBlock[3][3][0];
4192#if JEM_TOOLS || JVET_K0346 || JVET_K_AFFINE
4193  m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 3 << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE, false, true, chFmt, clpRng);
4194#else
4195  m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 3, false, true, chFmt, clpRng);
4196#endif
4197}
4198
4199
4200
4201
4202
4203//! set wp tables
4204void InterSearch::setWpScalingDistParam( int iRefIdx, RefPicList eRefPicListCur, Slice *pcSlice )
4205{
4206  if ( iRefIdx<0 )
4207  {
4208    m_cDistParam.applyWeight = false;
4209    return;
4210  }
4211
4212  WPScalingParam  *wp0 , *wp1;
4213
4214  m_cDistParam.applyWeight = ( pcSlice->getSliceType()==P_SLICE && pcSlice->testWeightPred() ) || ( pcSlice->getSliceType()==B_SLICE && pcSlice->testWeightBiPred() ) ;
4215
4216  if ( !m_cDistParam.applyWeight )
4217  {
4218    return;
4219  }
4220
4221  int iRefIdx0 = ( eRefPicListCur == REF_PIC_LIST_0 ) ? iRefIdx : (-1);
4222  int iRefIdx1 = ( eRefPicListCur == REF_PIC_LIST_1 ) ? iRefIdx : (-1);
4223
4224  getWpScaling( pcSlice, iRefIdx0, iRefIdx1, wp0 , wp1 );
4225
4226  if ( iRefIdx0 < 0 )
4227  {
4228    wp0 = NULL;
4229  }
4230  if ( iRefIdx1 < 0 )
4231  {
4232    wp1 = NULL;
4233  }
4234
4235  m_cDistParam.wpCur  = NULL;
4236
4237  if ( eRefPicListCur == REF_PIC_LIST_0 )
4238  {
4239    m_cDistParam.wpCur = wp0;
4240  }
4241  else
4242  {
4243    m_cDistParam.wpCur = wp1;
4244  }
4245}
4246
4247void InterSearch::xEncodeInterResidualQT(CodingStructure &cs, Partitioner &partitioner, const ComponentID &compID)
4248{
4249  const UnitArea& currArea    = partitioner.currArea();
4250  const TransformUnit &currTU = *cs.getTU(currArea.lumaPos(), partitioner.chType);
4251  const CodingUnit &cu        = *currTU.cu;
4252#if ENABLE_BMS
4253  const unsigned currDepth    = partitioner.currTrDepth;
4254
4255  const bool bSubdiv          = currDepth != currTU.depth;
4256#endif
4257
4258  if (compID == MAX_NUM_TBLOCKS)  // we are not processing a channel, instead we always recurse and code the CBFs
4259  {
4260#if ENABLE_BMS
4261    if( cs.pcv->noRQT )
4262    {
4263#if ENABLE_BMS
4264      if( partitioner.canSplit( TU_MAX_TR_SPLIT, cs ) )
4265      {
4266        CHECK( !bSubdiv, "Not performing the implicit TU split" );
4267      }
4268      else
4269#endif
4270      CHECK( bSubdiv, "transformsplit not supported" );
4271    }
4272#endif
4273    CHECK(CU::isIntra(cu), "Inter search provided with intra CU");
4274
4275    if( cu.chromaFormat != CHROMA_400 )
4276    {
4277#if ENABLE_BMS
4278      const bool firstCbfOfCU = ( currDepth == 0 );
4279      {
4280        if( firstCbfOfCU || TU::getCbfAtDepth( currTU, COMPONENT_Cb, currDepth - 1 ) )
4281        {
4282          const bool  chroma_cbf = TU::getCbfAtDepth( currTU, COMPONENT_Cb, currDepth );
4283          m_CABACEstimator->cbf_comp( cs, chroma_cbf, currArea.blocks[COMPONENT_Cb], currDepth );
4284        }
4285        if( firstCbfOfCU || TU::getCbfAtDepth( currTU, COMPONENT_Cr, currDepth - 1 ) )
4286        {
4287          const bool  chroma_cbf = TU::getCbfAtDepth( currTU, COMPONENT_Cr, currDepth );
4288#if JVET_K0072
4289          m_CABACEstimator->cbf_comp( cs, chroma_cbf, currArea.blocks[COMPONENT_Cr], currDepth, TU::getCbfAtDepth( currTU, COMPONENT_Cb, currDepth ) );
4290#else
4291          m_CABACEstimator->cbf_comp( cs, chroma_cbf, currArea.blocks[COMPONENT_Cr], currDepth );
4292#endif
4293        }
4294      }
4295    }
4296
4297    if( !bSubdiv )
4298    {
4299      m_CABACEstimator->cbf_comp( cs, TU::getCbfAtDepth( currTU, COMPONENT_Y, currDepth ), currArea.Y(), currDepth );
4300    }
4301#else
4302      m_CABACEstimator->cbf_comp( cs, TU::getCbf( currTU, COMPONENT_Cb ), currArea.blocks[COMPONENT_Cb] );
4303#if JVET_K0072
4304      m_CABACEstimator->cbf_comp( cs, TU::getCbf( currTU, COMPONENT_Cr ), currArea.blocks[COMPONENT_Cr], TU::getCbf( currTU, COMPONENT_Cb ) );
4305#else
4306      m_CABACEstimator->cbf_comp( cs, TU::getCbf( currTU, COMPONENT_Cr ), currArea.blocks[COMPONENT_Cr] );
4307#endif
4308    }
4309
4310    m_CABACEstimator->cbf_comp( cs, TU::getCbf( currTU, COMPONENT_Y ), currArea.Y() );
4311#endif
4312  }
4313
4314#if ENABLE_BMS
4315  if (!bSubdiv)
4316#endif
4317  {
4318    if (compID != MAX_NUM_TBLOCKS) // we have already coded the CBFs, so now we code coefficients
4319    {
4320      if( currArea.blocks[compID].valid() )
4321      {
4322        if( TU::hasCrossCompPredInfo( currTU, compID ) )
4323        {
4324          m_CABACEstimator->cross_comp_pred( currTU, compID );
4325        }
4326        if( TU::getCbf( currTU, compID ) )
4327        {
4328          m_CABACEstimator->residual_coding( currTU, compID );
4329        }
4330      }
4331    }
4332  }
4333#if ENABLE_BMS
4334  else
4335  {
4336    if( compID == MAX_NUM_TBLOCKS || TU::getCbfAtDepth( currTU, compID, currDepth ) )
4337    {
4338#if ENABLE_BMS
4339      if( partitioner.canSplit( TU_MAX_TR_SPLIT, cs ) )
4340      {
4341        partitioner.splitCurrArea( TU_MAX_TR_SPLIT, cs );
4342      }
4343      else
4344#endif
4345        THROW( "Implicit TU split not available!" );
4346
4347      do
4348      {
4349        xEncodeInterResidualQT( cs, partitioner, compID );
4350      } while( partitioner.nextPart( cs ) );
4351
4352      partitioner.exitCurrSplit();
4353    }
4354  }
4355#endif
4356#if JEM_TOOLS && !HM_EMT_NSST_AS_IN_JEM
4357
4358#if ENABLE_BMS
4359  if( isLuma( compID ) && currDepth == 0 )
4360#else
4361  if( isLuma( compID ) )
4362#endif
4363  {
4364    m_CABACEstimator->cu_emt_pertu_idx( cu );
4365  }
4366#endif
4367}
4368
4369void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &partitioner, Distortion *puiZeroDist /*= NULL*/)
4370{
4371  const UnitArea& currArea = partitioner.currArea();
4372  const SPS &sps           = *cs.sps;
4373  const PPS &pps           = *cs.pps;
4374  const uint32_t numValidComp  = getNumberValidComponents( sps.getChromaFormatIdc() );
4375  const uint32_t numTBlocks    = getNumberValidTBlocks   ( *cs.pcv );
4376#if ENABLE_BMS
4377  const unsigned currDepth = partitioner.currTrDepth;
4378
4379  bool bCheckSplit = false, bCheckFull = false;
4380#if ENABLE_BMS
4381  if( cs.pcv->noRQT )
4382  {
4383    bCheckFull  = !partitioner.canSplit( TU_MAX_TR_SPLIT, cs );
4384    bCheckSplit = !bCheckFull;
4385  }
4386#endif
4387
4388  // get temporary data
4389  CodingStructure *csSplit = nullptr;
4390  CodingStructure *csFull  = nullptr;
4391  if (bCheckSplit)
4392  {
4393    csSplit = &cs;
4394  }
4395  else if (bCheckFull)
4396  {
4397    csFull = &cs;
4398  }
4399#else
4400  bool bCheckFull = true;
4401  CodingStructure *csFull = &cs;
4402#endif
4403
4404  Distortion uiSingleDist         = 0;
4405  Distortion uiSingleDistComp [3] = { 0, 0, 0 };
4406  TCoeff     uiAbsSum         [3] = { 0, 0, 0 };
4407
4408  const TempCtx ctxStart  ( m_CtxCache, m_CABACEstimator->getCtx() );
4409  TempCtx       ctxBest   ( m_CtxCache );
4410
4411  if (bCheckFull)
4412  {
4413    TransformUnit &tu = csFull->addTU(currArea, partitioner.chType);
4414#if ENABLE_BMS
4415    tu.depth          = currDepth;
4416#endif
4417#if JEM_TOOLS || JVET_K1000_SIMPLIFIED_EMT
4418    tu.emtIdx         = 0;
4419#endif
4420
4421    double minCost            [MAX_NUM_TBLOCKS];
4422    bool   checkTransformSkip [MAX_NUM_TBLOCKS];
4423
4424    m_CABACEstimator->resetBits();
4425
4426    memset(m_pTempPel, 0, sizeof(Pel) * tu.Y().area()); // not necessary needed for inside of recursion (only at the beginning)
4427
4428    for (uint32_t i = 0; i < numTBlocks; i++)
4429    {
4430      minCost[i] = MAX_DOUBLE;
4431    }
4432
4433    CodingStructure &saveCS = *m_pSaveCS[0];
4434    saveCS.pcv     = cs.pcv;
4435    saveCS.picture = cs.picture;
4436    saveCS.area.repositionTo(currArea);
4437    saveCS.clearTUs();
4438
4439    TransformUnit &bestTU = saveCS.addTU( currArea, partitioner.chType );
4440
4441
4442    for( uint32_t c = 0; c < numTBlocks; c++ )
4443    {
4444      const ComponentID compID    = ComponentID(c);
4445      const CompArea&   compArea  = tu.blocks[compID];
4446      const int channelBitDepth   = sps.getBitDepth(toChannelType(compID));
4447
4448      checkTransformSkip[compID]  = false;
4449
4450      if( !tu.blocks[compID].valid() )
4451      {
4452        continue;
4453      }
4454
4455      checkTransformSkip[compID] = pps.getUseTransformSkip() && TU::hasTransformSkipFlag( *tu.cs, tu.blocks[compID] ) && !cs.isLossless;
4456#if JEM_TOOLS || JVET_K1000_SIMPLIFIED_EMT
4457      if( isLuma(compID) )
4458      {
4459        checkTransformSkip[compID]  &= !tu.cu->emtFlag;
4460      }
4461#endif
4462
4463      const bool isCrossCPredictionAvailable = TU::hasCrossCompPredInfo( tu, compID );
4464
4465      int8_t preCalcAlpha = 0;
4466      const CPelBuf lumaResi = csFull->getResiBuf(tu.Y());
4467
4468      if (isCrossCPredictionAvailable)
4469      {
4470        csFull->getResiBuf( compArea ).copyFrom( cs.getOrgResiBuf( compArea ) );
4471        preCalcAlpha = xCalcCrossComponentPredictionAlpha( tu, compID, m_pcEncCfg->getUseReconBasedCrossCPredictionEstimate() );
4472      }
4473
4474      const int crossCPredictionModesToTest = preCalcAlpha != 0 ? 2 : 1;
4475#if JEM_TOOLS || JVET_K1000_SIMPLIFIED_EMT
4476      const int numEmtTransformCandidates   = isLuma(compID) && tu.cu->emtFlag && sps.getSpsNext().getUseInterEMT() ? 4 : 1;
4477      const int numTransformCandidates      = checkTransformSkip[compID] ? ( numEmtTransformCandidates + 1 ) : numEmtTransformCandidates;
4478#else
4479      const int numTransformCandidates      = checkTransformSkip[compID] ? 2 : 1;
4480#endif
4481      int lastTransformModeIndex            = numTransformCandidates - 1; //lastTransformModeIndex is the mode for transformSkip (if transformSkip is active)
4482      const bool isOneMode                  = crossCPredictionModesToTest == 1 && numTransformCandidates == 1;
4483
4484      bool isLastBest = isOneMode;
4485      for( int transformMode = 0; transformMode < numTransformCandidates; transformMode++ )
4486      {
4487        for( int crossCPredictionModeId = 0; crossCPredictionModeId < crossCPredictionModesToTest; crossCPredictionModeId++ )
4488        {
4489          const bool isFirstMode  = transformMode == 0 && crossCPredictionModeId == 0;
4490          const bool isLastMode   = ( transformMode + 1 ) == numTransformCandidates && ( crossCPredictionModeId + 1 ) == crossCPredictionModesToTest;
4491          const bool bUseCrossCPrediction = crossCPredictionModeId != 0;
4492
4493          // copy the original residual into the residual buffer
4494          csFull->getResiBuf(compArea).copyFrom(cs.getOrgResiBuf(compArea));
4495
4496          m_CABACEstimator->getCtx() = ctxStart;
4497          m_CABACEstimator->resetBits();
4498
4499#if JEM_TOOLS || JVET_K1000_SIMPLIFIED_EMT
4500          if( isLuma( compID ) ) tu.emtIdx = transformMode;
4501#endif
4502          tu.transformSkip[compID]  = checkTransformSkip[compID] && transformMode == lastTransformModeIndex;
4503          tu.compAlpha[compID]      = bUseCrossCPrediction ? preCalcAlpha : 0;
4504
4505          const QpParam cQP(tu, compID);  // note: uses tu.transformSkip[compID]
4506
4507#if RDOQ_CHROMA_LAMBDA
4508          m_pcTrQuant->selectLambda(compID);
4509#endif
4510
4511          TCoeff     currAbsSum = 0;
4512          uint64_t   currCompFracBits = 0;
4513          Distortion currCompDist = 0;
4514          double     currCompCost = 0;
4515          uint64_t   nonCoeffFracBits = 0;
4516          Distortion nonCoeffDist = 0;
4517          double     nonCoeffCost = 0;
4518
4519          if (bUseCrossCPrediction)
4520          {
4521            PelBuf resiBuf = csFull->getResiBuf( compArea );
4522            crossComponentPrediction( tu, compID, lumaResi, resiBuf, resiBuf, false );
4523          }
4524
4525          m_pcTrQuant->transformNxN(tu, compID, cQP, currAbsSum, m_CABACEstimator->getCtx());
4526
4527          if (isFirstMode || (currAbsSum == 0))
4528          {
4529            const CPelBuf zeroBuf(m_pTempPel, compArea);
4530            const CPelBuf orgResi = csFull->getOrgResiBuf( compArea );
4531
4532            if (bUseCrossCPrediction)
4533            {
4534              PelBuf resi = csFull->getResiBuf( compArea );
4535              crossComponentPrediction( tu, compID, lumaResi, zeroBuf, resi, true );
4536              nonCoeffDist = m_pcRdCost->getDistPart( orgResi, resi, channelBitDepth, compID, DF_SSE );
4537            }
4538            else
4539            {
4540              nonCoeffDist = m_pcRdCost->getDistPart( zeroBuf, orgResi, channelBitDepth, compID, DF_SSE ); // initialized with zero residual distortion
4541            }
4542
4543#if JVET_K0072
4544            const bool prevCbf = ( compID == COMPONENT_Cr ? tu.cbf[COMPONENT_Cb] : false );
4545#if ENABLE_BMS
4546            m_CABACEstimator->cbf_comp( *csFull, false, compArea, currDepth, prevCbf );
4547#else
4548            m_CABACEstimator->cbf_comp( *csFull, false, compArea, prevCbf );
4549#endif
4550#else
4551#if ENABLE_BMS
4552            m_CABACEstimator->cbf_comp( *csFull, false, compArea, currDepth );
4553#else
4554            m_CABACEstimator->cbf_comp( *csFull, false, compArea );
4555#endif
4556#endif
4557
4558            if( isCrossCPredictionAvailable )
4559            {
4560              m_CABACEstimator->cross_comp_pred( tu, compID );
4561            }
4562
4563            nonCoeffFracBits = m_CABACEstimator->getEstFracBits();
4564#if WCG_EXT
4565            if( m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() )
4566            {
4567              nonCoeffCost   = m_pcRdCost->calcRdCost(nonCoeffFracBits, nonCoeffDist, false);
4568            }
4569            else
4570#endif
4571            nonCoeffCost     = m_pcRdCost->calcRdCost(nonCoeffFracBits, nonCoeffDist);
4572          }
4573
4574          if ((puiZeroDist != NULL) && isFirstMode)
4575          {
4576            *puiZeroDist += nonCoeffDist; // initialized with zero residual distortion
4577          }
4578
4579          if (currAbsSum > 0) //if non-zero coefficients are present, a residual needs to be derived for further prediction
4580          {
4581            if (isFirstMode)
4582            {
4583              m_CABACEstimator->getCtx() = ctxStart;
4584              m_CABACEstimator->resetBits();
4585            }
4586
4587#if JVET_K0072
4588            const bool prevCbf = ( compID == COMPONENT_Cr ? tu.cbf[COMPONENT_Cb] : false );
4589#if ENABLE_BMS
4590            m_CABACEstimator->cbf_comp( *csFull, true, compArea, currDepth, prevCbf );
4591#else
4592            m_CABACEstimator->cbf_comp( *csFull, true, compArea, prevCbf );
4593#endif
4594#else
4595#if ENABLE_BMS
4596            m_CABACEstimator->cbf_comp( *csFull, true, compArea, currDepth );
4597#else
4598            m_CABACEstimator->cbf_comp( *csFull, true, compArea );
4599#endif
4600#endif
4601
4602            if( isCrossCPredictionAvailable )
4603            {
4604              m_CABACEstimator->cross_comp_pred( tu, compID );
4605            }
4606            m_CABACEstimator->residual_coding( tu, compID );
4607
4608            currCompFracBits = m_CABACEstimator->getEstFracBits();
4609
4610            PelBuf resiBuf     = csFull->getResiBuf(compArea);
4611            CPelBuf orgResiBuf = csFull->getOrgResiBuf(compArea);
4612
4613            m_pcTrQuant->invTransformNxN(tu, compID, resiBuf, cQP);
4614
4615#if JEM_TOOLS
4616            if( cs.sps->getSpsNext().getUseBIF() &&  isLuma(compID) && (tu.cu->qp > 17) && (16 > std::min(tu.lumaSize().width, tu.lumaSize().height) ) )
4617            {
4618              const CPelBuf predBuf    = csFull->getPredBuf(compArea);
4619              m_bilateralFilter->bilateralFilterInter( resiBuf, predBuf, tu.cu->qp, cs.slice->clpRng( COMPONENT_Y ) );
4620            }
4621
4622#endif
4623            if (bUseCrossCPrediction)
4624            {
4625              crossComponentPrediction( tu, compID, lumaResi, resiBuf, resiBuf, true );
4626            }
4627
4628            currCompDist = m_pcRdCost->getDistPart(orgResiBuf, resiBuf, channelBitDepth, compID, DF_SSE);
4629           
4630#if WCG_EXT
4631            currCompCost = m_pcRdCost->calcRdCost(currCompFracBits, currCompDist, false);
4632#else
4633            currCompCost = m_pcRdCost->calcRdCost(currCompFracBits, currCompDist);
4634#endif
4635
4636            if (csFull->isLossless)
4637            {
4638              nonCoeffCost = MAX_DOUBLE;
4639            }
4640          }
4641          else if( ( transformMode == lastTransformModeIndex ) && checkTransformSkip[compID] && !bUseCrossCPrediction )
4642          {
4643            currCompCost = MAX_DOUBLE;
4644          }
4645          else
4646          {
4647            currCompFracBits = nonCoeffFracBits;
4648            currCompDist     = nonCoeffDist;
4649            currCompCost     = nonCoeffCost;
4650
4651            tu.cbf[compID] = 0;
4652          }
4653
4654          // evaluate
4655          if( ( currCompCost < minCost[compID] ) || ( transformMode == lastTransformModeIndex && checkTransformSkip[compID] && currCompCost == minCost[compID] ) )
4656          {
4657            // copy component
4658            if (isFirstMode && ((nonCoeffCost < currCompCost) || (currAbsSum == 0))) // check for forced null
4659            {
4660              tu.getCoeffs( compID ).fill( 0 );
4661              csFull->getResiBuf( compArea ).fill( 0 );
4662              tu.cbf[compID]   = 0;
4663
4664              currAbsSum       = 0;
4665              currCompFracBits = nonCoeffFracBits;
4666              currCompDist     = nonCoeffDist;
4667              currCompCost     = nonCoeffCost;
4668            }
4669
4670            uiAbsSum[compID]         = currAbsSum;
4671            uiSingleDistComp[compID] = currCompDist;
4672            minCost[compID]          = currCompCost;
4673
4674            if (uiAbsSum[compID] == 0)
4675            {
4676              if (bUseCrossCPrediction)
4677              {
4678                const CPelBuf zeroBuf( m_pTempPel, compArea );
4679                PelBuf resiBuf = csFull->getResiBuf( compArea );
4680
4681                crossComponentPrediction( tu, compID, lumaResi, zeroBuf, resiBuf, true );
4682              }
4683            }
4684
4685            if( !isLastMode )
4686            {
4687              bestTU.copyComponentFrom( tu, compID );
4688              saveCS.getResiBuf( compArea ).copyFrom( csFull->getResiBuf( compArea ) );
4689            }
4690
4691            isLastBest = isLastMode;
4692          }
4693        }
4694      }
4695
4696      if( !isLastBest )
4697      {
4698        // copy component
4699        tu.copyComponentFrom( bestTU, compID );
4700        csFull->getResiBuf( compArea ).copyFrom( saveCS.getResiBuf( compArea ) );
4701      }
4702    } // component loop
4703
4704    m_CABACEstimator->getCtx() = ctxStart;
4705    m_CABACEstimator->resetBits();
4706
4707    static const ComponentID cbf_getComp[3] = { COMPONENT_Cb, COMPONENT_Cr, COMPONENT_Y };
4708    for( unsigned c = 0; c < numTBlocks; c++)
4709    {
4710      const ComponentID compID = cbf_getComp[c];
4711      if( tu.blocks[compID].valid() )
4712      {
4713#if ENABLE_BMS
4714#if JVET_K0072
4715        const bool prevCbf = ( compID == COMPONENT_Cr ? TU::getCbfAtDepth( tu, COMPONENT_Cb, currDepth ) : false );
4716        m_CABACEstimator->cbf_comp( *csFull, TU::getCbfAtDepth( tu, compID, currDepth ), tu.blocks[compID], currDepth, prevCbf );
4717#else
4718        m_CABACEstimator->cbf_comp( *csFull, TU::getCbfAtDepth( tu, compID, currDepth ), tu.blocks[compID], currDepth );
4719#endif
4720#else
4721#if JVET_K0072
4722        const bool prevCbf = ( compID == COMPONENT_Cr ? TU::getCbf( tu, COMPONENT_Cb ) : false );
4723        m_CABACEstimator->cbf_comp( *csFull, TU::getCbf( tu, compID ), tu.blocks[compID], prevCbf );
4724#else
4725        m_CABACEstimator->cbf_comp( *csFull, TU::getCbf( tu, compID ), tu.blocks[compID] );
4726#endif
4727#endif
4728      }
4729    }
4730
4731    for (uint32_t ch = 0; ch < numValidComp; ch++)
4732    {
4733      const ComponentID compID = ComponentID(ch);
4734
4735      if (tu.blocks[compID].valid())
4736      {
4737        if( cs.pps->getPpsRangeExtension().getCrossComponentPredictionEnabledFlag() && isChroma(compID) && uiAbsSum[COMPONENT_Y] )
4738        {
4739          m_CABACEstimator->cross_comp_pred( tu, compID );
4740        }
4741        if( TU::getCbf( tu, compID ) )
4742        {
4743          m_CABACEstimator->residual_coding( tu, compID );
4744        }
4745        uiSingleDist += uiSingleDistComp[compID];
4746      }
4747    }
4748
4749    csFull->fracBits += m_CABACEstimator->getEstFracBits();
4750    csFull->dist     += uiSingleDist;
4751#if WCG_EXT
4752    if( m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() )
4753    {
4754      csFull->cost    = m_pcRdCost->calcRdCost(csFull->fracBits, csFull->dist, false);
4755    }
4756    else
4757#endif
4758    csFull->cost      = m_pcRdCost->calcRdCost(csFull->fracBits, csFull->dist);
4759  } // check full
4760#if ENABLE_BMS
4761
4762  // code sub-blocks
4763  if( bCheckSplit )
4764  {
4765    if( bCheckFull )
4766    {
4767      m_CABACEstimator->getCtx() = ctxStart;
4768    }
4769
4770#if ENABLE_BMS
4771    if( partitioner.canSplit( TU_MAX_TR_SPLIT, cs ) )
4772    {
4773      partitioner.splitCurrArea( TU_MAX_TR_SPLIT, cs );
4774    }
4775    else
4776#endif
4777      THROW( "Implicit TU split not available!" );
4778
4779    do
4780    {
4781      xEstimateInterResidualQT(*csSplit, partitioner, bCheckFull ? nullptr : puiZeroDist);
4782
4783      csSplit->cost = m_pcRdCost->calcRdCost( csSplit->fracBits, csSplit->dist );
4784#if JEM_TOOLS || JVET_K1000_SIMPLIFIED_EMT
4785      if( csFull && csSplit->cost >= csFull->cost && m_pcEncCfg->getFastInterEMT() )
4786      {
4787        break;
4788      }
4789#endif
4790    } while( partitioner.nextPart( *csSplit ) );
4791
4792    partitioner.exitCurrSplit();
4793
4794    unsigned        anyCbfSet   =   0;
4795    unsigned        compCbf[3]  = { 0, 0, 0 };
4796
4797#if JEM_TOOLS || JVET_K1000_SIMPLIFIED_EMT
4798    bool isSplit = bCheckFull ? false : true;
4799    if( !bCheckFull || ( csSplit->cost < csFull->cost && m_pcEncCfg->getFastInterEMT() ) || !m_pcEncCfg->getFastInterEMT() )
4800#else
4801    if( !bCheckFull )
4802#endif
4803    {
4804      for( auto &currTU : csSplit->traverseTUs( currArea, partitioner.chType ) )
4805      {
4806        for( unsigned ch = 0; ch < numTBlocks; ch++ )
4807        {
4808          compCbf[ ch ] |= ( TU::getCbfAtDepth( currTU, ComponentID(ch), currDepth + 1 ) ? 1 : 0 );
4809        }
4810      }
4811
4812      {
4813
4814        for( auto &currTU : csSplit->traverseTUs( currArea, partitioner.chType ) )
4815        {
4816          TU::setCbfAtDepth   ( currTU, COMPONENT_Y,  currDepth, compCbf[ COMPONENT_Y  ] );
4817          if( currArea.chromaFormat != CHROMA_400 )
4818          {
4819            TU::setCbfAtDepth ( currTU, COMPONENT_Cb, currDepth, compCbf[ COMPONENT_Cb ] );
4820            TU::setCbfAtDepth ( currTU, COMPONENT_Cr, currDepth, compCbf[ COMPONENT_Cr ] );
4821          }
4822        }
4823
4824        anyCbfSet    = compCbf[ COMPONENT_Y  ];
4825        if( currArea.chromaFormat != CHROMA_400 )
4826        {
4827          anyCbfSet |= compCbf[ COMPONENT_Cb ];
4828          anyCbfSet |= compCbf[ COMPONENT_Cr ];
4829        }
4830      }
4831
4832      m_CABACEstimator->getCtx() = ctxStart;
4833      m_CABACEstimator->resetBits();
4834
4835      // when compID isn't a channel, code Cbfs:
4836      xEncodeInterResidualQT( *csSplit, partitioner, MAX_NUM_TBLOCKS );
4837      for (uint32_t ch = 0; ch < numValidComp; ch++)
4838      {
4839        xEncodeInterResidualQT( *csSplit, partitioner, ComponentID( ch ) );
4840      }
4841
4842      csSplit->fracBits = m_CABACEstimator->getEstFracBits();
4843      csSplit->cost     = m_pcRdCost->calcRdCost(csSplit->fracBits, csSplit->dist);
4844
4845      if( bCheckFull && anyCbfSet && csSplit->cost < csFull->cost )
4846      {
4847        cs.useSubStructure( *csSplit, partitioner.chType, currArea, false, false, false, true );
4848        cs.cost = csSplit->cost;
4849#if JEM_TOOLS
4850        isSplit = true;
4851#endif
4852      }
4853    }
4854
4855#if JEM_TOOLS || JVET_K1000_SIMPLIFIED_EMT
4856    if( ( !isSplit && m_pcEncCfg->getFastInterEMT() ) || ( !m_pcEncCfg->getFastInterEMT() && !( !bCheckFull || ( anyCbfSet && csSplit->cost < csFull->cost ) ) ) )
4857#else
4858    if( !( !bCheckFull || ( anyCbfSet && csSplit->cost < csFull->cost ) ) )
4859#endif
4860    {
4861      CHECK( !bCheckFull, "Error!" );
4862      cs.useSubStructure( *csFull, partitioner.chType, currArea, false, false, false, true );
4863      cs.cost = csFull->cost;
4864      m_CABACEstimator->getCtx() = ctxBest;
4865    }
4866
4867    if( csSplit && csFull )
4868    {
4869      csSplit->releaseIntermediateData();
4870      csFull ->releaseIntermediateData();
4871    }
4872  }
4873#endif
4874}
4875
4876void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &partitioner, const bool &skipResidual)
4877{
4878  CodingUnit &cu = *cs.getCU( partitioner.chType );
4879
4880  const ChromaFormat format     = cs.area.chromaFormat;;
4881  const int  numValidComponents = getNumberValidComponents(format);
4882  const SPS &sps                = *cs.sps;
4883  const PPS &pps                = *cs.pps;
4884
4885  if( skipResidual ) //  No residual coding : SKIP mode
4886  {
4887    cu.skip    = true;
4888    cu.rootCbf = false;
4889    cs.getResiBuf().fill(0);
4890#if JEM_TOOLS
4891    if( sps.getSpsNext().getUseAClip() )
4892    {
4893       cs.getRecoBuf().copyClip( cs.getPredBuf(), cs.slice->getClpRngs() );
4894    }
4895    else
4896#endif
4897    {
4898      cs.getRecoBuf().copyFrom(cs.getPredBuf() );
4899    }
4900
4901
4902    // add an empty TU
4903    cs.addTU(cs.area, partitioner.chType);
4904
4905    Distortion distortion = 0;
4906
4907    for (int comp = 0; comp < numValidComponents; comp++)
4908    {
4909      const ComponentID compID = ComponentID(comp);
4910
4911      CPelBuf reco = cs.getRecoBuf (compID);
4912      CPelBuf org  = cs.getOrgBuf  (compID);
4913#if WCG_EXT
4914      if( m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() )
4915      {
4916        const CPelBuf orgLuma = cs.getOrgBuf( cs.area.blocks[COMPONENT_Y] );
4917        distortion += m_pcRdCost->getDistPart( org, reco, sps.getBitDepth( toChannelType( compID ) ), compID, DF_SSE_WTD, &orgLuma );
4918      }
4919      else
4920#endif
4921      distortion += m_pcRdCost->getDistPart( org, reco, sps.getBitDepth( toChannelType( compID ) ), compID, DF_SSE );
4922    }
4923
4924    m_CABACEstimator->resetBits();
4925
4926    if( pps.getTransquantBypassEnabledFlag() )
4927    {
4928      m_CABACEstimator->cu_transquant_bypass_flag( cu );
4929    }
4930
4931    PredictionUnit &pu = *cs.getPU( partitioner.chType );
4932
4933    m_CABACEstimator->cu_skip_flag  ( cu );
4934#if JEM_TOOLS
4935    m_CABACEstimator->fruc_mrg_mode ( pu );
4936    m_CABACEstimator->affine_flag   ( cu );
4937#endif
4938#if !JEM_TOOLS && JVET_K_AFFINE
4939    m_CABACEstimator->affine_flag( cu );
4940#endif
4941    m_CABACEstimator->merge_idx     ( pu );
4942#if !HM_LIC_MERGE_SKIP_AS_IN_JEM && JEM_TOOLS
4943    m_CABACEstimator->cu_lic_flag   ( cu );
4944#endif
4945
4946
4947    cs.dist     = distortion;
4948    cs.fracBits = m_CABACEstimator->getEstFracBits();
4949    cs.cost     = m_pcRdCost->calcRdCost(cs.fracBits, cs.dist);
4950
4951    return;
4952  }
4953
4954  //  Residual coding.
4955  cs.getResiBuf().copyFrom (cs.getOrgBuf());
4956  cs.getResiBuf().subtract (cs.getPredBuf());
4957
4958  Distortion zeroDistortion = 0;
4959
4960#if JEM_TOOLS
4961  if( m_pcEncCfg->getUseAClipEnc() )
4962  {
4963    PelUnitBuf resi = cs.getResiBuf();
4964    resi.smoothWithRef( cs.getOrgBuf(), cs.slice->clpRngs() );
4965  }
4966
4967#endif
4968  const TempCtx ctxStart( m_CtxCache, m_CABACEstimator->getCtx() );
4969
4970  cs.getOrgResiBuf().copyFrom(cs.getResiBuf());
4971
4972  xEstimateInterResidualQT(cs, partitioner, &zeroDistortion);
4973
4974  TransformUnit &firstTU = *cs.getTU( partitioner.chType );
4975
4976  cu.rootCbf = false;
4977  m_CABACEstimator->resetBits();
4978  m_CABACEstimator->rqt_root_cbf( cu );
4979  const uint64_t  zeroFracBits = m_CABACEstimator->getEstFracBits();
4980  double zeroCost;
4981  {
4982#if WCG_EXT
4983    if( m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() )
4984    {
4985      zeroCost = cs.isLossless ? ( cs.cost + 1 ) : m_pcRdCost->calcRdCost( zeroFracBits, zeroDistortion, false );
4986    }
4987    else
4988#endif
4989    zeroCost = cs.isLossless ? ( cs.cost + 1 ) : m_pcRdCost->calcRdCost( zeroFracBits, zeroDistortion );
4990  }
4991
4992  const int  numValidTBlocks   = ::getNumberValidTBlocks( *cs.pcv );
4993  for (uint32_t i = 0; i < numValidTBlocks; i++)
4994  {
4995    cu.rootCbf |= TU::getCbf( firstTU, ComponentID( i ) );
4996  }
4997
4998  // -------------------------------------------------------
4999  // If a block full of 0's is efficient, then just use 0's.
5000  // The costs at this point do not include header bits.
5001
5002  if (zeroCost < cs.cost || !cu.rootCbf)
5003  {
5004    cu.rootCbf = false;
5005
5006    cs.clearTUs();
5007
5008    // add a new "empty" TU spanning the whole CU
5009    TransformUnit& tu = cs.addTU(cu, partitioner.chType);
5010
5011    for (int comp = 0; comp < numValidComponents; comp++)
5012    {
5013      tu.rdpcm[comp] = RDPCM_OFF;
5014    }
5015    cu.firstTU = cu.lastTU = &tu;
5016  }
5017
5018
5019  // all decisions now made. Fully encode the CU, including the headers:
5020  m_CABACEstimator->getCtx() = ctxStart;
5021
5022  uint64_t finalFracBits = xGetSymbolFracBitsInter( cs, partitioner );
5023  // we've now encoded the CU, and so have a valid bit cost
5024  if (!cu.rootCbf)
5025  {
5026    cs.getResiBuf().fill(0); // Clear the residual image, if we didn't code it.
5027  }
5028
5029  cs.getRecoBuf().reconstruct(cs.getPredBuf(), cs.getResiBuf(), cs.slice->clpRngs());
5030
5031  // update with clipped distortion and cost (previously unclipped reconstruction values were used)
5032  Distortion finalDistortion = 0;
5033
5034  for (int comp = 0; comp < numValidComponents; comp++)
5035  {
5036    const ComponentID compID = ComponentID(comp);
5037
5038    CPelBuf reco = cs.getRecoBuf (compID);
5039    CPelBuf org  = cs.getOrgBuf  (compID);
5040
5041#if WCG_EXT
5042    if( m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() )
5043    {
5044      const CPelBuf orgLuma = cs.getOrgBuf( cs.area.blocks[COMPONENT_Y] );
5045      finalDistortion += m_pcRdCost->getDistPart( org, reco, sps.getBitDepth( toChannelType( compID ) ), compID, DF_SSE_WTD, &orgLuma );
5046    }
5047    else
5048#endif
5049    {
5050      finalDistortion += m_pcRdCost->getDistPart( org, reco, sps.getBitDepth( toChannelType( compID ) ), compID, DF_SSE );
5051    }
5052  }
5053
5054  cs.dist     = finalDistortion;
5055  cs.fracBits = finalFracBits;
5056  cs.cost     = m_pcRdCost->calcRdCost(cs.fracBits, cs.dist);
5057
5058  CHECK(cs.tus.size() == 0, "No TUs present");
5059}
5060
5061uint64_t InterSearch::xGetSymbolFracBitsInter(CodingStructure &cs, Partitioner &partitioner)
5062{
5063  uint64_t fracBits   = 0;
5064  CodingUnit &cu    = *cs.getCU( partitioner.chType );
5065
5066  m_CABACEstimator->resetBits();
5067
5068  if( cu.partSize == SIZE_2Nx2N && cu.firstPU->mergeFlag && !cu.rootCbf )
5069  {
5070    cu.skip = true;
5071
5072    if( cs.pps->getTransquantBypassEnabledFlag() )
5073    {
5074      m_CABACEstimator->cu_transquant_bypass_flag( cu );
5075    }
5076
5077    m_CABACEstimator->cu_skip_flag  ( cu );
5078#if JEM_TOOLS
5079    m_CABACEstimator->fruc_mrg_mode ( *cu.firstPU );
5080    m_CABACEstimator->affine_flag   ( cu );
5081#endif
5082#if !JEM_TOOLS && JVET_K_AFFINE
5083    m_CABACEstimator->affine_flag   ( cu );
5084#endif
5085    m_CABACEstimator->merge_idx     ( *cu.firstPU );
5086#if JEM_TOOLS
5087    m_CABACEstimator->cu_lic_flag   ( cu );
5088#endif
5089    fracBits   += m_CABACEstimator->getEstFracBits();
5090  }
5091  else
5092  {
5093    CHECK( cu.skip, "Skip flag has to be off at this point!" );
5094
5095    if( cs.pps->getTransquantBypassEnabledFlag() )
5096    {
5097      m_CABACEstimator->cu_transquant_bypass_flag( cu );
5098    }
5099
5100    m_CABACEstimator->cu_skip_flag( cu );
5101    m_CABACEstimator->pred_mode   ( cu );
5102    m_CABACEstimator->cu_pred_data( cu );
5103    CUCtx cuCtx;
5104    cuCtx.isDQPCoded = true;
5105    cuCtx.isChromaQpAdjCoded = true;
5106    m_CABACEstimator->cu_residual ( cu, partitioner, cuCtx );
5107    fracBits       += m_CABACEstimator->getEstFracBits();
5108  }
5109
5110  return fracBits;
5111}
5112
5113