Coverage Report

Created: 2026-08-13 07:23

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/vvenc/source/Lib/EncoderLib/InterSearch.cpp
Line
Count
Source
1
/* -----------------------------------------------------------------------------
2
The copyright in this software is being made available under the Clear BSD
3
License, included below. No patent rights, trademark rights and/or 
4
other Intellectual Property Rights other than the copyrights concerning 
5
the Software are granted under this license.
6
7
The Clear BSD License
8
9
Copyright (c) 2019-2026, Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. & The VVenC Authors.
10
All rights reserved.
11
12
Redistribution and use in source and binary forms, with or without modification,
13
are permitted (subject to the limitations in the disclaimer below) provided that
14
the following conditions are met:
15
16
     * Redistributions of source code must retain the above copyright notice,
17
     this list of conditions and the following disclaimer.
18
19
     * Redistributions in binary form must reproduce the above copyright
20
     notice, this list of conditions and the following disclaimer in the
21
     documentation and/or other materials provided with the distribution.
22
23
     * Neither the name of the copyright holder nor the names of its
24
     contributors may be used to endorse or promote products derived from this
25
     software without specific prior written permission.
26
27
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
28
THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
29
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
31
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
32
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
33
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
34
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
35
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
36
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38
POSSIBILITY OF SUCH DAMAGE.
39
40
41
------------------------------------------------------------------------------------------- */
42
43
44
/** \file     EncSearch.cpp
45
 *  \brief    encoder inter search class
46
 */
47
48
#include "InterSearch.h"
49
#include "EncModeCtrl.h"
50
#include "EncLib.h"
51
#include "CommonLib/CommonDef.h"
52
#include "CommonLib/Rom.h"
53
#include "CommonLib/MotionInfo.h"
54
#include "CommonLib/Picture.h"
55
#include "CommonLib/UnitTools.h"
56
#include "CommonLib/dtrace_next.h"
57
#include "CommonLib/dtrace_buffer.h"
58
#include "CommonLib/TimeProfiler.h"
59
60
#include <math.h>
61
62
 //! \ingroup EncoderLib
63
 //! \{
64
65
namespace vvenc {
66
67
static const Mv s_acMvRefineH[9] =
68
{
69
  Mv(  0,  0 ), // 0
70
  Mv(  0, -1 ), // 1
71
  Mv(  0,  1 ), // 2
72
  Mv( -1,  0 ), // 3
73
  Mv(  1,  0 ), // 4
74
  Mv( -1, -1 ), // 5
75
  Mv(  1, -1 ), // 6
76
  Mv( -1,  1 ), // 7
77
  Mv(  1,  1 )  // 8
78
};
79
80
static const Mv s_acMvRefineQ[9] =
81
{
82
  Mv(  0,  0 ), // 0
83
  Mv(  0, -1 ), // 1
84
  Mv(  0,  1 ), // 2
85
  Mv( -1, -1 ), // 5
86
  Mv(  1, -1 ), // 6
87
  Mv( -1,  0 ), // 3
88
  Mv(  1,  0 ), // 4
89
  Mv( -1,  1 ), // 7
90
  Mv(  1,  1 )  // 8
91
};
92
93
static const bool s_skipQpelPosition[ 42 ][ 9 ] =
94
{
95
  { false, true,  true,  true,  true,  true,  true,  true,  true  },
96
  { true,  true,  true,  true,  true,  false, true,  true,  true  },
97
  { true,  true,  true,  true,  true,  true,  false, true,  true  },
98
  { true,  false, true,  true,  true,  true,  true,  true,  true  },
99
  { true,  false, true,  false, true,  false, true,  true,  true  },
100
  { true,  false, true,  true,  false, true,  false, true,  true  },
101
  { true,  true,  false, true,  true,  true,  true,  true,  true  },
102
  { true,  true,  false, true,  true,  false, true,  false, true  },
103
  { true,  true,  false, true,  true,  true,  false, true,  false },
104
  { true,  true,  false, true,  true,  true,  true,  false, false },
105
  { true,  true,  true,  true,  true,  false, true,  true,  true  },
106
  { true,  true,  false, true,  true,  false, true,  false, true  },
107
  { true,  true,  true,  true,  true,  true,  false, true,  true  },
108
  { true,  true,  false, true,  true,  true,  false, true,  false },
109
  { true,  false, true,  false, false, true,  true,  true,  true  },
110
  { true,  true,  true,  true,  true,  false, true,  true,  true  },
111
  { true,  false, true,  false, true,  false, true,  true,  true  },
112
  { true,  true,  true,  true,  true,  true,  false, true,  true  },
113
  { true,  false, true,  true,  false, true,  false, true,  true  },
114
  { true,  true,  true,  true,  false, true,  false, true,  false },
115
  { true,  false, true,  true,  true,  true,  true,  true,  true  },
116
  { true,  false, true,  true,  false, true,  false, true,  true  },
117
  { true,  true,  false, true,  true,  true,  true,  true,  true  },
118
  { true,  true,  false, true,  true,  true,  false, true,  false },
119
  { true,  true,  true,  false, true,  false, true,  false, true  },
120
  { true,  false, true,  true,  true,  true,  true,  true,  true  },
121
  { true,  false, true,  false, true,  false, true,  true,  true  },
122
  { true,  true,  false, true,  true,  true,  true,  true,  true  },
123
  { true,  true,  false, true,  true,  false, true,  false, true  },
124
  { true,  true,  true,  true,  true,  true,  false, true,  true  },
125
  { true,  true,  false, true,  true,  true,  true,  true,  true  },
126
  { true,  true,  false, true,  true,  true,  false, true,  false },
127
  { true,  true,  true,  true,  true,  false, true,  true,  true  },
128
  { true,  true,  false, true,  true,  true,  true,  true,  true  },
129
  { true,  true,  false, true,  true,  false, true,  false, true  },
130
  { true,  true,  true,  true,  true,  true,  false, true,  true  },
131
  { true,  false, true,  true,  true,  true,  true,  true,  true  },
132
  { true,  false, true,  true,  false, true,  false, true,  true  },
133
  { true,  true,  true,  true,  true,  false, true,  true,  true  },
134
  { true,  false, true,  true,  true,  true,  true,  true,  true  },
135
  { true,  false, true,  false, true,  false, true,  true,  true  },
136
  { false, false, false, false, false, false, false, false, false },
137
};
138
139
//   1,0    3,0    0,1    1,1    2,1    3,1    1,2    3,2    0,3    1,3    2,3    3,3    H1,0   H3,0
140
static const bool s_doInterpQ[ 42 ][ 14 ] =
141
{
142
  { false, false, false, false, false, false, false, false, false, false, false, false, false, false },
143
  { false, false, false, false, false, false, false, false, true,  false, false, false, false, true  },
144
  { false, false, true,  false, false, false, false, false, false, false, false, false, true,  false },
145
  { false, true,  false, false, false, false, false, false, false, false, false, false, false, false },
146
  { false, true,  false, false, false, false, false, false, true,  false, false, true,  false, true  },
147
  { false, true,  true,  false, false, true,  false, false, false, false, false, false, true,  false },
148
  { true,  false, false, false, false, false, false, false, false, false, false, false, false, false },
149
  { true,  false, false, false, false, false, false, false, true,  true,  false, false, false, true  },
150
  { true,  false, true,  true,  false, false, false, false, false, false, false, false, true,  false },
151
  { false, true,  false, false, false, true,  false, false, false, false, false, true,  true,  true  },
152
  { false, false, false, false, false, false, false, false, false, false, true,  false, false, true  },
153
  { false, true,  false, false, false, false, false, false, false, false, true,  true,  false, true  },
154
  { false, false, false, false, true,  false, false, false, false, false, false, false, true,  false },
155
  { false, true,  false, false, true,  true,  false, false, false, false, false, false, true,  false },
156
  { true,  false, false, true,  false, false, false, false, false, true,  false, false, true,  true  },
157
  { false, false, false, false, false, false, false, false, false, false, true,  false, false, true  },
158
  { true,  false, false, false, false, false, false, false, false, true,  true,  false, false, true  },
159
  { false, false, false, false, true,  false, false, false, false, false, false, false, true,  false },
160
  { true,  false, false, true,  true,  false, false, false, false, false, false, false, true,  false },
161
  { false, false, false, false, false, false, false, false, true,  true,  false, true,  false, true  },
162
  { false, false, false, false, false, false, false, true,  false, false, false, false, false, false },
163
  { false, false, false, false, false, false, false, true,  true,  false, false, true,  false, true  },
164
  { false, false, false, false, false, false, true,  false, false, false, false, false, false, false },
165
  { false, false, false, false, false, false, true,  false, true,  true,  false, false, false, true  },
166
  { false, false, true,  true,  false, true,  false, false, false, false, false, false, true,  false },
167
  { false, false, false, false, false, false, false, true,  false, false, false, false, false, false },
168
  { false, false, true,  false, false, true,  false, true,  false, false, false, false, true,  false },
169
  { false, false, false, false, false, false, true,  false, false, false, false, false, false, false },
170
  { false, false, true,  true,  false, false, true,  false, false, false, false, false, true,  false },
171
  { false, false, false, false, false, false, false, false, false, false, true,  false, false, true  },
172
  { false, false, false, false, false, false, false, true,  false, false, false, false, false, false },
173
  { false, false, false, false, false, false, false, true,  false, false, true,  true,  false, true  },
174
  { false, false, false, false, true,  false, false, false, false, false, false, false, true,  false },
175
  { false, false, false, false, false, false, false, true,  false, false, false, false, false, false },
176
  { false, false, false, false, true,  true,  false, true,  false, false, false, false, true,  false },
177
  { false, false, false, false, false, false, false, false, false, false, true,  false, false, true  },
178
  { false, false, false, false, false, false, true,  false, false, false, false, false, false, false },
179
  { false, false, false, false, false, false, true,  false, false, true,  true,  false, false, true  },
180
  { false, false, false, false, true,  false, false, false, false, false, false, false, true,  false },
181
  { false, false, false, false, false, false, true,  false, false, false, false, false, false, false },
182
  { false, false, false, true,  true,  false, true,  false, false, false, false, false, true,  false },
183
  { true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true,  true  },
184
};
185
186
const int BlkUniMvInfoBuffer::m_uniMvListMaxSize;
187
188
InterSearch::InterSearch()
189
19.2k
  : m_modeCtrl                    (nullptr)
190
19.2k
  , m_defaultCachedBvs            (nullptr)
191
19.2k
  , m_pcEncCfg                    (nullptr)
192
19.2k
  , m_pcTrQuant                   (nullptr)
193
19.2k
  , m_iSearchRange                (0)
194
19.2k
  , m_bipredSearchRange           (0)
195
19.2k
  , m_motionEstimationSearchMethod(VVENC_MESEARCH_FULL)
196
19.2k
  , m_motionEstimationSearchMethodSCC( 0 )
197
19.2k
  , m_CABACEstimator              (nullptr)
198
19.2k
  , m_CtxCache                    (nullptr)
199
19.2k
  , m_pTempPel                    (nullptr)
200
19.2k
{
201
57.6k
  for (int i=0; i<MAX_NUM_REF_LIST_ADAPT_SR; i++)
202
38.4k
  {
203
38.4k
    memset (m_aaiAdaptSR[i], 0, MAX_IDX_ADAPT_SR * sizeof (int));
204
38.4k
  }
205
76.8k
  for (int i=0; i<AMVP_MAX_NUM_CANDS+1; i++)
206
57.6k
  {
207
57.6k
    memset (m_auiMVPIdxCost[i], 0, (AMVP_MAX_NUM_CANDS+1) * sizeof (uint32_t) );
208
57.6k
  }
209
19.2k
}
210
211
212
InterSearch::~InterSearch()
213
19.2k
{
214
19.2k
  destroy();
215
19.2k
}
216
217
void InterSearch::init( const VVEncCfg& encCfg, TrQuant* pTrQuant, RdCost* pRdCost, EncModeCtrl* pModeCtrl, CodingStructure **pSaveCS )
218
19.2k
{
219
19.2k
  InterPrediction::init( pRdCost, encCfg.m_internChromaFormat, encCfg.m_CTUSize, encCfg.m_ifpLines );
220
19.2k
  m_numBVs                       = 0;
221
19.2k
  m_pcEncCfg                     = &encCfg;
222
19.2k
  m_pcTrQuant                    = pTrQuant;
223
19.2k
  m_pcRdCost                     = pRdCost;
224
19.2k
  m_modeCtrl                     = pModeCtrl;
225
19.2k
  m_pSaveCS                      = pSaveCS;
226
227
19.2k
  m_iSearchRange                    = encCfg.m_SearchRange;
228
19.2k
  m_bipredSearchRange               = encCfg.m_bipredSearchRange;
229
19.2k
  m_motionEstimationSearchMethod    = vvencMESearchMethod( encCfg.m_motionEstimationSearchMethod );
230
19.2k
  m_motionEstimationSearchMethodSCC = encCfg.m_motionEstimationSearchMethodSCC;
231
232
57.6k
  for( uint32_t iDir = 0; iDir < MAX_NUM_REF_LIST_ADAPT_SR; iDir++ )
233
38.4k
  {
234
268k
    for( uint32_t iRefIdx = 0; iRefIdx < MAX_IDX_ADAPT_SR; iRefIdx++ )
235
230k
    {
236
230k
      m_aaiAdaptSR[iDir][iRefIdx] = m_iSearchRange;
237
230k
    }
238
38.4k
  }
239
240
  // initialize motion cost
241
76.8k
  for( int iNum = 0; iNum < AMVP_MAX_NUM_CANDS + 1; iNum++ )
242
57.6k
  {
243
172k
    for( int iIdx = 0; iIdx < AMVP_MAX_NUM_CANDS; iIdx++ )
244
115k
    {
245
115k
      if( iIdx < iNum )
246
57.6k
      {
247
57.6k
        m_auiMVPIdxCost[iIdx][iNum] = xGetMvpIdxBits( iIdx, iNum );
248
57.6k
      }
249
57.6k
      else
250
57.6k
      {
251
57.6k
        m_auiMVPIdxCost[iIdx][iNum] = MAX_UINT;
252
57.6k
      }
253
115k
    }
254
57.6k
  }
255
256
19.2k
  const ChromaFormat cform   = encCfg.m_internChromaFormat;
257
19.2k
  const int          ctuSize = encCfg.m_CTUSize;
258
57.6k
  for (uint32_t i = 0; i < NUM_REF_PIC_LIST_01; i++)
259
38.4k
  {
260
38.4k
    m_tmpPredStorage[i].create( UnitArea( cform, Area( 0, 0, ctuSize, ctuSize ) ) );
261
38.4k
  }
262
19.2k
  m_tmpStorageLCU.create( UnitArea( cform, Area( 0, 0, ctuSize, ctuSize ) ) );
263
19.2k
  m_pTempPel = new Pel[ctuSize * ctuSize];
264
19.2k
  m_tmpAffiStorage.create(UnitArea(cform, Area(0, 0, ctuSize, ctuSize + 2)));  // allow overread by 2 samples
265
19.2k
  m_tmpAffiError = new Pel[ctuSize * ctuSize];
266
19.2k
  m_tmpAffiDeri[0] = new Pel[ctuSize * ctuSize];
267
19.2k
  m_tmpAffiDeri[1] = new Pel[ctuSize * ctuSize];
268
269
19.2k
  CompArea chromaArea( COMP_Cb, cform, Area( 0, 0, encCfg.m_CTUSize, encCfg.m_CTUSize ), true );
270
96.0k
  for( int i = 0; i < 4; i++ )
271
76.8k
  {
272
76.8k
    m_orgResiCb[i].create( chromaArea );
273
76.8k
    m_orgResiCr[i].create( chromaArea );
274
76.8k
  }
275
19.2k
}
276
277
void InterSearch::destroy()
278
19.2k
{
279
19.2k
  if ( m_pTempPel )
280
19.2k
  {
281
19.2k
    delete [] m_pTempPel;
282
19.2k
    m_pTempPel = nullptr;
283
19.2k
  }
284
285
57.6k
  for( int i = 0; i < NUM_REF_PIC_LIST_01; i++ )
286
38.4k
  {
287
38.4k
    m_tmpPredStorage[i].destroy();
288
38.4k
  }
289
19.2k
  m_tmpStorageLCU.destroy();
290
19.2k
  m_tmpAffiStorage.destroy();
291
19.2k
  if (m_tmpAffiError != NULL)
292
19.2k
  {
293
19.2k
    delete[] m_tmpAffiError;
294
19.2k
    m_tmpAffiError = nullptr;
295
19.2k
  }
296
19.2k
  if (m_tmpAffiDeri[0] != NULL)
297
19.2k
  {
298
19.2k
    delete[] m_tmpAffiDeri[0];
299
19.2k
    m_tmpAffiDeri[0] = nullptr;
300
19.2k
  }
301
19.2k
  if (m_tmpAffiDeri[1] != NULL)
302
19.2k
  {
303
19.2k
    delete[] m_tmpAffiDeri[1];
304
19.2k
    m_tmpAffiDeri[1] = nullptr;
305
19.2k
  }
306
307
19.2k
  m_pSaveCS  = nullptr;
308
19.2k
}
309
310
void InterSearch::setCtuEncRsrc( CABACWriter* cabacEstimator, CtxCache* ctxCache, ReuseUniMv* pReuseUniMv, BlkUniMvInfoBuffer* pBlkUniMvInfoBuffer, AffineProfList* pAffineProfList, IbcBvCand* pCachedBvs )
311
3.84k
{
312
3.84k
  m_CABACEstimator     = cabacEstimator;
313
3.84k
  m_CtxCache           = ctxCache;
314
3.84k
  m_ReuseUniMv         = pReuseUniMv;
315
3.84k
  m_BlkUniMvInfoBuffer = pBlkUniMvInfoBuffer;
316
3.84k
  m_AffineProfList     = pAffineProfList;
317
3.84k
  m_defaultCachedBvs   = pCachedBvs;
318
3.84k
}
319
320
ReuseUniMv::ReuseUniMv()
321
8.54k
{
322
8.54k
  const int numPos     = MAX_CU_SIZE >> MIN_CU_LOG2;
323
8.54k
  const int maxSizeIdx = MAX_CU_SIZE_IDX-2;
324
59.8k
  for( int wIdx = 0; wIdx < maxSizeIdx; wIdx++ )
325
51.2k
  {
326
359k
    for( int hIdx = 0; hIdx < maxSizeIdx; hIdx++ )
327
307k
    {
328
10.1M
      for( int y = 0; y < numPos; y++ )
329
9.84M
      {
330
324M
        for( int x = 0; x < numPos; x++ )
331
315M
        {
332
315M
          m_reusedUniMVs[ wIdx ][ hIdx ][ x ][ y ] = nullptr;
333
315M
        }
334
9.84M
      }
335
307k
    }
336
51.2k
  }
337
8.54k
}
338
339
ReuseUniMv::~ReuseUniMv()
340
8.54k
{
341
8.54k
  resetReusedUniMvs();
342
8.54k
}
343
344
void ReuseUniMv::resetReusedUniMvs()
345
12.8k
{
346
12.8k
  const int numPos     = MAX_CU_SIZE >> MIN_CU_LOG2;
347
12.8k
  const int maxSizeIdx = MAX_CU_SIZE_IDX-2;
348
89.7k
  for ( int wIdx = 0; wIdx < maxSizeIdx; wIdx++ )
349
76.9k
  {
350
538k
    for ( int hIdx = 0; hIdx < maxSizeIdx; hIdx++ )
351
461k
    {
352
15.2M
      for ( int y = 0; y < numPos; y++ )
353
14.7M
      {
354
487M
        for ( int x = 0; x < numPos; x++ )
355
472M
        {
356
472M
          if ( m_reusedUniMVs[ wIdx ][ hIdx ][ x ][ y ] )
357
0
          {
358
0
            delete [] m_reusedUniMVs[ wIdx ][ hIdx ][ x ][ y ];
359
0
            m_reusedUniMVs[ wIdx ][ hIdx ][ x ][ y ] = nullptr;
360
0
          }
361
472M
        }
362
14.7M
      }
363
461k
    }
364
76.9k
  }
365
12.8k
}
366
367
void InterSearch::loadGlobalUniMvs( const Area& lumaArea, const PreCalcValues& pcv)
368
0
{
369
0
  unsigned idx1, idx2, idx3, idx4;
370
0
  getAreaIdxNew(lumaArea, pcv, idx1, idx2, idx3, idx4);
371
0
  if( m_ReuseUniMv->m_reusedUniMVs[idx1][idx2][idx3][idx4])
372
0
  {
373
//    DTRACE( g_trace_ctx, D_TMP, "%d unimv load %d %d %d %d \n", g_trace_ctx->getChannelCounter(D_TMP), idx3,idx4,idx1,idx2 );
374
0
    m_BlkUniMvInfoBuffer->insertUniMvCands(lumaArea, m_ReuseUniMv->m_reusedUniMVs[idx1][idx2][idx3][idx4]);
375
0
  }
376
0
}
377
378
void InterSearch::getBestSbt( CodingStructure* tempCS, CodingUnit* cu, uint8_t& histBestSbt, Distortion& curPuSse, uint8_t sbtAllowed, bool doPreAnalyzeResi, bool mtsAllowed )
379
0
{
380
0
  m_estMinDistSbt[NUMBER_SBT_MODE] = MAX_DISTORTION;
381
0
  m_skipSbtAll = false;
382
383
0
  if( doPreAnalyzeResi )
384
0
  {
385
0
    xCalcMinDistSbt( *tempCS, *cu, sbtAllowed );
386
0
  }
387
388
0
  curPuSse = getEstDistSbt( NUMBER_SBT_MODE );
389
390
0
  if( doPreAnalyzeResi )
391
0
  {
392
0
    if( m_skipSbtAll && !mtsAllowed )
393
0
    {
394
0
      histBestSbt = 0; //try DCT2
395
0
    }
396
0
    else
397
0
    {
398
0
      int  slShift = 4 + std::min( Log2( cu->lwidth() * cu->lheight() ), 9 );
399
0
      assert( curPuSse != MAX_DISTORTION );
400
0
      histBestSbt = m_modeCtrl->findBestSbt( cu->cs->area, (uint32_t)( curPuSse >> slShift ) );
401
0
      if( m_skipSbtAll && CU::isSbtMode( histBestSbt ) ) //special case, skip SBT when loading SBT
402
0
      {
403
0
        histBestSbt = 0; //try DCT2
404
0
      }
405
0
    }
406
0
  }
407
0
}
408
409
410
inline void InterSearch::xTZSearchHelp( TZSearchStruct& rcStruct, const int iSearchX, const int iSearchY, const uint8_t ucPointNr, const uint32_t uiDistance )
411
0
{
412
0
  Distortion  uiSad = 0;
413
414
0
  const Pel* const  piRefSrch = rcStruct.piRefY + iSearchY * rcStruct.iRefStride + iSearchX;
415
416
0
  m_cDistParam.cur.buf = piRefSrch;
417
418
0
  uiSad = m_cDistParam.distFunc( m_cDistParam );
419
420
  // only add motion cost if uiSad is smaller than best. Otherwise pointless
421
  // to add motion cost.
422
0
  if( uiSad < rcStruct.uiBestSad )
423
0
  {
424
    // motion cost
425
0
    uiSad += m_pcRdCost->getCostOfVectorWithPredictor( iSearchX, iSearchY, rcStruct.imvShift );
426
427
0
    if( uiSad < rcStruct.uiBestSad )
428
0
    {
429
0
      rcStruct.uiBestSad      = uiSad;
430
0
      rcStruct.iBestX         = iSearchX;
431
0
      rcStruct.iBestY         = iSearchY;
432
0
      rcStruct.uiBestDistance = uiDistance;
433
0
      rcStruct.uiBestRound    = 0;
434
0
      rcStruct.ucPointNr      = ucPointNr;
435
0
      m_cDistParam.maximumDistortionForEarlyExit = uiSad;
436
0
    }
437
0
  }
438
0
}
439
440
441
442
inline void InterSearch::xTZ2PointSearch( TZSearchStruct& rcStruct )
443
0
{
444
0
  const SearchRange& sr = rcStruct.searchRange;
445
446
0
  static const int xOffset[2][9] = { {  0, -1, -1,  0, -1, +1, -1, -1, +1 }, {  0,  0, +1, +1, -1, +1,  0, +1,  0 } };
447
0
  static const int yOffset[2][9] = { {  0,  0, -1, -1, +1, -1,  0, +1,  0 }, {  0, -1, -1,  0, -1, +1, +1, +1, +1 } };
448
449
  // 2 point search,                   //   1 2 3
450
  // check only the 2 untested points  //   4 0 5
451
  // around the start point            //   6 7 8
452
0
  const int iX1 = rcStruct.iBestX + xOffset[0][rcStruct.ucPointNr];
453
0
  const int iX2 = rcStruct.iBestX + xOffset[1][rcStruct.ucPointNr];
454
455
0
  const int iY1 = rcStruct.iBestY + yOffset[0][rcStruct.ucPointNr];
456
0
  const int iY2 = rcStruct.iBestY + yOffset[1][rcStruct.ucPointNr];
457
458
0
  if( iX1 >= sr.left && iX1 <= sr.right && iY1 >= sr.top && iY1 <= sr.bottom )
459
0
  {
460
0
    xTZSearchHelp( rcStruct, iX1, iY1, 0, 2 );
461
0
  }
462
463
0
  if( iX2 >= sr.left && iX2 <= sr.right && iY2 >= sr.top && iY2 <= sr.bottom )
464
0
  {
465
0
    xTZSearchHelp( rcStruct, iX2, iY2, 0, 2 );
466
0
  }
467
0
}
468
469
inline void InterSearch::xTZ4PointSquareSearch( TZSearchStruct & rcStruct, const int iStartX, const int iStartY, const int iDist )
470
0
{
471
0
  const SearchRange& sr = rcStruct.searchRange;
472
0
  CHECK( iDist == 0 || iDist > 2, "Invalid distance" );
473
  // 4 point search,                   //     1 2 3
474
  // search around the start point     //     4 0 5
475
  // with the required  distance       //     6 7 8
476
0
  const int iTop = iStartY - iDist;
477
0
  const int iBottom = iStartY + iDist;
478
0
  const int iLeft = iStartX - iDist;
479
0
  const int iRight = iStartX + iDist;
480
0
  rcStruct.uiBestRound += 1;
481
482
0
  if ( iTop >= sr.top )
483
0
  {
484
0
    if ( iLeft >= sr.left ) // check top left
485
0
    {
486
0
      xTZSearchHelp( rcStruct, iLeft, iTop, 1, iDist );
487
0
    }
488
0
    if ( iRight <= sr.right ) // check top right
489
0
    {
490
0
      xTZSearchHelp( rcStruct, iRight, iTop, 3, iDist );
491
0
    }
492
0
  }
493
0
  if ( iBottom <= sr.bottom )
494
0
  {
495
0
    if ( iLeft >= sr.left ) // check bottom left
496
0
    {
497
0
      xTZSearchHelp( rcStruct, iLeft, iBottom, 6, iDist );
498
0
    }
499
0
    if ( iRight <= sr.right ) // check bottom right
500
0
    {
501
0
      xTZSearchHelp( rcStruct, iRight, iBottom, 8, iDist );
502
0
    }
503
0
  }
504
0
}
505
506
inline void InterSearch::xTZ8PointSquareSearch( TZSearchStruct& rcStruct, const int iStartX, const int iStartY, const int iDist )
507
0
{
508
0
  const SearchRange& sr = rcStruct.searchRange;
509
0
  // 8 point search,                   //   1 2 3
510
0
  // search around the start point     //   4 0 5
511
0
  // with the required  distance       //   6 7 8
512
0
  CHECK( iDist == 0 , "Invalid distance");
513
0
  const int iTop        = iStartY - iDist;
514
0
  const int iBottom     = iStartY + iDist;
515
0
  const int iLeft       = iStartX - iDist;
516
0
  const int iRight      = iStartX + iDist;
517
0
  rcStruct.uiBestRound += 1;
518
0
519
0
  if ( iTop >= sr.top ) // check top
520
0
  {
521
0
    if ( iLeft >= sr.left ) // check top left
522
0
    {
523
0
      xTZSearchHelp( rcStruct, iLeft, iTop, 1, iDist );
524
0
    }
525
0
    // top middle
526
0
    xTZSearchHelp( rcStruct, iStartX, iTop, 2, iDist );
527
0
528
0
    if ( iRight <= sr.right ) // check top right
529
0
    {
530
0
      xTZSearchHelp( rcStruct, iRight, iTop, 3, iDist );
531
0
    }
532
0
  } // check top
533
0
  if ( iLeft >= sr.left ) // check middle left
534
0
  {
535
0
    xTZSearchHelp( rcStruct, iLeft, iStartY, 4, iDist );
536
0
  }
537
0
  if ( iRight <= sr.right ) // check middle right
538
0
  {
539
0
    xTZSearchHelp( rcStruct, iRight, iStartY, 5, iDist );
540
0
  }
541
0
  if ( iBottom <= sr.bottom ) // check bottom
542
0
  {
543
0
    if ( iLeft >= sr.left ) // check bottom left
544
0
    {
545
0
      xTZSearchHelp( rcStruct, iLeft, iBottom, 6, iDist );
546
0
    }
547
0
    // check bottom middle
548
0
    xTZSearchHelp( rcStruct, iStartX, iBottom, 7, iDist );
549
0
550
0
    if ( iRight <= sr.right ) // check bottom right
551
0
    {
552
0
      xTZSearchHelp( rcStruct, iRight, iBottom, 8, iDist );
553
0
    }
554
0
  } // check bottom
555
0
}
556
557
inline void InterSearch::xTZ8PointDiamondSearch( TZSearchStruct& rcStruct,
558
                                                 const int iStartX,
559
                                                 const int iStartY,
560
                                                 const int iDist,
561
                                                 const bool bCheckCornersAtDist1 )
562
0
{
563
0
  const SearchRange& sr = rcStruct.searchRange;
564
  // 8 point search,                   //   1 2 3
565
  // search around the start point     //   4 0 5
566
  // with the required  distance       //   6 7 8
567
0
  CHECK( iDist == 0, "Invalid distance" );
568
0
  const int iTop        = iStartY - iDist;
569
0
  const int iBottom     = iStartY + iDist;
570
0
  const int iLeft       = iStartX - iDist;
571
0
  const int iRight      = iStartX + iDist;
572
0
  rcStruct.uiBestRound += 1;
573
574
0
  if ( iDist == 1 )
575
0
  {
576
0
    if ( iTop >= sr.top ) // check top
577
0
    {
578
0
      if (bCheckCornersAtDist1)
579
0
      {
580
0
        if ( iLeft >= sr.left) // check top-left
581
0
        {
582
0
          xTZSearchHelp( rcStruct, iLeft, iTop, 1, iDist );
583
0
        }
584
0
        xTZSearchHelp( rcStruct, iStartX, iTop, 2, iDist );
585
0
        if ( iRight <= sr.right ) // check middle right
586
0
        {
587
0
          xTZSearchHelp( rcStruct, iRight, iTop, 3, iDist );
588
0
        }
589
0
      }
590
0
      else
591
0
      {
592
0
        xTZSearchHelp( rcStruct, iStartX, iTop, 2, iDist );
593
0
      }
594
0
    }
595
0
    if ( iLeft >= sr.left ) // check middle left
596
0
    {
597
0
      xTZSearchHelp( rcStruct, iLeft, iStartY, 4, iDist );
598
0
    }
599
0
    if ( iRight <= sr.right ) // check middle right
600
0
    {
601
0
      xTZSearchHelp( rcStruct, iRight, iStartY, 5, iDist );
602
0
    }
603
0
    if ( iBottom <= sr.bottom ) // check bottom
604
0
    {
605
0
      if (bCheckCornersAtDist1)
606
0
      {
607
0
        if ( iLeft >= sr.left) // check top-left
608
0
        {
609
0
          xTZSearchHelp( rcStruct, iLeft, iBottom, 6, iDist );
610
0
        }
611
0
        xTZSearchHelp( rcStruct, iStartX, iBottom, 7, iDist );
612
0
        if ( iRight <= sr.right ) // check middle right
613
0
        {
614
0
          xTZSearchHelp( rcStruct, iRight, iBottom, 8, iDist );
615
0
        }
616
0
      }
617
0
      else
618
0
      {
619
0
        xTZSearchHelp( rcStruct, iStartX, iBottom, 7, iDist );
620
0
      }
621
0
    }
622
0
  }
623
0
  else
624
0
  {
625
0
    if ( iDist <= 8 )
626
0
    {
627
0
      const int iTop_2      = iStartY - (iDist>>1);
628
0
      const int iBottom_2   = iStartY + (iDist>>1);
629
0
      const int iLeft_2     = iStartX - (iDist>>1);
630
0
      const int iRight_2    = iStartX + (iDist>>1);
631
632
0
      if (  iTop >= sr.top && iLeft >= sr.left &&
633
0
           iRight <= sr.right && iBottom <= sr.bottom ) // check border
634
0
      {
635
0
        xTZSearchHelp( rcStruct, iStartX,  iTop,      2, iDist    );
636
0
        xTZSearchHelp( rcStruct, iLeft_2,  iTop_2,    1, iDist>>1 );
637
0
        xTZSearchHelp( rcStruct, iRight_2, iTop_2,    3, iDist>>1 );
638
0
        xTZSearchHelp( rcStruct, iLeft,    iStartY,   4, iDist    );
639
0
        xTZSearchHelp( rcStruct, iRight,   iStartY,   5, iDist    );
640
0
        xTZSearchHelp( rcStruct, iLeft_2,  iBottom_2, 6, iDist>>1 );
641
0
        xTZSearchHelp( rcStruct, iRight_2, iBottom_2, 8, iDist>>1 );
642
0
        xTZSearchHelp( rcStruct, iStartX,  iBottom,   7, iDist    );
643
0
      }
644
0
      else // check border
645
0
      {
646
0
        if ( iTop >= sr.top ) // check top
647
0
        {
648
0
          xTZSearchHelp( rcStruct, iStartX, iTop, 2, iDist );
649
0
        }
650
0
        if ( iTop_2 >= sr.top ) // check half top
651
0
        {
652
0
          if ( iLeft_2 >= sr.left ) // check half left
653
0
          {
654
0
            xTZSearchHelp( rcStruct, iLeft_2, iTop_2, 1, (iDist>>1) );
655
0
          }
656
0
          if ( iRight_2 <= sr.right ) // check half right
657
0
          {
658
0
            xTZSearchHelp( rcStruct, iRight_2, iTop_2, 3, (iDist>>1) );
659
0
          }
660
0
        } // check half top
661
0
        if ( iLeft >= sr.left ) // check left
662
0
        {
663
0
          xTZSearchHelp( rcStruct, iLeft, iStartY, 4, iDist );
664
0
        }
665
0
        if ( iRight <= sr.right ) // check right
666
0
        {
667
0
          xTZSearchHelp( rcStruct, iRight, iStartY, 5, iDist );
668
0
        }
669
0
        if ( iBottom_2 <= sr.bottom ) // check half bottom
670
0
        {
671
0
          if ( iLeft_2 >= sr.left ) // check half left
672
0
          {
673
0
            xTZSearchHelp( rcStruct, iLeft_2, iBottom_2, 6, (iDist>>1) );
674
0
          }
675
0
          if ( iRight_2 <= sr.right ) // check half right
676
0
          {
677
0
            xTZSearchHelp( rcStruct, iRight_2, iBottom_2, 8, (iDist>>1) );
678
0
          }
679
0
        } // check half bottom
680
0
        if ( iBottom <= sr.bottom ) // check bottom
681
0
        {
682
0
          xTZSearchHelp( rcStruct, iStartX, iBottom, 7, iDist );
683
0
        }
684
0
      } // check border
685
0
    }
686
0
    else // iDist > 8
687
0
    {
688
0
      if ( iTop >= sr.top && iLeft >= sr.left &&
689
0
           iRight <= sr.right && iBottom <= sr.bottom ) // check border
690
0
      {
691
0
        xTZSearchHelp( rcStruct, iStartX, iTop,    0, iDist );
692
0
        xTZSearchHelp( rcStruct, iLeft,   iStartY, 0, iDist );
693
0
        xTZSearchHelp( rcStruct, iRight,  iStartY, 0, iDist );
694
0
        xTZSearchHelp( rcStruct, iStartX, iBottom, 0, iDist );
695
0
        for ( int index = 1; index < 4; index++ )
696
0
        {
697
0
          const int iPosYT = iTop    + ((iDist>>2) * index);
698
0
          const int iPosYB = iBottom - ((iDist>>2) * index);
699
0
          const int iPosXL = iStartX - ((iDist>>2) * index);
700
0
          const int iPosXR = iStartX + ((iDist>>2) * index);
701
0
          xTZSearchHelp( rcStruct, iPosXL, iPosYT, 0, iDist );
702
0
          xTZSearchHelp( rcStruct, iPosXR, iPosYT, 0, iDist );
703
0
          xTZSearchHelp( rcStruct, iPosXL, iPosYB, 0, iDist );
704
0
          xTZSearchHelp( rcStruct, iPosXR, iPosYB, 0, iDist );
705
0
        }
706
0
      }
707
0
      else // check border
708
0
      {
709
0
        if ( iTop >= sr.top ) // check top
710
0
        {
711
0
          xTZSearchHelp( rcStruct, iStartX, iTop, 0, iDist );
712
0
        }
713
0
        if ( iLeft >= sr.left ) // check left
714
0
        {
715
0
          xTZSearchHelp( rcStruct, iLeft, iStartY, 0, iDist );
716
0
        }
717
0
        if ( iRight <= sr.right ) // check right
718
0
        {
719
0
          xTZSearchHelp( rcStruct, iRight, iStartY, 0, iDist );
720
0
        }
721
0
        if ( iBottom <= sr.bottom ) // check bottom
722
0
        {
723
0
          xTZSearchHelp( rcStruct, iStartX, iBottom, 0, iDist );
724
0
        }
725
0
        for ( int index = 1; index < 4; index++ )
726
0
        {
727
0
          const int iPosYT = iTop    + ((iDist>>2) * index);
728
0
          const int iPosYB = iBottom - ((iDist>>2) * index);
729
0
          const int iPosXL = iStartX - ((iDist>>2) * index);
730
0
          const int iPosXR = iStartX + ((iDist>>2) * index);
731
732
0
          if ( iPosYT >= sr.top ) // check top
733
0
          {
734
0
            if ( iPosXL >= sr.left ) // check left
735
0
            {
736
0
              xTZSearchHelp( rcStruct, iPosXL, iPosYT, 0, iDist );
737
0
            }
738
0
            if ( iPosXR <= sr.right ) // check right
739
0
            {
740
0
              xTZSearchHelp( rcStruct, iPosXR, iPosYT, 0, iDist );
741
0
            }
742
0
          } // check top
743
0
          if ( iPosYB <= sr.bottom ) // check bottom
744
0
          {
745
0
            if ( iPosXL >= sr.left ) // check left
746
0
            {
747
0
              xTZSearchHelp( rcStruct, iPosXL, iPosYB, 0, iDist );
748
0
            }
749
0
            if ( iPosXR <= sr.right ) // check right
750
0
            {
751
0
              xTZSearchHelp( rcStruct, iPosXR, iPosYB, 0, iDist );
752
0
            }
753
0
          } // check bottom
754
0
        } // for ...
755
0
      } // check border
756
0
    } // iDist <= 8
757
0
  } // iDist == 1
758
0
}
759
760
Distortion InterSearch::xPatternRefinement( const CPelBuf* pcPatternKey,
761
                                            Mv baseRefMv,
762
                                            int iFrac, Mv& rcMvFrac,
763
                                            Distortion& uiDistBest,
764
                                            int& patternId,
765
                                            CPelBuf* pattern,
766
                                            bool useAltHpelIf )
767
0
{
768
0
  Distortion  uiDist;
769
0
  uiDistBest = m_pcEncCfg->m_fastSubPel == 1 ? uiDistBest : MAX_DISTORTION;
770
0
  uint32_t        uiDirecBest = 0;
771
0
  const int reduceTap = m_pcEncCfg->m_meReduceTap;
772
773
0
  Pel*  piRefPos;
774
0
  int iRefStride = pcPatternKey->width + 1;
775
0
  m_pcRdCost->setDistParam( m_cDistParam, *pcPatternKey, m_filteredBlock[0][0][0], iRefStride, m_lumaClpRng.bd, COMP_Y, 0, m_pcEncCfg->m_bUseHADME ? ( m_pcEncCfg->m_fastHad ? 2 : 1 ) : 0 );
776
777
0
  const ClpRng& clpRng = m_lumaClpRng;
778
0
  int width = pattern->width;
779
0
  int height = pattern->height;
780
0
  int srcStride = pattern->stride;
781
782
0
  int intStride = width + 1;
783
0
  int dstStride = width + 1;
784
0
  Pel* intPtr;
785
0
  Pel* dstPtr;
786
0
  int filterSize     = useAltHpelIf ? ( reduceTap >= 1 ? NTAPS_AFFINE : NTAPS_LUMA )
787
0
                                    : ( reduceTap == 1 ? NTAPS_AFFINE
788
0
                                                       : ( reduceTap == 0 ? NTAPS_LUMA : NTAPS_CHROMA ) );
789
0
  int halfFilterSize = ( filterSize >> 1 );
790
0
  const Pel* srcPtr  = pattern->buf - halfFilterSize*srcStride - 1;
791
792
0
  const ChromaFormat chFmt = m_currChromaFormat;
793
794
0
  Distortion distH[ 9 ] = { uiDistBest, uiDistBest, uiDistBest, uiDistBest, uiDistBest, uiDistBest, uiDistBest, uiDistBest, uiDistBest };
795
0
  const int TH = 17, TL = 15, shift = 4;
796
797
0
  const Mv* pcMvRefine = (iFrac == 2 ? s_acMvRefineH : s_acMvRefineQ);
798
0
  for (uint32_t i = 0; i < 9; i++)
799
0
  {
800
0
    if( m_pcEncCfg->m_fastSubPel == 1 )
801
0
    {
802
0
      if( s_skipQpelPosition[ patternId ][ i ] )
803
0
      {
804
0
        continue;
805
0
      }
806
807
0
      if( 2 == iFrac )
808
0
      {
809
0
        if ( ( 5 == i && 0 == uiDirecBest ) || ( 7 == i && 1 == uiDirecBest ) || ( 8 == i && ( 1 == uiDirecBest || 3 == uiDirecBest || 5 == uiDirecBest ) ) )
810
0
        {
811
0
          break;
812
0
        }
813
814
0
        if( 0 == i )
815
0
        {
816
          // split the prediction with funny widths into power-of-2 and +1 parts for the sake of SIMD speed-up
817
0
          m_if.filterHor( COMP_Y, srcPtr, srcStride, m_filteredBlockTmp[ 0 ][ 0 ], intStride, width, height + filterSize, 0 << MV_FRACTIONAL_BITS_DIFF, false, chFmt, clpRng, useAltHpelIf, 0, reduceTap );
818
0
          m_if.filterHor( COMP_Y, srcPtr + width, srcStride, m_filteredBlockTmp[ 0 ][ 0 ] + width, intStride, 1, height + filterSize, 0 << MV_FRACTIONAL_BITS_DIFF, false, chFmt, clpRng, useAltHpelIf, 0, reduceTap );
819
820
          // split the prediction with funny widths into power-of-2 and +1 parts for the sake of SIMD speed-up
821
0
          m_if.filterHor( COMP_Y, srcPtr, srcStride, m_filteredBlockTmp[ 2 ][ 0 ], intStride, width, height + filterSize, 2 << MV_FRACTIONAL_BITS_DIFF, false, chFmt, clpRng, useAltHpelIf, 0, reduceTap );
822
0
          m_if.filterHor( COMP_Y, srcPtr + width, srcStride, m_filteredBlockTmp[ 2 ][ 0 ] + width, intStride, 1, height + filterSize, 2 << MV_FRACTIONAL_BITS_DIFF, false, chFmt, clpRng, useAltHpelIf, 0, reduceTap );
823
824
0
          intPtr = m_filteredBlockTmp[ 0 ][ 0 ] + halfFilterSize * intStride + 1;
825
0
          dstPtr = m_filteredBlock[ 0 ][ 0 ][ 0 ];
826
0
          m_if.filterVer( COMP_Y, intPtr, intStride, dstPtr, dstStride, width + 0, height + 0, 0 << MV_FRACTIONAL_BITS_DIFF, false, true, chFmt, clpRng, useAltHpelIf, 0, reduceTap );
827
0
        }
828
0
        else if( 1 == i )
829
0
        {
830
0
          intPtr = m_filteredBlockTmp[ 0 ][ 0 ] + ( halfFilterSize - 1 ) * intStride + 1;
831
0
          dstPtr = m_filteredBlock[ 2 ][ 0 ][ 0 ];
832
0
          m_if.filterVer( COMP_Y, intPtr, intStride, dstPtr, dstStride, width + 0, height + 1, 2 << MV_FRACTIONAL_BITS_DIFF, false, true, chFmt, clpRng, useAltHpelIf, 0, reduceTap );
833
0
        }
834
0
        else if( 3 == i )
835
0
        {
836
0
          intPtr = m_filteredBlockTmp[ 2 ][ 0 ] + halfFilterSize * intStride;
837
0
          dstPtr = m_filteredBlock[ 0 ][ 2 ][ 0 ];
838
          // split the prediction with funny widths into power-of-2 and +1 parts for the sake of SIMD speed-up
839
0
          m_if.filterVer( COMP_Y, intPtr, intStride, dstPtr, dstStride, width, height + 0, 0 << MV_FRACTIONAL_BITS_DIFF, false, true, chFmt, clpRng, useAltHpelIf, 0, reduceTap );
840
0
          m_if.filterVer( COMP_Y, intPtr + width, intStride, dstPtr + width, dstStride, 1, height + 0, 0 << MV_FRACTIONAL_BITS_DIFF, false, true, chFmt, clpRng, useAltHpelIf, 0, reduceTap );
841
0
        }
842
0
        else if( 5 == i )
843
0
        {
844
0
          intPtr = m_filteredBlockTmp[ 2 ][ 0 ] + ( halfFilterSize - 1 ) * intStride;
845
0
          dstPtr = m_filteredBlock[ 2 ][ 2 ][ 0 ];
846
          // split the prediction with funny widths into power-of-2 and +1 parts for the sake of SIMD speed-up
847
0
          m_if.filterVer( COMP_Y, intPtr, intStride, dstPtr, dstStride, width, height + 1, 2 << MV_FRACTIONAL_BITS_DIFF, false, true, chFmt, clpRng, useAltHpelIf, 0, reduceTap );
848
0
          m_if.filterVer( COMP_Y, intPtr + width, intStride, dstPtr + width, dstStride, 1, height + 1, 2 << MV_FRACTIONAL_BITS_DIFF, false, true, chFmt, clpRng, useAltHpelIf, 0, reduceTap );
849
0
        }
850
0
      }
851
0
    }
852
0
    Mv cMvTest = pcMvRefine[ i ];
853
0
    cMvTest += baseRefMv;
854
855
0
    int horVal = cMvTest.hor * iFrac;
856
0
    int verVal = cMvTest.ver * iFrac;
857
0
    piRefPos = m_filteredBlock[verVal & 3][horVal & 3][0];
858
859
0
    if ( horVal == 2 && ( verVal & 1 ) == 0 )
860
0
    {
861
0
      piRefPos += 1;
862
0
    }
863
0
    if ( ( horVal & 1 ) == 0 && verVal == 2 )
864
0
    {
865
0
      piRefPos += iRefStride;
866
0
    }
867
0
    cMvTest = pcMvRefine[i];
868
0
    cMvTest += rcMvFrac;
869
870
871
0
    m_cDistParam.cur.buf   = piRefPos;
872
0
    uiDist = m_cDistParam.distFunc( m_cDistParam );
873
0
    uiDist += m_pcRdCost->getCostOfVectorWithPredictor( cMvTest.hor, cMvTest.ver, 0 );
874
875
0
    distH[ i ] = uiDist;
876
0
    if ( uiDist < uiDistBest )
877
0
    {
878
0
      uiDistBest  = uiDist;
879
0
      uiDirecBest = i;
880
0
      m_cDistParam.maximumDistortionForEarlyExit = uiDist;
881
0
    }
882
0
  }
883
884
0
  rcMvFrac = pcMvRefine[uiDirecBest];
885
886
0
  if( m_pcEncCfg->m_fastSubPel == 1 && iFrac == 2 )
887
0
  {
888
0
    switch ( uiDirecBest )
889
0
    {
890
0
    case 0:
891
      // hor
892
0
      distH[ 3 ] <<= shift;
893
0
      patternId += ( distH[ 3 ] > TH * distH[ 4 ] ? 2 : ( distH[ 3 ] < TL * distH[ 4 ] ? 1 : 0 ) );
894
      // ver
895
0
      distH[ 1 ] <<= shift;
896
0
      patternId += ( distH[ 1 ] > TH * distH[ 2 ] ? 6 : ( distH[ 1 ] < TL * distH[ 2 ] ? 3 : 0 ) );
897
0
      break;
898
0
    case 1:
899
      // hor
900
0
      distH[ 5 ] <<= shift;
901
0
      patternId += ( distH[ 5 ] > TH * distH[ 6 ] ? 4 : ( distH[ 5 ] < TL * distH[ 6 ] ? 2 : 0 ) );
902
      // ver
903
0
      patternId += ( distH[ 2 ] - distH[ 0 ] > distH[ 0 ] - distH[ 1 ] ? 1 : 0 );
904
905
0
      patternId += ( 41 == patternId ? 0 : 8 );
906
0
      break;
907
0
    case 2:
908
      // hor
909
0
      distH[ 7 ] <<= shift;
910
0
      patternId += ( distH[ 7 ] > TH * distH[ 8 ] ? 4 : ( distH[ 7 ] < TL * distH[ 8 ] ? 2 : 0 ) );
911
      // ver
912
0
      patternId += ( distH[ 1 ] - distH[ 0 ] > distH[ 0 ] - distH[ 2 ] ? 1 : 0 );
913
914
0
      patternId += ( 41 == patternId ? 0 : 13 );
915
0
      break;
916
0
    case 3:
917
      // hor
918
0
      patternId += ( distH[ 4 ] - distH[ 0 ] > distH[ 0 ] - distH[ 3 ] ? 1 : 0 );
919
      // ver
920
0
      distH[ 5 ] <<= shift;
921
0
      patternId += ( distH[ 5 ] > TH * distH[ 7 ] ? 4 : ( distH[ 5 ] < TL * distH[ 7 ] ? 2 : 0 ) );
922
923
0
      patternId += ( 41 == patternId ? 0 : 18 );
924
0
      break;
925
0
    case 4:
926
      // hor
927
0
      patternId += ( distH[ 3 ] - distH[ 0 ] > distH[ 0 ] - distH[ 4 ] ? 1 : 0 );
928
      // ver
929
0
      distH[ 6 ] <<= shift;
930
0
      patternId += ( distH[ 6 ] > TH * distH[ 8 ] ? 4 : ( distH[ 6 ] < TL * distH[ 8 ] ? 2 : 0 ) );
931
932
0
      patternId += ( 41 == patternId ? 0 : 23 );
933
0
      break;
934
0
    case 5:
935
      // hor
936
0
      patternId += ( distH[ 6 ] - distH[ 1 ] > distH[ 1 ] - distH[ 5 ] ? 1 : 0 );
937
      // ver
938
0
      patternId += ( distH[ 7 ] - distH[ 3 ] > distH[ 3 ] - distH[ 5 ] ? 2 : 0 );
939
940
0
      patternId += ( 41 == patternId ? 0 : 28 );
941
0
      break;
942
0
    case 6:
943
      // hor
944
0
      patternId += ( distH[ 5 ] - distH[ 1 ] > distH[ 1 ] - distH[ 6 ] ? 1 : 0 );
945
      // ver
946
0
      patternId += ( distH[ 8 ] - distH[ 4 ] > distH[ 4 ] - distH[ 6 ] ? 2 : 0 );
947
948
0
      patternId += ( 41 == patternId ? 0 : 31 );
949
0
      break;
950
0
    case 7:
951
      // hor
952
0
      patternId += ( distH[ 8 ] - distH[ 2 ] > distH[ 2 ] - distH[ 7 ] ? 1 : 0 );
953
      // ver
954
0
      patternId += ( distH[ 5 ] - distH[ 3 ] > distH[ 3 ] - distH[ 7 ] ? 2 : 0 );
955
956
0
      patternId += ( 41 == patternId ? 0 : 34 );
957
0
      break;
958
0
    case 8:
959
      // hor
960
0
      patternId += ( distH[ 7 ] - distH[ 2 ] > distH[ 2 ] - distH[ 8 ] ? 1 : 0 );
961
      // ver
962
0
      patternId += ( distH[ 6 ] - distH[ 4 ] > distH[ 4 ] - distH[ 8 ] ? 2 : 0 );
963
964
0
      patternId += ( 41 == patternId ? 0 : 37 );
965
0
      break;
966
0
    default:
967
0
      break;
968
0
    }
969
0
  }
970
971
0
  return uiDistBest;
972
0
}
973
974
//! search of the best candidate for inter prediction
975
bool InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner, double& bestCostInter)
976
0
{
977
0
  PROFILER_SCOPE_AND_STAGE_EXT( 1, _TPROF, P_INTER_MVD_SEARCH, cu.cs, partitioner.chType );
978
0
  CodingStructure& cs = *cu.cs;
979
980
0
  AMVPInfo     amvp[2];
981
0
  Mv           cMvSrchRngLT;
982
0
  Mv           cMvSrchRngRB;
983
0
  Mv           cMvZero;
984
0
  Mv           cMv[2];
985
0
  Mv           cMvBi[2];
986
0
  Mv           cMvTemp[2][MAX_REF_PICS];
987
0
  Mv           cMvHevcTemp[2][MAX_REF_PICS];
988
0
  int          iNumPredDir = cs.slice->isInterP() ? 1 : 2;
989
990
0
  Mv           cMvPred[2][MAX_REF_PICS];
991
992
0
  Mv           cMvPredBi[2][MAX_REF_PICS];
993
0
  int          aaiMvpIdxBi[2][MAX_REF_PICS];
994
995
0
  int          aaiMvpIdx[2][MAX_REF_PICS];
996
0
  int          aaiMvpNum[2][MAX_REF_PICS];
997
998
0
  AMVPInfo     aacAMVPInfo[2][MAX_REF_PICS];
999
1000
0
  int          iRefIdx[2]={0,0}; //If un-initialized, may cause SEGV in bi-directional prediction iterative stage.
1001
0
  int          iRefIdxBi[2] = { -1, -1 };
1002
1003
0
  uint32_t     uiMbBits[3] = {1, 1, 0};
1004
1005
0
  uint32_t     uiLastMode = 0;
1006
0
  int          iRefStart, iRefEnd;
1007
1008
0
  int          symMode = 0;
1009
1010
0
  int          bestBiPRefIdxL1 = 0;
1011
0
  int          bestBiPMvpL1    = 0;
1012
0
  Distortion   biPDistTemp     = MAX_DISTORTION;
1013
1014
0
  uint8_t      BcwIdx          = (cu.cs->slice->isInterB() ? cu.BcwIdx : BCW_DEFAULT);
1015
0
  bool         enforceBcwPred = false;
1016
1017
  // Loop over Prediction Units
1018
0
  uint32_t     puIdx = 0;
1019
0
  uint32_t     uiLastModeTemp = 0;
1020
0
  Distortion   uiAffineCost = MAX_DISTORTION;
1021
0
  Distortion   uiHevcCost = MAX_DISTORTION;
1022
0
  bool checkAffine = (cu.imv == IMV_OFF);
1023
0
  if (cu.cs->bestParent != nullptr && cu.cs->bestParent->getCU(CH_L,TREE_D) != nullptr && cu.cs->bestParent->getCU(CH_L,TREE_D)->affine == false)
1024
0
  {
1025
0
    m_skipPROF = true;
1026
0
  }
1027
1028
0
  m_encOnly = true;
1029
0
  {
1030
0
    CU::spanMotionInfo( cu );
1031
0
    Distortion   uiCost[2] = { MAX_DISTORTION, MAX_DISTORTION };
1032
0
    Distortion   uiCostBi  =   MAX_DISTORTION;
1033
0
    Distortion   uiCostTemp;
1034
1035
0
    uint32_t         uiBits[3];
1036
0
    uint32_t         uiBitsTemp;
1037
0
    Distortion   bestBiPDist = MAX_DISTORTION;
1038
1039
0
    Distortion   uiCostTempL0[MAX_NUM_REF];
1040
0
    for (int iNumRef=0; iNumRef < MAX_NUM_REF; iNumRef++)
1041
0
    {
1042
0
      uiCostTempL0[iNumRef] = MAX_DISTORTION;
1043
0
    }
1044
0
    uint32_t         uiBitsTempL0[MAX_NUM_REF];
1045
1046
0
    Mv           mvValidList1;
1047
0
    int          refIdxValidList1 = 0;
1048
0
    uint32_t         bitsValidList1   = MAX_UINT;
1049
0
    Distortion   costValidList1   = MAX_DISTORTION;
1050
1051
0
    CPelUnitBuf origBuf = cu.cs->getOrgBuf( cu );
1052
1053
0
    xGetBlkBits( cs.slice->isInterP(), puIdx, uiLastMode, uiMbBits );
1054
1055
0
    m_pcRdCost->selectMotionLambda();
1056
1057
0
    unsigned imvShift = cu.imv == IMV_HPEL ? 1 : (cu.imv << 1);
1058
1059
    //  Uni-directional prediction
1060
0
    for ( int iRefList = 0; iRefList < iNumPredDir; iRefList++ )
1061
0
    {
1062
0
      RefPicList  refPicList = ( iRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
1063
0
      for (int iRefIdxTemp = 0; iRefIdxTemp < cs.slice->numRefIdx[ refPicList ]; iRefIdxTemp++)
1064
0
      {
1065
0
        uiBitsTemp = uiMbBits[iRefList];
1066
0
        if ( cs.slice->numRefIdx[ refPicList ] > 1 )
1067
0
        {
1068
0
          uiBitsTemp += iRefIdxTemp+1;
1069
0
          if ( iRefIdxTemp == cs.slice->numRefIdx[ refPicList ]-1 )
1070
0
          {
1071
0
            uiBitsTemp--;
1072
0
          }
1073
0
        }
1074
0
        xEstimateMvPredAMVP( cu, origBuf, refPicList, iRefIdxTemp, cMvPred[iRefList][iRefIdxTemp], amvp[refPicList], biPDistTemp);
1075
1076
0
        aaiMvpIdx[iRefList][iRefIdxTemp] = cu.mvpIdx[refPicList];
1077
0
        aaiMvpNum[iRefList][iRefIdxTemp] = cu.mvpNum[refPicList];
1078
1079
0
        if(cs.picHeader->mvdL1Zero && iRefList==1 && biPDistTemp < bestBiPDist)
1080
0
        {
1081
0
          bestBiPDist = biPDistTemp;
1082
0
          bestBiPMvpL1 = aaiMvpIdx[iRefList][iRefIdxTemp];
1083
0
          bestBiPRefIdxL1 = iRefIdxTemp;
1084
0
        }
1085
1086
0
        uiBitsTemp += m_auiMVPIdxCost[aaiMvpIdx[iRefList][iRefIdxTemp]][AMVP_MAX_NUM_CANDS];
1087
1088
0
        if ( m_pcEncCfg->m_bFastMEForGenBLowDelayEnabled && iRefList == 1 )    // list 1
1089
0
        {
1090
0
          if ( cs.slice->list1IdxToList0Idx[ iRefIdxTemp ] >= 0 )
1091
0
          {
1092
0
            cMvTemp[1][iRefIdxTemp] = cMvTemp[0][cs.slice->list1IdxToList0Idx[iRefIdxTemp ]];
1093
0
            uiCostTemp = uiCostTempL0[cs.slice->list1IdxToList0Idx[ iRefIdxTemp ]];
1094
            /*first subtract the bit-rate part of the cost of the other list*/
1095
0
            uiCostTemp -= m_pcRdCost->getCost( uiBitsTempL0[cs.slice->list1IdxToList0Idx[ iRefIdxTemp ]] );
1096
            /*correct the bit-rate part of the current ref*/
1097
0
            m_pcRdCost->setPredictor  ( cMvPred[iRefList][iRefIdxTemp] );
1098
0
            uiBitsTemp += m_pcRdCost->getBitsOfVectorWithPredictor( cMvTemp[1][iRefIdxTemp].hor, cMvTemp[1][iRefIdxTemp].ver, imvShift + MV_FRACTIONAL_BITS_DIFF );
1099
            /*calculate the correct cost*/
1100
0
            uiCostTemp += m_pcRdCost->getCost( uiBitsTemp );
1101
0
          }
1102
0
          else
1103
0
          {
1104
0
            xMotionEstimation( cu, origBuf, refPicList, cMvPred[iRefList][iRefIdxTemp], iRefIdxTemp, cMvTemp[iRefList][iRefIdxTemp], aaiMvpIdx[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp, amvp[refPicList] );
1105
0
          }
1106
0
        }
1107
0
        else
1108
0
        {
1109
0
          xMotionEstimation( cu, origBuf, refPicList, cMvPred[iRefList][iRefIdxTemp], iRefIdxTemp, cMvTemp[iRefList][iRefIdxTemp], aaiMvpIdx[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp, amvp[refPicList] );
1110
0
        }
1111
          
1112
0
        if( cs.slice->sps->BCW && cu.BcwIdx == BCW_DEFAULT && cs.slice->isInterB() )
1113
0
        {
1114
0
          m_uniMotions.setReadMode( true, (uint32_t)iRefList, (uint32_t)iRefIdxTemp) ;
1115
0
          m_uniMotions.copyFrom( cMvTemp[iRefList][iRefIdxTemp], uiCostTemp - m_pcRdCost->getCost(uiBitsTemp), (uint32_t)iRefList, (uint32_t)iRefIdxTemp );
1116
0
        }
1117
1118
0
        xCopyAMVPInfo( &amvp[refPicList], &aacAMVPInfo[iRefList][iRefIdxTemp]); // must always be done ( also when AMVP_MODE = AM_NONE )
1119
0
        xCheckBestMVP( refPicList, cMvTemp[iRefList][iRefIdxTemp], cMvPred[iRefList][iRefIdxTemp], aaiMvpIdx[iRefList][iRefIdxTemp], amvp[refPicList], uiBitsTemp, uiCostTemp, cu.imv );
1120
1121
0
        if ( iRefList == 0 )
1122
0
        {
1123
0
          uiCostTempL0[iRefIdxTemp] = uiCostTemp;
1124
0
          uiBitsTempL0[iRefIdxTemp] = uiBitsTemp;
1125
0
        }
1126
0
        if ( uiCostTemp < uiCost[iRefList] )
1127
0
        {
1128
0
          uiCost[iRefList] = uiCostTemp;
1129
0
          uiBits[iRefList] = uiBitsTemp; // storing for bi-prediction
1130
1131
          // set motion
1132
0
          cMv    [iRefList] = cMvTemp[iRefList][iRefIdxTemp];
1133
0
          iRefIdx[iRefList] = iRefIdxTemp;
1134
0
        }
1135
1136
0
        if ( iRefList == 1 && uiCostTemp < costValidList1 && cs.slice->list1IdxToList0Idx[ iRefIdxTemp ] < 0 )
1137
0
        {
1138
0
          costValidList1 = uiCostTemp;
1139
0
          bitsValidList1 = uiBitsTemp;
1140
1141
          // set motion
1142
0
          mvValidList1     = cMvTemp[iRefList][iRefIdxTemp];
1143
0
          refIdxValidList1 = iRefIdxTemp;
1144
0
        }
1145
0
      }
1146
0
    }
1147
1148
0
    ::memcpy(cMvHevcTemp, cMvTemp, sizeof(cMvTemp));
1149
0
    if (cu.imv == IMV_OFF && (!cu.slice->sps->BCW || BcwIdx == BCW_DEFAULT))
1150
0
    {
1151
0
      m_BlkUniMvInfoBuffer->insertUniMvCands(cu.Y(), &cMvTemp[0][0]);
1152
1153
0
      unsigned idx1, idx2, idx3, idx4;
1154
0
      getAreaIdxNew(cu.Y(), *cs.pcv, idx1, idx2, idx3, idx4);
1155
0
      if( ! m_ReuseUniMv->m_reusedUniMVs[idx1][idx2][idx3][idx4] )
1156
0
      {
1157
0
        m_ReuseUniMv->m_reusedUniMVs[idx1][idx2][idx3][idx4] = new Mv[ 2 * MAX_REF_PICS ];
1158
//          DTRACE( g_trace_ctx, D_TMP, "%d unimv first reuse %d %d %d %d \n", g_trace_ctx->getChannelCounter(D_TMP), idx3,idx4,idx1,idx2 );
1159
0
      }
1160
0
      ::memcpy(m_ReuseUniMv->m_reusedUniMVs[idx1][idx2][idx3][idx4], cMvTemp, 2 * MAX_REF_PICS * sizeof(Mv));
1161
0
    }
1162
0
    if (bestCostInter != MAX_DOUBLE)
1163
0
    {
1164
0
      int L = (cu.slice->TLayer <= 2) ? 0 : (cu.slice->TLayer - 2);
1165
0
      double besCostMerge = bestCostInter;
1166
0
      bestCostInter = (uiCost[0] < uiCost[1]) ? uiCost[0] : uiCost[1];
1167
0
      if ((cu.slice->TLayer > (m_pcEncCfg->m_maxTLayer - (m_pcEncCfg->m_FastInferMerge & 7))) && bestCostInter > MRG_FAST_RATIOMYV[L] * besCostMerge)
1168
0
      {
1169
0
        m_skipPROF = false;
1170
0
        m_encOnly = false;
1171
0
        return true;
1172
0
      }
1173
0
    }
1174
    //  Bi-predictive Motion estimation
1175
0
    if( cs.slice->isInterB() && !CU::isBipredRestriction( cu ) && (cu.slice->checkLDC || BcwIdx == BCW_DEFAULT  || !m_affineModeSelected || m_pcEncCfg->m_BCW != 2 ) )
1176
0
    {
1177
0
      PROFILER_SCOPE_AND_STAGE_EXT( 1, _TPROF, P_INTER_MVD_SEARCH_B, &cs, partitioner.chType );
1178
0
      bool doBiPred = true;
1179
0
      cMvBi[0] = cMv[0];
1180
0
      cMvBi[1] = cMv[1];
1181
0
      iRefIdxBi[0] = iRefIdx[0];
1182
0
      iRefIdxBi[1] = iRefIdx[1];
1183
1184
0
      ::memcpy( cMvPredBi,   cMvPred,   sizeof( cMvPred   ) );
1185
0
      ::memcpy( aaiMvpIdxBi, aaiMvpIdx, sizeof( aaiMvpIdx ) );
1186
1187
0
      uint32_t uiMotBits[2];
1188
1189
0
      if(cs.picHeader->mvdL1Zero)
1190
0
      {
1191
        // case: no mvd for L1
1192
        // note: mv = mvp + mvd
1193
        // mv for L1 is equal to mvp(L1) and the mvd search is only performed for L0
1194
0
        xCopyAMVPInfo(&aacAMVPInfo[1][bestBiPRefIdxL1], &amvp[REF_PIC_LIST_1]);
1195
0
        aaiMvpIdxBi[1][bestBiPRefIdxL1] = bestBiPMvpL1;
1196
0
        cMvPredBi  [1][bestBiPRefIdxL1] = amvp[REF_PIC_LIST_1].mvCand[bestBiPMvpL1];
1197
0
        if( m_pcEncCfg->m_ifpLines && !CU::isMvInRangeFPP( cu.ly(), cu.lheight(), cMvPredBi[1][bestBiPRefIdxL1].ver, m_pcEncCfg->m_ifpLines, *cu.cs->pcv ) )
1198
0
        {
1199
          // this mvp cannot be used for mv, skip Bi-pred
1200
0
          uiCostBi = std::numeric_limits<Distortion>::max();
1201
0
          doBiPred = false;
1202
0
        }
1203
1204
0
        if( doBiPred )
1205
0
        {
1206
0
          cMvBi[1] = cMvPredBi[1][bestBiPRefIdxL1];
1207
0
          iRefIdxBi[1] = bestBiPRefIdxL1;
1208
0
          cu.mv[REF_PIC_LIST_1][0] = cMvBi[1];
1209
0
          cu.refIdx[REF_PIC_LIST_1] = iRefIdxBi[1];
1210
0
          cu.mvpIdx[REF_PIC_LIST_1] = bestBiPMvpL1;
1211
0
          PelUnitBuf predBufTmp = m_tmpPredStorage[REF_PIC_LIST_1].getCompactBuf( cu );
1212
0
          motionCompensation( cu, predBufTmp, REF_PIC_LIST_1 );
1213
1214
0
          uiMotBits[0] = uiBits[0] - uiMbBits[0];
1215
0
          uiMotBits[1] = uiMbBits[1];
1216
1217
0
          if(cs.slice->numRefIdx[REF_PIC_LIST_1] > 1)
1218
0
          {
1219
0
            uiMotBits[1] += bestBiPRefIdxL1 + 1;
1220
0
            if(bestBiPRefIdxL1 == cs.slice->numRefIdx[REF_PIC_LIST_1] - 1)
1221
0
            {
1222
0
              uiMotBits[1]--;
1223
0
            }
1224
0
          }
1225
1226
0
          uiMotBits[1] += m_auiMVPIdxCost[aaiMvpIdxBi[1][bestBiPRefIdxL1]][AMVP_MAX_NUM_CANDS];
1227
1228
0
          uiBits[2] = uiMbBits[2] + uiMotBits[0] + uiMotBits[1];
1229
1230
0
          cMvTemp[1][bestBiPRefIdxL1] = cMvBi[1];
1231
0
        }
1232
0
      }
1233
0
      else
1234
0
      {
1235
0
        uiMotBits[0] = uiBits[0] - uiMbBits[0];
1236
0
        uiMotBits[1] = uiBits[1] - uiMbBits[1];
1237
0
        uiBits[2] = uiMbBits[2] + uiMotBits[0] + uiMotBits[1];
1238
0
      }
1239
1240
0
      if( doBiPred )
1241
0
      {
1242
        // 4-times iteration (default)
1243
0
        int iNumIter = 4;
1244
1245
        // fast encoder setting: only one iteration
1246
0
        if ( m_pcEncCfg->m_fastInterSearchMode==VVENC_FASTINTERSEARCH_MODE3 || m_pcEncCfg->m_fastInterSearchMode==VVENC_FASTINTERSEARCH_MODE2 || cs.picHeader->mvdL1Zero )
1247
0
        {
1248
0
          iNumIter = 1;
1249
0
        }
1250
1251
0
        enforceBcwPred = (BcwIdx != BCW_DEFAULT);
1252
1253
0
        for ( int iIter = 0; iIter < iNumIter; iIter++ )
1254
0
        {
1255
0
          int         iRefList    = iIter % 2;
1256
1257
0
          if ( m_pcEncCfg->m_fastInterSearchMode==VVENC_FASTINTERSEARCH_MODE3 || m_pcEncCfg->m_fastInterSearchMode==VVENC_FASTINTERSEARCH_MODE2 )
1258
0
          {
1259
0
            if( uiCost[0] <= uiCost[1] )
1260
0
            {
1261
0
              iRefList = 1;
1262
0
            }
1263
0
            else
1264
0
            {
1265
0
              iRefList = 0;
1266
0
            }
1267
0
          }
1268
0
          else if ( iIter == 0 )
1269
0
          {
1270
0
            iRefList = 0;
1271
0
          }
1272
0
          if ( iIter == 0 && !cs.picHeader->mvdL1Zero)
1273
0
          {
1274
0
            cu.mv    [1 - iRefList][0] = cMv    [1 - iRefList];
1275
0
            cu.refIdx[1 - iRefList]    = iRefIdx[1 - iRefList];
1276
1277
0
            PelUnitBuf predBufTmp = m_tmpPredStorage[1 - iRefList].getCompactBuf( cu );
1278
0
            motionCompensation( cu, predBufTmp, RefPicList(1 - iRefList) );
1279
0
          }
1280
1281
0
          RefPicList  refPicList = ( iRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
1282
1283
0
          if(cs.picHeader->mvdL1Zero)
1284
0
          {
1285
0
            iRefList = 0;
1286
0
            refPicList = REF_PIC_LIST_0;
1287
0
          }
1288
1289
0
          bool bChanged = false;
1290
1291
0
          iRefStart = 0;
1292
0
          iRefEnd   = cs.slice->numRefIdx[ refPicList ]-1;
1293
0
          for (int iRefIdxTemp = iRefStart; iRefIdxTemp <= iRefEnd; iRefIdxTemp++)
1294
0
          {
1295
0
            uiBitsTemp = uiMbBits[2] + uiMotBits[1-iRefList];
1296
0
            uiBitsTemp += ( (cs.slice->sps->BCW == true) ? getWeightIdxBits(BcwIdx) : 0 );
1297
0
            if ( cs.slice->numRefIdx[ refPicList ] > 1 )
1298
0
            {
1299
0
              uiBitsTemp += iRefIdxTemp+1;
1300
0
              if ( iRefIdxTemp == cs.slice->numRefIdx[ refPicList ]-1 )
1301
0
              {
1302
0
                uiBitsTemp--;
1303
0
              }
1304
0
            }
1305
0
            uiBitsTemp += m_auiMVPIdxCost[aaiMvpIdxBi[iRefList][iRefIdxTemp]][AMVP_MAX_NUM_CANDS];
1306
0
            if ( cs.slice->biDirPred )
1307
0
            {
1308
0
              uiBitsTemp += 1; // add one bit for symmetrical MVD mode
1309
0
            }
1310
            // call ME
1311
0
            xCopyAMVPInfo(&aacAMVPInfo[iRefList][iRefIdxTemp], &amvp[refPicList] );
1312
0
            xMotionEstimation ( cu, origBuf, refPicList, cMvPredBi[iRefList][iRefIdxTemp], iRefIdxTemp, cMvTemp[iRefList][iRefIdxTemp], aaiMvpIdxBi[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp, amvp[refPicList], true );
1313
0
            xCheckBestMVP( refPicList, cMvTemp[iRefList][iRefIdxTemp], cMvPredBi[iRefList][iRefIdxTemp], aaiMvpIdxBi[iRefList][iRefIdxTemp], amvp[refPicList], uiBitsTemp, uiCostTemp, cu.imv);
1314
0
            if ( uiCostTemp < uiCostBi )
1315
0
            {
1316
0
              bChanged = true;
1317
1318
0
              cMvBi[iRefList]     = cMvTemp[iRefList][iRefIdxTemp];
1319
0
              iRefIdxBi[iRefList] = iRefIdxTemp;
1320
1321
0
              uiCostBi            = uiCostTemp;
1322
0
              uiMotBits[iRefList] = uiBitsTemp - uiMbBits[2] - uiMotBits[1-iRefList];
1323
0
              uiMotBits[iRefList] -= ( (cs.slice->sps->BCW == true) ? getWeightIdxBits(BcwIdx) : 0 );
1324
0
              uiBits[2]           = uiBitsTemp;
1325
1326
0
              if(iNumIter!=1)
1327
0
              {
1328
                //  Set motion
1329
0
                cu.mv    [refPicList][0] = cMvBi    [iRefList];
1330
0
                cu.refIdx[refPicList]    = iRefIdxBi[iRefList];
1331
1332
0
                PelUnitBuf predBufTmp = m_tmpPredStorage[iRefList].getCompactBuf( cu );
1333
0
                motionCompensation( cu, predBufTmp, refPicList );
1334
0
              }
1335
0
            }
1336
0
          } // for loop-iRefIdxTemp
1337
1338
0
          if( !bChanged )
1339
0
          {
1340
0
            if ((uiCostBi <= uiCost[0] && uiCostBi <= uiCost[1]) || enforceBcwPred)
1341
0
            {
1342
0
              xCopyAMVPInfo(&aacAMVPInfo[0][iRefIdxBi[0]], &amvp[REF_PIC_LIST_0]);
1343
0
              xCheckBestMVP( REF_PIC_LIST_0, cMvBi[0], cMvPredBi[0][iRefIdxBi[0]], aaiMvpIdxBi[0][iRefIdxBi[0]], amvp[REF_PIC_LIST_0], uiBits[2], uiCostBi, cu.imv);
1344
0
              if(!cs.picHeader->mvdL1Zero)
1345
0
              {
1346
0
                xCopyAMVPInfo(&aacAMVPInfo[1][iRefIdxBi[1]], &amvp[REF_PIC_LIST_1]);
1347
0
                xCheckBestMVP( REF_PIC_LIST_1, cMvBi[1], cMvPredBi[1][iRefIdxBi[1]], aaiMvpIdxBi[1][iRefIdxBi[1]], amvp[REF_PIC_LIST_1], uiBits[2], uiCostBi, cu.imv);
1348
0
              }
1349
0
            }
1350
0
            break;
1351
0
          }
1352
0
        } // for loop-iter
1353
0
      }
1354
1355
      // SMVD
1356
0
      if( cs.slice->biDirPred )
1357
0
      {
1358
0
        double th1 = 1.02;
1359
0
        bool testSME = true;
1360
0
        int numStartCand = m_pcEncCfg->m_SMVD > 1 ? 1 : 5;
1361
0
        Distortion symCost;
1362
0
        Mv cMvPredSym[2];
1363
0
        int mvpIdxSym[2];
1364
1365
0
        int curRefList = REF_PIC_LIST_0;
1366
0
        int tarRefList = 1 - curRefList;
1367
0
        RefPicList eCurRefList = (curRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0);
1368
0
        int refIdxCur = cs.slice->symRefIdx[ curRefList ];
1369
0
        int refIdxTar = cs.slice->symRefIdx[ tarRefList ];
1370
0
        if( aacAMVPInfo[ curRefList ][ refIdxCur ].mvCand[ 0 ] == aacAMVPInfo[ curRefList ][ refIdxCur ].mvCand[ 1 ] )
1371
0
        {
1372
0
          aacAMVPInfo[ curRefList ][ refIdxCur ].numCand = 1;
1373
0
        }
1374
0
        if( aacAMVPInfo[ tarRefList ][ refIdxTar ].mvCand[ 0 ] == aacAMVPInfo[ tarRefList ][ refIdxTar ].mvCand[ 1 ] )
1375
0
        {
1376
0
          aacAMVPInfo[ tarRefList ][ refIdxTar ].numCand = 1;
1377
0
        }
1378
1379
0
        MvField cCurMvField, cTarMvField;
1380
0
        Distortion costStart = MAX_DISTORTION;
1381
0
        for ( int i = 0; i < aacAMVPInfo[curRefList][refIdxCur].numCand; i++ )
1382
0
        {
1383
0
          for ( int j = 0; j < aacAMVPInfo[tarRefList][refIdxTar].numCand; j++ )
1384
0
          {
1385
            GCC_WARNING_DISABLE_array_bounds // probably a bug in gcc-10 static analyzer: It thinks the indices are -1 and therefore triggers -Werror=array-bounds
1386
0
            cCurMvField.setMvField( aacAMVPInfo[curRefList][refIdxCur].mvCand[i], refIdxCur );
1387
0
            cTarMvField.setMvField( aacAMVPInfo[tarRefList][refIdxTar].mvCand[j], refIdxTar );
1388
0
            GCC_WARNING_RESET
1389
0
            if( m_pcEncCfg->m_ifpLines )
1390
0
            {
1391
0
              xCheckAndClipMvToFppLine( cCurMvField.mv, cu.ly(), cu.lheight(), m_pcEncCfg->m_ifpLines, *cu.cs->pcv );
1392
0
              xCheckAndClipMvToFppLine( cTarMvField.mv, cu.ly(), cu.lheight(), m_pcEncCfg->m_ifpLines, *cu.cs->pcv );
1393
0
            }
1394
0
            Distortion cost = xGetSymCost( cu, origBuf, eCurRefList, cCurMvField, cTarMvField, BcwIdx );
1395
0
            if ( cost < costStart )
1396
0
            {
1397
0
              costStart = cost;
1398
0
              cMvPredSym[curRefList] = aacAMVPInfo[curRefList][refIdxCur].mvCand[i];
1399
0
              cMvPredSym[tarRefList] = aacAMVPInfo[tarRefList][refIdxTar].mvCand[j];
1400
0
              mvpIdxSym[curRefList] = i;
1401
0
              mvpIdxSym[tarRefList] = j;
1402
0
            }
1403
0
          }
1404
0
        }
1405
0
        cCurMvField.mv = cMvPredSym[curRefList];
1406
0
        cTarMvField.mv = cMvPredSym[tarRefList];
1407
1408
0
        m_pcRdCost->setCostScale(0);
1409
0
        Mv pred = cMvPredSym[curRefList];
1410
0
        pred.changeTransPrecInternal2Amvr(cu.imv);
1411
0
        m_pcRdCost->setPredictor(pred);
1412
0
        Mv mv = cCurMvField.mv;
1413
0
        mv.changeTransPrecInternal2Amvr(cu.imv);
1414
0
        uint32_t bits = m_pcRdCost->getBitsOfVectorWithPredictor(mv.hor, mv.ver, 0);
1415
0
        bits += m_auiMVPIdxCost[mvpIdxSym[curRefList]][AMVP_MAX_NUM_CANDS];
1416
0
        bits += m_auiMVPIdxCost[mvpIdxSym[tarRefList]][AMVP_MAX_NUM_CANDS];
1417
0
        costStart += m_pcRdCost->getCost(bits);
1418
1419
0
        std::vector<Mv> symmvdCands;
1420
0
        auto smmvdCandsGen = [&](Mv mvCand, bool mvPrecAdj)
1421
0
        {
1422
0
          if (mvPrecAdj && cu.imv)
1423
0
          {
1424
0
            mvCand.roundTransPrecInternal2Amvr(cu.imv);
1425
0
          }
1426
1427
0
          bool toAddMvCand = true;
1428
0
          for (std::vector<Mv>::iterator pos = symmvdCands.begin(); pos != symmvdCands.end(); pos++)
1429
0
          {
1430
0
            if (*pos == mvCand)
1431
0
            {
1432
0
              toAddMvCand = false;
1433
0
              break;
1434
0
            }
1435
0
          }
1436
1437
0
          if (toAddMvCand)
1438
0
          {
1439
0
            symmvdCands.push_back(mvCand);
1440
0
          }
1441
0
        };
1442
1443
0
        smmvdCandsGen(cMvHevcTemp[curRefList][refIdxCur], false);
1444
0
        smmvdCandsGen(cMvTemp[curRefList][refIdxCur], false);
1445
0
        if (iRefIdxBi[curRefList] == refIdxCur)
1446
0
        {
1447
0
          smmvdCandsGen(cMvBi[curRefList], false);
1448
0
        }
1449
0
        for (int i = 0; i < m_BlkUniMvInfoBuffer->m_uniMvListSize; i++)
1450
0
        {
1451
0
          if( symmvdCands.size() >= numStartCand )
1452
0
          {
1453
0
            break;
1454
0
          }
1455
0
          BlkUniMvInfo* curMvInfo = m_BlkUniMvInfoBuffer->getBlkUniMvInfo(i);
1456
0
          smmvdCandsGen(curMvInfo->uniMvs[curRefList][refIdxCur], true);
1457
0
        }
1458
1459
0
        for (auto mvStart : symmvdCands)
1460
0
        {
1461
0
          bool checked = false; //if it has been checkin in the mvPred.
1462
0
          for (int i = 0; i < aacAMVPInfo[curRefList][refIdxCur].numCand && !checked; i++)
1463
0
          {
1464
0
            checked |= (mvStart == aacAMVPInfo[curRefList][refIdxCur].mvCand[i]);
1465
0
          }
1466
0
          if (checked)
1467
0
          {
1468
0
            continue;
1469
0
          }
1470
1471
0
          Distortion bestCost = costStart;
1472
0
          xSymMvdCheckBestMvp(cu, origBuf, mvStart, (RefPicList)curRefList, aacAMVPInfo, BcwIdx, cMvPredSym, mvpIdxSym, costStart, false);
1473
0
          if (costStart < bestCost)
1474
0
          {
1475
0
            cCurMvField.setMvField(mvStart, refIdxCur);
1476
0
            cTarMvField.setMvField(mvStart.getSymmvdMv(cMvPredSym[curRefList], cMvPredSym[tarRefList]), refIdxTar);
1477
0
          }
1478
0
        }
1479
0
        Mv startPtMv = cCurMvField.mv;
1480
1481
0
        Distortion mvpCost = m_pcRdCost->getCost(m_auiMVPIdxCost[mvpIdxSym[curRefList]][AMVP_MAX_NUM_CANDS] + m_auiMVPIdxCost[mvpIdxSym[tarRefList]][AMVP_MAX_NUM_CANDS]);
1482
0
        symCost = costStart - mvpCost;
1483
1484
        // ME
1485
0
        testSME = m_pcEncCfg->m_SMVD <= 2 || ( symCost < uiCostBi * th1 && uiCostBi < uiCost[ 0 ] && uiCostBi < uiCost[ 1 ] );
1486
0
        if( testSME )
1487
0
        {
1488
0
          xSymMotionEstimation( cu, origBuf, cMvPredSym[ curRefList ], cMvPredSym[ tarRefList ], eCurRefList, cCurMvField, cTarMvField, symCost, BcwIdx );
1489
0
        }
1490
1491
0
        symCost += mvpCost;
1492
1493
0
        if (startPtMv != cCurMvField.mv)
1494
0
        { // if ME change MV, run a final check for best MVP.
1495
0
          xSymMvdCheckBestMvp(cu, origBuf, cCurMvField.mv, (RefPicList)curRefList, aacAMVPInfo, BcwIdx, cMvPredSym, mvpIdxSym, symCost, true);
1496
0
        }
1497
1498
0
        bits = uiMbBits[2];
1499
0
        bits += 1; // add one bit for #symmetrical MVD mode
1500
0
        bits += ( (cs.slice->sps->BCW == true) ? getWeightIdxBits(BcwIdx) : 0 );
1501
0
        symCost += m_pcRdCost->getCost(bits);
1502
0
        cTarMvField.setMvField(cCurMvField.mv.getSymmvdMv(cMvPredSym[curRefList], cMvPredSym[tarRefList]), refIdxTar);
1503
1504
        // save results
1505
0
        if ( symCost < uiCostBi  
1506
0
          && ( !m_pcEncCfg->m_ifpLines || 
1507
0
          ( CU::isMvInRangeFPP( cu.ly(), cu.lheight(), cCurMvField.mv.ver, m_pcEncCfg->m_ifpLines, *cu.cs->pcv ) &&
1508
0
            CU::isMvInRangeFPP( cu.ly(), cu.lheight(), cTarMvField.mv.ver, m_pcEncCfg->m_ifpLines, *cu.cs->pcv ) ) )          
1509
0
          )
1510
0
        {
1511
0
          uiCostBi = symCost;
1512
0
          symMode = 1 + curRefList;
1513
1514
0
          cMvBi[curRefList] = cCurMvField.mv;
1515
0
          iRefIdxBi[curRefList] = cCurMvField.refIdx;
1516
0
          aaiMvpIdxBi[curRefList][cCurMvField.refIdx] = mvpIdxSym[curRefList];
1517
0
          cMvPredBi[curRefList][iRefIdxBi[curRefList]] = cMvPredSym[curRefList];
1518
1519
0
          cMvBi[tarRefList] = cTarMvField.mv;
1520
0
          iRefIdxBi[tarRefList] = cTarMvField.refIdx;
1521
0
          aaiMvpIdxBi[tarRefList][cTarMvField.refIdx] = mvpIdxSym[tarRefList];
1522
0
          cMvPredBi[tarRefList][iRefIdxBi[tarRefList]] = cMvPredSym[tarRefList];
1523
0
        }
1524
0
      }
1525
0
    } // if (B_SLICE)
1526
1527
      //  Clear Motion Field
1528
0
    cu.mv [REF_PIC_LIST_0][0] = Mv();
1529
0
    cu.mv [REF_PIC_LIST_1][0] = Mv();
1530
0
    cu.mvd[REF_PIC_LIST_0][0] = cMvZero;
1531
0
    cu.mvd[REF_PIC_LIST_1][0] = cMvZero;
1532
0
    cu.refIdx[REF_PIC_LIST_0] = NOT_VALID;
1533
0
    cu.refIdx[REF_PIC_LIST_1] = NOT_VALID;
1534
0
    cu.mvpIdx[REF_PIC_LIST_0] = NOT_VALID;
1535
0
    cu.mvpIdx[REF_PIC_LIST_1] = NOT_VALID;
1536
0
    cu.mvpNum[REF_PIC_LIST_0] = NOT_VALID;
1537
0
    cu.mvpNum[REF_PIC_LIST_1] = NOT_VALID;
1538
1539
    // Set Motion Field
1540
0
    cMv    [1] = mvValidList1;
1541
0
    iRefIdx[1] = refIdxValidList1;
1542
0
    uiBits [1] = bitsValidList1;
1543
0
    uiCost [1] = costValidList1;
1544
0
    if( enforceBcwPred )
1545
0
    {
1546
0
      uiCost[0] = uiCost[1] = MAX_UINT;
1547
0
    }
1548
1549
0
    uiLastModeTemp = uiLastMode;
1550
0
    if ( uiCostBi <= uiCost[0] && uiCostBi <= uiCost[1])
1551
0
    {
1552
0
      bestCostInter = uiCostBi;
1553
0
      uiLastMode = 2;
1554
0
      cu.mv [REF_PIC_LIST_0][0] = cMvBi[0];
1555
0
      cu.mv [REF_PIC_LIST_1][0] = cMvBi[1];
1556
0
      cu.mvd[REF_PIC_LIST_0][0] = cMvBi[0] - cMvPredBi[0][iRefIdxBi[0]];
1557
0
      cu.mvd[REF_PIC_LIST_1][0] = cMvBi[1] - cMvPredBi[1][iRefIdxBi[1]];
1558
0
      cu.refIdx[REF_PIC_LIST_0] = iRefIdxBi[0];
1559
0
      cu.refIdx[REF_PIC_LIST_1] = iRefIdxBi[1];
1560
0
      cu.mvpIdx[REF_PIC_LIST_0] = aaiMvpIdxBi[0][iRefIdxBi[0]];
1561
0
      cu.mvpIdx[REF_PIC_LIST_1] = aaiMvpIdxBi[1][iRefIdxBi[1]];
1562
0
      cu.mvpNum[REF_PIC_LIST_0] = aaiMvpNum[0][iRefIdxBi[0]];
1563
0
      cu.mvpNum[REF_PIC_LIST_1] = aaiMvpNum[1][iRefIdxBi[1]];
1564
0
      cu.interDir = 3;
1565
1566
0
      cu.smvdMode = symMode;
1567
0
    }
1568
0
    else if ( uiCost[0] <= uiCost[1] )
1569
0
    {
1570
0
      bestCostInter = uiCost[0];
1571
0
      uiLastMode = 0;
1572
0
      cu.mv [REF_PIC_LIST_0][0] = cMv[0];
1573
0
      cu.mvd[REF_PIC_LIST_0][0] = cMv[0] - cMvPred[0][iRefIdx[0]];
1574
0
      cu.refIdx[REF_PIC_LIST_0] = iRefIdx[0];
1575
0
      cu.mvpIdx[REF_PIC_LIST_0] = aaiMvpIdx[0][iRefIdx[0]];
1576
0
      cu.mvpNum[REF_PIC_LIST_0] = aaiMvpNum[0][iRefIdx[0]];
1577
0
      cu.interDir = 1;
1578
0
    }
1579
0
    else
1580
0
    {
1581
0
      bestCostInter = uiCost[1];
1582
0
      uiLastMode = 1;
1583
0
      cu.mv [REF_PIC_LIST_1][0] = cMv[1];
1584
0
      cu.mvd[REF_PIC_LIST_1][0] = cMv[1] - cMvPred[1][iRefIdx[1]];
1585
0
      cu.refIdx[REF_PIC_LIST_1] = iRefIdx[1];
1586
0
      cu.mvpIdx[REF_PIC_LIST_1] = aaiMvpIdx[1][iRefIdx[1]];
1587
0
      cu.mvpNum[REF_PIC_LIST_1] = aaiMvpNum[1][iRefIdx[1]];
1588
0
      cu.interDir = 2;
1589
0
    }
1590
1591
0
    if( BcwIdx != BCW_DEFAULT )
1592
0
    {
1593
0
      cu.BcwIdx = BCW_DEFAULT; // Reset to default for the Non-NormalMC modes.
1594
0
    }
1595
0
    uiHevcCost = (uiCostBi <= uiCost[0] && uiCostBi <= uiCost[1]) ? uiCostBi : ((uiCost[0] <= uiCost[1]) ? uiCost[0] : uiCost[1]);
1596
0
    if (m_pcEncCfg->m_Affine > 2)
1597
0
    {
1598
0
      if (cu.slice->TLayer > 3)
1599
0
      {
1600
0
        checkAffine = false;
1601
0
      }
1602
0
      else
1603
0
      {
1604
0
        if( m_pcEncCfg->m_Affine >= 4 && cu.slice->TLayer >= 2 )
1605
0
        {
1606
0
          checkAffine = m_modeCtrl->comprCUCtx->bestCU ? (checkAffine && m_modeCtrl->comprCUCtx->bestCU->affine) : checkAffine;
1607
0
        }
1608
0
      }
1609
0
    }
1610
0
    if( checkAffine && cu.Y().width > 8 && cu.Y().height > 8 && m_pcEncCfg->m_Affine > 0 )
1611
0
    {
1612
      // Based on:
1613
      // H. Pejman*, S. Coulombe*, C. Vazquez*, M. Jamali° and A. Vakili°
1614
      // *École de technologie supérieure, °Summit Tech Multimedia
1615
      // "An Adjustable Fast Decision Method for Affine Motion Estimation in VVC,"
1616
      // ICIP, Kuala Lumpur, Malaysia, 2023, pp. 2695-2699, doi: 10.1109/ICIP49359.2023.10222750.
1617
      // https://ieeexplore.ieee.org/document/10222750
1618
1619
0
      static const double affine_thr_coffs[3] = { 2.534229853866437, 0.05173246 ,0.87650414 };
1620
0
      static const double affine_thr_param[5] = { 1, 1, 1, 1.3, 2.3 }; // TODO: Adapt if extending m_Affine range!
1621
0
      const int qp         = cu.qp;
1622
0
      const int blk_area   = cu.Y().area();
1623
0
      const double threshold  = affine_thr_param[m_pcEncCfg->m_Affine - 1];
1624
1625
      //Multiple linear regression (MLR):
1626
      //Y = b0 + b1*(QP) + b2*(LOG2(BLK_AREA))
1627
0
      double log_affine_thr =
1628
0
        affine_thr_coffs[0] +
1629
0
        qp * affine_thr_coffs[1] +
1630
0
        log2(blk_area) * affine_thr_coffs[2];
1631
1632
      //log_affine_thr is LOG 2 of estimated thr
1633
0
      double affine_thr = pow(2, log_affine_thr) * threshold;
1634
1635
0
      double scaled_uiHevcCost = (double)uiHevcCost;
1636
1637
      //The trained coefficients are based on the cost of internal 10 BitDepth. So, the cost should be scaled if the internal BitDepth is not 10.
1638
0
      if (m_pcEncCfg->m_internalBitDepth[0] !=10)
1639
0
      {
1640
        //Based on the CTC documnet to convert 8 bit to 10 bit video or vice versa, the VTM only multiply (8 to 10 bits) or divide (10 to 8 bits) pixel values to 4.
1641
        //In this case, the cost values are approximately scaled by 4.
1642
        //The trained data acquired from internal 10 bit data. So, if internal bit depth is 8, the conversion into 10-bit cost can be done as follows:
1643
0
        scaled_uiHevcCost = uiHevcCost * (pow(2.0, 10-m_pcEncCfg->m_internalBitDepth[0]));
1644
0
      }
1645
0
      if( scaled_uiHevcCost < affine_thr )
1646
0
      {
1647
0
        checkAffine = false;
1648
0
      }
1649
0
    }
1650
0
    if (cu.Y().width > 8 && cu.Y().height > 8 && cu.slice->sps->Affine && checkAffine)
1651
0
    {
1652
0
      PROFILER_SCOPE_AND_STAGE_EXT( 1, _TPROF, P_INTER_MVD_SEARCH_AFFINE, &cs, partitioner.chType );
1653
0
      m_hevcCost = uiHevcCost;
1654
      // save normal hevc result
1655
0
      uint32_t uiMRGIndex = cu.mergeIdx;
1656
0
      bool bMergeFlag = cu.mergeFlag;
1657
0
      uint32_t uiInterDir = cu.interDir;
1658
0
      int  iSymMode = cu.smvdMode;
1659
1660
0
      Mv cMvd[2];
1661
0
      uint32_t uiMvpIdx[2], uiMvpNum[2];
1662
0
      uiMvpIdx[0] = cu.mvpIdx[REF_PIC_LIST_0];
1663
0
      uiMvpIdx[1] = cu.mvpIdx[REF_PIC_LIST_1];
1664
0
      uiMvpNum[0] = cu.mvpNum[REF_PIC_LIST_0];
1665
0
      uiMvpNum[1] = cu.mvpNum[REF_PIC_LIST_1];
1666
0
      cMvd[0] = cu.mvd[REF_PIC_LIST_0][0];
1667
0
      cMvd[1] = cu.mvd[REF_PIC_LIST_1][0];
1668
1669
0
      MvField cHevcMvField[2];
1670
0
      cHevcMvField[0].setMvField(cu.mv[REF_PIC_LIST_0][0], cu.refIdx[REF_PIC_LIST_0]);
1671
0
      cHevcMvField[1].setMvField(cu.mv[REF_PIC_LIST_1][0], cu.refIdx[REF_PIC_LIST_1]);
1672
1673
      // do affine ME & Merge
1674
0
      cu.affineType = AFFINEMODEL_4PARAM;
1675
0
      Mv acMvAffine4Para[2][MAX_REF_PICS][3];
1676
0
      int refIdx4Para[2] = { -1, -1 };
1677
1678
0
      xPredAffineInterSearch(cu, origBuf, puIdx, uiLastModeTemp, uiAffineCost, cMvHevcTemp, acMvAffine4Para, refIdx4Para, BcwIdx, enforceBcwPred, (cs.slice->sps->BCW == true) ? getWeightIdxBits(BcwIdx) : 0 );
1679
1680
0
      if (cu.imv == IMV_OFF)
1681
0
      {
1682
0
        storeAffineMotion(cu.mv, cu.refIdx, AFFINEMODEL_4PARAM, BcwIdx);
1683
0
      }
1684
0
      if (cu.slice->sps->AffineType && uiAffineCost != MAX_DISTORTION)
1685
0
      {
1686
0
        if (uiAffineCost < uiHevcCost * 1.05) ///< condition for 6 parameter affine ME
1687
0
        {
1688
          // save 4 parameter results
1689
0
          Mv bestMv[2][3], bestMvd[2][3];
1690
0
          int bestMvpIdx[2], bestMvpNum[2], bestRefIdx[2];
1691
0
          uint8_t bestInterDir;
1692
1693
0
          bestInterDir = cu.interDir;
1694
0
          bestRefIdx[0] = cu.refIdx[0];
1695
0
          bestRefIdx[1] = cu.refIdx[1];
1696
0
          bestMvpIdx[0] = cu.mvpIdx[0];
1697
0
          bestMvpIdx[1] = cu.mvpIdx[1];
1698
0
          bestMvpNum[0] = cu.mvpNum[0];
1699
0
          bestMvpNum[1] = cu.mvpNum[1];
1700
1701
0
          for (int refList = 0; refList < 2; refList++)
1702
0
          {
1703
0
            bestMv[refList][0] = cu.mv[refList][0];
1704
0
            bestMv[refList][1] = cu.mv[refList][1];
1705
0
            bestMv[refList][2] = cu.mv[refList][2];
1706
0
            bestMvd[refList][0] = cu.mvd[refList][0];
1707
0
            bestMvd[refList][1] = cu.mvd[refList][1];
1708
0
            bestMvd[refList][2] = cu.mvd[refList][2];
1709
0
          }
1710
1711
0
          refIdx4Para[0] = bestRefIdx[0];
1712
0
          refIdx4Para[1] = bestRefIdx[1];
1713
1714
0
          Distortion uiAffine6Cost = MAX_DISTORTION;
1715
0
          cu.affineType = AFFINEMODEL_6PARAM;
1716
0
          xPredAffineInterSearch(cu, origBuf, puIdx, uiLastModeTemp, uiAffine6Cost, cMvHevcTemp, acMvAffine4Para, refIdx4Para, BcwIdx, enforceBcwPred, (cs.slice->sps->BCW == true) ? getWeightIdxBits(BcwIdx) : 0 );
1717
1718
0
          if (cu.imv == IMV_OFF)
1719
0
          {
1720
0
            storeAffineMotion(cu.mv, cu.refIdx, AFFINEMODEL_6PARAM, BcwIdx);
1721
0
          }
1722
1723
          // reset to 4 parameter affine inter mode
1724
0
          if (uiAffineCost <= uiAffine6Cost)
1725
0
          {
1726
0
            cu.affineType = AFFINEMODEL_4PARAM;
1727
0
            cu.interDir = bestInterDir;
1728
0
            cu.refIdx[0] = bestRefIdx[0];
1729
0
            cu.refIdx[1] = bestRefIdx[1];
1730
0
            cu.mvpIdx[0] = bestMvpIdx[0];
1731
0
            cu.mvpIdx[1] = bestMvpIdx[1];
1732
0
            cu.mvpNum[0] = bestMvpNum[0];
1733
0
            cu.mvpNum[1] = bestMvpNum[1];
1734
1735
0
            for (int verIdx = 0; verIdx < 3; verIdx++)
1736
0
            {
1737
0
              cu.mvd[REF_PIC_LIST_0][verIdx] = bestMvd[0][verIdx];
1738
0
              cu.mvd[REF_PIC_LIST_1][verIdx] = bestMvd[1][verIdx];
1739
0
            }
1740
1741
0
            CU::setAllAffineMv(cu, bestMv[0][0], bestMv[0][1], bestMv[0][2], REF_PIC_LIST_0);
1742
0
            CU::setAllAffineMv(cu, bestMv[1][0], bestMv[1][1], bestMv[1][2], REF_PIC_LIST_1);
1743
0
          }
1744
0
          else
1745
0
          {
1746
0
            uiAffineCost = uiAffine6Cost;
1747
0
          }
1748
0
        }
1749
1750
0
        uiAffineCost += m_pcRdCost->getCost(1); // add one bit for affine_type
1751
0
      }
1752
1753
0
      if (uiHevcCost <= uiAffineCost)
1754
0
      {
1755
        // set hevc me result
1756
0
        cu.affine = false;
1757
0
        cu.mergeFlag = bMergeFlag;
1758
0
        cu.mergeIdx = uiMRGIndex;
1759
0
        cu.interDir = uiInterDir;
1760
0
        cu.smvdMode = iSymMode;
1761
0
        cu.mv[REF_PIC_LIST_0][0]  = cHevcMvField[0].mv;
1762
0
        cu.refIdx[REF_PIC_LIST_0] = cHevcMvField[0].refIdx;
1763
0
        cu.mv[REF_PIC_LIST_1][0]  = cHevcMvField[1].mv;
1764
0
        cu.refIdx[REF_PIC_LIST_1] = cHevcMvField[1].refIdx;
1765
0
        cu.mvpIdx[REF_PIC_LIST_0] = uiMvpIdx[0];
1766
0
        cu.mvpIdx[REF_PIC_LIST_1] = uiMvpIdx[1];
1767
0
        cu.mvpNum[REF_PIC_LIST_0] = uiMvpNum[0];
1768
0
        cu.mvpNum[REF_PIC_LIST_1] = uiMvpNum[1];
1769
0
        cu.mvd[REF_PIC_LIST_0][0] = cMvd[0];
1770
0
        cu.mvd[REF_PIC_LIST_1][0] = cMvd[1];
1771
0
      }
1772
0
      else
1773
0
      {
1774
0
        cu.smvdMode = 0;
1775
0
        CHECK(!cu.affine, "Wrong.");
1776
0
        uiLastMode = uiLastModeTemp;
1777
0
      }
1778
0
    }
1779
1780
0
    if( cu.interDir == 3 && !cu.mergeFlag )
1781
0
    {
1782
0
      if (BcwIdx != BCW_DEFAULT)
1783
0
      {
1784
0
        cu.BcwIdx = BcwIdx;
1785
0
      }
1786
0
    }
1787
1788
0
    CU::spanMotionInfo( cu );
1789
1790
0
    m_skipPROF = false;
1791
0
    m_encOnly  = false;
1792
    //  MC
1793
0
    PelUnitBuf predBuf = cu.cs->getPredBuf(cu);
1794
0
    motionCompensation( cu, predBuf, REF_PIC_LIST_X );
1795
0
    puIdx++;
1796
0
  }
1797
1798
0
  return false;
1799
0
}
1800
1801
// AMVP
1802
void InterSearch::xEstimateMvPredAMVP( CodingUnit& cu, CPelUnitBuf& origBuf, RefPicList refPicList, int iRefIdx, Mv& rcMvPred, AMVPInfo& rAMVPInfo, Distortion& distBiP )
1803
0
{
1804
0
  Mv         cBestMv;
1805
0
  int        iBestIdx   = 0;
1806
0
  Distortion uiBestCost = MAX_DISTORTION;
1807
0
  int        i;
1808
1809
0
  AMVPInfo*  pcAMVPInfo = &rAMVPInfo;
1810
1811
  // Fill the MV Candidates
1812
0
  CU::fillMvpCand( cu, refPicList, iRefIdx, *pcAMVPInfo );
1813
1814
  // initialize Mvp index & Mvp
1815
0
  iBestIdx = 0;
1816
0
  cBestMv  = pcAMVPInfo->mvCand[0];
1817
1818
0
  PelUnitBuf predBuf = m_tmpStorageLCU.getCompactBuf( cu );
1819
1820
  //-- Check Minimum Cost.
1821
0
  for( i = 0 ; i < pcAMVPInfo->numCand; i++)
1822
0
  {
1823
0
    Mv mvCand = pcAMVPInfo->mvCand[i];
1824
0
    if( m_pcEncCfg->m_ifpLines )
1825
0
      xClipMvSearch( mvCand, cu.lumaPos(), cu.lumaSize(),*cu.cs->pcv, true );
1826
1827
0
    Distortion uiTmpCost = xGetTemplateCost( cu, origBuf, predBuf, mvCand, i, AMVP_MAX_NUM_CANDS, refPicList, iRefIdx );
1828
0
    if( uiBestCost > uiTmpCost )
1829
0
    {
1830
0
      uiBestCost  = uiTmpCost;
1831
0
      cBestMv     = pcAMVPInfo->mvCand[i];
1832
0
      iBestIdx    = i;
1833
0
      distBiP     = uiTmpCost;
1834
0
    }
1835
0
  }
1836
1837
  // Setting Best MVP
1838
0
  rcMvPred = cBestMv;
1839
0
  cu.mvpIdx[refPicList] = iBestIdx;
1840
0
  cu.mvpNum[refPicList] = pcAMVPInfo->numCand;
1841
1842
0
  return;
1843
0
}
1844
1845
uint32_t InterSearch::xGetMvpIdxBits(int iIdx, int iNum)
1846
57.6k
{
1847
57.6k
  CHECK(iIdx < 0 || iNum < 0 || iIdx >= iNum, "Invalid parameters");
1848
1849
57.6k
  if (iNum == 1)
1850
19.2k
  {
1851
19.2k
    return 0;
1852
19.2k
  }
1853
1854
38.4k
  uint32_t uiLength = 1;
1855
38.4k
  int iTemp = iIdx;
1856
38.4k
  if ( iTemp == 0 )
1857
19.2k
  {
1858
19.2k
    return uiLength;
1859
19.2k
  }
1860
1861
19.2k
  bool bCodeLast = ( iNum-1 > iTemp );
1862
1863
19.2k
  uiLength += (iTemp-1);
1864
1865
19.2k
  if( bCodeLast )
1866
0
  {
1867
0
    uiLength++;
1868
0
  }
1869
1870
19.2k
  return uiLength;
1871
38.4k
}
1872
1873
void InterSearch::xGetBlkBits( bool bPSlice, int iPartIdx, uint32_t uiLastMode, uint32_t uiBlkBit[3])
1874
0
{
1875
0
  uiBlkBit[0] = (! bPSlice) ? 3 : 1;
1876
0
  uiBlkBit[1] = 3;
1877
0
  uiBlkBit[2] = 5;
1878
0
}
1879
1880
void InterSearch::xCopyAMVPInfo (AMVPInfo* pSrc, AMVPInfo* pDst)
1881
0
{
1882
0
  pDst->numCand = pSrc->numCand;
1883
0
  for (int i = 0; i < pSrc->numCand; i++)
1884
0
  {
1885
0
    pDst->mvCand[i] = pSrc->mvCand[i];
1886
0
  }
1887
0
}
1888
1889
void InterSearch::xCheckBestMVP ( RefPicList refPicList, const Mv& cMv, Mv& rcMvPred, int& riMVPIdx, AMVPInfo& amvpInfo, uint32_t& ruiBits, Distortion& ruiCost, const uint8_t imv )
1890
0
{
1891
0
  if ( imv > 0 && imv < 3 )
1892
0
  {
1893
0
    return;
1894
0
  }
1895
1896
0
  AMVPInfo* pcAMVPInfo = &amvpInfo;
1897
1898
0
  CHECK(pcAMVPInfo->mvCand[riMVPIdx] != rcMvPred, "Invalid MV prediction candidate");
1899
1900
0
  if (pcAMVPInfo->numCand < 2)
1901
0
  {
1902
0
    return;
1903
0
  }
1904
1905
0
  m_pcRdCost->setCostScale ( 0    );
1906
1907
0
  int iBestMVPIdx = riMVPIdx;
1908
1909
0
  Mv pred = rcMvPred;
1910
0
  pred.changeTransPrecInternal2Amvr(imv);
1911
0
  m_pcRdCost->setPredictor( pred );
1912
0
  Mv mv = cMv;
1913
0
  mv.changeTransPrecInternal2Amvr(imv);
1914
0
  int iOrgMvBits = m_pcRdCost->getBitsOfVectorWithPredictor(mv.hor, mv.ver, 0);
1915
0
  iOrgMvBits += m_auiMVPIdxCost[riMVPIdx][AMVP_MAX_NUM_CANDS];
1916
0
  int iBestMvBits = iOrgMvBits;
1917
1918
0
  for (int iMVPIdx = 0; iMVPIdx < pcAMVPInfo->numCand; iMVPIdx++)
1919
0
  {
1920
0
    if (iMVPIdx == riMVPIdx)
1921
0
    {
1922
0
      continue;
1923
0
    }
1924
1925
0
    pred = pcAMVPInfo->mvCand[iMVPIdx];
1926
0
    pred.changeTransPrecInternal2Amvr(imv);
1927
0
    m_pcRdCost->setPredictor( pred );
1928
0
    int iMvBits = m_pcRdCost->getBitsOfVectorWithPredictor(mv.hor, mv.ver, 0);
1929
0
    iMvBits += m_auiMVPIdxCost[iMVPIdx][AMVP_MAX_NUM_CANDS];
1930
1931
0
    if (iMvBits < iBestMvBits)
1932
0
    {
1933
0
      iBestMvBits = iMvBits;
1934
0
      iBestMVPIdx = iMVPIdx;
1935
0
    }
1936
0
  }
1937
1938
0
  if (iBestMVPIdx != riMVPIdx)  //if changed
1939
0
  {
1940
0
    rcMvPred = pcAMVPInfo->mvCand[iBestMVPIdx];
1941
1942
0
    riMVPIdx = iBestMVPIdx;
1943
0
    uint32_t uiOrgBits = ruiBits;
1944
0
    ruiBits = uiOrgBits - iOrgMvBits + iBestMvBits;
1945
0
    ruiCost = (ruiCost - m_pcRdCost->getCost( uiOrgBits ))  + m_pcRdCost->getCost( ruiBits );
1946
0
  }
1947
0
}
1948
1949
1950
Distortion InterSearch::xGetTemplateCost( const CodingUnit& cu,
1951
                                          CPelUnitBuf& origBuf,
1952
                                          PelUnitBuf&  predBuf,
1953
                                          Mv           cMvCand,
1954
                                          int          iMVPIdx,
1955
                                          int          iMVPNum,
1956
                                          RefPicList   refPicList,
1957
                                          int          iRefIdx
1958
)
1959
0
{
1960
0
  Distortion uiCost = MAX_DISTORTION;
1961
1962
0
  const Picture* picRef = cu.slice->getRefPic( refPicList, iRefIdx );
1963
0
  clipMv( cMvCand, cu.lumaPos(), cu.lumaSize(), *cu.cs->pcv );
1964
1965
  // prediction pattern
1966
0
  xPredInterBlk( COMP_Y, cu, picRef, cMvCand, predBuf, false, cu.slice->clpRngs[ COMP_Y ], false, false);
1967
1968
  // calc distortion
1969
1970
0
  uiCost = m_pcRdCost->getDistPart(origBuf.Y(), predBuf.Y(), cu.cs->sps->bitDepths[ CH_L ], COMP_Y, DF_SAD);
1971
0
  uiCost += m_pcRdCost->getCost( m_auiMVPIdxCost[iMVPIdx][iMVPNum] );
1972
1973
0
  return uiCost;
1974
0
}
1975
1976
void InterSearch::xMotionEstimation(CodingUnit& cu, CPelUnitBuf& origBuf, RefPicList refPicList, Mv& rcMvPred, int iRefIdxPred, Mv& rcMv, int& riMVPIdx, uint32_t& ruiBits, Distortion& ruiCost, const AMVPInfo& amvpInfo, bool bBi)
1977
0
{
1978
0
  if( cu.cs->sps->BCW && cu.BcwIdx != BCW_DEFAULT && !bBi && xReadBufferedUniMv( cu, refPicList, iRefIdxPred, rcMvPred, rcMv, ruiBits, ruiCost ) )
1979
0
  {
1980
0
    return;
1981
0
  }
1982
1983
0
  Mv cMvHalf, cMvQter;
1984
1985
0
  CHECK(refPicList >= MAX_NUM_REF_LIST_ADAPT_SR || iRefIdxPred>=int(MAX_IDX_ADAPT_SR), "Invalid reference picture list");
1986
0
  m_iSearchRange = m_aaiAdaptSR[refPicList][iRefIdxPred];
1987
1988
0
  int    iSrchRng   = (bBi ? m_bipredSearchRange : m_iSearchRange);
1989
0
  double fWeight    = 1.0;
1990
1991
0
  CPelUnitBuf  origBufTmpCnst;
1992
0
  CPelUnitBuf* pBuf      = &origBuf;
1993
1994
0
  if(bBi) // Bi-predictive ME
1995
0
  {
1996
0
    PelUnitBuf  origBufTmp = m_tmpStorageLCU.getCompactBuf( cu );
1997
    // NOTE: Other buf contains predicted signal from another direction
1998
0
    PelUnitBuf otherBuf = m_tmpPredStorage[1 - (int)refPicList].getCompactBuf( cu );
1999
0
    origBufTmp.copyFrom(origBuf);
2000
0
    origBufTmp.removeHighFreq( otherBuf, m_pcEncCfg->m_bClipForBiPredMeEnabled, cu.slice->clpRngs );
2001
   
2002
0
    origBufTmpCnst = origBufTmp;
2003
0
    pBuf           = &origBufTmpCnst;
2004
0
    fWeight        = xGetMEDistortionWeight( cu.BcwIdx, refPicList );
2005
0
  }
2006
2007
  //  Search key pattern initialization
2008
0
  CPelBuf  tmpPattern   = pBuf->Y();
2009
0
  CPelBuf* pcPatternKey = &tmpPattern;
2010
2011
0
  m_lumaClpRng = cu.cs->slice->clpRngs[ COMP_Y ];
2012
2013
0
  const Picture* refPic = cu.slice->getRefPic(refPicList, iRefIdxPred);
2014
0
  CPelBuf buf = refPic->getRecoBuf(cu.blocks[COMP_Y]);
2015
2016
0
  TZSearchStruct cStruct;
2017
0
  cStruct.pcPatternKey  = pcPatternKey;
2018
0
  cStruct.iRefStride    = buf.stride;
2019
0
  cStruct.piRefY        = buf.buf;
2020
0
  cStruct.imvShift      = cu.imv == IMV_HPEL ? 1 : (cu.imv << 1);
2021
0
  cStruct.useAltHpelIf  = cu.imv == IMV_HPEL;
2022
0
  cStruct.zeroMV        = false;
2023
0
  cStruct.uiBestSad     = MAX_DISTORTION;
2024
2025
2026
0
  CodedCUInfo &relatedCU = m_modeCtrl->getBlkInfo( cu );
2027
2028
0
  bool bQTBTMV = false;
2029
0
  Mv cIntMv;
2030
0
  if( !bBi )
2031
0
  {
2032
0
    bool bValid = relatedCU.getMv( refPicList, iRefIdxPred, cIntMv );
2033
0
    if( bValid )
2034
0
    {
2035
0
      bQTBTMV = true;
2036
0
      cIntMv.changePrecision( MV_PRECISION_INT, MV_PRECISION_INTERNAL);
2037
0
    }
2038
0
  }
2039
2040
0
  Mv predQuarter = rcMvPred;
2041
0
  predQuarter.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
2042
0
  m_pcRdCost->setPredictor( predQuarter );
2043
0
  m_pcRdCost->setCostScale(2);
2044
2045
  //  Do integer search
2046
0
  if( m_motionEstimationSearchMethod == VVENC_MESEARCH_FULL || bBi )
2047
0
  {
2048
0
    cStruct.subShiftMode = m_pcEncCfg->m_fastInterSearchMode == VVENC_FASTINTERSEARCH_MODE1 || m_pcEncCfg->m_fastInterSearchMode == VVENC_FASTINTERSEARCH_MODE3 ? 1 : 0;
2049
0
    m_pcRdCost->setDistParam( m_cDistParam, *cStruct.pcPatternKey, cStruct.piRefY, cStruct.iRefStride, m_lumaClpRng.bd, COMP_Y, cStruct.subShiftMode );
2050
2051
0
    Mv bestInitMv = (bBi ? rcMv : rcMvPred);
2052
0
    Mv cTmpMv     = bestInitMv;
2053
0
    xClipMvSearch(cTmpMv, cu.lumaPos(), cu.lumaSize(), *cu.cs->pcv, m_pcEncCfg->m_ifpLines );
2054
0
    cTmpMv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT);
2055
0
    m_cDistParam.cur.buf = cStruct.piRefY + (cTmpMv.ver * cStruct.iRefStride) + cTmpMv.hor;
2056
0
    Distortion uiBestSad = m_cDistParam.distFunc(m_cDistParam);
2057
0
    uiBestSad += m_pcRdCost->getCostOfVectorWithPredictor(cTmpMv.hor, cTmpMv.ver, cStruct.imvShift);
2058
2059
0
    Mv prevMv[BlkUniMvInfoBuffer::m_uniMvListMaxSize];
2060
2061
0
    for( int i = 0; i < m_BlkUniMvInfoBuffer->m_uniMvListSize; i++ )
2062
0
    {
2063
0
      const BlkUniMvInfo* curMvInfo = m_BlkUniMvInfoBuffer->getBlkUniMvInfo( i );
2064
0
      cTmpMv = curMvInfo->uniMvs[refPicList][iRefIdxPred];
2065
0
      prevMv[i] = cTmpMv;
2066
2067
0
      int j = 0;
2068
0
      for( ; j < i; j++ )
2069
0
      {
2070
0
        if( cTmpMv == prevMv[j] )
2071
0
        {
2072
0
          break;
2073
0
        }
2074
0
      }
2075
0
      if( j < i )
2076
0
        continue;
2077
2078
0
      xClipMvSearch(cTmpMv, cu.lumaPos(), cu.lumaSize(), *cu.cs->pcv, m_pcEncCfg->m_ifpLines);
2079
0
      cTmpMv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT);
2080
0
      m_cDistParam.cur.buf = cStruct.piRefY + (cTmpMv.ver * cStruct.iRefStride) + cTmpMv.hor;
2081
2082
0
      Distortion uiSad = m_cDistParam.distFunc(m_cDistParam);
2083
0
      uiSad += m_pcRdCost->getCostOfVectorWithPredictor(cTmpMv.hor, cTmpMv.ver, cStruct.imvShift);
2084
0
      if( uiSad < uiBestSad )
2085
0
      {
2086
0
        uiBestSad = uiSad;
2087
0
        bestInitMv = curMvInfo->uniMvs[refPicList][iRefIdxPred];
2088
0
        m_cDistParam.maximumDistortionForEarlyExit = uiSad;
2089
0
      }
2090
0
    }
2091
2092
0
    xSetSearchRange( cu, bestInitMv, iSrchRng, cStruct.searchRange );
2093
0
    xPatternSearch ( cStruct, rcMv, ruiCost);
2094
0
  }
2095
0
  else if( bQTBTMV )
2096
0
  {
2097
0
    rcMv = cIntMv;
2098
0
    cStruct.subShiftMode = ( m_pcEncCfg->m_fastInterSearchMode == VVENC_FASTINTERSEARCH_MODE1 || m_pcEncCfg->m_fastInterSearchMode == VVENC_FASTINTERSEARCH_MODE3 ) ? 1 : 0;
2099
0
    xTZSearch( cu, refPicList, iRefIdxPred, cStruct, rcMv, ruiCost, false, true );
2100
0
  }
2101
0
  else
2102
0
  {
2103
0
    cStruct.subShiftMode = ( m_pcEncCfg->m_fastInterSearchMode == VVENC_FASTINTERSEARCH_MODE1 || m_pcEncCfg->m_fastInterSearchMode == VVENC_FASTINTERSEARCH_MODE3 ) ? 1 : 0;
2104
0
    rcMv = rcMvPred;
2105
0
    xPatternSearchFast(cu, refPicList, iRefIdxPred, cStruct, rcMv, ruiCost );
2106
0
    relatedCU.setMv( refPicList, iRefIdxPred, rcMv );
2107
0
  }
2108
2109
0
  DTRACE( g_trace_ctx, D_ME, "%d %d %d :MECostFPel<L%d,%d>: %d,%d,%dx%d, %d", DTRACE_GET_COUNTER( g_trace_ctx, D_ME ), cu.slice->poc, 0, ( int ) refPicList, ( int ) bBi, cu.Y().x, cu.Y().y, cu.Y().width, cu.Y().height, ruiCost );
2110
  // sub-pel refinement for sub-pel resolution
2111
0
  if ( cu.imv == IMV_OFF || cu.imv == IMV_HPEL )
2112
0
  {
2113
0
    if ( m_pcEncCfg->m_fastSubPel != 2 )
2114
0
    {
2115
0
      xPatternSearchFracDIF( cu, refPicList, iRefIdxPred, cStruct, rcMv, cMvHalf, cMvQter, ruiCost );
2116
0
    }
2117
0
    m_pcRdCost->setCostScale( 0 );
2118
0
    rcMv <<= 2;
2119
0
    rcMv  += ( cMvHalf <<= 1 );
2120
0
    rcMv  += cMvQter;
2121
0
    uint32_t uiMvBits = m_pcRdCost->getBitsOfVectorWithPredictor( rcMv.hor, rcMv.ver, cStruct.imvShift );
2122
0
    ruiBits += uiMvBits;
2123
0
    ruiCost = ( Distortion ) ( floor( fWeight * ( ( double ) ruiCost - ( double ) m_pcRdCost->getCost( uiMvBits ) ) ) + ( double ) m_pcRdCost->getCost( ruiBits ) );
2124
0
    rcMv.changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL);
2125
0
  }
2126
0
  else // integer refinement for integer-pel and 4-pel resolution
2127
0
  {
2128
0
    rcMv.changePrecision(MV_PRECISION_INT, MV_PRECISION_INTERNAL);
2129
0
    xPatternSearchIntRefine( cu, cStruct, rcMv, rcMvPred, riMVPIdx, ruiBits, ruiCost, amvpInfo, fWeight);
2130
0
  }
2131
0
  DTRACE(g_trace_ctx, D_ME, "   MECost<L%d,%d>: %6d (%d)  MV:%d,%d\n", (int)refPicList, (int)bBi, ruiCost, ruiBits, rcMv.hor << 2, rcMv.ver << 2);
2132
0
}
2133
2134
void InterSearch::xClipMvSearch( Mv& rcMv, const Position& pos, const struct Size& size, const PreCalcValues& pcv, const int ifpLines )
2135
0
{
2136
0
  int iMvShift = MV_FRACTIONAL_BITS_INTERNAL;
2137
0
  int iOffset = 8;
2138
0
  int iHorMax = ( pcv.lumaWidth + iOffset - ( int ) pos.x - 1 ) << iMvShift;
2139
0
  int iHorMin = ( -( int ) pcv.maxCUSize   - iOffset - ( int ) pos.x + 1 ) * (1 << iMvShift);
2140
2141
0
  int maxLumaHeight = ifpLines && ((pos.y >> pcv.maxCUSizeLog2) + ifpLines + 1 < pcv.heightInCtus) ? 
2142
    
2143
0
    (((pos.y >> pcv.maxCUSizeLog2) + ifpLines + 1) << pcv.maxCUSizeLog2 ) - size.height - 4  // 4 samples from DCTIF vertical bottom part
2144
2145
0
    : pcv.lumaHeight + iOffset;
2146
2147
0
  int iVerMax = ( maxLumaHeight - ( int ) pos.y - 1 ) << iMvShift;
2148
0
  int iVerMin = ( -( int ) pcv.maxCUSize   - iOffset - ( int ) pos.y + 1 ) * (1 << iMvShift);
2149
2150
0
  rcMv.hor = ( std::min( iHorMax, std::max( iHorMin, rcMv.hor ) ) );
2151
0
  rcMv.ver = ( std::min( iVerMax, std::max( iVerMin, rcMv.ver ) ) );
2152
0
}
2153
2154
void InterSearch::xClipMvToFppLine( Mv& mv, const int yB, const int nH, const int ifpLines, const PreCalcValues& pcv )
2155
0
{
2156
0
  const int yCompScale = 0;
2157
0
  const int mvPrecShift = MV_FRACTIONAL_BITS_INTERNAL;
2158
0
  const int ctuLogScale = pcv.maxCUSizeLog2 - yCompScale;
2159
0
  const int yRefMax     = ( ( ( yB >> ctuLogScale ) + ifpLines + 1 ) << ctuLogScale ) - 1;
2160
0
  const int yRefMv      = yB + nH + ( 4 >> yCompScale ) + (mv.ver >> mvPrecShift) - 1;
2161
0
  CHECKD( yRefMv <= yRefMax, "Not expected" );
2162
0
  mv.ver -= ( yRefMv - yRefMax ) << mvPrecShift;
2163
0
}
2164
2165
void InterSearch::xCheckAndClipMvToFppLine( Mv& mv, const int yB, const int nH, const int ifpLines, const PreCalcValues& pcv )
2166
0
{
2167
0
  const int yCompScale  = 0;
2168
0
  const int mvPrecShift = MV_FRACTIONAL_BITS_INTERNAL;
2169
0
  const int ctuLogScale = pcv.maxCUSizeLog2 - yCompScale;
2170
0
  const int yBMax       = ( pcv.heightInCtus - 1 - ifpLines ) << ctuLogScale;
2171
0
  if( yB < yBMax )
2172
0
  {
2173
0
    const int yRefMax = ( ( ( yB >> ctuLogScale ) + ifpLines + 1 ) << ctuLogScale ) - 1;
2174
0
    const int yRefMv  = yB + nH + ( 4 >> yCompScale ) + (mv.ver >> mvPrecShift) - 1;
2175
0
    if( yRefMv > yRefMax )
2176
0
    {
2177
      // clip MV
2178
0
      mv.ver -= (yRefMv - yRefMax) << mvPrecShift;
2179
0
    }
2180
0
  }
2181
0
}
2182
2183
void InterSearch::xSetSearchRange ( const CodingUnit& cu,
2184
                                    const Mv& cMvPred,
2185
                                    const int iSrchRng,
2186
                                    SearchRange& sr )
2187
0
{
2188
0
  const PreCalcValues& pcv = *cu.cs->pcv;
2189
0
  const int iMvShift = MV_FRACTIONAL_BITS_INTERNAL;
2190
0
  Mv cFPMvPred = cMvPred;
2191
0
  clipMv( cFPMvPred, cu.lumaPos(), cu.lumaSize(), pcv );
2192
2193
0
  Mv mvTL(cFPMvPred.hor - (iSrchRng << iMvShift), cFPMvPred.ver - (iSrchRng << iMvShift));
2194
0
  Mv mvBR(cFPMvPred.hor + (iSrchRng << iMvShift), cFPMvPred.ver + (iSrchRng << iMvShift));
2195
2196
0
  clipMv( mvTL, cu.lumaPos(), cu.lumaSize(), pcv);
2197
0
  xClipMvSearch( mvBR, cu.lumaPos(), cu.lumaSize(), pcv, m_pcEncCfg->m_ifpLines );
2198
2199
0
  mvTL.divideByPowerOf2( iMvShift );
2200
0
  mvBR.divideByPowerOf2( iMvShift );
2201
2202
0
  sr.left   = mvTL.hor;
2203
0
  sr.top    = mvTL.ver;
2204
0
  sr.right  = mvBR.hor;
2205
0
  sr.bottom = mvBR.ver;
2206
0
}
2207
2208
2209
void InterSearch::xPatternSearch( TZSearchStruct&  cStruct,
2210
                                  Mv&                 rcMv,
2211
                                  Distortion&         ruiSAD )
2212
0
{
2213
0
  Distortion  uiSad;
2214
0
  Distortion  uiSadBest = MAX_DISTORTION;
2215
0
  int         iBestX = 0;
2216
0
  int         iBestY = 0;
2217
2218
  //-- jclee for using the SAD function pointer
2219
0
  m_pcRdCost->setDistParam( m_cDistParam, *cStruct.pcPatternKey, cStruct.piRefY, cStruct.iRefStride, m_lumaClpRng.bd, COMP_Y, cStruct.subShiftMode );
2220
2221
0
  const SearchRange& sr = cStruct.searchRange;
2222
2223
0
  const Pel* piRef = cStruct.piRefY + (sr.top * cStruct.iRefStride);
2224
0
  for ( int y = sr.top; y <= sr.bottom; y++ )
2225
0
  {
2226
0
    for ( int x = sr.left; x <= sr.right; x++ )
2227
0
    {
2228
      //  find min. distortion position
2229
0
      m_cDistParam.cur.buf = piRef + x;
2230
2231
0
      uiSad = m_cDistParam.distFunc( m_cDistParam );
2232
2233
      // motion cost
2234
0
      uiSad += m_pcRdCost->getCostOfVectorWithPredictor( x, y, cStruct.imvShift );
2235
2236
0
      if ( uiSad < uiSadBest )
2237
0
      {
2238
0
        uiSadBest = uiSad;
2239
0
        iBestX    = x;
2240
0
        iBestY    = y;
2241
0
        m_cDistParam.maximumDistortionForEarlyExit = uiSad;
2242
0
      }
2243
0
    }
2244
0
    piRef += cStruct.iRefStride;
2245
0
  }
2246
0
  rcMv.set( iBestX, iBestY );
2247
2248
0
  cStruct.uiBestSad = uiSadBest; // th for testing
2249
0
  ruiSAD = uiSadBest - m_pcRdCost->getCostOfVectorWithPredictor( iBestX, iBestY, cStruct.imvShift );
2250
0
  return;
2251
0
}
2252
2253
2254
void InterSearch::xPatternSearchFast( const CodingUnit& cu,
2255
                                      RefPicList            refPicList,
2256
                                      int                   iRefIdxPred,
2257
                                      TZSearchStruct&       cStruct,
2258
                                      Mv&                   rcMv,
2259
                                      Distortion&           ruiSAD )
2260
0
{
2261
0
  if( cu.cs->picture->useME )
2262
0
  {
2263
0
    switch ( m_motionEstimationSearchMethodSCC )
2264
0
    {
2265
0
      case 3: //VVENC_MESEARCH_DIAMOND_FAST:
2266
0
        xTZSearch( cu, refPicList, iRefIdxPred, cStruct, rcMv, ruiSAD, true, true );
2267
0
        break;
2268
0
      case 2: //VVENC_MESEARCH_DIAMOND:
2269
0
        xTZSearch( cu, refPicList, iRefIdxPred, cStruct, rcMv, ruiSAD, true );
2270
0
        break;
2271
0
      default:
2272
0
        THROW("shouldn't get here");
2273
0
        break;
2274
0
    }
2275
0
    return;
2276
0
  }
2277
2278
0
  switch ( m_motionEstimationSearchMethod )
2279
0
  {
2280
0
    case VVENC_MESEARCH_DIAMOND_FAST:
2281
0
      xTZSearch         ( cu, refPicList, iRefIdxPred, cStruct, rcMv, ruiSAD, false, true );
2282
0
      break;
2283
0
    case VVENC_MESEARCH_DIAMOND:
2284
0
      xTZSearch         ( cu, refPicList, iRefIdxPred, cStruct, rcMv, ruiSAD, false );
2285
0
      break;
2286
0
    case VVENC_MESEARCH_DIAMOND_ENHANCED:
2287
0
      xTZSearch         ( cu, refPicList, iRefIdxPred, cStruct, rcMv, ruiSAD, true );
2288
0
      break;
2289
0
    case VVENC_MESEARCH_FULL:
2290
0
    default:
2291
0
      THROW("shouldn't get here");
2292
0
      break;
2293
0
  }
2294
0
}
2295
2296
2297
void InterSearch::xTZSearch( const CodingUnit& cu,
2298
                             RefPicList            refPicList,
2299
                             int                   iRefIdxPred,
2300
                             TZSearchStruct&       cStruct,
2301
                             Mv&                   rcMv,
2302
                             Distortion&           ruiSAD,
2303
                             const bool            bExtendedSettings,
2304
                             const bool            bFastSettings)
2305
0
{
2306
0
  const bool bUseRasterInFastMode                    = true; //toggle this to further reduce runtime
2307
0
  const bool bUseAdaptiveRaster                      = bExtendedSettings;
2308
0
  const int  iRaster                                 = (bFastSettings && bUseRasterInFastMode) ? 8 : 5;
2309
0
  const bool bTestZeroVector                         = true && !bFastSettings;
2310
0
  const bool bTestZeroVectorStart                    = bExtendedSettings;
2311
0
  const bool bTestZeroVectorStop                     = false;
2312
0
  const bool bFirstSearchDiamond                     = true;  // 1 = xTZ8PointDiamondSearch   0 = xTZ8PointSquareSearch
2313
0
  const bool bFirstCornersForDiamondDist1            = bExtendedSettings;
2314
0
  const bool bFirstSearchStop                        = m_pcEncCfg->m_bFastMEAssumingSmootherMVEnabled;
2315
0
  const uint32_t uiFirstSearchRounds                 = bFastSettings ? (bUseRasterInFastMode?3:2) : 3;     // first search stop X rounds after best match (must be >=1)
2316
0
  const bool bEnableRasterSearch                     = bFastSettings ? bUseRasterInFastMode : true;
2317
0
  const bool bAlwaysRasterSearch                     = bExtendedSettings;  // true: BETTER but factor 2 slower
2318
0
  const bool bRasterRefinementEnable                 = false; // enable either raster refinement or star refinement
2319
0
  const bool bRasterRefinementDiamond                = false; // 1 = xTZ8PointDiamondSearch   0 = xTZ8PointSquareSearch
2320
0
  const bool bRasterRefinementCornersForDiamondDist1 = bExtendedSettings;
2321
0
  const bool bStarRefinementEnable                   = true;  // enable either star refinement or raster refinement
2322
0
  const bool bStarRefinementDiamond                  = true;  // 1 = xTZ8PointDiamondSearch   0 = xTZ8PointSquareSearch
2323
0
  const bool bStarRefinementCornersForDiamondDist1   = bExtendedSettings;
2324
0
  const bool bStarRefinementStop                     = bFastSettings;
2325
0
  const uint32_t uiStarRefinementRounds              = 2;  // star refinement stop X rounds after best match (must be >=1)
2326
0
  const bool bNewZeroNeighbourhoodTest               = bExtendedSettings;
2327
2328
0
  int iSearchRange = m_iSearchRange;
2329
0
  xClipMvSearch( rcMv, cu.lumaPos(), cu.lumaSize(),*cu.cs->pcv, m_pcEncCfg->m_ifpLines );
2330
0
  rcMv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
2331
0
  rcMv.divideByPowerOf2(2);
2332
2333
  //
2334
0
  m_cDistParam.maximumDistortionForEarlyExit = cStruct.uiBestSad;
2335
0
  m_pcRdCost->setDistParam( m_cDistParam, *cStruct.pcPatternKey, cStruct.piRefY, cStruct.iRefStride, m_lumaClpRng.bd, COMP_Y, cStruct.subShiftMode );
2336
2337
  // set rcMv (Median predictor) as start point and as best point
2338
0
  xTZSearchHelp( cStruct, rcMv.hor, rcMv.ver, 0, 0 );
2339
2340
  // test whether zero Mv is better start point than Median predictor
2341
0
  if ( bTestZeroVector )
2342
0
  {
2343
0
    if( ( rcMv.hor != 0 || rcMv.ver != 0 ) && ( 0 != cStruct.iBestX || 0 != cStruct.iBestY ) )
2344
0
    {
2345
      // only test 0-vector if not obviously previously tested.
2346
0
      xTZSearchHelp( cStruct, 0, 0, 0, 0 );
2347
0
    }
2348
0
  }
2349
2350
0
  SearchRange& sr = cStruct.searchRange;
2351
2352
0
  for (int i = 0; i < m_BlkUniMvInfoBuffer->m_uniMvListSize; i++)
2353
0
  {
2354
0
    const BlkUniMvInfo* curMvInfo = m_BlkUniMvInfoBuffer->getBlkUniMvInfo(i);
2355
0
    Mv cTmpMv = curMvInfo->uniMvs[refPicList][iRefIdxPred];
2356
2357
0
    xClipMvSearch(cTmpMv, cu.lumaPos(), cu.lumaSize(), *cu.cs->pcv, m_pcEncCfg->m_ifpLines);
2358
0
    cTmpMv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT);
2359
0
    m_cDistParam.cur.buf = cStruct.piRefY + (cTmpMv.ver * cStruct.iRefStride) + cTmpMv.hor;
2360
2361
0
    Distortion uiSad = m_cDistParam.distFunc(m_cDistParam);
2362
0
    uiSad += m_pcRdCost->getCostOfVectorWithPredictor(cTmpMv.hor, cTmpMv.ver, cStruct.imvShift);
2363
0
    if (uiSad < cStruct.uiBestSad)
2364
0
    {
2365
0
      cStruct.uiBestSad = uiSad;
2366
0
      cStruct.iBestX = cTmpMv.hor;
2367
0
      cStruct.iBestY = cTmpMv.ver;
2368
0
      m_cDistParam.maximumDistortionForEarlyExit = uiSad;
2369
0
    }
2370
0
  }
2371
2372
0
  {
2373
    // set search range
2374
0
    Mv currBestMv(cStruct.iBestX, cStruct.iBestY );
2375
0
    currBestMv <<= MV_FRACTIONAL_BITS_INTERNAL;
2376
0
    xSetSearchRange(cu, currBestMv, m_iSearchRange >> (bFastSettings ? 1 : 0), sr );
2377
0
  }
2378
2379
  // starting point after initial examination
2380
0
  int  iDist = 0;
2381
0
  int  iStartX = cStruct.iBestX;
2382
0
  int  iStartY = cStruct.iBestY;
2383
2384
  // Early termination of motion search after selection of starting candidate
2385
0
  if( m_pcEncCfg->m_bIntegerET )
2386
0
  {
2387
0
    bool isLargeBlock = cu.lumaSize().area() > 64;
2388
0
    xTZ8PointDiamondSearch( cStruct, iStartX, iStartY, 1, false ); // 4-point small diamond search
2389
0
    if ( cStruct.iBestX == iStartX && cStruct.iBestY == iStartY )
2390
0
    {
2391
0
      if ( isLargeBlock )
2392
0
      {
2393
0
        xTZ4PointSquareSearch( cStruct, iStartX, iStartY, 1 );
2394
0
        if ( cStruct.iBestX == iStartX && cStruct.iBestY == iStartY )
2395
0
        {
2396
          // write out best match
2397
0
          rcMv.set( cStruct.iBestX, cStruct.iBestY );
2398
0
          ruiSAD = cStruct.uiBestSad - m_pcRdCost->getCostOfVectorWithPredictor( cStruct.iBestX, cStruct.iBestY, cStruct.imvShift );
2399
0
          return;
2400
0
        }
2401
0
      }
2402
0
      else
2403
0
      {
2404
        // write out best match
2405
0
        rcMv.set( cStruct.iBestX, cStruct.iBestY );
2406
0
        ruiSAD = cStruct.uiBestSad - m_pcRdCost->getCostOfVectorWithPredictor( cStruct.iBestX, cStruct.iBestY, cStruct.imvShift );
2407
0
        return;
2408
0
      }
2409
0
    }
2410
0
  }
2411
2412
  // start search
2413
0
  iDist = 0;
2414
0
  iStartX = cStruct.iBestX;
2415
0
  iStartY = cStruct.iBestY;
2416
2417
0
  const bool bBestCandidateZero = ( cStruct.iBestX == 0 ) && ( cStruct.iBestY == 0 );
2418
2419
  // first search around best position up to now.
2420
  // The following works as a "subsampled/log" window search around the best candidate
2421
0
  for( iDist = 1; iDist <= iSearchRange; iDist *= 2 )
2422
0
  {
2423
0
    if( bFirstSearchDiamond == 1 )
2424
0
    {
2425
0
      xTZ8PointDiamondSearch( cStruct, iStartX, iStartY, iDist, bFirstCornersForDiamondDist1 );
2426
0
    }
2427
0
    else
2428
0
    {
2429
0
      xTZ8PointSquareSearch( cStruct, iStartX, iStartY, iDist );
2430
0
    }
2431
2432
0
    if( bFirstSearchStop && ( cStruct.uiBestRound >= uiFirstSearchRounds ) ) // stop criterion
2433
0
    {
2434
0
      break;
2435
0
    }
2436
0
  }
2437
2438
0
  if( bNewZeroNeighbourhoodTest )
2439
0
  {
2440
0
    if( bTestZeroVectorStart && !bBestCandidateZero )
2441
0
    {
2442
0
      for( iDist = 1; iDist <= ( iSearchRange >> 1 ); iDist *= 2 )
2443
0
      {
2444
0
        xTZ8PointDiamondSearch( cStruct, 0, 0, iDist, false );
2445
0
        if( bTestZeroVectorStop && ( cStruct.uiBestRound > 2 ) ) // stop criterion
2446
0
        {
2447
0
          break;
2448
0
        }
2449
0
      }
2450
0
    }
2451
0
  }
2452
2453
  // calculate only 2 missing points instead 8 points if cStruct.uiBestDistance == 1
2454
0
  if ( cStruct.uiBestDistance == 1 )
2455
0
  {
2456
0
    cStruct.uiBestDistance = 0;
2457
0
    xTZ2PointSearch( cStruct );
2458
0
  }
2459
2460
  // raster search if distance is too big
2461
0
  if( bUseAdaptiveRaster )
2462
0
  {
2463
0
    int iWindowSize     = iRaster;
2464
0
    SearchRange localsr = sr;
2465
2466
0
    if( !( bEnableRasterSearch && ( ( ( int ) ( cStruct.uiBestDistance ) >= iRaster ) ) ) )
2467
0
    {
2468
0
      iWindowSize++;
2469
0
      localsr.left    /= 2;
2470
0
      localsr.right   /= 2;
2471
0
      localsr.top     /= 2;
2472
0
      localsr.bottom  /= 2;
2473
0
    }
2474
2475
0
    cStruct.uiBestDistance = iWindowSize;
2476
2477
0
    for( iStartY = localsr.top; iStartY <= localsr.bottom; iStartY += iWindowSize )
2478
0
    {
2479
0
      for( iStartX = localsr.left; iStartX <= localsr.right; iStartX += iWindowSize )
2480
0
      {
2481
0
        xTZSearchHelp( cStruct, iStartX, iStartY, 0, iWindowSize );
2482
0
      }
2483
0
    }
2484
0
  }
2485
0
  else
2486
0
  {
2487
0
    if( bEnableRasterSearch && ( ( ( int ) ( cStruct.uiBestDistance ) >= iRaster ) || bAlwaysRasterSearch ) )
2488
0
    {
2489
0
      cStruct.uiBestDistance = iRaster;
2490
2491
0
      for( iStartY = sr.top; iStartY <= sr.bottom; iStartY += iRaster )
2492
0
      {
2493
0
        for( iStartX = sr.left; iStartX <= sr.right; iStartX += iRaster )
2494
0
        {
2495
0
          xTZSearchHelp( cStruct, iStartX, iStartY, 0, iRaster );
2496
0
        }
2497
0
      }
2498
0
    }
2499
0
  }
2500
2501
  // raster refinement
2502
2503
0
  if ( bRasterRefinementEnable && cStruct.uiBestDistance > 0 )
2504
0
  {
2505
0
    while ( cStruct.uiBestDistance > 0 )
2506
0
    {
2507
0
      iStartX = cStruct.iBestX;
2508
0
      iStartY = cStruct.iBestY;
2509
0
      if ( cStruct.uiBestDistance > 1 )
2510
0
      {
2511
0
        iDist = cStruct.uiBestDistance >>= 1;
2512
0
        if ( bRasterRefinementDiamond == 1 )
2513
0
        {
2514
0
          xTZ8PointDiamondSearch ( cStruct, iStartX, iStartY, iDist, bRasterRefinementCornersForDiamondDist1 );
2515
0
        }
2516
0
        else
2517
0
        {
2518
0
          xTZ8PointSquareSearch  ( cStruct, iStartX, iStartY, iDist );
2519
0
        }
2520
0
      }
2521
2522
      // calculate only 2 missing points instead 8 points if cStruct.uiBestDistance == 1
2523
0
      if ( cStruct.uiBestDistance == 1 )
2524
0
      {
2525
0
        cStruct.uiBestDistance = 0;
2526
0
        if ( cStruct.ucPointNr != 0 )
2527
0
        {
2528
0
          xTZ2PointSearch( cStruct );
2529
0
        }
2530
0
      }
2531
0
    }
2532
0
  }
2533
2534
  // star refinement
2535
0
  if ( bStarRefinementEnable && cStruct.uiBestDistance > 0 )
2536
0
  {
2537
0
    while ( cStruct.uiBestDistance > 0 )
2538
0
    {
2539
0
      iStartX = cStruct.iBestX;
2540
0
      iStartY = cStruct.iBestY;
2541
0
      cStruct.uiBestDistance = 0;
2542
0
      cStruct.ucPointNr = 0;
2543
0
      for ( iDist = 1; iDist < iSearchRange + 1; iDist*=2 )
2544
0
      {
2545
0
        if ( bStarRefinementDiamond == 1 )
2546
0
        {
2547
0
          xTZ8PointDiamondSearch ( cStruct, iStartX, iStartY, iDist, bStarRefinementCornersForDiamondDist1 );
2548
0
        }
2549
0
        else
2550
0
        {
2551
0
          xTZ8PointSquareSearch  ( cStruct, iStartX, iStartY, iDist );
2552
0
        }
2553
0
        if ( bStarRefinementStop && (cStruct.uiBestRound >= uiStarRefinementRounds) ) // stop criterion
2554
0
        {
2555
0
          break;
2556
0
        }
2557
0
      }
2558
2559
      // calculate only 2 missing points instead 8 points if cStrukt.uiBestDistance == 1
2560
0
      if ( cStruct.uiBestDistance == 1 )
2561
0
      {
2562
0
        cStruct.uiBestDistance = 0;
2563
0
        if ( cStruct.ucPointNr != 0 )
2564
0
        {
2565
0
          xTZ2PointSearch( cStruct );
2566
0
        }
2567
0
      }
2568
0
    }
2569
0
  }
2570
2571
  // write out best match
2572
0
  rcMv.set( cStruct.iBestX, cStruct.iBestY );
2573
0
  ruiSAD = cStruct.uiBestSad - m_pcRdCost->getCostOfVectorWithPredictor( cStruct.iBestX, cStruct.iBestY, cStruct.imvShift );
2574
0
}
2575
2576
void InterSearch::xPatternSearchIntRefine(CodingUnit& cu, TZSearchStruct&  cStruct, Mv& rcMv, Mv& rcMvPred, int& riMVPIdx, uint32_t& ruiBits, Distortion& ruiCost, const AMVPInfo& amvpInfo, double fWeight)
2577
0
{
2578
2579
0
  CHECK( cu.imv == IMV_OFF || cu.imv == IMV_HPEL , "xPatternSearchIntRefine(): Sub-pel MV used.");
2580
0
  CHECK( amvpInfo.mvCand[riMVPIdx] != rcMvPred, "xPatternSearchIntRefine(): MvPred issue.");
2581
2582
0
  m_pcRdCost->setDistParam(m_cDistParam, *cStruct.pcPatternKey, cStruct.piRefY, cStruct.iRefStride, m_lumaClpRng.bd, COMP_Y, 0, m_pcEncCfg->m_bUseHADME ? ( m_pcEncCfg->m_fastHad ? 2 : 1 ) : 0 );
2583
2584
  // -> set MV scale for cost calculation to QPEL (0)
2585
0
  m_pcRdCost->setCostScale ( 0 );
2586
2587
0
  Distortion  uiDist, uiSATD = 0;
2588
0
  Distortion  uiBestDist  = MAX_DISTORTION;
2589
  // subtract old MVP costs because costs for all newly tested MVPs are added in here
2590
0
  ruiBits -= m_auiMVPIdxCost[riMVPIdx][AMVP_MAX_NUM_CANDS];
2591
2592
0
  Mv cBestMv = rcMv;
2593
0
  Mv cBaseMvd[2];
2594
0
  int iBestBits = 0;
2595
0
  int iBestMVPIdx = riMVPIdx;
2596
0
  Mv testPos[9] = { { 0, 0}, { -1, -1},{ -1, 0},{ -1, 1},{ 0, -1},{ 0, 1},{ 1, -1},{ 1, 0},{ 1, 1} };
2597
2598
2599
0
  cBaseMvd[0] = (rcMv - amvpInfo.mvCand[0]);
2600
0
  cBaseMvd[1] = (rcMv - amvpInfo.mvCand[1]);
2601
0
  CHECK( (cBaseMvd[0].hor & 0x03) != 0 || (cBaseMvd[0].ver & 0x03) != 0 , "xPatternSearchIntRefine(): AMVP cand 0 Mvd issue.");
2602
0
  CHECK( (cBaseMvd[1].hor & 0x03) != 0 || (cBaseMvd[1].ver & 0x03) != 0 , "xPatternSearchIntRefine(): AMVP cand 1 Mvd issue.");
2603
2604
0
  cBaseMvd[0].roundTransPrecInternal2Amvr(cu.imv);
2605
0
  cBaseMvd[1].roundTransPrecInternal2Amvr(cu.imv);
2606
2607
  // test best integer position and all 8 neighboring positions
2608
0
  for (int pos = 0; pos < 9; pos ++)
2609
0
  {
2610
0
    Mv cTestMv[2];
2611
    // test both AMVP candidates for each position
2612
0
    for (int iMVPIdx = 0; iMVPIdx < amvpInfo.numCand; iMVPIdx++)
2613
0
    {
2614
0
      cTestMv[iMVPIdx] = testPos[pos];
2615
0
      cTestMv[iMVPIdx].changeTransPrecAmvr2Internal(cu.imv);
2616
0
      cTestMv[iMVPIdx] += cBaseMvd[iMVPIdx];
2617
0
      cTestMv[iMVPIdx] += amvpInfo.mvCand[iMVPIdx];
2618
2619
0
      if( m_pcEncCfg->m_ifpLines && !CU::isMvInRangeFPP( cu.ly(), cu.lheight(), cTestMv[iMVPIdx].ver, m_pcEncCfg->m_ifpLines, *cu.cs->pcv ) )
2620
0
      {
2621
0
        xClipMvToFppLine( cTestMv[iMVPIdx], cu.ly(), cu.lheight(), m_pcEncCfg->m_ifpLines, *cu.cs->pcv );
2622
0
        cTestMv[iMVPIdx].roundTransPrecInternal2AmvrVertical(cu.imv);
2623
0
      }
2624
2625
0
      if ( iMVPIdx == 0 || cTestMv[0] != cTestMv[1])
2626
0
      {
2627
0
        Mv cTempMV = cTestMv[iMVPIdx];
2628
0
        clipMv(cTempMV, cu.lumaPos(), cu.lumaSize(), *cu.cs->pcv);
2629
0
        m_cDistParam.cur.buf = cStruct.piRefY  + cStruct.iRefStride * (cTempMV.ver >>  MV_FRACTIONAL_BITS_INTERNAL) + (cTempMV.hor >> MV_FRACTIONAL_BITS_INTERNAL);
2630
0
        uiDist = uiSATD = (Distortion) (m_cDistParam.distFunc( m_cDistParam ) * fWeight);
2631
0
      }
2632
0
      else
2633
0
      {
2634
0
        uiDist = uiSATD;
2635
0
      }
2636
2637
0
      int iMvBits = m_auiMVPIdxCost[iMVPIdx][AMVP_MAX_NUM_CANDS];
2638
0
      Mv pred = amvpInfo.mvCand[iMVPIdx];
2639
0
      pred.changeTransPrecInternal2Amvr(cu.imv);
2640
0
      m_pcRdCost->setPredictor( pred );
2641
0
      Mv mv = cTestMv[iMVPIdx];
2642
0
      mv.changeTransPrecInternal2Amvr(cu.imv);
2643
0
      iMvBits += m_pcRdCost->getBitsOfVectorWithPredictor( mv.hor, mv.ver, 0 );
2644
0
      uiDist += m_pcRdCost->getCost(iMvBits);
2645
2646
0
      if (uiDist < uiBestDist)
2647
0
      {
2648
0
        uiBestDist = uiDist;
2649
0
        cBestMv = cTestMv[iMVPIdx];
2650
0
        iBestMVPIdx = iMVPIdx;
2651
0
        iBestBits = iMvBits;
2652
0
      }
2653
0
    }
2654
0
  }
2655
0
  if( uiBestDist == MAX_DISTORTION )
2656
0
  {
2657
0
    ruiCost = MAX_DISTORTION;
2658
0
    return;
2659
0
  }
2660
2661
0
  rcMv = cBestMv;
2662
0
  rcMvPred = amvpInfo.mvCand[iBestMVPIdx];
2663
0
  riMVPIdx = iBestMVPIdx;
2664
0
  m_pcRdCost->setPredictor( rcMvPred );
2665
2666
0
  ruiBits += iBestBits;
2667
  // taken from JEM 5.0
2668
  // verify since it makes no sence to subtract Lamda*(Rmvd+Rmvpidx) from D+Lamda(Rmvd)
2669
  // this would take the rate for the MVP idx out of the cost calculation
2670
  // however this rate is always 1 so impact is small
2671
0
  ruiCost = uiBestDist - m_pcRdCost->getCost(iBestBits) + m_pcRdCost->getCost(ruiBits);
2672
  // taken from JEM 5.0
2673
  // verify since it makes no sense to add rate for MVDs twicce
2674
2675
0
  return;
2676
0
}
2677
2678
void InterSearch::xPatternSearchFracDIF(
2679
  const CodingUnit& cu,
2680
  RefPicList            refPicList,
2681
  int                   iRefIdx,
2682
  TZSearchStruct&    cStruct,
2683
  const Mv&             rcMvInt,
2684
  Mv&                   rcMvHalf,
2685
  Mv&                   rcMvQter,
2686
  Distortion&           ruiCost
2687
)
2688
0
{
2689
0
  PROFILER_SCOPE_AND_STAGE( 0, _TPROF, P_FRAC_PEL );
2690
2691
  //  Reference pattern initialization (integer scale)
2692
0
  int         iOffset    = rcMvInt.hor + rcMvInt.ver * cStruct.iRefStride;
2693
0
  CPelBuf cPatternRoi(cStruct.piRefY + iOffset, cStruct.iRefStride, *cStruct.pcPatternKey);
2694
2695
  //  Half-pel refinement
2696
0
  m_pcRdCost->setCostScale(1);
2697
0
  if( 0 == m_pcEncCfg->m_fastSubPel )
2698
0
  {
2699
0
    xExtDIFUpSamplingH( &cPatternRoi, cStruct.useAltHpelIf );
2700
0
  }
2701
2702
0
  rcMvHalf = rcMvInt;   rcMvHalf <<= 1;    // for mv-cost
2703
0
  Mv baseRefMv(0, 0);
2704
0
  Distortion  uiDistBest = MAX_DISTORTION;
2705
0
  int patternId = 41;
2706
0
  ruiCost = xPatternRefinement( cStruct.pcPatternKey, baseRefMv, 2, rcMvHalf, uiDistBest, patternId, &cPatternRoi, cStruct.useAltHpelIf );
2707
0
  patternId -= ( m_pcEncCfg->m_fastSubPel == 1 ? 41 : 0 );
2708
2709
2710
  //  quarter-pel refinement
2711
0
  if( cStruct.imvShift == IMV_OFF && 0 != patternId )
2712
0
  {
2713
0
    PROFILER_SCOPE_AND_STAGE( 0, _TPROF, P_QPEL );
2714
0
    m_pcRdCost->setCostScale( 0 );
2715
0
    xExtDIFUpSamplingQ( &cPatternRoi, rcMvHalf, patternId );
2716
0
    baseRefMv = rcMvHalf;
2717
0
    baseRefMv <<= 1;
2718
2719
0
    rcMvQter = rcMvInt;    rcMvQter <<= 1;    // for mv-cost
2720
0
    rcMvQter += rcMvHalf;  rcMvQter <<= 1;
2721
0
    ruiCost = xPatternRefinement( cStruct.pcPatternKey, baseRefMv, 1, rcMvQter, uiDistBest, patternId, &cPatternRoi, cStruct.useAltHpelIf );
2722
0
  }
2723
2724
0
}
2725
2726
Distortion InterSearch::xGetSymCost( const CodingUnit& cu, CPelUnitBuf& origBuf, RefPicList eCurRefPicList, const MvField& cCurMvField, MvField& cTarMvField, int BcwIdx )
2727
0
{
2728
0
  Distortion cost = MAX_DISTORTION;
2729
0
  RefPicList eTarRefPicList = (RefPicList)(1 - (int)eCurRefPicList);
2730
2731
  // get prediction of eCurRefPicList
2732
0
  PelUnitBuf  predBufA  = m_tmpPredStorage[eCurRefPicList].getCompactBuf( cu );
2733
0
  const Picture* picRefA = cu.slice->getRefPic( eCurRefPicList, cCurMvField.refIdx );
2734
0
  Mv mvA = cCurMvField.mv;
2735
0
  clipMv( mvA, cu.lumaPos(), cu.lumaSize(), *cu.cs->pcv );
2736
0
  xPredInterBlk( COMP_Y, cu, picRefA, mvA, predBufA, false, cu.slice->clpRngs[ COMP_Y ], false, false );
2737
2738
  // get prediction of eTarRefPicList
2739
0
  PelUnitBuf predBufB = m_tmpPredStorage[eTarRefPicList].getCompactBuf( cu );
2740
0
  const Picture* picRefB = cu.slice->getRefPic( eTarRefPicList, cTarMvField.refIdx );
2741
0
  Mv mvB = cTarMvField.mv;
2742
0
  clipMv( mvB, cu.lumaPos(), cu.lumaSize(), *cu.cs->pcv );
2743
0
  xPredInterBlk( COMP_Y, cu, picRefB, mvB, predBufB, false, cu.slice->clpRngs[ COMP_Y ], false, false );
2744
2745
0
  PelUnitBuf bufTmp = m_tmpStorageLCU.getCompactBuf( cu );
2746
0
  bufTmp.copyFrom( origBuf );
2747
0
  bufTmp.removeHighFreq( predBufA, m_pcEncCfg->m_bClipForBiPredMeEnabled, cu.slice->clpRngs/*, getBcwWeight( cu.BcwIdx, eTarRefPicList )*/ );
2748
0
  double fWeight = xGetMEDistortionWeight( cu.BcwIdx, eTarRefPicList );
2749
2750
  // calc distortion
2751
0
  cost = ( Distortion ) floor( fWeight * ( double ) m_pcRdCost->getDistPart( bufTmp.Y(), predBufB.Y(), cu.cs->sps->bitDepths[ CH_L ], COMP_Y, DF_HAD ) );
2752
2753
0
  return(cost);
2754
0
}
2755
2756
Distortion InterSearch::xSymRefineMvSearch( CodingUnit& cu, CPelUnitBuf& origBuf, Mv& rcMvCurPred, Mv& rcMvTarPred, RefPicList refPicList, MvField& rCurMvField, 
2757
                                            MvField& rTarMvField, Distortion uiMinCost, int SearchPattern, int nSearchStepShift, uint32_t uiMaxSearchRounds, int BcwIdx )
2758
0
{
2759
0
  const Mv mvSearchOffsetCross[4] = { Mv( 0 , 1 ) , Mv( 1 , 0 ) , Mv( 0 , -1 ) , Mv( -1 ,  0 ) };
2760
0
  const Mv mvSearchOffsetSquare[8] = { Mv( -1 , 1 ) , Mv( 0 , 1 ) , Mv( 1 ,  1 ) , Mv( 1 ,  0 ) , Mv( 1 , -1 ) , Mv( 0 , -1 ) , Mv( -1 , -1 ) , Mv( -1 , 0 ) };
2761
0
  const Mv mvSearchOffsetDiamond[8] = { Mv( 0 , 2 ) , Mv( 1 , 1 ) , Mv( 2 ,  0 ) , Mv( 1 , -1 ) , Mv( 0 , -2 ) , Mv( -1 , -1 ) , Mv( -2 ,  0 ) , Mv( -1 , 1 ) };
2762
0
  const Mv mvSearchOffsetHexagon[6] = { Mv( 2 , 0 ) , Mv( 1 , 2 ) , Mv( -1 ,  2 ) , Mv( -2 ,  0 ) , Mv( -1 , -2 ) , Mv( 1 , -2 ) };
2763
2764
0
  int nDirectStart = 0, nDirectEnd = 0, nDirectRounding = 0, nDirectMask = 0;
2765
0
  const Mv * pSearchOffset;
2766
0
  if ( SearchPattern == 0 )
2767
0
  {
2768
0
    nDirectEnd = 3;
2769
0
    nDirectRounding = 4;
2770
0
    nDirectMask = 0x03;
2771
0
    pSearchOffset = mvSearchOffsetCross;
2772
0
  }
2773
0
  else if ( SearchPattern == 1 )
2774
0
  {
2775
0
    nDirectEnd = 7;
2776
0
    nDirectRounding = 8;
2777
0
    nDirectMask = 0x07;
2778
0
    pSearchOffset = mvSearchOffsetSquare;
2779
0
  }
2780
0
  else if ( SearchPattern == 2 )
2781
0
  {
2782
0
    nDirectEnd = 7;
2783
0
    nDirectRounding = 8;
2784
0
    nDirectMask = 0x07;
2785
0
    pSearchOffset = mvSearchOffsetDiamond;
2786
0
  }
2787
0
  else if ( SearchPattern == 3 )
2788
0
  {
2789
0
    nDirectEnd = 5;
2790
0
    pSearchOffset = mvSearchOffsetHexagon;
2791
0
  }
2792
0
  else
2793
0
  {
2794
0
    THROW( "Invalid search pattern" );
2795
0
  }
2796
2797
0
  int nBestDirect;
2798
0
  for ( uint32_t uiRound = 0; uiRound < uiMaxSearchRounds; uiRound++ )
2799
0
  {
2800
0
    Distortion roundZeroBestCost = MAX_DISTORTION;
2801
0
    const int positionLut[ 8 ] = { 0, 2, 4, 6, 1, 3, 5, 7 };
2802
0
    nBestDirect = -1;
2803
0
    MvField mvCurCenter = rCurMvField;
2804
0
    for ( int nIdx = nDirectStart; nIdx <= nDirectEnd; nIdx++ )
2805
0
    {
2806
      // terminate the search if none of the first four tested points hasn't provided improvement
2807
0
      if( m_pcEncCfg->m_SMVD > 1 && 2 == SearchPattern && 0 == uiRound && 4 == nIdx && roundZeroBestCost > uiMinCost )
2808
0
      {
2809
0
        break;
2810
0
      }
2811
0
      int nDirect;
2812
0
      if ( SearchPattern == 3 )
2813
0
      {
2814
0
        nDirect = nIdx < 0 ? nIdx + 6 : nIdx >= 6 ? nIdx - 6 : nIdx;
2815
0
      }
2816
0
      else
2817
0
      {
2818
0
        if( m_pcEncCfg->m_SMVD > 1 && 2 == SearchPattern && 0 == uiRound )
2819
0
        {
2820
0
          nDirect = positionLut[ ( nIdx + nDirectRounding ) & nDirectMask ];
2821
0
        }
2822
0
        else
2823
0
        {
2824
0
          nDirect = ( nIdx + nDirectRounding ) & nDirectMask;
2825
0
        }
2826
0
      }
2827
2828
0
      Mv mvOffset = pSearchOffset[nDirect];
2829
0
      mvOffset <<= nSearchStepShift;
2830
0
      MvField mvCand = mvCurCenter, mvPair;
2831
0
      mvCand.mv += mvOffset;
2832
0
      if( m_pcEncCfg->m_ifpLines && !CU::isMvInRangeFPP( cu.ly(), cu.lheight(), mvCand.mv.ver, m_pcEncCfg->m_ifpLines, *cu.cs->pcv ) )
2833
0
      {
2834
0
        continue; // Skip this pos
2835
0
      }
2836
2837
      // get MVD cost
2838
0
      Mv pred = rcMvCurPred;
2839
0
      pred.changeTransPrecInternal2Amvr(cu.imv);
2840
0
      m_pcRdCost->setPredictor( pred );
2841
0
      m_pcRdCost->setCostScale( 0 );
2842
0
      Mv mv = mvCand.mv;
2843
0
      mv.changeTransPrecInternal2Amvr(cu.imv);
2844
0
      uint32_t uiMvBits = m_pcRdCost->getBitsOfVectorWithPredictor( mv.hor, mv.ver, 0 );
2845
0
      Distortion uiCost = m_pcRdCost->getCost( uiMvBits );
2846
2847
      // get MVD pair and set target MV
2848
0
      mvPair.refIdx = rTarMvField.refIdx;
2849
0
      mvPair.mv.set( rcMvTarPred.hor - (mvCand.mv.hor - rcMvCurPred.hor), rcMvTarPred.ver - (mvCand.mv.ver - rcMvCurPred.ver) );
2850
2851
0
      if( m_pcEncCfg->m_ifpLines && !CU::isMvInRangeFPP( cu.ly(), cu.lheight(), mvPair.mv.ver, m_pcEncCfg->m_ifpLines, *cu.cs->pcv ) )
2852
0
      {
2853
0
        continue; // Skip this pos
2854
0
      }
2855
2856
0
      uiCost += xGetSymCost( cu, origBuf, refPicList, mvCand, mvPair, BcwIdx );
2857
0
      if ( uiCost < uiMinCost )
2858
0
      {
2859
0
        uiMinCost = uiCost;
2860
0
        rCurMvField = mvCand;
2861
0
        rTarMvField = mvPair;
2862
0
        nBestDirect = nDirect;
2863
0
      }
2864
0
      if ( m_pcEncCfg->m_SMVD > 1 && 2 == SearchPattern && 0 == uiRound && 4 > nIdx && uiCost < roundZeroBestCost)
2865
0
      {
2866
0
        roundZeroBestCost = uiCost;
2867
0
      }
2868
0
    }
2869
2870
0
    if ( nBestDirect == -1 )
2871
0
    {
2872
0
      break;
2873
0
    }
2874
0
    int nStep = 1;
2875
0
    if( (SearchPattern == 1 || SearchPattern == 2) && m_pcEncCfg->m_SMVD <= 1 )
2876
0
    {
2877
      // test at most 3 points in fast presets
2878
0
      nStep = 2 - ( nBestDirect & 0x01 );
2879
0
    }
2880
0
    nDirectStart = nBestDirect - nStep;
2881
0
    nDirectEnd = nBestDirect + nStep;
2882
0
  }
2883
2884
0
  return(uiMinCost);
2885
0
}
2886
2887
2888
void InterSearch::xSymMotionEstimation( CodingUnit& cu, CPelUnitBuf& origBuf, Mv& rcMvCurPred, Mv& rcMvTarPred, RefPicList refPicList, MvField& rCurMvField, MvField& rTarMvField, Distortion& ruiCost, int BcwIdx )
2889
0
{
2890
  // Refine Search
2891
0
  int nSearchStepShift = MV_FRACTIONAL_BITS_DIFF;
2892
0
  int nDiamondRound = 8;
2893
0
  int nCrossRound = 1;
2894
2895
0
  nSearchStepShift += cu.imv == IMV_HPEL ? 1 : (cu.imv << 1);
2896
0
  nDiamondRound >>= cu.imv;
2897
2898
0
  ruiCost = xSymRefineMvSearch( cu, origBuf, rcMvCurPred, rcMvTarPred, refPicList, rCurMvField, rTarMvField, ruiCost, 2, nSearchStepShift, nDiamondRound, BcwIdx );
2899
0
  if( m_pcEncCfg->m_SMVD < 3 )
2900
0
  {
2901
0
    ruiCost = xSymRefineMvSearch( cu, origBuf, rcMvCurPred, rcMvTarPred, refPicList, rCurMvField, rTarMvField, ruiCost, 0, nSearchStepShift, nCrossRound, BcwIdx );
2902
0
  }
2903
0
}
2904
2905
2906
/**
2907
* \brief Generate half-sample interpolated block
2908
*
2909
* \param pattern Reference picture ROI
2910
* \param biPred    Flag indicating whether block is for biprediction
2911
*/
2912
void InterSearch::xExtDIFUpSamplingH(CPelBuf* pattern, bool useAltHpelIf)
2913
0
{
2914
0
  PROFILER_SCOPE_AND_STAGE( 0, _TPROF, P_HPEL_INTERP );
2915
0
  const ClpRng& clpRng = m_lumaClpRng;
2916
0
  int width            = pattern->width;
2917
0
  int height           = pattern->height;
2918
0
  int srcStride        = pattern->stride;
2919
0
  const int reduceTap = m_pcEncCfg->m_meReduceTap;
2920
2921
0
  int intStride = width + 1;
2922
0
  int dstStride = width + 1;
2923
0
  Pel* intPtr;
2924
0
  Pel* dstPtr;
2925
0
  int filterSize     = useAltHpelIf ? ( reduceTap >= 1 ? NTAPS_AFFINE : NTAPS_LUMA )
2926
0
                                    : ( reduceTap == 1 ? NTAPS_AFFINE
2927
0
                                                       : ( reduceTap == 0 ? NTAPS_LUMA : NTAPS_CHROMA ) );
2928
0
  int halfFilterSize = ( filterSize >> 1 );
2929
0
  const Pel *srcPtr  = pattern->buf - halfFilterSize * srcStride - 1;
2930
2931
0
  const ChromaFormat chFmt = m_currChromaFormat;
2932
2933
  // split the prediction with funny widths into power-of-2 and +1 parts for the sake of SIMD speed-up
2934
0
  m_if.filterHor( COMP_Y, srcPtr,         srcStride, m_filteredBlockTmp[0][0]        , intStride, width, height + filterSize, 0 << MV_FRACTIONAL_BITS_DIFF, false, chFmt, clpRng, useAltHpelIf, 0, reduceTap );
2935
0
  m_if.filterHor( COMP_Y, srcPtr + width, srcStride, m_filteredBlockTmp[0][0] + width, intStride,     1, height + filterSize, 0 << MV_FRACTIONAL_BITS_DIFF, false, chFmt, clpRng, useAltHpelIf, 0, reduceTap );
2936
2937
  // split the prediction with funny widths into power-of-2 and +1 parts for the sake of SIMD speed-up
2938
0
  m_if.filterHor( COMP_Y, srcPtr,         srcStride, m_filteredBlockTmp[2][0],         intStride, width, height + filterSize, 2 << MV_FRACTIONAL_BITS_DIFF, false, chFmt, clpRng, useAltHpelIf, 0, reduceTap );
2939
0
  m_if.filterHor( COMP_Y, srcPtr + width, srcStride, m_filteredBlockTmp[2][0] + width, intStride,     1, height + filterSize, 2 << MV_FRACTIONAL_BITS_DIFF, false, chFmt, clpRng, useAltHpelIf, 0, reduceTap );
2940
2941
0
  intPtr = m_filteredBlockTmp[0][0] + halfFilterSize * intStride + 1;
2942
0
  dstPtr = m_filteredBlock[0][0][0];
2943
0
  m_if.filterVer( COMP_Y, intPtr, intStride, dstPtr, dstStride, width + 0, height + 0, 0 << MV_FRACTIONAL_BITS_DIFF, false, true, chFmt, clpRng, useAltHpelIf, 0, reduceTap );
2944
2945
0
  intPtr = m_filteredBlockTmp[0][0] + (halfFilterSize - 1) * intStride + 1;
2946
0
  dstPtr = m_filteredBlock[2][0][0];
2947
0
  m_if.filterVer( COMP_Y, intPtr, intStride, dstPtr, dstStride, width + 0, height + 1, 2 << MV_FRACTIONAL_BITS_DIFF, false, true, chFmt, clpRng, useAltHpelIf, 0, reduceTap );
2948
2949
0
  intPtr = m_filteredBlockTmp[2][0] + halfFilterSize * intStride;
2950
0
  dstPtr = m_filteredBlock[0][2][0];
2951
  // split the prediction with funny widths into power-of-2 and +1 parts for the sake of SIMD speed-up
2952
0
  m_if.filterVer( COMP_Y, intPtr,         intStride, dstPtr,         dstStride, width, height + 0, 0 << MV_FRACTIONAL_BITS_DIFF, false, true, chFmt, clpRng, useAltHpelIf, 0, reduceTap );
2953
0
  m_if.filterVer( COMP_Y, intPtr + width, intStride, dstPtr + width, dstStride,     1, height + 0, 0 << MV_FRACTIONAL_BITS_DIFF, false, true, chFmt, clpRng, useAltHpelIf, 0, reduceTap );
2954
2955
0
  intPtr = m_filteredBlockTmp[2][0] + (halfFilterSize - 1) * intStride;
2956
0
  dstPtr = m_filteredBlock[2][2][0];
2957
  // split the prediction with funny widths into power-of-2 and +1 parts for the sake of SIMD speed-up
2958
0
  m_if.filterVer( COMP_Y, intPtr,         intStride, dstPtr,         dstStride, width, height + 1, 2 << MV_FRACTIONAL_BITS_DIFF, false, true, chFmt, clpRng, useAltHpelIf, 0, reduceTap );
2959
0
  m_if.filterVer( COMP_Y, intPtr + width, intStride, dstPtr + width, dstStride,     1, height + 1, 2 << MV_FRACTIONAL_BITS_DIFF, false, true, chFmt, clpRng, useAltHpelIf, 0, reduceTap );
2960
0
}
2961
2962
2963
2964
2965
2966
/**
2967
* \brief Generate quarter-sample interpolated blocks
2968
*
2969
* \param pattern    Reference picture ROI
2970
* \param halfPelRef Half-pel mv
2971
* \param biPred     Flag indicating whether block is for biprediction
2972
*/
2973
void InterSearch::xExtDIFUpSamplingQ( CPelBuf* pattern, Mv halfPelRef, int& patternId )
2974
0
{
2975
0
  PROFILER_SCOPE_AND_STAGE( 0, _TPROF, P_QPEL_INTERP );
2976
0
  const ClpRng& clpRng = m_lumaClpRng;
2977
0
  int width      = pattern->width;
2978
0
  int height     = pattern->height;
2979
0
  int srcStride  = pattern->stride;
2980
0
  const int reduceTap = m_pcEncCfg->m_meReduceTap;
2981
2982
0
  Pel const* srcPtr;
2983
0
  int intStride = width + 1;
2984
0
  int dstStride = width + 1;
2985
0
  Pel* intPtr;
2986
0
  Pel* dstPtr;
2987
2988
0
  int filterSize     = reduceTap == 1 ? NTAPS_AFFINE
2989
0
                   : ( reduceTap == 0 ? NTAPS_LUMA : NTAPS_CHROMA );
2990
2991
0
  int halfFilterSize = (filterSize>>1);
2992
2993
0
  int extHeight = (halfPelRef.ver == 0) ? height + filterSize : height + filterSize-1;
2994
2995
0
  const ChromaFormat chFmt = m_currChromaFormat;
2996
2997
0
  if( s_doInterpQ[ patternId ][ 12 ] )
2998
0
  {
2999
    // Horizontal filter 1/4
3000
0
    srcPtr = pattern->buf - halfFilterSize * srcStride - 1;
3001
0
    intPtr = m_filteredBlockTmp[ 1 ][ 0 ];
3002
0
    if( halfPelRef.ver > 0 )
3003
0
    {
3004
0
      srcPtr += srcStride;
3005
0
    }
3006
0
    if( halfPelRef.hor >= 0 )
3007
0
    {
3008
0
      srcPtr += 1;
3009
0
    }
3010
0
    m_if.filterHor( COMP_Y, srcPtr, srcStride, intPtr, intStride, width, extHeight, 1 << MV_FRACTIONAL_BITS_DIFF, false, chFmt, clpRng, false, 0, reduceTap );
3011
0
  }
3012
3013
0
  if( s_doInterpQ[ patternId ][ 13 ] )
3014
0
  {
3015
    // Horizontal filter 3/4
3016
0
    srcPtr = pattern->buf - halfFilterSize*srcStride - 1;
3017
0
    intPtr = m_filteredBlockTmp[ 3 ][ 0 ];
3018
0
    if( halfPelRef.ver > 0 )
3019
0
    {
3020
0
      srcPtr += srcStride;
3021
0
    }
3022
0
    if( halfPelRef.hor > 0 )
3023
0
    {
3024
0
      srcPtr += 1;
3025
0
    }
3026
0
    m_if.filterHor( COMP_Y, srcPtr, srcStride, intPtr, intStride, width, extHeight, 3 << MV_FRACTIONAL_BITS_DIFF, false, chFmt, clpRng, false, 0, reduceTap );
3027
0
  }
3028
3029
0
  if( s_doInterpQ[ patternId ][ 3 ] )
3030
0
  {
3031
    // Generate @ 1,1
3032
0
    intPtr = m_filteredBlockTmp[ 1 ][ 0 ] + ( halfFilterSize - 1 ) * intStride;
3033
0
    dstPtr = m_filteredBlock[ 1 ][ 1 ][ 0 ];
3034
0
    if( halfPelRef.ver == 0 )
3035
0
    {
3036
0
      intPtr += intStride;
3037
0
    }
3038
0
    m_if.filterVer( COMP_Y, intPtr, intStride, dstPtr, dstStride, width, height, 1 << MV_FRACTIONAL_BITS_DIFF, false, true, chFmt, clpRng, false, 0, reduceTap );
3039
0
  }
3040
3041
0
  if( s_doInterpQ[ patternId ][ 11 ] )
3042
0
  {
3043
    // Generate @ 3,3
3044
0
    intPtr = m_filteredBlockTmp[ 3 ][ 0 ] + ( halfFilterSize - 1 ) * intStride;
3045
0
    dstPtr = m_filteredBlock[ 3 ][ 3 ][ 0 ];
3046
0
    m_if.filterVer( COMP_Y, intPtr, intStride, dstPtr, dstStride, width, height, 3 << MV_FRACTIONAL_BITS_DIFF, false, true, chFmt, clpRng, false, 0, reduceTap );
3047
0
  }
3048
3049
0
  if( s_doInterpQ[ patternId ][ 5 ] )
3050
0
  {
3051
    // Generate @ 3,1
3052
0
    intPtr = m_filteredBlockTmp[ 1 ][ 0 ] + ( halfFilterSize - 1 ) * intStride;
3053
0
    dstPtr = m_filteredBlock[ 3 ][ 1 ][ 0 ];
3054
0
    m_if.filterVer( COMP_Y, intPtr, intStride, dstPtr, dstStride, width, height, 3 << MV_FRACTIONAL_BITS_DIFF, false, true, chFmt, clpRng, false, 0, reduceTap );
3055
0
  }
3056
3057
0
  if( s_doInterpQ[ patternId ][ 9 ] )
3058
0
  {
3059
    // Generate @ 1,3
3060
0
    intPtr = m_filteredBlockTmp[ 3 ][ 0 ] + ( halfFilterSize - 1 ) * intStride;
3061
0
    dstPtr = m_filteredBlock[ 1 ][ 3 ][ 0 ];
3062
0
    if( halfPelRef.ver == 0 )
3063
0
    {
3064
0
      intPtr += intStride;
3065
0
    }
3066
0
    m_if.filterVer( COMP_Y, intPtr, intStride, dstPtr, dstStride, width, height, 1 << MV_FRACTIONAL_BITS_DIFF, false, true, chFmt, clpRng, false, 0, reduceTap );
3067
0
  }
3068
3069
0
  if (halfPelRef.ver != 0)
3070
0
  {
3071
0
    if( s_doInterpQ[ patternId ][ 4 ] )
3072
0
    {
3073
      // Generate @ 2,1
3074
0
      intPtr = m_filteredBlockTmp[ 1 ][ 0 ] + ( halfFilterSize - 1 ) * intStride;
3075
0
      dstPtr = m_filteredBlock[ 2 ][ 1 ][ 0 ];
3076
0
      if( halfPelRef.ver == 0 )
3077
0
      {
3078
0
        intPtr += intStride;
3079
0
      }
3080
0
      m_if.filterVer( COMP_Y, intPtr, intStride, dstPtr, dstStride, width, height, 2 << MV_FRACTIONAL_BITS_DIFF, false, true, chFmt, clpRng, false, 0, reduceTap );
3081
0
    }
3082
3083
0
    if( s_doInterpQ[ patternId ][ 10 ] )
3084
0
    {
3085
      // Generate @ 2,3
3086
0
      intPtr = m_filteredBlockTmp[ 3 ][ 0 ] + ( halfFilterSize - 1 ) * intStride;
3087
0
      dstPtr = m_filteredBlock[ 2 ][ 3 ][ 0 ];
3088
0
      if( halfPelRef.ver == 0 )
3089
0
      {
3090
0
        intPtr += intStride;
3091
0
      }
3092
0
      m_if.filterVer( COMP_Y, intPtr, intStride, dstPtr, dstStride, width, height, 2 << MV_FRACTIONAL_BITS_DIFF, false, true, chFmt, clpRng, false, 0, reduceTap );
3093
0
    }
3094
0
  }
3095
0
  else
3096
0
  {
3097
0
    if( s_doInterpQ[ patternId ][ 2 ] )
3098
0
    {
3099
      // Generate @ 0,1
3100
0
      intPtr = m_filteredBlockTmp[ 1 ][ 0 ] + halfFilterSize * intStride;
3101
0
      dstPtr = m_filteredBlock[ 0 ][ 1 ][ 0 ];
3102
0
      m_if.filterVer( COMP_Y, intPtr, intStride, dstPtr, dstStride, width, height, 0 << MV_FRACTIONAL_BITS_DIFF, false, true, chFmt, clpRng, false, 0, reduceTap );
3103
0
    }
3104
3105
0
    if( s_doInterpQ[ patternId ][ 8 ] )
3106
0
    {
3107
      // Generate @ 0,3
3108
0
      intPtr = m_filteredBlockTmp[ 3 ][ 0 ] + halfFilterSize * intStride;
3109
0
      dstPtr = m_filteredBlock[ 0 ][ 3 ][ 0 ];
3110
0
      m_if.filterVer( COMP_Y, intPtr, intStride, dstPtr, dstStride, width, height, 0 << MV_FRACTIONAL_BITS_DIFF, false, true, chFmt, clpRng, false, 0, reduceTap );
3111
0
    }
3112
0
  }
3113
3114
0
  if (halfPelRef.hor != 0)
3115
0
  {
3116
0
    if( s_doInterpQ[ patternId ][ 6 ] )
3117
0
    {
3118
      // Generate @ 1,2
3119
0
      intPtr = m_filteredBlockTmp[ 2 ][ 0 ] + ( halfFilterSize - 1 ) * intStride;
3120
0
      dstPtr = m_filteredBlock[ 1 ][ 2 ][ 0 ];
3121
0
      if( halfPelRef.hor > 0 )
3122
0
      {
3123
0
        intPtr += 1;
3124
0
      }
3125
0
      if( halfPelRef.ver >= 0 )
3126
0
      {
3127
0
        intPtr += intStride;
3128
0
      }
3129
0
      m_if.filterVer( COMP_Y, intPtr, intStride, dstPtr, dstStride, width, height, 1 << MV_FRACTIONAL_BITS_DIFF, false, true, chFmt, clpRng, false, 0, reduceTap );
3130
0
    }
3131
3132
0
    if( s_doInterpQ[ patternId ][ 7 ] )
3133
0
    {
3134
      // Generate @ 3,2
3135
0
      intPtr = m_filteredBlockTmp[ 2 ][ 0 ] + ( halfFilterSize - 1 ) * intStride;
3136
0
      dstPtr = m_filteredBlock[ 3 ][ 2 ][ 0 ];
3137
0
      if( halfPelRef.hor > 0 )
3138
0
      {
3139
0
        intPtr += 1;
3140
0
      }
3141
0
      if( halfPelRef.ver > 0 )
3142
0
      {
3143
0
        intPtr += intStride;
3144
0
      }
3145
0
      m_if.filterVer( COMP_Y, intPtr, intStride, dstPtr, dstStride, width, height, 3 << MV_FRACTIONAL_BITS_DIFF, false, true, chFmt, clpRng, false, 0, reduceTap );
3146
0
    }
3147
0
  }
3148
0
  else
3149
0
  {
3150
0
    if( s_doInterpQ[ patternId ][ 0 ] )
3151
0
    {
3152
      // Generate @ 1,0
3153
0
      intPtr = m_filteredBlockTmp[ 0 ][ 0 ] + ( halfFilterSize - 1 ) * intStride + 1;
3154
0
      dstPtr = m_filteredBlock[ 1 ][ 0 ][ 0 ];
3155
0
      if( halfPelRef.ver >= 0 )
3156
0
      {
3157
0
        intPtr += intStride;
3158
0
      }
3159
0
      m_if.filterVer( COMP_Y, intPtr, intStride, dstPtr, dstStride, width, height, 1 << MV_FRACTIONAL_BITS_DIFF, false, true, chFmt, clpRng, false, 0, reduceTap );
3160
0
    }
3161
3162
0
    if( s_doInterpQ[ patternId ][ 1 ] )
3163
0
    {
3164
      // Generate @ 3,0
3165
0
      intPtr = m_filteredBlockTmp[ 0 ][ 0 ] + ( halfFilterSize - 1 ) * intStride + 1;
3166
0
      dstPtr = m_filteredBlock[ 3 ][ 0 ][ 0 ];
3167
0
      if( halfPelRef.ver > 0 )
3168
0
      {
3169
0
        intPtr += intStride;
3170
0
      }
3171
0
      m_if.filterVer( COMP_Y, intPtr, intStride, dstPtr, dstStride, width, height, 3 << MV_FRACTIONAL_BITS_DIFF, false, true, chFmt, clpRng, false, 0, reduceTap );
3172
0
    }
3173
0
  }
3174
0
}
3175
3176
3177
void InterSearch::xEncodeInterResidualQT(CodingStructure &cs, Partitioner &partitioner, const ComponentID compID)
3178
0
{
3179
0
  const UnitArea& currArea    = partitioner.currArea();
3180
0
  const TransformUnit& currTU = *cs.getTU(isLuma(partitioner.chType) ? currArea.lumaPos() : currArea.chromaPos(), partitioner.chType);
3181
0
  const CodingUnit &cu        = *currTU.cu;
3182
0
  const unsigned currDepth    = partitioner.currTrDepth;
3183
3184
0
  const bool bSubdiv          = currDepth != currTU.depth;
3185
3186
0
  if (compID == MAX_NUM_TBLOCKS)  // we are not processing a channel, instead we always recurse and code the CBFs
3187
0
  {
3188
0
    if( partitioner.canSplit( TU_MAX_TR_SPLIT, cs ) )
3189
0
    {
3190
0
      CHECK( !bSubdiv, "Not performing the implicit TU split" );
3191
0
    }
3192
0
    else if( cu.sbtInfo && partitioner.canSplit( CU::getSbtTuSplit( cu.sbtInfo ), cs ) )
3193
0
    {
3194
0
      CHECK( !bSubdiv, "Not performing the implicit TU split - sbt" );
3195
0
    }
3196
0
    else
3197
0
    {
3198
0
      CHECK( bSubdiv, "transformsplit not supported" );
3199
0
    }
3200
3201
0
    CHECK(CU::isIntra(cu), "Inter search provided with intra CU");
3202
3203
0
    if( cu.chromaFormat != CHROMA_400
3204
0
      && (!CU::isSepTree(cu) || isChroma(partitioner.chType))
3205
0
      )
3206
0
    {
3207
0
      {
3208
0
        {
3209
0
          const bool  chroma_cbf = TU::getCbfAtDepth( currTU, COMP_Cb, currDepth );
3210
0
          if (!(cu.sbtInfo && (currDepth == 0 || (currDepth == 1 && currTU.noResidual))))
3211
0
          m_CABACEstimator->cbf_comp( cu, chroma_cbf, currArea.blocks[COMP_Cb], currDepth );
3212
0
        }
3213
0
        {
3214
0
          const bool  chroma_cbf = TU::getCbfAtDepth( currTU, COMP_Cr, currDepth );
3215
0
          if (!(cu.sbtInfo && (currDepth == 0 || (currDepth == 1 && currTU.noResidual))))
3216
0
          m_CABACEstimator->cbf_comp( cu, chroma_cbf, currArea.blocks[COMP_Cr], currDepth, TU::getCbfAtDepth( currTU, COMP_Cb, currDepth ) );
3217
0
        }
3218
0
      }
3219
0
    }
3220
3221
0
    if( !bSubdiv && !( cu.sbtInfo && currTU.noResidual )
3222
0
      && !isChroma(partitioner.chType)
3223
0
      )
3224
0
    {
3225
0
      m_CABACEstimator->cbf_comp( cu, TU::getCbfAtDepth( currTU, COMP_Y, currDepth ), currArea.Y(), currDepth );
3226
0
    }
3227
0
  }
3228
3229
0
  if (!bSubdiv)
3230
0
  {
3231
0
    if (compID != MAX_NUM_TBLOCKS) // we have already coded the CBFs, so now we code coefficients
3232
0
    {
3233
0
      if( currArea.blocks[compID].valid() )
3234
0
      {
3235
0
        if( compID == COMP_Cr )
3236
0
        {
3237
0
          const int cbfMask = ( TU::getCbf( currTU, COMP_Cb ) ? 2 : 0) + ( TU::getCbf( currTU, COMP_Cr ) ? 1 : 0 );
3238
0
          m_CABACEstimator->joint_cb_cr( currTU, cbfMask );
3239
0
        }
3240
0
        if( TU::getCbf( currTU, compID ) )
3241
0
        {
3242
0
          m_CABACEstimator->residual_coding( currTU, compID );
3243
0
        }
3244
0
      }
3245
0
    }
3246
0
  }
3247
0
  else
3248
0
  {
3249
0
    if( compID == MAX_NUM_TBLOCKS || TU::getCbfAtDepth( currTU, compID, currDepth ) )
3250
0
    {
3251
0
      if( partitioner.canSplit( TU_MAX_TR_SPLIT, cs ) )
3252
0
      {
3253
0
        partitioner.splitCurrArea( TU_MAX_TR_SPLIT, cs );
3254
0
      }
3255
0
      else if( cu.sbtInfo && partitioner.canSplit( CU::getSbtTuSplit( cu.sbtInfo ), cs ) )
3256
0
      {
3257
0
        partitioner.splitCurrArea( CU::getSbtTuSplit( cu.sbtInfo ), cs );
3258
0
      }
3259
0
      else
3260
0
        THROW( "Implicit TU split not available!" );
3261
3262
0
      do
3263
0
      {
3264
0
        xEncodeInterResidualQT( cs, partitioner, compID );
3265
0
      } while( partitioner.nextPart( cs ) );
3266
3267
0
      partitioner.exitCurrSplit();
3268
0
    }
3269
0
  }
3270
0
}
3271
3272
void InterSearch::xCalcMinDistSbt( CodingStructure &cs, const CodingUnit& cu, const uint8_t sbtAllowed )
3273
0
{
3274
0
  if( !sbtAllowed )
3275
0
  {
3276
0
    m_estMinDistSbt[NUMBER_SBT_MODE] = 0;
3277
0
    for( int comp = 0; comp < getNumberValidTBlocks( *cs.pcv ); comp++ )
3278
0
    {
3279
0
      const ComponentID compID = ComponentID( comp );
3280
0
      CPelBuf pred = cs.getPredBuf( compID );
3281
0
      CPelBuf org  = cs.getOrgBuf( compID );
3282
0
      m_estMinDistSbt[NUMBER_SBT_MODE] += m_pcRdCost->getDistPart( org, pred, cs.sps->bitDepths[ toChannelType( compID ) ], compID, DF_SSE );
3283
0
    }
3284
0
    return;
3285
0
  }
3286
3287
  //SBT fast algorithm 2.1 : estimate a minimum RD cost of a SBT mode based on the luma distortion of uncoded part and coded part (assuming distorted can be reduced to 1/16);
3288
  //                         if this cost is larger than the best cost, no need to try a specific SBT mode
3289
0
  int cuWidth  = cu.lwidth();
3290
0
  int cuHeight = cu.lheight();
3291
0
  int numPartX = cuWidth  >= 16 ? 4 : ( cuWidth  == 4 ? 1 : 2 );
3292
0
  int numPartY = cuHeight >= 16 ? 4 : ( cuHeight == 4 ? 1 : 2 );
3293
0
  Distortion dist[4][4];
3294
0
  memset( dist, 0, sizeof( Distortion ) * 16 );
3295
3296
0
  for( uint32_t c = 0; c < getNumberValidTBlocks( *cs.pcv ); c++ )
3297
0
  {
3298
0
    const ComponentID compID   = ComponentID( c );
3299
0
    const CompArea&   compArea = cu.blocks[compID];
3300
0
    const CPelBuf orgPel  = cs.getOrgBuf( compArea );
3301
0
    const CPelBuf predPel = cs.getPredBuf( compArea );
3302
0
    int lengthX = compArea.width / numPartX;
3303
0
    int lengthY = compArea.height / numPartY;
3304
0
    int strideOrg  = orgPel.stride;
3305
0
    int stridePred = predPel.stride;
3306
0
    uint32_t   uiShift = DISTORTION_PRECISION_ADJUSTMENT( ( *cs.sps.bitDepths[ toChannelType( compID ) ] - 8 ) << 1 );
3307
0
    Intermediate_Int iTemp;
3308
3309
    //calc distY of 16 sub parts
3310
0
    for( int j = 0; j < numPartY; j++ )
3311
0
    {
3312
0
      for( int i = 0; i < numPartX; i++ )
3313
0
      {
3314
0
        int posX = i * lengthX;
3315
0
        int posY = j * lengthY;
3316
0
        const Pel* ptrOrg  = orgPel.bufAt( posX, posY );
3317
0
        const Pel* ptrPred = predPel.bufAt( posX, posY );
3318
0
        Distortion uiSum = 0;
3319
0
        for( int n = 0; n < lengthY; n++ )
3320
0
        {
3321
0
          for( int m = 0; m < lengthX; m++ )
3322
0
          {
3323
0
            iTemp = ptrOrg[m] - ptrPred[m];
3324
0
            uiSum += Distortion( ( iTemp * iTemp ) >> uiShift );
3325
0
          }
3326
0
          ptrOrg += strideOrg;
3327
0
          ptrPred += stridePred;
3328
0
        }
3329
0
        if( isChroma( compID ) )
3330
0
        {
3331
0
          uiSum = (Distortion)( uiSum * m_pcRdCost->getChromaWeight() );
3332
0
        }
3333
0
        dist[j][i] += uiSum;
3334
0
      }
3335
0
    }
3336
0
  }
3337
3338
  //SSE of a CU
3339
0
  m_estMinDistSbt[NUMBER_SBT_MODE] = 0;
3340
0
  for( int j = 0; j < numPartY; j++ )
3341
0
  {
3342
0
    for( int i = 0; i < numPartX; i++ )
3343
0
    {
3344
0
      m_estMinDistSbt[NUMBER_SBT_MODE] += dist[j][i];
3345
0
    }
3346
0
  }
3347
  //init per-mode dist
3348
0
  for( int i = SBT_VER_H0; i < NUMBER_SBT_MODE; i++ )
3349
0
  {
3350
0
    m_estMinDistSbt[i] = MAX_DISTORTION;
3351
0
  }
3352
3353
  //SBT fast algorithm 1: not try SBT if the residual is too small to compensate bits for encoding residual info
3354
0
  uint64_t minNonZeroResiFracBits = 12 << SCALE_BITS;
3355
0
  if( m_pcRdCost->calcRdCost( 0, m_estMinDistSbt[NUMBER_SBT_MODE] ) < m_pcRdCost->calcRdCost( minNonZeroResiFracBits, 0 ) )
3356
0
  {
3357
0
    m_skipSbtAll = true;
3358
0
    return;
3359
0
  }
3360
3361
  //derive estimated minDist of SBT = zero-residual part distortion + non-zero residual part distortion / 16
3362
0
  int shift = 5;
3363
0
  Distortion distResiPart = 0, distNoResiPart = 0;
3364
3365
0
  if( CU::targetSbtAllowed( SBT_VER_HALF, sbtAllowed ) )
3366
0
  {
3367
0
    int offsetResiPart = 0;
3368
0
    int offsetNoResiPart = numPartX / 2;
3369
0
    distResiPart = distNoResiPart = 0;
3370
0
    assert( numPartX >= 2 );
3371
0
    for( int j = 0; j < numPartY; j++ )
3372
0
    {
3373
0
      for( int i = 0; i < numPartX / 2; i++ )
3374
0
      {
3375
0
        distResiPart   += dist[j][i + offsetResiPart];
3376
0
        distNoResiPart += dist[j][i + offsetNoResiPart];
3377
0
      }
3378
0
    }
3379
0
    m_estMinDistSbt[SBT_VER_H0] = ( distResiPart >> shift ) + distNoResiPart;
3380
0
    m_estMinDistSbt[SBT_VER_H1] = ( distNoResiPart >> shift ) + distResiPart;
3381
0
  }
3382
3383
0
  if( CU::targetSbtAllowed( SBT_HOR_HALF, sbtAllowed ) )
3384
0
  {
3385
0
    int offsetResiPart = 0;
3386
0
    int offsetNoResiPart = numPartY / 2;
3387
0
    assert( numPartY >= 2 );
3388
0
    distResiPart = distNoResiPart = 0;
3389
0
    for( int j = 0; j < numPartY / 2; j++ )
3390
0
    {
3391
0
      for( int i = 0; i < numPartX; i++ )
3392
0
      {
3393
0
        distResiPart   += dist[j + offsetResiPart][i];
3394
0
        distNoResiPart += dist[j + offsetNoResiPart][i];
3395
0
      }
3396
0
    }
3397
0
    m_estMinDistSbt[SBT_HOR_H0] = ( distResiPart >> shift ) + distNoResiPart;
3398
0
    m_estMinDistSbt[SBT_HOR_H1] = ( distNoResiPart >> shift ) + distResiPart;
3399
0
  }
3400
3401
0
  if( CU::targetSbtAllowed( SBT_VER_QUAD, sbtAllowed ) )
3402
0
  {
3403
0
    assert( numPartX == 4 );
3404
0
    m_estMinDistSbt[SBT_VER_Q0] = m_estMinDistSbt[SBT_VER_Q1] = 0;
3405
0
    for( int j = 0; j < numPartY; j++ )
3406
0
    {
3407
0
      m_estMinDistSbt[SBT_VER_Q0] += dist[j][0] + ( ( dist[j][1] + dist[j][2] + dist[j][3] ) << shift );
3408
0
      m_estMinDistSbt[SBT_VER_Q1] += dist[j][3] + ( ( dist[j][0] + dist[j][1] + dist[j][2] ) << shift );
3409
0
    }
3410
0
    m_estMinDistSbt[SBT_VER_Q0] = m_estMinDistSbt[SBT_VER_Q0] >> shift;
3411
0
    m_estMinDistSbt[SBT_VER_Q1] = m_estMinDistSbt[SBT_VER_Q1] >> shift;
3412
0
  }
3413
3414
0
  if( CU::targetSbtAllowed( SBT_HOR_QUAD, sbtAllowed ) )
3415
0
  {
3416
0
    assert( numPartY == 4 );
3417
0
    m_estMinDistSbt[SBT_HOR_Q0] = m_estMinDistSbt[SBT_HOR_Q1] = 0;
3418
0
    for( int i = 0; i < numPartX; i++ )
3419
0
    {
3420
0
      m_estMinDistSbt[SBT_HOR_Q0] += dist[0][i] + ( ( dist[1][i] + dist[2][i] + dist[3][i] ) << shift );
3421
0
      m_estMinDistSbt[SBT_HOR_Q1] += dist[3][i] + ( ( dist[0][i] + dist[1][i] + dist[2][i] ) << shift );
3422
0
    }
3423
0
    m_estMinDistSbt[SBT_HOR_Q0] = m_estMinDistSbt[SBT_HOR_Q0] >> shift;
3424
0
    m_estMinDistSbt[SBT_HOR_Q1] = m_estMinDistSbt[SBT_HOR_Q1] >> shift;
3425
0
  }
3426
3427
  //SBT fast algorithm 5: try N SBT modes with the lowest distortion
3428
0
  Distortion temp[NUMBER_SBT_MODE];
3429
0
  memcpy( temp, m_estMinDistSbt, sizeof( Distortion ) * NUMBER_SBT_MODE );
3430
0
  memset( m_sbtRdoOrder, 255, NUMBER_SBT_MODE );
3431
0
  int startIdx = 0, numRDO;
3432
0
  numRDO = CU::targetSbtAllowed( SBT_VER_HALF, sbtAllowed ) + CU::targetSbtAllowed( SBT_HOR_HALF, sbtAllowed );
3433
0
  numRDO = std::min( ( numRDO << 1 ), SBT_NUM_RDO );
3434
0
  for( int i = startIdx; i < startIdx + numRDO; i++ )
3435
0
  {
3436
0
    Distortion minDist = MAX_DISTORTION;
3437
0
    for( int n = SBT_VER_H0; n <= SBT_HOR_H1; n++ )
3438
0
    {
3439
0
      if( temp[n] < minDist )
3440
0
      {
3441
0
        minDist = temp[n];
3442
0
        m_sbtRdoOrder[i] = n;
3443
0
      }
3444
0
    }
3445
0
    temp[m_sbtRdoOrder[i]] = MAX_DISTORTION;
3446
0
  }
3447
3448
0
  startIdx += numRDO;
3449
0
  numRDO = CU::targetSbtAllowed( SBT_VER_QUAD, sbtAllowed ) + CU::targetSbtAllowed( SBT_HOR_QUAD, sbtAllowed );
3450
0
  numRDO = std::min( ( numRDO << 1 ), SBT_NUM_RDO );
3451
0
  for( int i = startIdx; i < startIdx + numRDO; i++ )
3452
0
  {
3453
0
    Distortion minDist = MAX_DISTORTION;
3454
0
    for( int n = SBT_VER_Q0; n <= SBT_HOR_Q1; n++ )
3455
0
    {
3456
0
      if( temp[n] < minDist )
3457
0
      {
3458
0
        minDist = temp[n];
3459
0
        m_sbtRdoOrder[i] = n;
3460
0
      }
3461
0
    }
3462
0
    temp[m_sbtRdoOrder[i]] = MAX_DISTORTION;
3463
0
  }
3464
0
}
3465
3466
uint8_t InterSearch::skipSbtByRDCost( int width, int height, int mtDepth, uint8_t sbtIdx, uint8_t sbtPos, double bestCost, Distortion distSbtOff, double costSbtOff, bool rootCbfSbtOff )
3467
0
{
3468
0
  int sbtMode = CU::getSbtMode( sbtIdx, sbtPos );
3469
3470
  //SBT fast algorithm 2.2 : estimate a minimum RD cost of a SBT mode based on the luma distortion of uncoded part and coded part (assuming distorted can be reduced to 1/16);
3471
  //                         if this cost is larger than the best cost, no need to try a specific SBT mode
3472
0
  if( m_pcRdCost->calcRdCost( 11 << SCALE_BITS, m_estMinDistSbt[sbtMode] ) > bestCost )
3473
0
  {
3474
0
    return 0; //early skip type 0
3475
0
  }
3476
3477
0
  if( costSbtOff != MAX_DOUBLE )
3478
0
  {
3479
0
    if( !rootCbfSbtOff )
3480
0
    {
3481
      //SBT fast algorithm 3: skip SBT when the residual is too small (estCost is more accurate than fast algorithm 1, counting PU mode bits)
3482
0
      uint64_t minNonZeroResiFracBits = 10 << SCALE_BITS;
3483
0
      Distortion distResiPart;
3484
0
      if( sbtIdx == SBT_VER_HALF || sbtIdx == SBT_HOR_HALF )
3485
0
      {
3486
0
        distResiPart = (Distortion)( ( ( m_estMinDistSbt[NUMBER_SBT_MODE] - m_estMinDistSbt[sbtMode] ) * 9 ) >> 4 );
3487
0
      }
3488
0
      else
3489
0
      {
3490
0
        distResiPart = (Distortion)( ( ( m_estMinDistSbt[NUMBER_SBT_MODE] - m_estMinDistSbt[sbtMode] ) * 3 ) >> 3 );
3491
0
      }
3492
3493
0
      double estCost = ( costSbtOff - m_pcRdCost->calcRdCost( 0 << SCALE_BITS, distSbtOff ) ) + m_pcRdCost->calcRdCost( minNonZeroResiFracBits, m_estMinDistSbt[sbtMode] + distResiPart );
3494
0
      if( estCost > costSbtOff )
3495
0
      {
3496
0
        return 1;
3497
0
      }
3498
0
      if( estCost > bestCost )
3499
0
      {
3500
0
        return 2;
3501
0
      }
3502
0
    }
3503
0
    else
3504
0
    {
3505
      //SBT fast algorithm 4: skip SBT when an estimated RD cost is larger than the bestCost
3506
0
      double weight = sbtMode > SBT_HOR_H1 ? 0.4 : 0.6;
3507
0
      double estCost = ( ( costSbtOff - m_pcRdCost->calcRdCost( 0 << SCALE_BITS, distSbtOff ) ) * weight ) + m_pcRdCost->calcRdCost( 0 << SCALE_BITS, m_estMinDistSbt[sbtMode] );
3508
0
      if( estCost > bestCost )
3509
0
      {
3510
0
        return 3;
3511
0
      }
3512
0
    }
3513
0
  }
3514
0
  return MAX_UCHAR;
3515
0
}
3516
3517
void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &partitioner, Distortion *puiZeroDist /*= NULL*/)
3518
22.7k
{
3519
22.7k
  const UnitArea& currArea = partitioner.currArea();
3520
22.7k
  const SPS &sps           = *cs.sps;
3521
3522
22.7k
  const uint32_t numValidComp  = getNumberValidComponents( sps.chromaFormatIdc );
3523
22.7k
  const uint32_t numTBlocks    = getNumberValidTBlocks   ( *cs.pcv );
3524
22.7k
  CodingUnit& cu               = *cs.getCU(partitioner.chType, partitioner.treeType);
3525
22.7k
  const unsigned currDepth = partitioner.currTrDepth;
3526
22.7k
  const bool useTS = cs.picture->useTS;
3527
3528
22.7k
  bool bCheckFull  = !partitioner.canSplit( TU_MAX_TR_SPLIT, cs );
3529
22.7k
  if( cu.sbtInfo && partitioner.canSplit( CU::getSbtTuSplit( cu.sbtInfo ), cs ) )
3530
0
  {
3531
0
    bCheckFull = false;
3532
0
  }
3533
22.7k
  bool bCheckSplit = !bCheckFull;
3534
3535
  // get temporary data
3536
22.7k
  CodingStructure *csSplit = nullptr;
3537
22.7k
  CodingStructure *csFull  = nullptr;
3538
22.7k
  if (bCheckSplit)
3539
0
  {
3540
0
    csSplit = &cs;
3541
0
  }
3542
22.7k
  else if (bCheckFull)
3543
22.7k
  {
3544
22.7k
    csFull = &cs;
3545
22.7k
  }
3546
3547
22.7k
  Distortion uiSingleDist         = 0;
3548
22.7k
  Distortion uiSingleDistComp [3] = { 0, 0, 0 };
3549
3550
22.7k
  const TempCtx ctxStart  ( m_CtxCache, m_CABACEstimator->getCtx() );
3551
22.7k
  TempCtx       ctxBest   ( m_CtxCache );
3552
3553
22.7k
  PelUnitBuf    orgResiBuf;
3554
22.7k
  orgResiBuf = m_tmpStorageLCU.getCompactBuf( currArea );
3555
22.7k
  orgResiBuf.copyFrom(cs.getResiBuf(currArea));
3556
3557
22.7k
  if (bCheckFull)
3558
22.7k
  {
3559
22.7k
    TransformUnit& tu = csFull->addTU(CS::getArea(cs, currArea, partitioner.chType, partitioner.treeType), partitioner.chType, &cu);
3560
22.7k
    tu.depth          = currDepth;
3561
22.7k
    tu.mtsIdx[COMP_Y] = MTS_DCT2_DCT2;
3562
22.7k
    tu.checkTuNoResidual( partitioner.currPartIdx() );
3563
3564
22.7k
    double minCost [MAX_NUM_TBLOCKS];
3565
3566
22.7k
    m_CABACEstimator->resetBits();
3567
3568
22.7k
    memset(m_pTempPel, 0, sizeof(Pel) * tu.Y().area()); // not necessary needed for inside of recursion (only at the beginning)
3569
3570
91.0k
    for (uint32_t i = 0; i < numTBlocks; i++)
3571
68.2k
    {
3572
68.2k
      minCost[i] = MAX_DOUBLE;
3573
68.2k
    }
3574
3575
22.7k
    CodingStructure &saveCS = *m_pSaveCS[1];
3576
22.7k
    saveCS.pcv     = cs.pcv;
3577
22.7k
    saveCS.picture = cs.picture;
3578
22.7k
    saveCS.area.repositionTo( currArea );
3579
3580
22.7k
    TransformUnit& bestTU = saveCS.tus.empty() ? saveCS.addTU( currArea, partitioner.chType, nullptr ) : *saveCS.tus.front();
3581
22.7k
    bestTU.initData();
3582
22.7k
    bestTU.UnitArea::operator=( currArea );
3583
3584
91.0k
    for( uint32_t c = 0; c < numTBlocks; c++ )
3585
68.2k
    {
3586
68.2k
      const ComponentID compID    = ComponentID(c);
3587
68.2k
      const CompArea&   compArea  = tu.blocks[compID];
3588
68.2k
      const int channelBitDepth   = sps.bitDepths[toChannelType(compID)];
3589
3590
68.2k
      if( !tu.blocks[compID].valid() )
3591
45.5k
      {
3592
45.5k
        continue;
3593
45.5k
      }
3594
22.7k
      bool tsAllowed = useTS && TU::isTSAllowed(tu, compID) && (isLuma(compID) || (isChroma(compID) && m_pcEncCfg->m_useChromaTS));
3595
22.7k
      if (isChroma(compID) && tsAllowed && (tu.mtsIdx[COMP_Y] != MTS_SKIP))
3596
0
      {
3597
0
        tsAllowed = false;
3598
0
      }
3599
22.7k
      uint8_t nNumTransformCands = 1 + (tsAllowed ? 1 : 0); // DCT + TS = 2 tests
3600
22.7k
      std::vector<TrMode> trModes;
3601
3602
22.7k
      if (nNumTransformCands > 1)
3603
3.13k
      {
3604
3.13k
        trModes.push_back(TrMode(0, true)); //DCT2
3605
        //for a SBT-no-residual TU, the RDO process should be called once, in order to get the RD cost
3606
3.13k
        if ( !tu.noResidual )
3607
3.13k
        {
3608
3.13k
          trModes.push_back(TrMode(1, true));
3609
3.13k
        }
3610
0
        else
3611
0
        {
3612
0
          nNumTransformCands--;
3613
0
        }
3614
3.13k
      }
3615
22.7k
      bool isLast = true;
3616
48.4k
      for (int transformMode = 0; transformMode < nNumTransformCands; transformMode++)
3617
25.6k
      {
3618
25.6k
        const bool isFirstMode = transformMode == 0;
3619
3620
        // copy the original residual into the residual buffer
3621
25.6k
        csFull->getResiBuf(compArea).copyFrom(orgResiBuf.get(compID));
3622
3623
3624
25.6k
        m_CABACEstimator->getCtx() = ctxStart;
3625
25.6k
        m_CABACEstimator->resetBits();
3626
3627
25.6k
        if (bestTU.mtsIdx[compID] == MTS_SKIP && m_pcEncCfg->m_TS)
3628
0
        {
3629
0
          continue;
3630
0
        }
3631
25.6k
        tu.mtsIdx[compID] = transformMode ? trModes[transformMode].first : 0;
3632
3633
25.6k
        const QpParam cQP(tu, compID);  // note: uses tu.transformSkip[compID]
3634
25.6k
        m_pcTrQuant->selectLambda(compID);
3635
3636
25.6k
        if ( sps.jointCbCr && isChroma( compID ) && ( tu.cu->cs->slice->sliceQp > 18 ) )
3637
0
        {
3638
0
          m_pcTrQuant->scaleLambda( 1.05 );
3639
0
        }
3640
25.6k
        TCoeff     currAbsSum = 0;
3641
25.6k
        uint64_t   currCompFracBits = 0;
3642
25.6k
        Distortion currCompDist = 0;
3643
25.6k
        double     currCompCost = 0;
3644
25.6k
        uint64_t   nonCoeffFracBits = 0;
3645
25.6k
        Distortion nonCoeffDist = 0;
3646
25.6k
        double     nonCoeffCost = 0;
3647
3648
25.6k
        if (nNumTransformCands > 1)
3649
6.06k
        {
3650
6.06k
          if (transformMode == 0)
3651
3.13k
          {
3652
3.13k
            m_pcTrQuant->checktransformsNxN(tu, &trModes, 2, compID);
3653
3.13k
            tu.mtsIdx[compID] = trModes[0].first;
3654
3.13k
            if (!trModes[transformMode + 1].second)
3655
204
            {
3656
204
              nNumTransformCands = 1;
3657
204
            }
3658
3.13k
          }
3659
6.06k
          m_pcTrQuant->transformNxN(tu, compID, cQP, currAbsSum, m_CABACEstimator->getCtx(), true);
3660
6.06k
        }
3661
19.6k
        else
3662
19.6k
        {
3663
19.6k
          m_pcTrQuant->transformNxN(tu, compID, cQP, currAbsSum, m_CABACEstimator->getCtx());
3664
19.6k
        }
3665
25.6k
        if (isFirstMode || (currAbsSum == 0))
3666
25.6k
        {
3667
25.6k
          const CPelBuf zeroBuf(m_pTempPel, compArea);
3668
25.6k
          const CPelBuf& orgResi = orgResiBuf.get(compID);
3669
3670
25.6k
          nonCoeffDist = m_pcRdCost->getDistPart(zeroBuf, orgResi, channelBitDepth, compID, DF_SSE); // initialized with zero residual distortion
3671
3672
25.6k
          if (!tu.noResidual)
3673
25.6k
          {
3674
25.6k
            const bool prevCbf = (compID == COMP_Cr ? tu.cbf[COMP_Cb] : false);
3675
25.6k
            m_CABACEstimator->cbf_comp(*tu.cu, false, compArea, currDepth, prevCbf);
3676
25.6k
          }
3677
3678
25.6k
          nonCoeffFracBits = m_CABACEstimator->getEstFracBits();
3679
25.6k
          nonCoeffCost = m_pcRdCost->calcRdCost(nonCoeffFracBits, nonCoeffDist, !m_pcEncCfg->m_lumaLevelToDeltaQPEnabled);
3680
25.6k
        }
3681
3682
25.6k
        if ((puiZeroDist != NULL) && isFirstMode)
3683
22.7k
        {
3684
22.7k
          *puiZeroDist += nonCoeffDist; // initialized with zero residual distortion
3685
22.7k
        }
3686
3687
25.6k
        if (currAbsSum > 0) //if non-zero coefficients are present, a residual needs to be derived for further prediction
3688
192
        {
3689
192
          if (isFirstMode)
3690
192
          {
3691
192
            m_CABACEstimator->getCtx() = ctxStart;
3692
192
            m_CABACEstimator->resetBits();
3693
192
          }
3694
3695
192
          const bool prevCbf = ( compID == COMP_Cr ? tu.cbf[COMP_Cb] : false );
3696
192
          m_CABACEstimator->cbf_comp( *tu.cu, true, compArea, currDepth, prevCbf );
3697
192
          if( compID == COMP_Cr )
3698
0
          {
3699
0
            const int cbfMask = ( tu.cbf[COMP_Cb] ? 2 : 0 ) + 1;
3700
0
            m_CABACEstimator->joint_cb_cr( tu, cbfMask );
3701
0
          }
3702
192
          CUCtx cuCtx;
3703
192
          cuCtx.isDQPCoded = true;
3704
192
          cuCtx.isChromaQpAdjCoded = true;
3705
192
          m_CABACEstimator->residual_coding(tu, compID, &cuCtx);
3706
192
          m_CABACEstimator->mts_idx(cu, &cuCtx);
3707
3708
192
          currCompFracBits = m_CABACEstimator->getEstFracBits();
3709
3710
192
          PelBuf resiBuf  = csFull->getResiBuf(compArea);
3711
192
          CPelBuf orgResi = orgResiBuf.get(compID);
3712
3713
192
          m_pcTrQuant->invTransformNxN(tu, compID, resiBuf, cQP);
3714
192
          currCompDist = m_pcRdCost->getDistPart(orgResi, resiBuf, channelBitDepth, compID, DF_SSE);
3715
192
          currCompCost = m_pcRdCost->calcRdCost(currCompFracBits, currCompDist, false);
3716
192
        }
3717
25.4k
        else if (transformMode > 0)
3718
2.92k
        {
3719
2.92k
          currCompCost = MAX_DOUBLE;
3720
2.92k
        }
3721
22.5k
        else
3722
22.5k
        {
3723
22.5k
          currCompFracBits = nonCoeffFracBits;
3724
22.5k
          currCompDist     = nonCoeffDist;
3725
22.5k
          currCompCost     = nonCoeffCost;
3726
3727
22.5k
          tu.cbf[compID] = 0;
3728
22.5k
        }
3729
3730
        // evaluate
3731
25.6k
        if ((currCompCost < minCost[compID]) || (transformMode == 1 && currCompCost == minCost[compID]))
3732
22.7k
        {
3733
          // copy component
3734
22.7k
          if (isFirstMode && ((nonCoeffCost < currCompCost) || (currAbsSum == 0))) // check for forced null
3735
22.6k
          {
3736
22.6k
            tu.getCoeffs( compID ).fill( 0 );
3737
22.6k
            csFull->getResiBuf( compArea ).fill( 0 );
3738
22.6k
            tu.cbf[compID]   = 0;
3739
3740
22.6k
            currAbsSum       = 0;
3741
22.6k
            currCompFracBits = nonCoeffFracBits;
3742
22.6k
            currCompDist     = nonCoeffDist;
3743
22.6k
            currCompCost     = nonCoeffCost;
3744
22.6k
          }
3745
3746
22.7k
          uiSingleDistComp[compID] = currCompDist;
3747
22.7k
          minCost[compID]          = currCompCost;
3748
22.7k
          if (transformMode != (nNumTransformCands - 1))
3749
2.92k
          {
3750
2.92k
            bestTU.copyComponentFrom(tu, compID);
3751
2.92k
            saveCS.getResiBuf(compArea).copyFrom(csFull->getResiBuf(compArea));
3752
2.92k
          }
3753
19.8k
          else
3754
19.8k
          {
3755
19.8k
            isLast = false;
3756
19.8k
          }
3757
22.7k
        }
3758
25.6k
        if( tu.noResidual )
3759
0
        {
3760
0
          CHECK( currCompFracBits > 0 || currAbsSum, "currCompFracBits > 0 when tu noResidual" );
3761
0
        }
3762
25.6k
      }
3763
22.7k
      if (isLast)
3764
2.92k
      {
3765
2.92k
        tu.copyComponentFrom(bestTU, compID);
3766
2.92k
        csFull->getResiBuf(compArea).copyFrom(saveCS.getResiBuf(compArea));
3767
2.92k
      }
3768
22.7k
    } // component loop
3769
3770
22.7k
    if ( tu.blocks.size()>2 && tu.blocks[COMP_Cb].valid() )
3771
0
    {
3772
0
      const CompArea& cbArea = tu.blocks[COMP_Cb];
3773
0
      const CompArea& crArea = tu.blocks[COMP_Cr];
3774
0
      bool checkJointCbCr = (sps.jointCbCr) && (!tu.noResidual) && (TU::getCbf(tu, COMP_Cb) || TU::getCbf(tu, COMP_Cr));
3775
0
      const int channelBitDepth = sps.bitDepths[toChannelType(COMP_Cb)];
3776
0
      double minCostCbCr = minCost[COMP_Cb] + minCost[COMP_Cr];
3777
0
      bool   isLastBest  = false;
3778
3779
0
      bool checkDCTOnly = m_pcEncCfg->m_useChromaTS && ((TU::getCbf(tu, COMP_Cb) && tu.mtsIdx[COMP_Cb] == MTS_DCT2_DCT2 && !TU::getCbf(tu, COMP_Cr)) ||
3780
0
        (TU::getCbf(tu, COMP_Cr) && tu.mtsIdx[COMP_Cr] == MTS_DCT2_DCT2 && !TU::getCbf(tu, COMP_Cb)) ||
3781
0
        (TU::getCbf(tu, COMP_Cb) && tu.mtsIdx[COMP_Cb] == MTS_DCT2_DCT2 && TU::getCbf(tu, COMP_Cr) && tu.mtsIdx[COMP_Cr] == MTS_DCT2_DCT2));
3782
0
      bool checkTSOnly = m_pcEncCfg->m_useChromaTS && ((TU::getCbf(tu, COMP_Cb) && tu.mtsIdx[COMP_Cb] == MTS_SKIP && !TU::getCbf(tu, COMP_Cr)) ||
3783
0
        (TU::getCbf(tu, COMP_Cr) && tu.mtsIdx[COMP_Cr] == MTS_SKIP && !TU::getCbf(tu, COMP_Cb)) ||
3784
0
        (TU::getCbf(tu, COMP_Cb) && tu.mtsIdx[COMP_Cb] == MTS_SKIP && TU::getCbf(tu, COMP_Cr) && tu.mtsIdx[COMP_Cr] == MTS_SKIP));
3785
3786
0
      std::vector<int> jointCbfMasksToTest;
3787
0
      if ( checkJointCbCr )
3788
0
      {
3789
0
        for( int i = 0; i < 4; i++ )
3790
0
        {
3791
0
          m_orgResiCb[i].compactResize(cbArea);
3792
0
          m_orgResiCr[i].compactResize(crArea);
3793
0
        }
3794
0
        m_orgResiCb[0].copyFrom(orgResiBuf.Cb());
3795
0
        m_orgResiCr[0].copyFrom(orgResiBuf.Cr());
3796
3797
0
        jointCbfMasksToTest = m_pcTrQuant->selectICTCandidates(tu, m_orgResiCb, m_orgResiCr);
3798
3799
0
        bestTU.copyComponentFrom(tu, COMP_Cb);
3800
0
        bestTU.copyComponentFrom(tu, COMP_Cr);
3801
0
        saveCS.getResiBuf(cbArea).copyFrom(csFull->getResiBuf(cbArea));
3802
0
        saveCS.getResiBuf(crArea).copyFrom(csFull->getResiBuf(crArea));
3803
0
      }
3804
3805
0
      for (int cbfMask: jointCbfMasksToTest)
3806
0
      {
3807
0
        ComponentID codeCompId = (cbfMask >> 1 ? COMP_Cb : COMP_Cr);
3808
0
        ComponentID otherCompId = (codeCompId == COMP_Cr ? COMP_Cb : COMP_Cr);
3809
0
        bool tsAllowed = useTS && TU::isTSAllowed(tu, codeCompId) && (m_pcEncCfg->m_useChromaTS);
3810
0
        if (tsAllowed && (tu.mtsIdx[COMP_Y] != MTS_SKIP))
3811
0
        {
3812
0
          tsAllowed = false;
3813
0
        }
3814
0
        if (!tsAllowed)
3815
0
        {
3816
0
          checkTSOnly = false;
3817
0
        }
3818
0
        uint8_t     numTransformCands = 1 + (tsAllowed && (!(checkDCTOnly || checkTSOnly)) ? 1 : 0); // DCT + TS = 2 tests
3819
0
        std::vector<TrMode> trModes;
3820
0
        if (numTransformCands > 1)
3821
0
        {
3822
0
          trModes.push_back(TrMode(0, true)); // DCT2
3823
0
          trModes.push_back(TrMode(1, true));//TS
3824
0
        }
3825
0
        else
3826
0
        {
3827
0
          tu.mtsIdx[codeCompId] = checkTSOnly ? 1 : 0;
3828
0
        }
3829
0
        for (int modeId = 0; modeId < numTransformCands; modeId++)
3830
0
        {
3831
0
          TCoeff     currAbsSum = 0;
3832
0
          uint64_t   currCompFracBits = 0;
3833
0
          Distortion currCompDistCb = 0;
3834
0
          Distortion currCompDistCr = 0;
3835
0
          double     currCompCost = 0;
3836
3837
0
          tu.jointCbCr = (uint8_t)cbfMask;
3838
0
          if (numTransformCands > 1)
3839
0
          {
3840
0
            tu.mtsIdx[codeCompId] = trModes[modeId].first;
3841
0
          }
3842
0
          tu.mtsIdx[otherCompId] = MTS_DCT2_DCT2;
3843
0
          const QpParam cQP(tu, COMP_Cb);  // note: uses tu.transformSkip[compID]
3844
0
          m_pcTrQuant->selectLambda(COMP_Cb);
3845
3846
          // Lambda is loosened for the joint mode with respect to single modes as the same residual is used for both chroma blocks
3847
0
          const int    absIct = abs(TU::getICTMode(tu));
3848
0
          const double lfact = (absIct == 1 || absIct == 3 ? 0.8 : 0.5);
3849
0
          m_pcTrQuant->scaleLambda(lfact);
3850
0
          if (checkJointCbCr && (tu.cu->cs->slice->sliceQp > 18))
3851
0
          {
3852
0
            m_pcTrQuant->scaleLambda(1.05);
3853
0
          }
3854
3855
0
          m_CABACEstimator->getCtx() = ctxStart;
3856
0
          m_CABACEstimator->resetBits();
3857
3858
0
          PelBuf cbResi = csFull->getResiBuf(cbArea);
3859
0
          PelBuf crResi = csFull->getResiBuf(crArea);
3860
0
          cbResi.copyFrom(m_orgResiCb[cbfMask]);
3861
0
          crResi.copyFrom(m_orgResiCr[cbfMask]);
3862
3863
0
          int         codedCbfMask = 0;
3864
0
          ComponentID codeCompId = (tu.jointCbCr >> 1 ? COMP_Cb : COMP_Cr);
3865
0
          ComponentID otherCompId = (codeCompId == COMP_Cr ? COMP_Cb : COMP_Cr);
3866
0
          const QpParam qpCbCr(tu, codeCompId);
3867
3868
0
          tu.getCoeffs(otherCompId).fill(0);   // do we need that?
3869
0
          TU::setCbfAtDepth(tu, otherCompId, tu.depth, false);
3870
3871
0
          PelBuf& codeResi = (codeCompId == COMP_Cr ? crResi : cbResi);
3872
0
          TCoeff  compAbsSum = 0;
3873
0
          if (numTransformCands > 1)
3874
0
          {
3875
0
            if (modeId == 0)
3876
0
            {
3877
0
              m_pcTrQuant->checktransformsNxN(tu, &trModes, 2, codeCompId);
3878
0
              tu.mtsIdx[codeCompId] = trModes[modeId].first;
3879
0
              tu.mtsIdx[otherCompId] = MTS_DCT2_DCT2;
3880
0
              if (!trModes[modeId + 1].second)
3881
0
              {
3882
0
                numTransformCands = 1;
3883
0
              }
3884
0
            }
3885
0
            m_pcTrQuant->transformNxN(tu, codeCompId, qpCbCr, compAbsSum, m_CABACEstimator->getCtx(), true);
3886
0
          }
3887
0
          else
3888
0
          {
3889
0
            m_pcTrQuant->transformNxN(tu, codeCompId, qpCbCr, compAbsSum, m_CABACEstimator->getCtx());
3890
0
          }
3891
0
          if (compAbsSum > 0)
3892
0
          {
3893
0
            m_pcTrQuant->invTransformNxN(tu, codeCompId, codeResi, qpCbCr);
3894
0
            codedCbfMask += (codeCompId == COMP_Cb ? 2 : 1);
3895
0
          }
3896
0
          else
3897
0
          {
3898
0
            codeResi.fill(0);
3899
0
          }
3900
3901
0
          if (tu.jointCbCr == 3 && codedCbfMask == 2)
3902
0
          {
3903
0
            codedCbfMask = 3;
3904
0
            TU::setCbfAtDepth(tu, COMP_Cr, tu.depth, true);
3905
0
          }
3906
0
          if (codedCbfMask && tu.jointCbCr != codedCbfMask)
3907
0
          {
3908
0
            codedCbfMask = 0;
3909
0
          }
3910
0
          currAbsSum = codedCbfMask;
3911
0
          if (!tu.mtsIdx[codeCompId])
3912
0
          {
3913
0
            numTransformCands = (currAbsSum <= 0) ? 1 : numTransformCands;
3914
0
          }
3915
0
          if (currAbsSum > 0)
3916
0
          {
3917
0
            m_CABACEstimator->cbf_comp(*tu.cu, codedCbfMask >> 1, cbArea, currDepth, false);
3918
0
            m_CABACEstimator->cbf_comp(*tu.cu, codedCbfMask & 1, crArea, currDepth, codedCbfMask >> 1);
3919
0
            m_CABACEstimator->joint_cb_cr(tu, codedCbfMask);
3920
0
            if (codedCbfMask >> 1)
3921
0
              m_CABACEstimator->residual_coding(tu, COMP_Cb);
3922
0
            if (codedCbfMask & 1)
3923
0
              m_CABACEstimator->residual_coding(tu, COMP_Cr);
3924
0
            currCompFracBits = m_CABACEstimator->getEstFracBits();
3925
3926
0
            m_pcTrQuant->invTransformICT(tu, cbResi, crResi);
3927
3928
0
            currCompDistCb = m_pcRdCost->getDistPart(orgResiBuf.Cb(), cbResi, channelBitDepth, COMP_Cb, DF_SSE);
3929
0
            currCompDistCr = m_pcRdCost->getDistPart(orgResiBuf.Cr(), crResi, channelBitDepth, COMP_Cr, DF_SSE);
3930
0
            currCompCost = m_pcRdCost->calcRdCost(currCompFracBits, currCompDistCr + currCompDistCb, false);
3931
0
          }
3932
0
          else
3933
0
            currCompCost = MAX_DOUBLE;
3934
3935
          // evaluate
3936
0
          if (currCompCost < minCostCbCr)
3937
0
          {
3938
0
            uiSingleDistComp[COMP_Cb] = currCompDistCb;
3939
0
            uiSingleDistComp[COMP_Cr] = currCompDistCr;
3940
0
            minCostCbCr = currCompCost;
3941
0
            isLastBest = (cbfMask == jointCbfMasksToTest.back()) && (modeId == (numTransformCands - 1));
3942
0
            if (!isLastBest)
3943
0
            {
3944
0
              bestTU.copyComponentFrom(tu, COMP_Cb);
3945
0
              bestTU.copyComponentFrom(tu, COMP_Cr);
3946
0
              saveCS.getResiBuf(cbArea).copyFrom(csFull->getResiBuf(cbArea));
3947
0
              saveCS.getResiBuf(crArea).copyFrom(csFull->getResiBuf(crArea));
3948
0
            }
3949
0
          }
3950
0
        }
3951
3952
0
        if( !isLastBest )
3953
0
        {
3954
          // copy component
3955
0
          tu.copyComponentFrom( bestTU, COMP_Cb );
3956
0
          tu.copyComponentFrom( bestTU, COMP_Cr );
3957
0
          csFull->getResiBuf( cbArea ).copyFrom( saveCS.getResiBuf( cbArea ) );
3958
0
          csFull->getResiBuf( crArea ).copyFrom( saveCS.getResiBuf( crArea ) );
3959
0
        }
3960
0
      }
3961
0
    }
3962
3963
22.7k
    m_CABACEstimator->getCtx() = ctxStart;
3964
22.7k
    m_CABACEstimator->resetBits();
3965
22.7k
    if( !tu.noResidual )
3966
22.7k
    {
3967
22.7k
      static const ComponentID cbf_getComp[3] = { COMP_Cb, COMP_Cr, COMP_Y };
3968
91.0k
      for( unsigned c = 0; c < numTBlocks; c++)
3969
68.2k
      {
3970
68.2k
        const ComponentID compID = numTBlocks>1 ? cbf_getComp[c] : COMP_Y;
3971
68.2k
        if( tu.blocks[compID].valid() )
3972
22.7k
        {
3973
22.7k
          const bool prevCbf = ( compID == COMP_Cr ? TU::getCbfAtDepth( tu, COMP_Cb, currDepth ) : false );
3974
22.7k
          m_CABACEstimator->cbf_comp( *tu.cu, TU::getCbfAtDepth( tu, compID, currDepth ), tu.blocks[compID], currDepth, prevCbf );
3975
22.7k
        }
3976
68.2k
      }
3977
22.7k
    }
3978
3979
91.0k
    for (uint32_t ch = 0; ch < numValidComp; ch++)
3980
68.2k
    {
3981
68.2k
      const ComponentID compID = ComponentID(ch);
3982
68.2k
      if (tu.blocks[compID].valid())
3983
22.7k
      {
3984
22.7k
        if( compID == COMP_Cr )
3985
0
        {
3986
0
          const int cbfMask = ( TU::getCbf( tu, COMP_Cb ) ? 2 : 0 ) + ( TU::getCbf( tu, COMP_Cr ) ? 1 : 0 );
3987
0
          m_CABACEstimator->joint_cb_cr(tu, cbfMask);
3988
0
        }
3989
22.7k
        if( TU::getCbf( tu, compID ) )
3990
129
        {
3991
129
          m_CABACEstimator->residual_coding( tu, compID );
3992
129
        }
3993
22.7k
        uiSingleDist += uiSingleDistComp[compID];
3994
22.7k
      }
3995
68.2k
    }
3996
22.7k
    if( tu.noResidual )
3997
0
    {
3998
0
      CHECK( m_CABACEstimator->getEstFracBits() > 0, "no residual TU's bits shall be 0" );
3999
0
    }
4000
4001
22.7k
    csFull->fracBits += m_CABACEstimator->getEstFracBits();
4002
22.7k
    csFull->dist     += uiSingleDist;
4003
22.7k
    csFull->cost      = m_pcRdCost->calcRdCost(csFull->fracBits, csFull->dist, !m_pcEncCfg->m_lumaLevelToDeltaQPEnabled);
4004
22.7k
  } // check full
4005
4006
  // code sub-blocks
4007
22.7k
  if( bCheckSplit )
4008
0
  {
4009
0
    if( bCheckFull )
4010
0
    {
4011
0
      m_CABACEstimator->getCtx() = ctxStart;
4012
0
    }
4013
4014
0
    if( partitioner.canSplit( TU_MAX_TR_SPLIT, cs ) )
4015
0
    {
4016
0
      partitioner.splitCurrArea( TU_MAX_TR_SPLIT, cs );
4017
0
    }
4018
0
    else if( cu.sbtInfo && partitioner.canSplit( CU::getSbtTuSplit( cu.sbtInfo ), cs ) )
4019
0
    {
4020
0
      partitioner.splitCurrArea( CU::getSbtTuSplit( cu.sbtInfo ), cs );
4021
0
    }
4022
0
    else
4023
0
      THROW( "Implicit TU split not available!" );
4024
4025
0
    do
4026
0
    {
4027
0
      xEstimateInterResidualQT(*csSplit, partitioner, bCheckFull ? nullptr : puiZeroDist );
4028
4029
0
      csSplit->cost = m_pcRdCost->calcRdCost( csSplit->fracBits, csSplit->dist );
4030
0
    } while( partitioner.nextPart( *csSplit ) );
4031
4032
0
    partitioner.exitCurrSplit();
4033
4034
0
    unsigned        compCbf[3]  = { 0, 0, 0 };
4035
4036
0
    if( !bCheckFull )
4037
0
    {
4038
0
      for( auto &currTU : csSplit->traverseTUs( currArea, partitioner.chType ) )
4039
0
      {
4040
0
        for( unsigned ch = 0; ch < numTBlocks; ch++ )
4041
0
        {
4042
0
          compCbf[ ch ] |= ( TU::getCbfAtDepth( currTU, ComponentID(ch), currDepth + 1 ) ? 1 : 0 );
4043
0
        }
4044
0
      }
4045
4046
0
      for( auto &currTU : csSplit->traverseTUs( currArea, partitioner.chType ) )
4047
0
      {
4048
0
        TU::setCbfAtDepth   ( currTU, COMP_Y,  currDepth, compCbf[ COMP_Y  ] );
4049
0
        if( currArea.chromaFormat != CHROMA_400 )
4050
0
        {
4051
0
          TU::setCbfAtDepth ( currTU, COMP_Cb, currDepth, compCbf[ COMP_Cb ] );
4052
0
          TU::setCbfAtDepth ( currTU, COMP_Cr, currDepth, compCbf[ COMP_Cr ] );
4053
0
        }
4054
0
      }
4055
4056
0
      m_CABACEstimator->getCtx() = ctxStart;
4057
0
      m_CABACEstimator->resetBits();
4058
4059
      // when compID isn't a channel, code Cbfs:
4060
0
      xEncodeInterResidualQT( *csSplit, partitioner, MAX_NUM_TBLOCKS );
4061
4062
0
      for (uint32_t ch = 0; ch < numValidComp; ch++)
4063
0
      {
4064
0
        const ComponentID compID = ComponentID(ch);
4065
0
        xEncodeInterResidualQT( *csSplit, partitioner, compID );
4066
0
      }
4067
4068
0
      csSplit->fracBits = m_CABACEstimator->getEstFracBits();
4069
0
      csSplit->cost     = m_pcRdCost->calcRdCost(csSplit->fracBits, csSplit->dist);
4070
0
    }
4071
0
  }
4072
22.7k
}
4073
4074
void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &partitioner, const bool skipResidual )
4075
22.7k
{
4076
22.7k
  CodingUnit &cu = *cs.getCU( partitioner.chType, partitioner.treeType );
4077
22.7k
  bool luma      = true;
4078
22.7k
  bool chroma    = cs.pcv->chrFormat != VVENC_CHROMA_400;
4079
22.7k
  if( cu.predMode == MODE_IBC )
4080
22.7k
  {
4081
22.7k
    luma    = !cu.mccNoLuma  ();
4082
22.7k
    chroma &= !cu.mccNoChroma();
4083
22.7k
  }
4084
22.7k
  if( cu.predMode == MODE_INTER )
4085
22.7k
    CHECK( CU::isSepTree(cu), "CU with Inter mode must be in single tree" );
4086
4087
22.7k
  const ChromaFormat format      = cs.area.chromaFormat;;
4088
22.7k
  const int  numValidComponents  = getNumberValidComponents(format);
4089
22.7k
  const SPS &sps                 = *cs.sps;
4090
4091
22.7k
  if( skipResidual ) //  No residual coding : SKIP mode
4092
0
  {
4093
0
    cu.skip    = true;
4094
0
    cu.rootCbf = false;
4095
0
    CHECK( cu.sbtInfo != 0, "sbtInfo shall be 0 if CU has no residual" );
4096
0
    cs.getResiBuf().fill(0);
4097
0
    cs.getRecoBuf().copyFrom(cs.getPredBuf() );
4098
4099
    // add new "empty" TU(s) spanning the whole CU
4100
0
    cs.addEmptyTUs( partitioner, &cu );
4101
0
    Distortion distortion = 0;
4102
4103
0
    for (int comp = 0; comp < numValidComponents; comp++)
4104
0
    {
4105
0
      const ComponentID compID = ComponentID(comp);
4106
0
      if (compID == COMP_Y && !luma)
4107
0
        continue;
4108
0
      if (compID != COMP_Y && !chroma)
4109
0
        continue;
4110
0
      CPelBuf reco = cs.getRecoBuf (compID);
4111
0
      CPelBuf org  = cs.getOrgBuf  (compID);
4112
4113
0
      distortion  += m_pcRdCost->getDistPart( org, reco, sps.bitDepths[ toChannelType( compID ) ], compID, DF_SSE );
4114
0
    }
4115
4116
0
    CodingUnit& cu = *cs.getCU(partitioner.chType, TREE_D);
4117
0
    m_CABACEstimator->resetBits();
4118
0
    m_CABACEstimator->cu_skip_flag  ( cu );
4119
0
    m_CABACEstimator->merge_data(cu);
4120
0
    cs.fracBits = m_CABACEstimator->getEstFracBits();
4121
0
    cs.dist     = distortion;
4122
0
    cs.cost     = m_pcRdCost->calcRdCost(cs.fracBits, cs.dist);
4123
4124
0
    return;
4125
0
  }
4126
4127
  //  Residual coding.
4128
22.7k
  if (luma)
4129
22.7k
  {
4130
22.7k
    cs.getResiBuf(COMP_Y).subtract(cs.getOrgBuf(COMP_Y), cs.getPredBuf(COMP_Y));
4131
22.7k
  }
4132
22.7k
  if (chroma)
4133
0
  {
4134
0
    cs.getResiBuf(COMP_Cb).subtract(cs.getOrgBuf(COMP_Cb), cs.getPredBuf(COMP_Cb));
4135
0
    cs.getResiBuf(COMP_Cr).subtract(cs.getOrgBuf(COMP_Cr), cs.getPredBuf(COMP_Cr));
4136
0
  }
4137
4138
22.7k
  Distortion zeroDistortion = 0;
4139
4140
22.7k
  const TempCtx ctxStart( m_CtxCache, m_CABACEstimator->getCtx() );
4141
4142
22.7k
  xEstimateInterResidualQT(cs, partitioner, &zeroDistortion );
4143
22.7k
  TransformUnit& firstTU = *cs.getTU( partitioner.chType );
4144
4145
22.7k
  cu.rootCbf = false;
4146
22.7k
  m_CABACEstimator->resetBits();
4147
22.7k
  m_CABACEstimator->rqt_root_cbf( cu );
4148
22.7k
  const uint64_t  zeroFracBits = m_CABACEstimator->getEstFracBits();
4149
22.7k
  double zeroCost = m_pcRdCost->calcRdCost( zeroFracBits, zeroDistortion, !m_pcEncCfg->m_lumaLevelToDeltaQPEnabled );
4150
4151
22.7k
  const int  numValidTBlocks   = getNumberValidTBlocks( *cs.pcv );
4152
91.0k
  for (uint32_t i = 0; i < numValidTBlocks; i++)
4153
68.2k
  {
4154
68.2k
    cu.rootCbf |= TU::getCbfAtDepth(firstTU, ComponentID(i), 0);
4155
68.2k
  }
4156
4157
  // -------------------------------------------------------
4158
  // If a block full of 0's is efficient, then just use 0's.
4159
  // The costs at this point do not include header bits.
4160
4161
22.7k
  if (zeroCost < cs.cost || !cu.rootCbf)
4162
22.6k
  {
4163
22.6k
    cu.sbtInfo = 0;
4164
22.6k
    cu.rootCbf = false;
4165
4166
22.6k
    cs.clearTUs();
4167
4168
    // add a new "empty" TU spanning the whole CU
4169
22.6k
    cs.addEmptyTUs( partitioner, &cu );
4170
22.6k
  }
4171
4172
  // all decisions now made. Fully encode the CU, including the headers:
4173
22.7k
  m_CABACEstimator->getCtx() = ctxStart;
4174
4175
22.7k
  uint64_t finalFracBits = xGetSymbolFracBitsInter( cs, partitioner );
4176
  // we've now encoded the CU, and so have a valid bit cost
4177
22.7k
  if (!cu.rootCbf)
4178
22.6k
  {
4179
22.6k
    if (luma)
4180
22.6k
    {
4181
22.6k
      cs.getResiBuf().bufs[0].fill(0); // Clear the residual image, if we didn't code it.
4182
22.6k
    }
4183
22.6k
    if (chroma && isChromaEnabled(cs.pcv->chrFormat))
4184
0
    {
4185
0
      cs.getResiBuf().bufs[1].fill(0); // Clear the residual image, if we didn't code it.
4186
0
      cs.getResiBuf().bufs[2].fill(0); // Clear the residual image, if we didn't code it.
4187
0
    }
4188
22.6k
  }
4189
22.7k
  if (luma)
4190
22.7k
  {
4191
22.7k
    cs.getRecoBuf().bufs[0].reconstruct(cs.getPredBuf().bufs[0], cs.getResiBuf().bufs[0], cs.slice->clpRngs[COMP_Y]);
4192
22.7k
  }
4193
22.7k
  if (chroma)
4194
0
  {
4195
0
    cs.getRecoBuf().bufs[1].reconstruct(cs.getPredBuf().bufs[1], cs.getResiBuf().bufs[1], cs.slice->clpRngs[COMP_Cb]);
4196
0
    cs.getRecoBuf().bufs[2].reconstruct(cs.getPredBuf().bufs[2], cs.getResiBuf().bufs[2], cs.slice->clpRngs[COMP_Cr]);
4197
0
  }
4198
  // update with clipped distortion and cost (previously unclipped reconstruction values were used)
4199
22.7k
  Distortion finalDistortion = 0;
4200
4201
91.0k
  for (int comp = 0; comp < numValidComponents; comp++)
4202
68.2k
  {
4203
68.2k
    const ComponentID compID = ComponentID(comp);
4204
68.2k
    if (compID == COMP_Y && !luma)
4205
0
      continue;
4206
68.2k
    if (compID != COMP_Y && !chroma)
4207
45.5k
      continue;
4208
22.7k
    CPelBuf reco = cs.getRecoBuf (compID);
4209
22.7k
    CPelBuf org  = cs.getOrgBuf  (compID);
4210
4211
22.7k
    finalDistortion += m_pcRdCost->getDistPart( org, reco, sps.bitDepths[toChannelType(compID)], compID, DF_SSE );
4212
22.7k
  }
4213
4214
22.7k
  cs.dist     = finalDistortion;
4215
22.7k
  cs.fracBits = finalFracBits;
4216
22.7k
  cs.cost     = m_pcRdCost->calcRdCost(cs.fracBits, cs.dist);
4217
4218
22.7k
  CHECK(cs.tus.size() == 0, "No TUs present");
4219
22.7k
}
4220
4221
uint64_t InterSearch::xGetSymbolFracBitsInter(CodingStructure &cs, Partitioner &partitioner)
4222
22.7k
{
4223
22.7k
  uint64_t fracBits   = 0;
4224
22.7k
  CodingUnit &cu    = *cs.getCU( partitioner.chType, partitioner.treeType );
4225
4226
22.7k
  m_CABACEstimator->resetBits();
4227
4228
22.7k
  if( cu.mergeFlag && !cu.rootCbf )
4229
0
  {
4230
0
    cu.skip = true;
4231
4232
0
    m_CABACEstimator->cu_skip_flag  ( cu );
4233
0
    if (!cu.ciip)
4234
0
    {
4235
0
      m_CABACEstimator->merge_data(cu);
4236
0
    }
4237
0
    fracBits   += m_CABACEstimator->getEstFracBits();
4238
0
  }
4239
22.7k
  else
4240
22.7k
  {
4241
22.7k
    CHECK( cu.skip, "Skip flag has to be off at this point!" );
4242
4243
22.7k
    if (cu.Y().valid())
4244
22.7k
    m_CABACEstimator->cu_skip_flag( cu );
4245
22.7k
    m_CABACEstimator->pred_mode   ( cu );
4246
22.7k
    m_CABACEstimator->cu_pred_data( cu );
4247
22.7k
    CUCtx cuCtx;
4248
22.7k
    cuCtx.isDQPCoded = true;
4249
22.7k
    cuCtx.isChromaQpAdjCoded = true;
4250
22.7k
    m_CABACEstimator->cu_residual ( cu, partitioner, cuCtx );
4251
22.7k
    fracBits       += m_CABACEstimator->getEstFracBits();
4252
22.7k
  }
4253
4254
22.7k
  return fracBits;
4255
22.7k
}
4256
4257
double InterSearch::xGetMEDistortionWeight(uint8_t BcwIdx, RefPicList refPicList)
4258
0
{
4259
0
  if( BcwIdx != BCW_DEFAULT )
4260
0
  {
4261
0
    return fabs( (double)getBcwWeight( BcwIdx, refPicList ) / (double)g_BcwWeightBase );
4262
0
  }
4263
0
  else
4264
0
  {
4265
0
    return 0.5;
4266
0
  }
4267
0
}
4268
4269
bool InterSearch::xReadBufferedUniMv( CodingUnit& cu, RefPicList eRefPicList, int32_t iRefIdx, Mv& pcMvPred, Mv& rcMv, uint32_t& ruiBits, Distortion& ruiCost )
4270
0
{
4271
0
  if( m_uniMotions.isReadMode( (uint32_t)eRefPicList, (uint32_t)iRefIdx ) )
4272
0
  {
4273
0
    m_uniMotions.copyTo(rcMv, ruiCost, (uint32_t)eRefPicList, (uint32_t)iRefIdx);
4274
4275
0
    Mv pred = pcMvPred;
4276
0
    pred.changeTransPrecInternal2Amvr( cu.imv );
4277
0
    m_pcRdCost->setPredictor(pred);
4278
0
    m_pcRdCost->setCostScale(0);
4279
4280
0
    Mv mv = rcMv;
4281
0
    mv.changeTransPrecInternal2Amvr( cu.imv );
4282
0
    uint32_t mvBits = m_pcRdCost->getBitsOfVectorWithPredictor( mv.hor, mv.ver, 0 );
4283
4284
0
    ruiBits += mvBits;
4285
0
    ruiCost += m_pcRdCost->getCost(ruiBits);
4286
0
    return true;
4287
0
  }
4288
0
  return false;
4289
0
}
4290
4291
bool InterSearch::xReadBufferedAffineUniMv( CodingUnit& cu, RefPicList eRefPicList, int32_t iRefIdx, Mv acMvPred[3], Mv acMv[3], uint32_t& ruiBits, Distortion& ruiCost, int& mvpIdx, const AffineAMVPInfo& aamvpi )
4292
0
{
4293
0
  if( m_uniMotions.isReadModeAffine( (uint32_t)eRefPicList, (uint32_t)iRefIdx, cu.affineType ) )
4294
0
  {
4295
0
    m_uniMotions.copyAffineMvTo( acMv, ruiCost, (uint32_t)eRefPicList, (uint32_t)iRefIdx, cu.affineType, mvpIdx );
4296
0
    m_pcRdCost->setCostScale(0);
4297
0
    acMvPred[0] = aamvpi.mvCandLT[mvpIdx];
4298
0
    acMvPred[1] = aamvpi.mvCandRT[mvpIdx];
4299
0
    acMvPred[2] = aamvpi.mvCandLB[mvpIdx];
4300
4301
0
    uint32_t mvBits = 0;
4302
0
    for( int verIdx = 0; verIdx < ( cu.affineType ? 3 : 2 ); verIdx++ )
4303
0
    {
4304
0
      Mv pred = verIdx ? acMvPred[verIdx] + acMv[0] - acMvPred[0] : acMvPred[verIdx];
4305
0
      pred.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
4306
0
      m_pcRdCost->setPredictor(pred);
4307
0
      Mv mv = acMv[verIdx];
4308
0
      mv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
4309
0
      mvBits += m_pcRdCost->getBitsOfVectorWithPredictor( mv.hor, mv.ver, 0 );
4310
0
    }
4311
0
    ruiBits += mvBits;
4312
0
    ruiCost += m_pcRdCost->getCost(ruiBits);
4313
0
    return true;
4314
0
  }
4315
0
  return false;
4316
0
}
4317
4318
void InterSearch::xSymMvdCheckBestMvp(
4319
  CodingUnit& cu,
4320
  CPelUnitBuf& origBuf,
4321
  Mv curMv,
4322
  RefPicList curRefList,
4323
  AMVPInfo amvpInfo[2][MAX_REF_PICS],
4324
  int32_t BcwIdx,
4325
  Mv cMvPredSym[2],
4326
  int32_t mvpIdxSym[2],
4327
  Distortion& bestCost,
4328
  bool skip
4329
)
4330
0
{
4331
0
  RefPicList tarRefList = (RefPicList)(1 - curRefList);
4332
0
  int32_t refIdxCur = cu.slice->symRefIdx[curRefList];
4333
0
  int32_t refIdxTar = cu.slice->symRefIdx[tarRefList];
4334
4335
0
  MvField cCurMvField, cTarMvField;
4336
0
  cCurMvField.setMvField(curMv, refIdxCur);
4337
0
  AMVPInfo& amvpCur = amvpInfo[curRefList][refIdxCur];
4338
0
  AMVPInfo& amvpTar = amvpInfo[tarRefList][refIdxTar];
4339
0
  m_pcRdCost->setCostScale(0);
4340
4341
0
  double fWeight = 0.0;
4342
0
  PelUnitBuf bufTmp;
4343
4344
  // get prediction of eCurRefPicList
4345
0
  PelUnitBuf predBufA = m_tmpPredStorage[curRefList].getCompactBuf( cu );
4346
0
  const Picture* picRefA = cu.slice->getRefPic(curRefList, cCurMvField.refIdx);
4347
0
  Mv mvA = cCurMvField.mv;
4348
0
  xClipMvSearch( mvA, cu.lumaPos(), cu.lumaSize(), *cu.cs->pcv, m_ifpLines );
4349
0
  xPredInterBlk( COMP_Y, cu, picRefA, mvA, predBufA, false, cu.slice->clpRngs[ COMP_Y ], false, false );
4350
4351
0
  bufTmp = m_tmpStorageLCU.getCompactBuf( cu );
4352
0
  bufTmp.copyFrom( origBuf );
4353
0
  bufTmp.removeHighFreq( predBufA, m_pcEncCfg->m_bClipForBiPredMeEnabled, cu.slice->clpRngs/*, getBcwWeight( cu.BcwIdx, tarRefList )*/ );
4354
0
  fWeight = xGetMEDistortionWeight( cu.BcwIdx, tarRefList );
4355
4356
0
  int32_t skipMvpIdx[2];
4357
0
  skipMvpIdx[0] = skip ? mvpIdxSym[0] : -1;
4358
0
  skipMvpIdx[1] = skip ? mvpIdxSym[1] : -1;
4359
4360
0
  for (int i = 0; i < amvpCur.numCand; i++)
4361
0
  {
4362
0
    for (int j = 0; j < amvpTar.numCand; j++)
4363
0
    {
4364
0
      if (skipMvpIdx[curRefList] == i && skipMvpIdx[tarRefList] == j)
4365
0
        continue;
4366
4367
0
      Distortion cost = MAX_DISTORTION;
4368
0
      cTarMvField.setMvField(curMv.getSymmvdMv(amvpCur.mvCand[i], amvpTar.mvCand[j]), refIdxTar);
4369
4370
      // get prediction of eTarRefPicList
4371
0
      PelUnitBuf predBufB = m_tmpPredStorage[tarRefList].getCompactBuf( cu );
4372
0
      const Picture* picRefB = cu.slice->getRefPic(tarRefList, cTarMvField.refIdx);
4373
0
      Mv mvB = cTarMvField.mv;
4374
0
      xClipMvSearch( mvB, cu.lumaPos(), cu.lumaSize(), *cu.cs->pcv, m_ifpLines );
4375
0
      xPredInterBlk( COMP_Y, cu, picRefB, mvB, predBufB, false, cu.slice->clpRngs[ COMP_Y ], false, false );
4376
4377
      // calc distortion
4378
0
      cost = ( Distortion ) floor( fWeight * ( double ) m_pcRdCost->getDistPart( bufTmp.Y(), predBufB.Y(), cu.cs->sps->bitDepths[ CH_L ], COMP_Y, DF_HAD ) );
4379
4380
0
      Mv pred = amvpCur.mvCand[i];
4381
0
      pred.changeTransPrecInternal2Amvr(cu.imv);
4382
0
      m_pcRdCost->setPredictor(pred);
4383
0
      Mv mv = curMv;
4384
0
      mv.changeTransPrecInternal2Amvr(cu.imv);
4385
0
      uint32_t bits = m_pcRdCost->getBitsOfVectorWithPredictor(mv.hor, mv.ver, 0);
4386
0
      bits += m_auiMVPIdxCost[i][AMVP_MAX_NUM_CANDS];
4387
0
      bits += m_auiMVPIdxCost[j][AMVP_MAX_NUM_CANDS];
4388
0
      cost += m_pcRdCost->getCost(bits);
4389
0
      if (cost < bestCost)
4390
0
      {
4391
0
        bestCost = cost;
4392
0
        cMvPredSym[curRefList] = amvpCur.mvCand[i];
4393
0
        cMvPredSym[tarRefList] = amvpTar.mvCand[j];
4394
0
        mvpIdxSym[curRefList] = i;
4395
0
        mvpIdxSym[tarRefList] = j;
4396
0
      }
4397
0
    }
4398
0
  }
4399
0
}
4400
4401
void InterSearch::resetSavedAffineMotion()
4402
130k
{
4403
392k
  for (int i = 0; i < 2; i++)
4404
261k
  {
4405
785k
    for (int j = 0; j < 2; j++)
4406
523k
    {
4407
523k
      m_affineMotion.acMvAffine4Para[i][j] = Mv(0, 0);
4408
523k
      m_affineMotion.acMvAffine6Para[i][j] = Mv(0, 0);
4409
523k
    }
4410
261k
    m_affineMotion.acMvAffine6Para[i][2] = Mv(0, 0);
4411
4412
261k
    m_affineMotion.affine4ParaRefIdx[i] = -1;
4413
261k
    m_affineMotion.affine6ParaRefIdx[i] = -1;
4414
261k
  }
4415
130k
  m_affineMotion.affine4ParaAvail = false;
4416
130k
  m_affineMotion.affine6ParaAvail = false;
4417
130k
}
4418
4419
void InterSearch::storeAffineMotion(Mv acAffineMv[2][3], int16_t affineRefIdx[2], EAffineModel affineType, int BcwIdx)
4420
0
{
4421
0
  if ((BcwIdx == BCW_DEFAULT || !m_affineMotion.affine6ParaAvail) && affineType == AFFINEMODEL_6PARAM)
4422
0
  {
4423
0
    for (int i = 0; i < 2; i++)
4424
0
    {
4425
0
      for (int j = 0; j < 3; j++)
4426
0
      {
4427
0
        m_affineMotion.acMvAffine6Para[i][j] = acAffineMv[i][j];
4428
0
      }
4429
0
      m_affineMotion.affine6ParaRefIdx[i] = affineRefIdx[i];
4430
0
    }
4431
0
    m_affineMotion.affine6ParaAvail = true;
4432
0
  }
4433
4434
0
  if ((BcwIdx == BCW_DEFAULT || !m_affineMotion.affine4ParaAvail) && affineType == AFFINEMODEL_4PARAM)
4435
0
  {
4436
0
    for (int i = 0; i < 2; i++)
4437
0
    {
4438
0
      for (int j = 0; j < 2; j++)
4439
0
      {
4440
0
        m_affineMotion.acMvAffine4Para[i][j] = acAffineMv[i][j];
4441
0
      }
4442
0
      m_affineMotion.affine4ParaRefIdx[i] = affineRefIdx[i];
4443
0
    }
4444
0
    m_affineMotion.affine4ParaAvail = true;
4445
0
  }
4446
0
}
4447
4448
void InterSearch::xPredAffineInterSearch( CodingUnit& cu,
4449
                                          CPelUnitBuf&    origBuf,
4450
                                          int             puIdx,
4451
                                          uint32_t&       lastMode,
4452
                                          Distortion&     affineCost,
4453
                                          Mv              hevcMv[2][MAX_REF_PICS],
4454
                                          Mv              mvAffine4Para[2][MAX_REF_PICS][3],
4455
                                          int             refIdx4Para[2],
4456
                                          uint8_t         BcwIdx,
4457
                                          bool            enforceBcwPred,
4458
                                          uint32_t        BcwIdxBits )
4459
0
{
4460
0
  const Slice &slice = *cu.slice;
4461
4462
0
  affineCost = MAX_DISTORTION;
4463
4464
0
  Mv        cMvZero;
4465
0
  Mv        aacMv[2][3];
4466
0
  Mv        cMvBi[2][3];
4467
0
  AffineMVInfo tmp;
4468
4469
0
  int       iNumPredDir = slice.isInterP() ? 1 : 2;
4470
4471
0
  int mvNum = 2;
4472
0
  mvNum = cu.affineType ? 3 : 2;
4473
4474
  // Mvp
4475
0
  Mv        cMvPred[2][MAX_REF_PICS][3];
4476
0
  Mv        cMvPredBi[2][MAX_REF_PICS][3];
4477
0
  int       aaiMvpIdxBi[2][MAX_REF_PICS];
4478
0
  int       aaiMvpIdx[2][MAX_REF_PICS];
4479
0
  int       aaiMvpNum[2][MAX_REF_PICS];
4480
4481
0
  AffineAMVPInfo aacAffineAMVPInfo[2][MAX_REF_PICS];
4482
0
  AffineAMVPInfo affiAMVPInfoTemp[2];
4483
4484
0
  uint32_t      uiMbBits[3] = { 1, 1, 0 };
4485
0
  int           iRefIdx[2] = { 0,0 }; // If un-initialized, may cause SEGV in bi-directional prediction iterative stage.
4486
0
  int           iRefIdxBi[2];
4487
0
  int           iRefStart, iRefEnd;
4488
0
  int           bestBiPRefIdxL1 = 0;
4489
0
  int           bestBiPMvpL1 = 0;
4490
0
  Distortion    biPDistTemp = MAX_DISTORTION;
4491
4492
0
  Distortion    uiCost[2] = { MAX_DISTORTION, MAX_DISTORTION };
4493
0
  Distortion    uiCostBi = MAX_DISTORTION;
4494
0
  Distortion    uiCostTemp;
4495
4496
0
  uint32_t      uiBits[3] = { 0 };
4497
0
  uint32_t      uiBitsTemp;
4498
0
  Distortion    bestBiPDist = MAX_DISTORTION;
4499
4500
0
  Distortion    uiCostTempL0[MAX_NUM_REF];
4501
0
  for (int iNumRef = 0; iNumRef < MAX_NUM_REF; iNumRef++)
4502
0
  {
4503
0
    uiCostTempL0[iNumRef] = MAX_DISTORTION;
4504
0
  }
4505
0
  uint32_t      uiBitsTempL0[MAX_NUM_REF];
4506
4507
0
  Mv            mvValidList1[4];
4508
0
  int           refIdxValidList1 = 0;
4509
0
  uint32_t      bitsValidList1 = MAX_UINT;
4510
0
  Distortion    costValidList1 = MAX_DISTORTION;
4511
0
  Mv            mvHevc[3];
4512
0
  const bool    affineAmvrEnabled = false;
4513
4514
0
  xGetBlkBits(slice.isInterP(), puIdx, lastMode, uiMbBits);
4515
4516
0
  cu.affine = true;
4517
0
  cu.mergeFlag = false;
4518
0
  if (BcwIdx != BCW_DEFAULT)
4519
0
  {
4520
0
    cu.BcwIdx = BcwIdx;
4521
0
  }
4522
4523
  // Uni-directional prediction
4524
0
  for (int iRefList = 0; iRefList < iNumPredDir; iRefList++)
4525
0
  {
4526
0
    RefPicList  refPicList = (iRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0);
4527
0
    cu.interDir = (iRefList ? 2 : 1);
4528
0
    for (int iRefIdxTemp = 0; iRefIdxTemp < slice.numRefIdx[refPicList]; iRefIdxTemp++)
4529
0
    {
4530
      // Get RefIdx bits
4531
0
      uiBitsTemp = uiMbBits[iRefList];
4532
0
      if (slice.numRefIdx[refPicList] > 1)
4533
0
      {
4534
0
        uiBitsTemp += iRefIdxTemp + 1;
4535
0
        if (iRefIdxTemp == slice.numRefIdx[refPicList] - 1)
4536
0
        {
4537
0
          uiBitsTemp--;
4538
0
        }
4539
0
      }
4540
4541
      // Do Affine AMVP
4542
0
      bool foundPred = xEstimateAffineAMVP(cu, affiAMVPInfoTemp[refPicList], origBuf, refPicList, iRefIdxTemp, cMvPred[iRefList][iRefIdxTemp], biPDistTemp);
4543
0
      if( !foundPred )
4544
0
        return;
4545
4546
0
      if (affineAmvrEnabled)
4547
0
      {
4548
0
        biPDistTemp += m_pcRdCost->getCost(xCalcAffineMVBits(cu, cMvPred[iRefList][iRefIdxTemp], cMvPred[iRefList][iRefIdxTemp]));
4549
0
      }
4550
0
      aaiMvpIdx[iRefList][iRefIdxTemp] = cu.mvpIdx[refPicList];
4551
0
      aaiMvpNum[iRefList][iRefIdxTemp] = cu.mvpNum[refPicList];;
4552
0
      if (cu.affineType == AFFINEMODEL_6PARAM && refIdx4Para[iRefList] != iRefIdxTemp)
4553
0
      {
4554
0
        xCopyAffineAMVPInfo(affiAMVPInfoTemp[refPicList], aacAffineAMVPInfo[iRefList][iRefIdxTemp]);
4555
0
        continue;
4556
0
      }
4557
4558
      // set hevc ME result as start search position when it is best than mvp
4559
0
      for (int i = 0; i<3; i++)
4560
0
      {
4561
0
        mvHevc[i] = hevcMv[iRefList][iRefIdxTemp];
4562
0
        mvHevc[i].roundAffinePrecInternal2Amvr(cu.imv);
4563
0
      }
4564
0
      PelUnitBuf predBuf = m_tmpStorageLCU.getCompactBuf(cu);
4565
4566
0
      Distortion uiCandCost = xGetAffineTemplateCost(cu, origBuf, predBuf, mvHevc, aaiMvpIdx[iRefList][iRefIdxTemp],
4567
0
        AMVP_MAX_NUM_CANDS, refPicList, iRefIdxTemp);
4568
4569
0
      if (affineAmvrEnabled)
4570
0
      {
4571
0
        uiCandCost += m_pcRdCost->getCost(xCalcAffineMVBits(cu, mvHevc, cMvPred[iRefList][iRefIdxTemp]));
4572
0
      }
4573
4574
      //check stored affine motion
4575
0
      bool affine4Para = cu.affineType == AFFINEMODEL_4PARAM;
4576
0
      bool savedParaAvail = cu.imv && ((m_affineMotion.affine4ParaRefIdx[iRefList] == iRefIdxTemp && affine4Para && m_affineMotion.affine4ParaAvail) ||
4577
0
        (m_affineMotion.affine6ParaRefIdx[iRefList] == iRefIdxTemp && !affine4Para && m_affineMotion.affine6ParaAvail));
4578
4579
0
      if (savedParaAvail)
4580
0
      {
4581
0
        Mv mvFour[3];
4582
0
        for (int i = 0; i < mvNum; i++)
4583
0
        {
4584
0
          mvFour[i] = affine4Para ? m_affineMotion.acMvAffine4Para[iRefList][i] : m_affineMotion.acMvAffine6Para[iRefList][i];
4585
0
          mvFour[i].roundAffinePrecInternal2Amvr(cu.imv);
4586
0
        }
4587
4588
0
        Distortion candCostInherit = xGetAffineTemplateCost(cu, origBuf, predBuf, mvFour, aaiMvpIdx[iRefList][iRefIdxTemp], AMVP_MAX_NUM_CANDS, refPicList, iRefIdxTemp);
4589
0
        candCostInherit += m_pcRdCost->getCost(xCalcAffineMVBits(cu, mvFour, cMvPred[iRefList][iRefIdxTemp]));
4590
4591
0
        if (candCostInherit < uiCandCost)
4592
0
        {
4593
0
          uiCandCost = candCostInherit;
4594
0
          memcpy(mvHevc, mvFour, 3 * sizeof(Mv));
4595
0
        }
4596
0
      }
4597
4598
0
      if( cu.affineType == AFFINEMODEL_4PARAM && m_AffineProfList->m_affMVListSize && (!cu.cs->sps->BCW || BcwIdx == BCW_DEFAULT ) )
4599
0
      {
4600
0
        int shift = MAX_CU_DEPTH;
4601
0
        for (int i = 0; i < m_AffineProfList->m_affMVListSize; i++)
4602
0
        {
4603
0
          AffineMVInfo *mvInfo = m_AffineProfList->m_affMVList + ((m_AffineProfList->m_affMVListIdx - i - 1 + m_AffineProfList->m_affMVListMaxSize) % (m_AffineProfList->m_affMVListMaxSize));
4604
          //check;
4605
0
          int j = 0;
4606
0
          for (; j < i; j++)
4607
0
          {
4608
0
            AffineMVInfo *prevMvInfo = m_AffineProfList->m_affMVList + ((m_AffineProfList->m_affMVListIdx - j - 1 + m_AffineProfList->m_affMVListMaxSize) % (m_AffineProfList->m_affMVListMaxSize));
4609
0
            if ((mvInfo->affMVs[iRefList][iRefIdxTemp][0] == prevMvInfo->affMVs[iRefList][iRefIdxTemp][0]) &&
4610
0
              (mvInfo->affMVs[iRefList][iRefIdxTemp][1] == prevMvInfo->affMVs[iRefList][iRefIdxTemp][1])
4611
0
              && (mvInfo->x == prevMvInfo->x) && (mvInfo->y == prevMvInfo->y)
4612
0
              && (mvInfo->w == prevMvInfo->w)
4613
0
              )
4614
0
            {
4615
0
              break;
4616
0
            }
4617
0
          }
4618
0
          if (j < i)
4619
0
            continue;
4620
4621
0
          Mv mvTmp[3], *nbMv = mvInfo->affMVs[iRefList][iRefIdxTemp];
4622
0
          int vx, vy;
4623
0
          int dMvHorX, dMvHorY, dMvVerX, dMvVerY;
4624
0
          int mvScaleHor = nbMv[0].hor * (1<< shift);
4625
0
          int mvScaleVer = nbMv[0].ver * (1<< shift);
4626
0
          Mv dMv = nbMv[1] - nbMv[0];
4627
0
          dMvHorX = dMv.hor *(1<<(shift - Log2(mvInfo->w)));
4628
0
          dMvHorY = dMv.ver *(1<< (shift - Log2(mvInfo->w)));
4629
0
          dMvVerX = -dMvHorY;
4630
0
          dMvVerY = dMvHorX;
4631
0
          vx = mvScaleHor + dMvHorX * (cu.Y().x - mvInfo->x) + dMvVerX * (cu.Y().y - mvInfo->y);
4632
0
          vy = mvScaleVer + dMvHorY * (cu.Y().x - mvInfo->x) + dMvVerY * (cu.Y().y - mvInfo->y);
4633
0
          roundAffineMv(vx, vy, shift);
4634
0
          mvTmp[0] = Mv(vx, vy);
4635
0
          mvTmp[0].clipToStorageBitDepth();
4636
0
          clipMv(mvTmp[0], cu.lumaPos(), cu.lumaSize(), *cu.cs->pcv);
4637
0
          mvTmp[0].roundAffinePrecInternal2Amvr(cu.imv);
4638
0
          vx = mvScaleHor + dMvHorX * (cu.Y().x + cu.Y().width - mvInfo->x) + dMvVerX * (cu.Y().y - mvInfo->y);
4639
0
          vy = mvScaleVer + dMvHorY * (cu.Y().x + cu.Y().width - mvInfo->x) + dMvVerY * (cu.Y().y - mvInfo->y);
4640
0
          roundAffineMv(vx, vy, shift);
4641
0
          mvTmp[1] = Mv(vx, vy);
4642
0
          mvTmp[1].clipToStorageBitDepth();
4643
0
          clipMv(mvTmp[1], cu.lumaPos(), cu.lumaSize(), *cu.cs->pcv);
4644
0
          mvTmp[0].roundAffinePrecInternal2Amvr(cu.imv);
4645
0
          mvTmp[1].roundAffinePrecInternal2Amvr(cu.imv);
4646
0
          Distortion tmpCost = xGetAffineTemplateCost(cu, origBuf, predBuf, mvTmp, aaiMvpIdx[iRefList][iRefIdxTemp], AMVP_MAX_NUM_CANDS, refPicList, iRefIdxTemp);
4647
0
          if (affineAmvrEnabled)
4648
0
          {
4649
0
            tmpCost += m_pcRdCost->getCost(xCalcAffineMVBits(cu, mvTmp, cMvPred[iRefList][iRefIdxTemp]));
4650
0
          }
4651
0
          if (tmpCost < uiCandCost)
4652
0
          {
4653
0
            uiCandCost = tmpCost;
4654
0
            std::memcpy(mvHevc, mvTmp, 3 * sizeof(Mv));
4655
0
          }
4656
0
        }
4657
0
      }
4658
0
      if (cu.affineType == AFFINEMODEL_6PARAM)
4659
0
      {
4660
0
        Mv mvFour[3];
4661
0
        mvFour[0] = mvAffine4Para[iRefList][iRefIdxTemp][0];
4662
0
        mvFour[1] = mvAffine4Para[iRefList][iRefIdxTemp][1];
4663
0
        mvAffine4Para[iRefList][iRefIdxTemp][0].roundAffinePrecInternal2Amvr(cu.imv);
4664
0
        mvAffine4Para[iRefList][iRefIdxTemp][1].roundAffinePrecInternal2Amvr(cu.imv);
4665
4666
0
        int shift = MAX_CU_DEPTH;
4667
0
        int vx2 = (mvFour[0].hor * (1<< shift)) - ((mvFour[1].ver - mvFour[0].ver) * (1<< (shift + Log2(cu.lheight()) - Log2(cu.lwidth()))));
4668
0
        int vy2 = (mvFour[0].ver * (1<< shift)) + ((mvFour[1].hor - mvFour[0].hor) * (1<< (shift + Log2(cu.lheight()) - Log2(cu.lwidth()))));
4669
0
        int offset = (1 << (shift - 1));
4670
0
        vx2 = (vx2 + offset - (vx2 >= 0)) >> shift;
4671
0
        vy2 = (vy2 + offset - (vy2 >= 0)) >> shift;
4672
0
        mvFour[2].hor = vx2;
4673
0
        mvFour[2].ver = vy2;
4674
0
        mvFour[2].clipToStorageBitDepth();
4675
0
        mvFour[0].roundAffinePrecInternal2Amvr(cu.imv);
4676
0
        mvFour[1].roundAffinePrecInternal2Amvr(cu.imv);
4677
0
        mvFour[2].roundAffinePrecInternal2Amvr(cu.imv);
4678
0
        Distortion uiCandCostInherit = xGetAffineTemplateCost(cu, origBuf, predBuf, mvFour, aaiMvpIdx[iRefList][iRefIdxTemp], AMVP_MAX_NUM_CANDS, refPicList, iRefIdxTemp);
4679
0
        if (affineAmvrEnabled)
4680
0
        {
4681
0
          uiCandCostInherit += m_pcRdCost->getCost(xCalcAffineMVBits(cu, mvFour, cMvPred[iRefList][iRefIdxTemp]));
4682
0
        }
4683
0
        if (uiCandCostInherit < uiCandCost)
4684
0
        {
4685
0
          uiCandCost = uiCandCostInherit;
4686
0
          for (int i = 0; i < 3; i++)
4687
0
          {
4688
0
            mvHevc[i] = mvFour[i];
4689
0
          }
4690
0
        }
4691
0
      }
4692
4693
0
      if (uiCandCost < biPDistTemp)
4694
0
      {
4695
0
        ::memcpy(tmp.affMVs[iRefList][iRefIdxTemp], mvHevc, sizeof(Mv) * 3);
4696
0
      }
4697
0
      else
4698
0
      {
4699
0
        ::memcpy(tmp.affMVs[iRefList][iRefIdxTemp], cMvPred[iRefList][iRefIdxTemp], sizeof(Mv) * 3);
4700
0
      }
4701
4702
      // GPB list 1, save the best MvpIdx, RefIdx and Cost
4703
0
      if (slice.picHeader->mvdL1Zero && iRefList == 1 && biPDistTemp < bestBiPDist)
4704
0
      {
4705
0
        bestBiPDist = biPDistTemp;
4706
0
        bestBiPMvpL1 = aaiMvpIdx[iRefList][iRefIdxTemp];
4707
0
        bestBiPRefIdxL1 = iRefIdxTemp;
4708
0
      }
4709
4710
      // Update bits
4711
0
      uiBitsTemp += m_auiMVPIdxCost[aaiMvpIdx[iRefList][iRefIdxTemp]][AMVP_MAX_NUM_CANDS];
4712
4713
0
      if (m_pcEncCfg->m_bFastMEForGenBLowDelayEnabled && iRefList == 1)   // list 1
4714
0
      {
4715
0
        if (slice.list1IdxToList0Idx[iRefIdxTemp] >= 0 && (cu.affineType != AFFINEMODEL_6PARAM || slice.list1IdxToList0Idx[iRefIdxTemp] == refIdx4Para[0]))
4716
0
        {
4717
0
          int iList1ToList0Idx = slice.list1IdxToList0Idx[iRefIdxTemp];
4718
0
          ::memcpy(tmp.affMVs[1][iRefIdxTemp], tmp.affMVs[0][iList1ToList0Idx], sizeof(Mv) * 3);
4719
0
          uiCostTemp = uiCostTempL0[iList1ToList0Idx];
4720
4721
0
          uiCostTemp -= m_pcRdCost->getCost(uiBitsTempL0[iList1ToList0Idx]);
4722
0
          uiBitsTemp += xCalcAffineMVBits(cu, tmp.affMVs[iRefList][iRefIdxTemp], cMvPred[iRefList][iRefIdxTemp]);
4723
          /*calculate the correct cost*/
4724
0
          uiCostTemp += m_pcRdCost->getCost(uiBitsTemp);
4725
0
          DTRACE(g_trace_ctx, D_COMMON, " (%d) uiCostTemp=%d\n", DTRACE_GET_COUNTER(g_trace_ctx, D_COMMON), uiCostTemp);
4726
0
        }
4727
0
        else
4728
0
        {
4729
0
          xAffineMotionEstimation(cu, origBuf, refPicList, cMvPred[iRefList][iRefIdxTemp], iRefIdxTemp, tmp.affMVs[iRefList][iRefIdxTemp], 
4730
0
                                  uiBitsTemp, uiCostTemp, aaiMvpIdx[iRefList][iRefIdxTemp], affiAMVPInfoTemp[refPicList]);
4731
0
        }
4732
0
      }
4733
0
      else
4734
0
      {
4735
0
        xAffineMotionEstimation(cu, origBuf, refPicList, cMvPred[iRefList][iRefIdxTemp], iRefIdxTemp, tmp.affMVs[iRefList][iRefIdxTemp], 
4736
0
                                uiBitsTemp, uiCostTemp, aaiMvpIdx[iRefList][iRefIdxTemp], affiAMVPInfoTemp[refPicList]);
4737
0
      }
4738
      
4739
0
      if( slice.sps->BCW && cu.BcwIdx == BCW_DEFAULT && slice.isInterB() )
4740
0
      {
4741
0
        m_uniMotions.setReadModeAffine( true, (uint8_t)iRefList, (uint8_t)iRefIdxTemp, cu.affineType );
4742
0
        m_uniMotions.copyAffineMvFrom( tmp.affMVs[iRefList][iRefIdxTemp], uiCostTemp - m_pcRdCost->getCost(uiBitsTemp), (uint8_t)iRefList, (uint8_t)iRefIdxTemp, cu.affineType,
4743
0
                                       aaiMvpIdx[iRefList][iRefIdxTemp] );
4744
0
      }
4745
4746
      // Set best AMVP Index
4747
0
      xCopyAffineAMVPInfo(affiAMVPInfoTemp[refPicList], aacAffineAMVPInfo[iRefList][iRefIdxTemp]);
4748
0
      if (cu.imv != 2)//|| !m_pcEncCfg->getUseAffineAmvrEncOpt())
4749
0
        xCheckBestAffineMVP(cu, affiAMVPInfoTemp[refPicList], refPicList, tmp.affMVs[iRefList][iRefIdxTemp], cMvPred[iRefList][iRefIdxTemp], aaiMvpIdx[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp);
4750
4751
0
      if (iRefList == 0)
4752
0
      {
4753
0
        uiCostTempL0[iRefIdxTemp] = uiCostTemp;
4754
0
        uiBitsTempL0[iRefIdxTemp] = uiBitsTemp;
4755
0
      }
4756
0
      DTRACE(g_trace_ctx, D_COMMON, " (%d) uiCostTemp=%d, uiCost[iRefList]=%d\n", DTRACE_GET_COUNTER(g_trace_ctx, D_COMMON), uiCostTemp, uiCost[iRefList]);
4757
0
      if (uiCostTemp < uiCost[iRefList])
4758
0
      {
4759
0
        uiCost[iRefList] = uiCostTemp;
4760
0
        uiBits[iRefList] = uiBitsTemp; // storing for bi-prediction
4761
4762
                                       // set best motion
4763
0
        ::memcpy(aacMv[iRefList], tmp.affMVs[iRefList][iRefIdxTemp], sizeof(Mv) * 3);
4764
0
        iRefIdx[iRefList] = iRefIdxTemp;
4765
0
      }
4766
4767
0
      if (iRefList == 1 && uiCostTemp < costValidList1 && slice.list1IdxToList0Idx[iRefIdxTemp] < 0)
4768
0
      {
4769
0
        costValidList1 = uiCostTemp;
4770
0
        bitsValidList1 = uiBitsTemp;
4771
4772
        // set motion
4773
0
        memcpy(mvValidList1, tmp.affMVs[iRefList][iRefIdxTemp], sizeof(Mv) * 3);
4774
0
        refIdxValidList1 = iRefIdxTemp;
4775
0
      }
4776
0
    } // End refIdx loop
4777
0
  } // end Uni-prediction
4778
4779
0
  if (cu.affineType == AFFINEMODEL_4PARAM)
4780
0
  {
4781
0
    ::memcpy(mvAffine4Para, tmp.affMVs, sizeof(tmp.affMVs));
4782
0
    if (cu.imv == IMV_OFF)
4783
0
    {
4784
0
      m_AffineProfList->insert( tmp, cu.Y());
4785
0
    }
4786
0
  }
4787
4788
  // Bi-directional prediction
4789
0
  if (slice.isInterB() && !CU::isBipredRestriction(cu))
4790
0
  {
4791
0
    cu.interDir = 3;
4792
0
    m_isBi = true;
4793
4794
    // Set as best list0 and list1
4795
0
    iRefIdxBi[0] = iRefIdx[0];
4796
0
    iRefIdxBi[1] = iRefIdx[1];
4797
4798
0
    ::memcpy(cMvBi, aacMv, sizeof(aacMv));
4799
0
    ::memcpy(cMvPredBi, cMvPred, sizeof(cMvPred));
4800
0
    ::memcpy(aaiMvpIdxBi, aaiMvpIdx, sizeof(aaiMvpIdx));
4801
4802
0
    uint32_t uiMotBits[2];
4803
0
    bool doBiPred = true;
4804
4805
0
    if (slice.picHeader->mvdL1Zero) // GPB, list 1 only use Mvp
4806
0
    {
4807
0
      xCopyAffineAMVPInfo(aacAffineAMVPInfo[1][bestBiPRefIdxL1], affiAMVPInfoTemp[REF_PIC_LIST_1]);
4808
0
      cu.mvpIdx[REF_PIC_LIST_1] = bestBiPMvpL1;
4809
0
      aaiMvpIdxBi[1][bestBiPRefIdxL1] = bestBiPMvpL1;
4810
4811
      // Set Mv for list1
4812
0
      Mv pcMvTemp[3] = { affiAMVPInfoTemp[REF_PIC_LIST_1].mvCandLT[bestBiPMvpL1],
4813
0
                         affiAMVPInfoTemp[REF_PIC_LIST_1].mvCandRT[bestBiPMvpL1],
4814
0
                         affiAMVPInfoTemp[REF_PIC_LIST_1].mvCandLB[bestBiPMvpL1] };
4815
0
      ::memcpy(cMvPredBi[1][bestBiPRefIdxL1], pcMvTemp, sizeof(Mv) * 3);
4816
0
      ::memcpy(cMvBi[1], pcMvTemp, sizeof(Mv) * 3);
4817
0
      ::memcpy(tmp.affMVs[1][bestBiPRefIdxL1], pcMvTemp, sizeof(Mv) * 3);
4818
0
      iRefIdxBi[1] = bestBiPRefIdxL1;
4819
4820
0
      if( m_pcEncCfg->m_ifpLines && !xIsAffineMvInRangeFPP( cu, pcMvTemp, m_pcEncCfg->m_ifpLines ) )
4821
0
      {
4822
        // this mvp cannot be used for mv, skip Bi-pred
4823
0
        uiCostBi = MAX_DISTORTION;
4824
0
        doBiPred = false;
4825
0
      }
4826
0
      else
4827
0
      {
4828
4829
        // Get list1 prediction block
4830
0
        CU::setAllAffineMv(cu, cMvBi[1][0], cMvBi[1][1], cMvBi[1][2], REF_PIC_LIST_1);
4831
0
        cu.refIdx[REF_PIC_LIST_1] = iRefIdxBi[1];
4832
4833
0
        PelUnitBuf predBufTmp = m_tmpPredStorage[REF_PIC_LIST_1].getCompactBuf( cu );
4834
0
        motionCompensation(cu, predBufTmp, REF_PIC_LIST_1);
4835
4836
        // Update bits
4837
0
        uiMotBits[0] = uiBits[0] - uiMbBits[0];
4838
0
        uiMotBits[1] = uiMbBits[1];
4839
4840
0
        if (slice.numRefIdx[REF_PIC_LIST_1] > 1)
4841
0
        {
4842
0
          uiMotBits[1] += bestBiPRefIdxL1 + 1;
4843
0
          if (bestBiPRefIdxL1 == slice.numRefIdx[REF_PIC_LIST_1] - 1)
4844
0
          {
4845
0
            uiMotBits[1]--;
4846
0
          }
4847
0
        }
4848
0
        uiMotBits[1] += m_auiMVPIdxCost[aaiMvpIdxBi[1][bestBiPRefIdxL1]][AMVP_MAX_NUM_CANDS];
4849
0
        uiBits[2] = uiMbBits[2] + uiMotBits[0] + uiMotBits[1];
4850
0
      }
4851
0
    }
4852
0
    else
4853
0
    {
4854
0
      uiMotBits[0] = uiBits[0] - uiMbBits[0];
4855
0
      uiMotBits[1] = uiBits[1] - uiMbBits[1];
4856
0
      uiBits[2] = uiMbBits[2] + uiMotBits[0] + uiMotBits[1];
4857
0
    }
4858
4859
0
    if (doBiPred)
4860
0
    {
4861
      // 4-times iteration (default)
4862
0
      int iNumIter = 4;
4863
      // fast encoder setting or GPB: only one iteration
4864
0
      if (m_pcEncCfg->m_fastInterSearchMode == VVENC_FASTINTERSEARCH_MODE3 || m_pcEncCfg->m_fastInterSearchMode == VVENC_FASTINTERSEARCH_MODE2 || slice.picHeader->mvdL1Zero)
4865
0
      {
4866
0
        iNumIter = 1;
4867
0
      }
4868
4869
0
      for (int iIter = 0; iIter < iNumIter; iIter++)
4870
0
      {
4871
        // Set RefList
4872
0
        int iRefList = iIter % 2;
4873
0
        if (m_pcEncCfg->m_fastInterSearchMode == VVENC_FASTINTERSEARCH_MODE3 || m_pcEncCfg->m_fastInterSearchMode == VVENC_FASTINTERSEARCH_MODE2)
4874
0
        {
4875
0
          if (uiCost[0] <= uiCost[1])
4876
0
          {
4877
0
            iRefList = 1;
4878
0
          }
4879
0
          else
4880
0
          {
4881
0
            iRefList = 0;
4882
0
          }
4883
0
        }
4884
0
        else if (iIter == 0)
4885
0
        {
4886
0
          iRefList = 0;
4887
0
        }
4888
4889
        // First iterate, get prediction block of opposite direction
4890
0
        if (iIter == 0 && !slice.picHeader->mvdL1Zero)
4891
0
        {
4892
0
          if( m_pcEncCfg->m_ifpLines && !xIsAffineMvInRangeFPP( cu, aacMv[1 - iRefList], m_pcEncCfg->m_ifpLines ) )
4893
0
          {
4894
0
            continue;
4895
0
          }
4896
4897
0
          CU::setAllAffineMv(cu, aacMv[1 - iRefList][0], aacMv[1 - iRefList][1], aacMv[1 - iRefList][2], RefPicList(1 - iRefList));
4898
0
          cu.refIdx[1 - iRefList] = iRefIdx[1 - iRefList];
4899
4900
0
          PelUnitBuf predBufTmp = m_tmpPredStorage[1 - iRefList].getCompactBuf( cu );
4901
0
          motionCompensation(cu, predBufTmp, RefPicList(1 - iRefList));
4902
0
        }
4903
4904
0
        RefPicList refPicList = (iRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0);
4905
4906
0
        if (slice.picHeader->mvdL1Zero) // GPB, fix List 1, search List 0
4907
0
        {
4908
0
          iRefList = 0;
4909
0
          refPicList = REF_PIC_LIST_0;
4910
0
        }
4911
4912
0
        bool bChanged = false;
4913
4914
0
        iRefStart = 0;
4915
0
        iRefEnd = slice.numRefIdx[refPicList] - 1;
4916
0
        for (int iRefIdxTemp = iRefStart; iRefIdxTemp <= iRefEnd; iRefIdxTemp++)
4917
0
        {
4918
0
          if (cu.affineType == AFFINEMODEL_6PARAM && refIdx4Para[iRefList] != iRefIdxTemp)
4919
0
          {
4920
0
            continue;
4921
0
          }
4922
          // update bits
4923
0
          uiBitsTemp = uiMbBits[2] + uiMotBits[1 - iRefList];
4924
0
          uiBitsTemp += ( (cu.slice->sps->BCW == true) ? BcwIdxBits : 0 );
4925
0
          if (slice.numRefIdx[refPicList] > 1)
4926
0
          {
4927
0
            uiBitsTemp += iRefIdxTemp + 1;
4928
0
            if (iRefIdxTemp == slice.numRefIdx[refPicList] - 1)
4929
0
            {
4930
0
              uiBitsTemp--;
4931
0
            }
4932
0
          }
4933
0
          uiBitsTemp += m_auiMVPIdxCost[aaiMvpIdxBi[iRefList][iRefIdxTemp]][AMVP_MAX_NUM_CANDS];
4934
4935
          // call Affine ME
4936
0
          xAffineMotionEstimation(cu, origBuf, refPicList, cMvPredBi[iRefList][iRefIdxTemp], iRefIdxTemp, tmp.affMVs[iRefList][iRefIdxTemp], 
4937
0
                                  uiBitsTemp, uiCostTemp, aaiMvpIdxBi[iRefList][iRefIdxTemp], aacAffineAMVPInfo[iRefList][iRefIdxTemp], true);
4938
0
          xCopyAffineAMVPInfo(aacAffineAMVPInfo[iRefList][iRefIdxTemp], affiAMVPInfoTemp[refPicList]);
4939
0
          if (cu.imv != 2)
4940
0
          {
4941
0
            xCheckBestAffineMVP(cu, affiAMVPInfoTemp[refPicList], refPicList, tmp.affMVs[iRefList][iRefIdxTemp], cMvPredBi[iRefList][iRefIdxTemp], aaiMvpIdxBi[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp);
4942
0
          }
4943
4944
0
          if (uiCostTemp < uiCostBi)
4945
0
          {
4946
0
            bChanged = true;
4947
0
            ::memcpy(cMvBi[iRefList], tmp.affMVs[iRefList][iRefIdxTemp], sizeof(Mv) * 3);
4948
0
            iRefIdxBi[iRefList] = iRefIdxTemp;
4949
4950
0
            uiCostBi = uiCostTemp;
4951
0
            uiMotBits[iRefList] = uiBitsTemp - uiMbBits[2] - uiMotBits[1 - iRefList];
4952
0
            uiMotBits[iRefList] -= ( (cu.slice->sps->BCW == true) ? BcwIdxBits : 0 );
4953
0
            uiBits[2] = uiBitsTemp;
4954
4955
0
            if (iNumIter != 1) // MC for next iter
4956
0
            {
4957
              //  Set motion
4958
0
              CU::setAllAffineMv(cu, cMvBi[iRefList][0], cMvBi[iRefList][1], cMvBi[iRefList][2], refPicList);
4959
0
              cu.refIdx[refPicList] = iRefIdxBi[refPicList];
4960
0
              PelUnitBuf predBufTmp = m_tmpPredStorage[iRefList].getCompactBuf( cu );
4961
0
              motionCompensation(cu, predBufTmp, refPicList);
4962
0
            }
4963
0
          }
4964
0
        } // for loop-iRefIdxTemp
4965
4966
0
        if (!bChanged)
4967
0
        {
4968
0
          if ((uiCostBi <= uiCost[0] && uiCostBi <= uiCost[1]) || enforceBcwPred)
4969
0
          {
4970
0
            xCopyAffineAMVPInfo(aacAffineAMVPInfo[0][iRefIdxBi[0]], affiAMVPInfoTemp[REF_PIC_LIST_0]);
4971
0
            xCheckBestAffineMVP(cu, affiAMVPInfoTemp[REF_PIC_LIST_0], REF_PIC_LIST_0, cMvBi[0], cMvPredBi[0][iRefIdxBi[0]], aaiMvpIdxBi[0][iRefIdxBi[0]], uiBits[2], uiCostBi);
4972
4973
0
            if (!slice.picHeader->mvdL1Zero)
4974
0
            {
4975
0
              xCopyAffineAMVPInfo(aacAffineAMVPInfo[1][iRefIdxBi[1]], affiAMVPInfoTemp[REF_PIC_LIST_1]);
4976
0
              xCheckBestAffineMVP(cu, affiAMVPInfoTemp[REF_PIC_LIST_1], REF_PIC_LIST_1, cMvBi[1], cMvPredBi[1][iRefIdxBi[1]], aaiMvpIdxBi[1][iRefIdxBi[1]], uiBits[2], uiCostBi);
4977
0
            }
4978
0
          }
4979
0
          break;
4980
0
        }
4981
0
      } // for loop-iter
4982
0
    }
4983
0
    m_isBi = false;
4984
0
  } // if (B_SLICE)
4985
4986
0
  cu.mv [REF_PIC_LIST_0][0] = Mv();
4987
0
  cu.mv [REF_PIC_LIST_1][0] = Mv();
4988
0
  cu.mvd[REF_PIC_LIST_0][0] = cMvZero;
4989
0
  cu.mvd[REF_PIC_LIST_1][0] = cMvZero;
4990
0
  cu.refIdx[REF_PIC_LIST_0] = NOT_VALID;
4991
0
  cu.refIdx[REF_PIC_LIST_1] = NOT_VALID;
4992
0
  cu.mvpIdx[REF_PIC_LIST_0] = NOT_VALID;
4993
0
  cu.mvpIdx[REF_PIC_LIST_1] = NOT_VALID;
4994
0
  cu.mvpNum[REF_PIC_LIST_0] = NOT_VALID;
4995
0
  cu.mvpNum[REF_PIC_LIST_1] = NOT_VALID;
4996
4997
0
  for (int verIdx = 0; verIdx < 3; verIdx++)
4998
0
  {
4999
0
    cu.mvd[REF_PIC_LIST_0][verIdx] = cMvZero;
5000
0
    cu.mvd[REF_PIC_LIST_1][verIdx] = cMvZero;
5001
0
  }
5002
5003
  // Set Motion Field
5004
0
  memcpy(aacMv[1], mvValidList1, sizeof(Mv) * 3);
5005
0
  iRefIdx[1] = refIdxValidList1;
5006
0
  uiBits[1] = bitsValidList1;
5007
0
  uiCost[1] = costValidList1;
5008
5009
0
  if (enforceBcwPred)
5010
0
  {
5011
0
    uiCost[0] = uiCost[1] = MAX_UINT;
5012
0
  }
5013
5014
  // Affine ME result set
5015
0
  if (uiCostBi <= uiCost[0] && uiCostBi <= uiCost[1]) // Bi
5016
0
  {
5017
0
    lastMode = 2;
5018
0
    affineCost = uiCostBi;
5019
0
    cu.interDir = 3;
5020
0
    CU::setAllAffineMv(cu, cMvBi[0][0], cMvBi[0][1], cMvBi[0][2], REF_PIC_LIST_0);
5021
0
    CU::setAllAffineMv(cu, cMvBi[1][0], cMvBi[1][1], cMvBi[1][2], REF_PIC_LIST_1);
5022
0
    cu.refIdx[REF_PIC_LIST_0] = iRefIdxBi[0];
5023
0
    cu.refIdx[REF_PIC_LIST_1] = iRefIdxBi[1];
5024
5025
0
    for (int verIdx = 0; verIdx < mvNum; verIdx++)
5026
0
    {
5027
0
      cu.mvd[REF_PIC_LIST_0][verIdx] = cMvBi[0][verIdx] - cMvPredBi[0][iRefIdxBi[0]][verIdx];
5028
0
      cu.mvd[REF_PIC_LIST_1][verIdx] = cMvBi[1][verIdx] - cMvPredBi[1][iRefIdxBi[1]][verIdx];
5029
0
      if (verIdx != 0)
5030
0
      {
5031
0
        cu.mvd[0][verIdx] = cu.mvd[0][verIdx] - cu.mvd[0][0];
5032
0
        cu.mvd[1][verIdx] = cu.mvd[1][verIdx] - cu.mvd[1][0];
5033
0
      }
5034
0
    }
5035
5036
5037
0
    cu.mvpIdx[REF_PIC_LIST_0] = aaiMvpIdxBi[0][iRefIdxBi[0]];
5038
0
    cu.mvpNum[REF_PIC_LIST_0] = aaiMvpNum[0][iRefIdxBi[0]];
5039
0
    cu.mvpIdx[REF_PIC_LIST_1] = aaiMvpIdxBi[1][iRefIdxBi[1]];
5040
0
    cu.mvpNum[REF_PIC_LIST_1] = aaiMvpNum[1][iRefIdxBi[1]];
5041
0
  }
5042
0
  else if (uiCost[0] <= uiCost[1]) // List 0
5043
0
  {
5044
0
    lastMode = 0;
5045
0
    affineCost = uiCost[0];
5046
0
    cu.interDir = 1;
5047
0
    CU::setAllAffineMv(cu, aacMv[0][0], aacMv[0][1], aacMv[0][2], REF_PIC_LIST_0);
5048
0
    cu.refIdx[REF_PIC_LIST_0] = iRefIdx[0];
5049
5050
0
    for (int verIdx = 0; verIdx < mvNum; verIdx++)
5051
0
    {
5052
0
      cu.mvd[REF_PIC_LIST_0][verIdx] = aacMv[0][verIdx] - cMvPred[0][iRefIdx[0]][verIdx];
5053
0
      if (verIdx != 0)
5054
0
      {
5055
0
        cu.mvd[0][verIdx] = cu.mvd[0][verIdx] - cu.mvd[0][0];
5056
0
      }
5057
0
    }
5058
5059
0
    cu.mvpIdx[REF_PIC_LIST_0] = aaiMvpIdx[0][iRefIdx[0]];
5060
0
    cu.mvpNum[REF_PIC_LIST_0] = aaiMvpNum[0][iRefIdx[0]];
5061
0
  }
5062
0
  else
5063
0
  {
5064
0
    lastMode = 1;
5065
0
    affineCost = uiCost[1];
5066
0
    cu.interDir = 2;
5067
0
    CU::setAllAffineMv(cu, aacMv[1][0], aacMv[1][1], aacMv[1][2], REF_PIC_LIST_1);
5068
0
    cu.refIdx[REF_PIC_LIST_1] = iRefIdx[1];
5069
5070
0
    for (int verIdx = 0; verIdx < mvNum; verIdx++)
5071
0
    {
5072
0
      cu.mvd[REF_PIC_LIST_1][verIdx] = aacMv[1][verIdx] - cMvPred[1][iRefIdx[1]][verIdx];
5073
0
      if (verIdx != 0)
5074
0
      {
5075
0
        cu.mvd[1][verIdx] = cu.mvd[1][verIdx] - cu.mvd[1][0];
5076
0
      }
5077
0
    }
5078
5079
0
    cu.mvpIdx[REF_PIC_LIST_1] = aaiMvpIdx[1][iRefIdx[1]];
5080
0
    cu.mvpNum[REF_PIC_LIST_1] = aaiMvpNum[1][iRefIdx[1]];
5081
0
  }
5082
0
  if (BcwIdx != BCW_DEFAULT)
5083
0
  {
5084
0
    cu.BcwIdx = BCW_DEFAULT;
5085
0
  }
5086
0
}
5087
5088
Distortion InterSearch::xGetAffineTemplateCost(CodingUnit& cu, CPelUnitBuf& origBuf, PelUnitBuf& predBuf, Mv acMvCand[3], int iMVPIdx, int iMVPNum, RefPicList refPicList, int iRefIdx)
5089
0
{
5090
0
  Distortion uiCost = MAX_DISTORTION;
5091
5092
0
  const Picture* picRef = cu.slice->getRefPic(refPicList, iRefIdx);
5093
5094
  // prediction pattern
5095
0
  Mv mv[3];
5096
0
  memcpy(mv, acMvCand, sizeof(mv));
5097
5098
0
  if( m_pcEncCfg->m_ifpLines && !xIsAffineMvInRangeFPP( cu, mv, m_pcEncCfg->m_ifpLines ) )
5099
0
  {
5100
0
    return MAX_DISTORTION>>1;  
5101
0
  }
5102
5103
0
  xPredAffineBlk(COMP_Y, cu, picRef, mv, predBuf, false, cu.slice->clpRngs[COMP_Y], refPicList);
5104
5105
  // calc distortion
5106
0
  uiCost = m_pcRdCost->getDistPart(origBuf.Y(), predBuf.Y(), cu.cs->sps->bitDepths[CH_L], COMP_Y, DF_HAD );
5107
0
  uiCost += m_pcRdCost->getCost(m_auiMVPIdxCost[iMVPIdx][iMVPNum]);
5108
5109
0
  DTRACE(g_trace_ctx, D_COMMON, " (%d) affineTemplateCost=%d\n", DTRACE_GET_COUNTER(g_trace_ctx, D_COMMON), uiCost);
5110
0
  return uiCost;
5111
0
}
5112
5113
void solveEqual(double** dEqualCoeff, int iOrder, double* dAffinePara)
5114
0
{
5115
0
  for (int k = 0; k < iOrder; k++)
5116
0
  {
5117
0
    dAffinePara[k] = 0.;
5118
0
  }
5119
5120
  // row echelon
5121
0
  for (int i = 1; i < iOrder; i++)
5122
0
  {
5123
    // find column max
5124
0
    double temp = fabs(dEqualCoeff[i][i - 1]);
5125
0
    int tempIdx = i;
5126
0
    for (int j = i + 1; j < iOrder + 1; j++)
5127
0
    {
5128
0
      if (fabs(dEqualCoeff[j][i - 1]) > temp)
5129
0
      {
5130
0
        temp = fabs(dEqualCoeff[j][i - 1]);
5131
0
        tempIdx = j;
5132
0
      }
5133
0
    }
5134
5135
    // swap line
5136
0
    if (tempIdx != i)
5137
0
    {
5138
0
      for (int j = 0; j < iOrder + 1; j++)
5139
0
      {
5140
0
        dEqualCoeff[0][j] = dEqualCoeff[i][j];
5141
0
        dEqualCoeff[i][j] = dEqualCoeff[tempIdx][j];
5142
0
        dEqualCoeff[tempIdx][j] = dEqualCoeff[0][j];
5143
0
      }
5144
0
    }
5145
5146
    // elimination first column
5147
0
    if (dEqualCoeff[i][i - 1] == 0.)
5148
0
    {
5149
0
      return;
5150
0
    }
5151
0
    for (int j = i + 1; j < iOrder + 1; j++)
5152
0
    {
5153
0
      for (int k = i; k < iOrder + 1; k++)
5154
0
      {
5155
0
        dEqualCoeff[j][k] = dEqualCoeff[j][k] - dEqualCoeff[i][k] * dEqualCoeff[j][i - 1] / dEqualCoeff[i][i - 1];
5156
0
      }
5157
0
    }
5158
0
  }
5159
5160
0
  if (dEqualCoeff[iOrder][iOrder - 1] == 0.)
5161
0
  {
5162
0
    return;
5163
0
  }
5164
0
  dAffinePara[iOrder - 1] = dEqualCoeff[iOrder][iOrder] / dEqualCoeff[iOrder][iOrder - 1];
5165
0
  for (int i = iOrder - 2; i >= 0; i--)
5166
0
  {
5167
0
    if (dEqualCoeff[i + 1][i] == 0.)
5168
0
    {
5169
0
      for (int k = 0; k < iOrder; k++)
5170
0
      {
5171
0
        dAffinePara[k] = 0.;
5172
0
      }
5173
0
      return;
5174
0
    }
5175
0
    double temp = 0;
5176
0
    for (int j = i + 1; j < iOrder; j++)
5177
0
    {
5178
0
      temp += dEqualCoeff[i + 1][j] * dAffinePara[j];
5179
0
    }
5180
0
    dAffinePara[i] = (dEqualCoeff[i + 1][iOrder] - temp) / dEqualCoeff[i + 1][i];
5181
0
  }
5182
0
}
5183
5184
void InterSearch::xCheckBestAffineMVP(CodingUnit& cu, AffineAMVPInfo &affineAMVPInfo, RefPicList refPicList, Mv acMv[3], Mv acMvPred[3], int& riMVPIdx, uint32_t& ruiBits, Distortion& ruiCost)
5185
0
{
5186
0
  if (affineAMVPInfo.numCand < 2)
5187
0
  {
5188
0
    return;
5189
0
  }
5190
5191
0
  int mvNum = cu.affineType ? 3 : 2;
5192
5193
0
  m_pcRdCost->selectMotionLambda();
5194
0
  m_pcRdCost->setCostScale(0);
5195
5196
0
  int iBestMVPIdx = riMVPIdx;
5197
5198
  // Get origin MV bits
5199
0
  Mv tmpPredMv[3];
5200
0
  int iOrgMvBits = xCalcAffineMVBits(cu, acMv, acMvPred);
5201
0
  iOrgMvBits += m_auiMVPIdxCost[riMVPIdx][AMVP_MAX_NUM_CANDS];
5202
5203
0
  int iBestMvBits = iOrgMvBits;
5204
0
  for (int iMVPIdx = 0; iMVPIdx < affineAMVPInfo.numCand; iMVPIdx++)
5205
0
  {
5206
0
    if (iMVPIdx == riMVPIdx)
5207
0
    {
5208
0
      continue;
5209
0
    }
5210
0
    tmpPredMv[0] = affineAMVPInfo.mvCandLT[iMVPIdx];
5211
0
    tmpPredMv[1] = affineAMVPInfo.mvCandRT[iMVPIdx];
5212
0
    if (mvNum == 3)
5213
0
    {
5214
0
      tmpPredMv[2] = affineAMVPInfo.mvCandLB[iMVPIdx];
5215
0
    }
5216
0
    int iMvBits = xCalcAffineMVBits(cu, acMv, tmpPredMv);
5217
0
    iMvBits += m_auiMVPIdxCost[iMVPIdx][AMVP_MAX_NUM_CANDS];
5218
5219
0
    if (iMvBits < iBestMvBits)
5220
0
    {
5221
0
      iBestMvBits = iMvBits;
5222
0
      iBestMVPIdx = iMVPIdx;
5223
0
    }
5224
0
  }
5225
5226
0
  if (iBestMVPIdx != riMVPIdx)  // if changed
5227
0
  {
5228
0
    acMvPred[0] = affineAMVPInfo.mvCandLT[iBestMVPIdx];
5229
0
    acMvPred[1] = affineAMVPInfo.mvCandRT[iBestMVPIdx];
5230
0
    acMvPred[2] = affineAMVPInfo.mvCandLB[iBestMVPIdx];
5231
0
    riMVPIdx = iBestMVPIdx;
5232
0
    uint32_t uiOrgBits = ruiBits;
5233
0
    ruiBits = uiOrgBits - iOrgMvBits + iBestMvBits;
5234
0
    ruiCost = (ruiCost - m_pcRdCost->getCost(uiOrgBits)) + m_pcRdCost->getCost(ruiBits);
5235
0
  }
5236
0
}
5237
5238
void InterSearch::xAffineMotionEstimation(CodingUnit& cu,
5239
  CPelUnitBuf&    origBuf,
5240
  RefPicList      refPicList,
5241
  Mv              acMvPred[3],
5242
  int             iRefIdxPred,
5243
  Mv              acMv[3],
5244
  uint32_t&       ruiBits,
5245
  Distortion&     ruiCost,
5246
  int&            mvpIdx,
5247
  const AffineAMVPInfo& aamvpi,
5248
  bool            bBi)
5249
0
{
5250
0
  if( cu.cs->sps->BCW && cu.BcwIdx != BCW_DEFAULT && !bBi && xReadBufferedAffineUniMv( cu, refPicList, iRefIdxPred, acMvPred, acMv, ruiBits, ruiCost, mvpIdx, aamvpi ) )
5251
0
  {
5252
0
    return;
5253
0
  }
5254
5255
0
  int bestMvpIdx = mvpIdx;
5256
0
  const int width = cu.Y().width;
5257
0
  const int height = cu.Y().height;
5258
5259
0
  const Picture* refPic = cu.slice->getRefPic(refPicList, iRefIdxPred);
5260
5261
  // Set Origin YUV: pcYuv
5262
0
  CPelUnitBuf*   pBuf = &origBuf;
5263
0
  double        fWeight = 1.0;
5264
5265
0
  CPelUnitBuf  origBufTmpCnst;
5266
5267
  // if Bi, set to ( 2 * Org - ListX )
5268
0
  if (bBi)
5269
0
  {
5270
0
    PelUnitBuf  origBufTmp = m_tmpStorageLCU.getCompactBuf(cu);
5271
    // NOTE: Other buf contains predicted signal from another direction
5272
0
    PelUnitBuf otherBuf = m_tmpPredStorage[1 - (int)refPicList].getCompactBuf( cu );
5273
0
    origBufTmp.copyFrom(origBuf);
5274
0
    origBufTmp.removeHighFreq(otherBuf, m_pcEncCfg->m_bClipForBiPredMeEnabled, cu.slice->clpRngs);
5275
5276
0
    origBufTmpCnst = origBufTmp;
5277
0
    pBuf           = &origBufTmpCnst;
5278
0
    fWeight        = xGetMEDistortionWeight(cu.BcwIdx, refPicList);
5279
0
  }
5280
5281
  // pred YUV
5282
0
  PelUnitBuf  predBuf = m_tmpAffiStorage.getCompactBuf(cu);
5283
5284
  // Set start Mv position, use input mv as started search mv
5285
0
  Mv acMvTemp[3];
5286
0
  ::memcpy(acMvTemp, acMv, sizeof(Mv) * 3);
5287
  // Set delta mv
5288
  // malloc buffer
5289
0
  int iParaNum = cu.affineType ? 7 : 5;
5290
0
  int affineParaNum = iParaNum - 1;
5291
0
  int mvNum = cu.affineType ? 3 : 2;
5292
0
  double **pdEqualCoeff;
5293
0
  pdEqualCoeff = new double *[iParaNum];
5294
0
  for (int i = 0; i < iParaNum; i++)
5295
0
  {
5296
0
    pdEqualCoeff[i] = new double[iParaNum];
5297
0
  }
5298
5299
0
  int64_t  i64EqualCoeff[7][7];
5300
0
  Pel    *piError = m_tmpAffiError;
5301
0
  Pel    *pdDerivate[2];
5302
0
  pdDerivate[0] = m_tmpAffiDeri[0];
5303
0
  pdDerivate[1] = m_tmpAffiDeri[1];
5304
5305
0
  Distortion uiCostBest = MAX_DISTORTION;
5306
0
  uint32_t uiBitsBest = 0;
5307
5308
  // do motion compensation with origin mv
5309
5310
0
  clipMv(acMvTemp[0], cu.lumaPos(), cu.lumaSize(), *cu.cs->pcv);
5311
0
  clipMv(acMvTemp[1], cu.lumaPos(), cu.lumaSize(), *cu.cs->pcv);
5312
0
  if (cu.affineType == AFFINEMODEL_6PARAM)
5313
0
  {
5314
0
    clipMv(acMvTemp[2], cu.lumaPos(), cu.lumaSize(), *cu.cs->pcv);
5315
0
  }
5316
5317
0
  acMvTemp[0].roundAffinePrecInternal2Amvr(cu.imv);
5318
0
  acMvTemp[1].roundAffinePrecInternal2Amvr(cu.imv);
5319
0
  if (cu.affineType == AFFINEMODEL_6PARAM)
5320
0
  {
5321
0
    acMvTemp[2].roundAffinePrecInternal2Amvr(cu.imv);
5322
0
  }
5323
0
  if( !m_pcEncCfg->m_ifpLines || xIsAffineMvInRangeFPP( cu, acMvTemp, m_pcEncCfg->m_ifpLines ) )
5324
0
  {
5325
0
    xPredAffineBlk(COMP_Y, cu, refPic, acMvTemp, predBuf, false, cu.cs->slice->clpRngs[COMP_Y], refPicList);
5326
5327
    // get error
5328
0
    uiCostBest = m_pcRdCost->getDistPart(predBuf.Y(), pBuf->Y(), cu.cs->sps->bitDepths[CH_L], COMP_Y, DF_HAD);
5329
5330
    // get cost with mv
5331
0
    m_pcRdCost->setCostScale(0);
5332
0
    uiBitsBest = ruiBits;
5333
0
    DTRACE(g_trace_ctx, D_COMMON, " (%d) xx uiBitsBest=%d\n", DTRACE_GET_COUNTER(g_trace_ctx, D_COMMON), uiBitsBest);
5334
0
    uiBitsBest += xCalcAffineMVBits(cu, acMvTemp, acMvPred);
5335
0
    DTRACE(g_trace_ctx, D_COMMON, " (%d) yy uiBitsBest=%d\n", DTRACE_GET_COUNTER(g_trace_ctx, D_COMMON), uiBitsBest);
5336
0
    uiCostBest = (Distortion)(floor(fWeight * (double)uiCostBest) + (double)m_pcRdCost->getCost(uiBitsBest));
5337
5338
0
    DTRACE(g_trace_ctx, D_COMMON, " (%d) uiBitsBest=%d, uiCostBest=%d\n", DTRACE_GET_COUNTER(g_trace_ctx, D_COMMON), uiBitsBest, uiCostBest);
5339
5340
0
    ::memcpy(acMv, acMvTemp, sizeof(Mv) * 3);
5341
0
  }
5342
0
  const int predBufStride = predBuf.Y().stride;
5343
0
  Mv prevIterMv[7][3];
5344
0
  int iIterTime;
5345
0
  if (cu.affineType == AFFINEMODEL_6PARAM)
5346
0
  {
5347
0
    iIterTime = bBi ? 3 : 4;
5348
0
  }
5349
0
  else
5350
0
  {
5351
0
    iIterTime = bBi ? 3 : 5;
5352
0
  }
5353
5354
0
  if (!cu.cs->sps->AffineType)// getUseAffineType())
5355
0
  {
5356
0
    iIterTime = bBi ? 5 : 7;
5357
0
  }
5358
5359
0
  for (int iter = 0; iter<iIterTime; iter++)    // iterate loop
5360
0
  {
5361
0
    memcpy(prevIterMv[iter], acMvTemp, sizeof(Mv) * 3);
5362
    /*********************************************************************************
5363
    *                         use gradient to update mv
5364
    *********************************************************************************/
5365
    // get Error Matrix
5366
0
    PelBuf( piError, width, height ).subtract( pBuf->Y(), predBuf.Y() );
5367
5368
    // sobel x direction
5369
    // -1 0 1
5370
    // -2 0 2
5371
    // -1 0 1
5372
0
    Pel* pPred = predBuf.Y().buf;
5373
0
    m_HorizontalSobelFilter(pPred, predBufStride, pdDerivate[0], width, width, height);
5374
5375
    // sobel y direction
5376
    // -1 -2 -1
5377
    //  0  0  0
5378
    //  1  2  1
5379
0
    m_VerticalSobelFilter(pPred, predBufStride, pdDerivate[1], width, width, height);
5380
5381
    // solve delta x and y
5382
0
    for (int row = 0; row < iParaNum; row++)
5383
0
    {
5384
0
      memset(&i64EqualCoeff[row][0], 0, iParaNum * sizeof(int64_t));
5385
0
    }
5386
5387
0
    m_EqualCoeffComputer[cu.affineType]( piError, width, pdDerivate, width, width, height, i64EqualCoeff );
5388
5389
0
    for (int row = 0; row < iParaNum; row++)
5390
0
    {
5391
0
      for (int i = 0; i < iParaNum; i++)
5392
0
      {
5393
0
        pdEqualCoeff[row][i] = (double)i64EqualCoeff[row][i];
5394
0
      }
5395
0
    }
5396
5397
0
    double dAffinePara[6];
5398
0
    double dDeltaMv[6];
5399
0
    Mv acDeltaMv[3];
5400
5401
0
    solveEqual(pdEqualCoeff, affineParaNum, dAffinePara);
5402
5403
    // convert to delta mv
5404
0
    dDeltaMv[0] = dAffinePara[0];
5405
0
    dDeltaMv[2] = dAffinePara[2];
5406
0
    const bool extParams = cu.affineType == AFFINEMODEL_6PARAM;
5407
0
    if (extParams)
5408
0
    {
5409
0
      dDeltaMv[1] = dAffinePara[1] * width + dAffinePara[0];
5410
0
      dDeltaMv[3] = dAffinePara[3] * width + dAffinePara[2];
5411
0
      dDeltaMv[4] = dAffinePara[4] * height + dAffinePara[0];
5412
0
      dDeltaMv[5] = dAffinePara[5] * height + dAffinePara[2];
5413
0
    }
5414
0
    else
5415
0
    {
5416
0
      dDeltaMv[1] = dAffinePara[1] * width + dAffinePara[0];
5417
0
      dDeltaMv[3] = -dAffinePara[3] * width + dAffinePara[2];
5418
0
    }
5419
5420
0
    const int normShiftTab[3] = { MV_PRECISION_QUARTER - MV_PRECISION_INT, MV_PRECISION_SIXTEENTH - MV_PRECISION_INT, MV_PRECISION_QUARTER - MV_PRECISION_INT };
5421
0
    const int stepShiftTab[3] = { MV_PRECISION_INTERNAL - MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL - MV_PRECISION_SIXTEENTH, MV_PRECISION_INTERNAL - MV_PRECISION_QUARTER };
5422
0
    const int multiShift = 1 << normShiftTab[cu.imv];
5423
0
    const int mvShift = stepShiftTab[cu.imv];
5424
5425
0
    acDeltaMv[0] = Mv((int)(dDeltaMv[0] * multiShift + SIGN(dDeltaMv[0]) * 0.5) * (1<< mvShift), (int)(dDeltaMv[2] * multiShift + SIGN(dDeltaMv[2]) * 0.5) * (1<< mvShift));
5426
0
    acDeltaMv[1] = Mv((int)(dDeltaMv[1] * multiShift + SIGN(dDeltaMv[1]) * 0.5) * (1<< mvShift), (int)(dDeltaMv[3] * multiShift + SIGN(dDeltaMv[3]) * 0.5) * (1<< mvShift));
5427
0
    if (extParams)
5428
0
    {
5429
0
      acDeltaMv[2] = Mv((int)(dDeltaMv[4] * multiShift + SIGN(dDeltaMv[4]) * 0.5) *  (1<< mvShift), (int)(dDeltaMv[5] * multiShift + SIGN(dDeltaMv[5]) * 0.5) *  (1<< mvShift));
5430
0
    }
5431
0
    bool bAllZero = false;
5432
0
    for (int i = 0; i < mvNum; i++)
5433
0
    {
5434
0
      Mv deltaMv = acDeltaMv[i];
5435
0
      if (cu.imv == IMV_4PEL)
5436
0
      {
5437
0
        deltaMv.roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_HALF);
5438
0
      }
5439
0
      if (deltaMv.hor != 0 || deltaMv.ver != 0)
5440
0
      {
5441
0
        bAllZero = false;
5442
0
        break;
5443
0
      }
5444
0
      bAllZero = true;
5445
0
    }
5446
5447
0
    if (bAllZero)
5448
0
      break;
5449
5450
    // do motion compensation with updated mv
5451
0
    for (int i = 0; i < mvNum; i++)
5452
0
    {
5453
0
      acMvTemp[i] += acDeltaMv[i];
5454
0
      acMvTemp[i].hor = Clip3(MV_MIN, MV_MAX, acMvTemp[i].hor);
5455
0
      acMvTemp[i].ver = Clip3(MV_MIN, MV_MAX, acMvTemp[i].ver);
5456
0
      acMvTemp[i].roundAffinePrecInternal2Amvr(cu.imv);
5457
5458
0
      clipMv(acMvTemp[i], cu.lumaPos(), cu.lumaSize(), *cu.cs->pcv);
5459
0
    }
5460
5461
0
    if( !m_pcEncCfg->m_ifpLines || xIsAffineMvInRangeFPP( cu, acMvTemp, m_pcEncCfg->m_ifpLines ) )
5462
0
    {
5463
0
      xPredAffineBlk(COMP_Y, cu, refPic, acMvTemp, predBuf, false, cu.slice->clpRngs[COMP_Y], refPicList);
5464
5465
      // get error
5466
0
      Distortion uiCostTemp = m_pcRdCost->getDistPart(predBuf.Y(), pBuf->Y(), cu.cs->sps->bitDepths[CH_L], COMP_Y, DF_HAD);
5467
0
      DTRACE(g_trace_ctx, D_COMMON, " (%d) uiCostTemp=%d\n", DTRACE_GET_COUNTER(g_trace_ctx, D_COMMON), uiCostTemp);
5468
5469
      // get cost with mv
5470
0
      m_pcRdCost->setCostScale(0);
5471
0
      uint32_t uiBitsTemp = ruiBits;
5472
0
      uiBitsTemp += xCalcAffineMVBits(cu, acMvTemp, acMvPred);
5473
0
      uiCostTemp = (Distortion)(floor(fWeight * (double)uiCostTemp) + (double)m_pcRdCost->getCost(uiBitsTemp));
5474
5475
      // store best cost and mv
5476
0
      if (uiCostTemp < uiCostBest)
5477
0
      {
5478
0
        uiCostBest = uiCostTemp;
5479
0
        uiBitsBest = uiBitsTemp;
5480
0
        memcpy(acMv, acMvTemp, sizeof(Mv) * 3);
5481
0
        mvpIdx = bestMvpIdx;
5482
0
      }
5483
0
      else if(m_pcEncCfg->m_Affine > 1)
5484
0
      {
5485
0
        break;
5486
0
      }
5487
0
    }
5488
0
  }
5489
5490
0
  auto checkCPMVRdCost = [&](Mv ctrlPtMv[3])
5491
0
  {
5492
0
    if( !m_pcEncCfg->m_ifpLines || xIsAffineMvInRangeFPP( cu, ctrlPtMv, m_pcEncCfg->m_ifpLines ) )
5493
0
    {
5494
0
      xPredAffineBlk(COMP_Y, cu, refPic, ctrlPtMv, predBuf, false, cu.slice->clpRngs[COMP_Y], refPicList);
5495
      // get error
5496
0
      Distortion costTemp = m_pcRdCost->getDistPart(predBuf.Y(), pBuf->Y(), cu.cs->sps->bitDepths[CH_L], COMP_Y, DF_HAD);
5497
      // get cost with mv
5498
0
      m_pcRdCost->setCostScale(0);
5499
0
      uint32_t bitsTemp = ruiBits;
5500
0
      bitsTemp += xCalcAffineMVBits(cu, ctrlPtMv, acMvPred);
5501
0
      costTemp = (Distortion)(floor(fWeight * (double)costTemp) + (double)m_pcRdCost->getCost(bitsTemp));
5502
      // store best cost and mv
5503
0
      if (costTemp < uiCostBest)
5504
0
      {
5505
0
        uiCostBest = costTemp;
5506
0
        uiBitsBest = bitsTemp;
5507
0
        ::memcpy(acMv, ctrlPtMv, sizeof(Mv) * 3);
5508
0
      }
5509
0
    }
5510
0
  };
5511
5512
0
  const uint32_t mvShiftTable[3] = { MV_PRECISION_INTERNAL - MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL - MV_PRECISION_INTERNAL, MV_PRECISION_INTERNAL - MV_PRECISION_INT };
5513
0
  const uint32_t mvShift = mvShiftTable[cu.imv];
5514
0
  if (uiCostBest <= AFFINE_ME_LIST_MVP_TH*m_hevcCost)
5515
0
  {
5516
0
    Mv mvPredTmp[3] = { acMvPred[0], acMvPred[1], acMvPred[2] };
5517
0
    Mv mvME[3];
5518
0
    ::memcpy(mvME, acMv, sizeof(Mv) * 3);
5519
0
    Mv dMv = mvME[0] - mvPredTmp[0];
5520
5521
0
    for (int j = 0; j < mvNum; j++)
5522
0
    {
5523
0
      if ((!j && mvME[j] != mvPredTmp[j]) || (j && mvME[j] != (mvPredTmp[j] + dMv)))
5524
0
      {
5525
0
        ::memcpy(acMvTemp, mvME, sizeof(Mv) * 3);
5526
0
        acMvTemp[j] = mvPredTmp[j];
5527
5528
0
        if (j)
5529
0
          acMvTemp[j] += dMv;
5530
5531
0
        checkCPMVRdCost(acMvTemp);
5532
0
      }
5533
0
    }
5534
5535
    //keep the rotation/zoom;
5536
0
    if (mvME[0] != mvPredTmp[0])
5537
0
    {
5538
0
      ::memcpy(acMvTemp, mvME, sizeof(Mv) * 3);
5539
0
      for (int i = 1; i < mvNum; i++)
5540
0
      {
5541
0
        acMvTemp[i] -= dMv;
5542
0
      }
5543
0
      acMvTemp[0] = mvPredTmp[0];
5544
5545
0
      checkCPMVRdCost(acMvTemp);
5546
0
    }
5547
5548
    //keep the translation;
5549
0
    if (cu.affineType == AFFINEMODEL_6PARAM && mvME[1] != (mvPredTmp[1] + dMv) && mvME[2] != (mvPredTmp[2] + dMv))
5550
0
    {
5551
0
      ::memcpy(acMvTemp, mvME, sizeof(Mv) * 3);
5552
5553
0
      acMvTemp[1] = mvPredTmp[1] + dMv;
5554
0
      acMvTemp[2] = mvPredTmp[2] + dMv;
5555
5556
0
      checkCPMVRdCost(acMvTemp);
5557
0
    }
5558
5559
    // 8 nearest neighbor search
5560
0
    int testPos[8][2] = { { -1, 0 },{ 0, -1 },{ 0, 1 },{ 1, 0 },{ -1, -1 },{ -1, 1 },{ 1, 1 },{ 1, -1 } };
5561
0
    const int maxSearchRound = 3;
5562
5563
0
    for (int rnd = 0; rnd < maxSearchRound; rnd++)
5564
0
    {
5565
0
      bool modelChange = false;
5566
      //search the model parameters with finear granularity;
5567
0
      for (int j = 0; j < mvNum; j++)
5568
0
      {
5569
0
        bool loopChange = false;
5570
0
        for (int iter = 0; iter < 2; iter++)
5571
0
        {
5572
0
          if (iter == 1 && !loopChange)
5573
0
          {
5574
0
            break;
5575
0
          }
5576
0
          Mv centerMv[3];
5577
0
          memcpy(centerMv, acMv, sizeof(Mv) * 3);
5578
0
          memcpy(acMvTemp, acMv, sizeof(Mv) * 3);
5579
5580
0
          for (int i = ((iter == 0) ? 0 : 4); i < ((iter == 0) ? 4 : 8); i++)
5581
0
          {
5582
0
            acMvTemp[j].set(centerMv[j].hor + (testPos[i][0] * (1 << mvShift)), centerMv[j].ver + (testPos[i][1] * (1 << mvShift)));
5583
0
            clipMv(acMvTemp[j], cu.lumaPos(), cu.lumaSize(), *cu.cs->pcv);
5584
5585
0
            if( !m_pcEncCfg->m_ifpLines || xIsAffineMvInRangeFPP( cu, acMvTemp, m_pcEncCfg->m_ifpLines ) )
5586
0
            {
5587
0
              xPredAffineBlk(COMP_Y, cu, refPic, acMvTemp, predBuf, false, cu.slice->clpRngs[COMP_Y], refPicList);
5588
5589
0
              Distortion costTemp = m_pcRdCost->getDistPart(predBuf.Y(), pBuf->Y(), cu.cs->sps->bitDepths[CH_L], COMP_Y, DF_HAD);
5590
0
              uint32_t bitsTemp = ruiBits;
5591
0
              bitsTemp += xCalcAffineMVBits(cu, acMvTemp, acMvPred);
5592
0
              costTemp = (Distortion)(floor(fWeight * (double)costTemp) + (double)m_pcRdCost->getCost(bitsTemp));
5593
5594
0
              if (costTemp < uiCostBest)
5595
0
              {
5596
0
                uiCostBest = costTemp;
5597
0
                uiBitsBest = bitsTemp;
5598
0
                ::memcpy(acMv, acMvTemp, sizeof(Mv) * 3);
5599
0
                modelChange = true;
5600
0
                loopChange = true;
5601
0
              }
5602
0
            }
5603
0
          }
5604
0
        }
5605
0
      }
5606
5607
0
      if (!modelChange)
5608
0
      {
5609
0
        break;
5610
0
      }
5611
0
    }
5612
0
  }
5613
0
  acMvPred[0] = aamvpi.mvCandLT[mvpIdx];
5614
0
  acMvPred[1] = aamvpi.mvCandRT[mvpIdx];
5615
0
  acMvPred[2] = aamvpi.mvCandLB[mvpIdx];
5616
5617
  // free buffer
5618
0
  for (int i = 0; i<iParaNum; i++)
5619
0
    delete[]pdEqualCoeff[i];
5620
0
  delete[]pdEqualCoeff;
5621
5622
0
  ruiBits = uiBitsBest;
5623
0
  ruiCost = uiCostBest;
5624
0
  DTRACE(g_trace_ctx, D_COMMON, " (%d) uiBitsBest=%d, uiCostBest=%d\n", DTRACE_GET_COUNTER(g_trace_ctx, D_COMMON), uiBitsBest, uiCostBest);
5625
0
}
5626
5627
bool InterSearch::xEstimateAffineAMVP(CodingUnit& cu, AffineAMVPInfo& affineAMVPInfo, CPelUnitBuf& origBuf, RefPicList refPicList, int iRefIdx, Mv acMvPred[3], Distortion& distBiP)
5628
0
{
5629
0
  Mv         bestMvLT, bestMvRT, bestMvLB;
5630
0
  int        iBestIdx = 0;
5631
0
  Distortion uiBestCost = MAX_DISTORTION;
5632
5633
  // Fill the MV Candidates
5634
0
  CU::fillAffineMvpCand(cu, refPicList, iRefIdx, affineAMVPInfo);
5635
0
  CHECK(affineAMVPInfo.numCand == 0, "Assertion failed.");
5636
5637
0
  PelUnitBuf predBuf = m_tmpStorageLCU.getCompactBuf( cu );
5638
5639
0
  bool stop_check = false;
5640
0
  if (affineAMVPInfo.mvCandLT[0] == affineAMVPInfo.mvCandLT[1])
5641
0
  {
5642
0
    if ((affineAMVPInfo.mvCandRT[0] == affineAMVPInfo.mvCandRT[1]) && (affineAMVPInfo.mvCandLB[0] == affineAMVPInfo.mvCandLB[1]))
5643
0
    {
5644
0
      stop_check = true;
5645
0
    }
5646
0
  }
5647
5648
  // initialize Mvp index & Mvp
5649
0
  iBestIdx = -1;
5650
0
  for (int i = 0; i < affineAMVPInfo.numCand; i++)
5651
0
  {
5652
0
    if (i && stop_check)
5653
0
    {
5654
0
      continue;
5655
0
    }
5656
0
    Mv mv[3] = { affineAMVPInfo.mvCandLT[i], affineAMVPInfo.mvCandRT[i], affineAMVPInfo.mvCandLB[i] };
5657
0
    Distortion uiTmpCost = xGetAffineTemplateCost(cu, origBuf, predBuf, mv, i, AMVP_MAX_NUM_CANDS, refPicList, iRefIdx);
5658
5659
0
    if (uiBestCost > uiTmpCost)
5660
0
    {
5661
0
      uiBestCost = uiTmpCost;
5662
0
      bestMvLT = affineAMVPInfo.mvCandLT[i];
5663
0
      bestMvRT = affineAMVPInfo.mvCandRT[i];
5664
0
      bestMvLB = affineAMVPInfo.mvCandLB[i];
5665
0
      iBestIdx = i;
5666
0
      distBiP  = uiTmpCost;
5667
0
    }
5668
0
  }
5669
5670
0
  if( iBestIdx < 0 )
5671
0
    return false;
5672
5673
  // Setting Best MVP
5674
0
  acMvPred[0] = bestMvLT;
5675
0
  acMvPred[1] = bestMvRT;
5676
0
  acMvPred[2] = bestMvLB;
5677
5678
0
  cu.mvpIdx[refPicList] = iBestIdx;
5679
0
  cu.mvpNum[refPicList] = affineAMVPInfo.numCand;
5680
0
  DTRACE(g_trace_ctx, D_COMMON, "#estAffi=%d \n", affineAMVPInfo.numCand);
5681
0
  return true;
5682
0
}
5683
5684
void InterSearch::xCopyAffineAMVPInfo(AffineAMVPInfo& src, AffineAMVPInfo& dst)
5685
0
{
5686
0
  dst.numCand = src.numCand;
5687
0
  DTRACE(g_trace_ctx, D_COMMON, " (%d) #copyAffi=%d \n", DTRACE_GET_COUNTER(g_trace_ctx, D_COMMON), src.numCand);
5688
0
  ::memcpy(dst.mvCandLT, src.mvCandLT, sizeof(Mv)*src.numCand);
5689
0
  ::memcpy(dst.mvCandRT, src.mvCandRT, sizeof(Mv)*src.numCand);
5690
0
  ::memcpy(dst.mvCandLB, src.mvCandLB, sizeof(Mv)*src.numCand);
5691
0
}
5692
5693
uint32_t InterSearch::xCalcAffineMVBits(CodingUnit& cu, Mv acMvTemp[3], Mv acMvPred[3])
5694
0
{
5695
0
  int mvNum = cu.affineType ? 3 : 2;
5696
0
  m_pcRdCost->setCostScale(0);
5697
0
  uint32_t bitsTemp = 0;
5698
5699
0
  for (int verIdx = 0; verIdx < mvNum; verIdx++)
5700
0
  {
5701
0
    Mv pred = verIdx == 0 ? acMvPred[verIdx] : acMvPred[verIdx] + acMvTemp[0] - acMvPred[0];
5702
0
    pred.changeAffinePrecInternal2Amvr(cu.imv);
5703
0
    m_pcRdCost->setPredictor(pred);
5704
0
    Mv mv = acMvTemp[verIdx];
5705
0
    mv.changeAffinePrecInternal2Amvr(cu.imv);
5706
5707
0
    bitsTemp += m_pcRdCost->getBitsOfVectorWithPredictor(mv.hor, mv.ver, 0);
5708
0
  }
5709
5710
0
  return bitsTemp;
5711
0
}
5712
5713
5714
//! set adaptive search range based on poc difference
5715
void InterSearch::setSearchRange( const Slice* slice, const VVEncCfg& encCfg )
5716
4.80k
{
5717
4.80k
  if( !encCfg.m_bUseASR || slice->isIRAP() )
5718
4.80k
  {
5719
4.80k
    return;
5720
4.80k
  }
5721
5722
0
  int iCurrPOC = slice->poc;
5723
0
  int iRefPOC;
5724
0
  int iGOPSize = encCfg.m_GOPSize;
5725
0
  int iOffset = (iGOPSize >> 1);
5726
0
  int iMaxSR = encCfg.m_SearchRange;
5727
0
  int iNumPredDir = slice->isInterP() ? 1 : 2;
5728
5729
0
  for (int iDir = 0; iDir < iNumPredDir; iDir++)
5730
0
  {
5731
0
    RefPicList  e = ( iDir ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
5732
0
    for (int iRefIdx = 0; iRefIdx < slice->numRefIdx[e]; iRefIdx++)
5733
0
    {
5734
0
      iRefPOC = slice->getRefPic(e, iRefIdx)->getPOC();
5735
0
      int newSearchRange = Clip3(encCfg.m_minSearchWindow, iMaxSR, (iMaxSR*ADAPT_SR_SCALE*abs(iCurrPOC - iRefPOC)+iOffset)/iGOPSize);
5736
0
      m_aaiAdaptSR[iDir][iRefIdx] = newSearchRange;
5737
0
    }
5738
0
  }
5739
0
}
5740
5741
void InterSearch::xIBCSearchMVCandUpdate(Distortion  sad, int x, int y, Distortion* sadBestCand, Mv* cMVCand)
5742
1.22M
{
5743
1.22M
  int j = CHROMA_REFINEMENT_CANDIDATES - 1;
5744
5745
1.22M
  if (sad < sadBestCand[CHROMA_REFINEMENT_CANDIDATES - 1])
5746
197k
  {
5747
1.77M
    for (int t = CHROMA_REFINEMENT_CANDIDATES - 1; t >= 0; t--)
5748
1.57M
    {
5749
1.57M
      if (sad < sadBestCand[t])
5750
948k
        j = t;
5751
1.57M
    }
5752
5753
948k
    for (int k = CHROMA_REFINEMENT_CANDIDATES - 1; k > j; k--)
5754
751k
    {
5755
751k
      sadBestCand[k] = sadBestCand[k - 1];
5756
5757
751k
      cMVCand[k].set(cMVCand[k - 1].hor, cMVCand[k - 1].ver);
5758
751k
    }
5759
197k
    sadBestCand[j] = sad;
5760
197k
    cMVCand[j].set(x, y);
5761
197k
  }
5762
1.22M
}
5763
5764
int InterSearch::xIBCSearchMVChromaRefine(CodingUnit& cu,
5765
  int         roiWidth,
5766
  int         roiHeight,
5767
  int         cuPelX,
5768
  int         cuPelY,
5769
  Distortion* sadBestCand,
5770
  Mv* cMVCand
5771
5772
)
5773
21.3k
{
5774
21.3k
  if ((!isChromaEnabled(cu.chromaFormat)) || (!cu.Cb().valid()))
5775
21.3k
  {
5776
21.3k
    return 0;
5777
21.3k
  }
5778
5779
0
  int bestCandIdx = 0;
5780
0
  Distortion  sadBest = std::numeric_limits<Distortion>::max();
5781
0
  Distortion  tempSad;
5782
5783
0
  Pel* pRef;
5784
0
  Pel* pOrg;
5785
0
  int refStride, orgStride;
5786
0
  int width, height;
5787
5788
0
  int picWidth = cu.cs->slice->pps->picWidthInLumaSamples;
5789
0
  int picHeight = cu.cs->slice->pps->picHeightInLumaSamples;
5790
5791
0
  UnitArea allCompBlocks(cu.chromaFormat, (Area)cu.block(COMP_Y));
5792
0
  for (int cand = 0; cand < CHROMA_REFINEMENT_CANDIDATES; cand++)
5793
0
  {
5794
0
    if (sadBestCand[cand] == std::numeric_limits<Distortion>::max())
5795
0
    {
5796
0
      continue;
5797
0
    }
5798
5799
0
    if ((!cMVCand[cand].hor) && (!cMVCand[cand].ver))
5800
0
      continue;
5801
5802
0
    if (((int)(cuPelY + cMVCand[cand].ver + roiHeight) >= picHeight) || ((cuPelY + cMVCand[cand].ver) < 0))
5803
0
      continue;
5804
5805
0
    if (((int)(cuPelX + cMVCand[cand].hor + roiWidth) >= picWidth) || ((cuPelX + cMVCand[cand].hor) < 0))
5806
0
      continue;
5807
5808
0
    tempSad = sadBestCand[cand];
5809
5810
0
    cu.mv[0][0] = cMVCand[cand];
5811
0
    cu.mv[0][0].changePrecision(MV_PRECISION_INT, MV_PRECISION_INTERNAL);
5812
0
    cu.interDir = 1;
5813
0
    cu.refIdx[0] = cu.cs->slice->numRefIdx[REF_PIC_LIST_0]; // last idx in the list
5814
5815
0
    PelUnitBuf predBufTmp = m_tmpPredStorage[REF_PIC_LIST_0].getCompactBuf(cu);
5816
0
    motionCompensation(cu, predBufTmp, REF_PIC_LIST_0);
5817
5818
0
    for (unsigned int ch = COMP_Cb; ch < getNumberValidComponents(cu.cs->sps->chromaFormatIdc); ch++)
5819
0
    {
5820
0
      width = roiWidth >> getComponentScaleX(ComponentID(ch), cu.chromaFormat);
5821
0
      height = roiHeight >> getComponentScaleY(ComponentID(ch), cu.chromaFormat);
5822
5823
0
      PelUnitBuf origBuf = cu.cs->getOrgBuf(allCompBlocks);
5824
0
      PelUnitBuf* pBuf = &origBuf;
5825
0
      CPelBuf  tmpPattern = pBuf->get(ComponentID(ch));
5826
0
      pOrg = (Pel*)tmpPattern.buf;
5827
5828
0
      Picture* refPic = cu.slice->pic;
5829
0
      const CPelBuf refBuf = refPic->getRecoBuf(allCompBlocks.blocks[ComponentID(ch)]);
5830
0
      pRef = (Pel*)refBuf.buf;
5831
5832
0
      refStride = refBuf.stride;
5833
0
      orgStride = tmpPattern.stride;
5834
5835
      //ComponentID compID = (ComponentID)ch;
5836
0
      PelUnitBuf* pBufRef = &predBufTmp;
5837
0
      CPelBuf  tmpPatternRef = pBufRef->get(ComponentID(ch));
5838
0
      pRef = (Pel*)tmpPatternRef.buf;
5839
0
      refStride = tmpPatternRef.stride;
5840
5841
5842
0
      for (int row = 0; row < height; row++)
5843
0
      {
5844
0
        for (int col = 0; col < width; col++)
5845
0
        {
5846
0
          tempSad += ((abs(pRef[col] - pOrg[col])) >> (cu.cs->sps->bitDepths[CH_C] - 8));
5847
0
        }
5848
0
        pRef += refStride;
5849
0
        pOrg += orgStride;
5850
0
      }
5851
0
    }
5852
5853
0
    if (tempSad < sadBest)
5854
0
    {
5855
0
      sadBest = tempSad;
5856
0
      bestCandIdx = cand;
5857
0
    }
5858
0
  }
5859
5860
0
  return bestCandIdx;
5861
21.3k
}
5862
static unsigned int xMergeCandLists(Mv* dst, unsigned int dn, unsigned int dstTotalLength, Mv* src, unsigned int sn)
5863
127k
{
5864
989k
  for (unsigned int cand = 0; cand < sn && dn < dstTotalLength; cand++)
5865
862k
  {
5866
862k
    if (src[cand] == Mv())
5867
66.1k
    {
5868
66.1k
      continue;
5869
66.1k
    }
5870
796k
    bool found = false;
5871
6.01M
    for (int j = 0; j < dn; j++)
5872
5.32M
    {
5873
5.32M
      if (src[cand] == dst[j])
5874
110k
      {
5875
110k
        found = true;
5876
110k
        break;
5877
110k
      }
5878
5.32M
    }
5879
5880
796k
    if (!found)
5881
686k
    {
5882
686k
      dst[dn] = src[cand];
5883
686k
      dn++;
5884
686k
    }
5885
796k
  }
5886
5887
127k
  return dn;
5888
127k
}
5889
void InterSearch::xIntraPatternSearchIBC(CodingUnit& cu, TZSearchStruct& cStruct, Mv& rcMv, Distortion& ruiCost, Mv* pcMvSrchRngLT, Mv* pcMvSrchRngRB, Mv* pcMvPred)
5890
25.4k
{
5891
25.4k
  const int   srchRngHorLeft = pcMvSrchRngLT->hor;
5892
25.4k
  const int   srchRngHorRight = pcMvSrchRngRB->hor;
5893
25.4k
  const int   srchRngVerTop = pcMvSrchRngLT->ver;
5894
25.4k
  const int   srchRngVerBottom = pcMvSrchRngRB->ver;
5895
5896
25.4k
  const unsigned int  lcuWidth = cu.cs->slice->sps->CTUSize;
5897
25.4k
  const int   puPelOffsetX = 0;
5898
25.4k
  const int   puPelOffsetY = 0;
5899
25.4k
  const int   cuPelX = cu.Y().x;
5900
25.4k
  const int   cuPelY = cu.Y().y;
5901
5902
25.4k
  int          roiWidth = cu.lwidth();
5903
25.4k
  int          roiHeight = cu.lheight();
5904
5905
25.4k
  Distortion  sad;
5906
25.4k
  Distortion  sadBest = std::numeric_limits<Distortion>::max();
5907
25.4k
  int         bestX = 0;
5908
25.4k
  int         bestY = 0;
5909
5910
25.4k
  const Pel* piRefSrch = cStruct.piRefY; 
5911
5912
25.4k
  int         bestCandIdx = 0;
5913
5914
25.4k
  Distortion  sadBestCand[CHROMA_REFINEMENT_CANDIDATES];
5915
25.4k
  Mv          cMVCand[CHROMA_REFINEMENT_CANDIDATES];
5916
5917
25.4k
  const bool  useAmvr = cu.cs->sps->AMVR;
5918
5919
5920
228k
  for (int cand = 0; cand < CHROMA_REFINEMENT_CANDIDATES; cand++)
5921
203k
  {
5922
203k
    sadBestCand[cand] = std::numeric_limits<Distortion>::max();
5923
203k
    cMVCand[cand].set(0, 0);
5924
203k
  }
5925
5926
25.4k
  m_pcRdCost->setDistParam(m_cDistParam, *cStruct.pcPatternKey, cStruct.piRefY, cStruct.iRefStride, m_lumaClpRng.bd, COMP_Y, cStruct.subShiftMode);
5927
5928
25.4k
  const int picWidth = cu.cs->slice->pps->picWidthInLumaSamples;
5929
25.4k
  const int picHeight = cu.cs->slice->pps->picHeightInLumaSamples;
5930
5931
5932
25.4k
  {
5933
25.4k
    m_cDistParam.subShift = 0;
5934
25.4k
    Distortion tempSadBest = 0;
5935
5936
25.4k
    int srLeft = srchRngHorLeft, srRight = srchRngHorRight, srTop = srchRngVerTop, srBottom = srchRngVerBottom;
5937
25.4k
    m_numBVs = 0;
5938
25.4k
    m_numBVs = xMergeCandLists(m_acBVs, m_numBVs, (2 * IBC_NUM_CANDIDATES), m_defaultCachedBvs->m_bvCands, m_defaultCachedBvs->currCnt);
5939
5940
25.4k
    Mv cMvPredEncOnly[IBC_NUM_CANDIDATES];
5941
25.4k
    int nbPreds = 0;
5942
25.4k
    CU::getIbcMVPsEncOnly(cu, cMvPredEncOnly, nbPreds);
5943
25.4k
    m_numBVs = xMergeCandLists(m_acBVs, m_numBVs, (2 * IBC_NUM_CANDIDATES), cMvPredEncOnly, nbPreds);
5944
5945
245k
    for (unsigned int cand = 0; cand < m_numBVs; cand++)
5946
219k
    {
5947
219k
      int xPred = m_acBVs[cand].hor;
5948
219k
      int yPred = m_acBVs[cand].ver;
5949
5950
219k
      if (!(xPred == 0 && yPred == 0)
5951
219k
        && !((yPred < srTop) || (yPred > srBottom))
5952
197k
        && !((xPred < srLeft) || (xPred > srRight)))
5953
197k
      {
5954
197k
        bool validCand = searchBvIBC(cu, cuPelX, cuPelY, roiWidth, roiHeight, picWidth, picHeight, xPred, yPred, lcuWidth);
5955
5956
197k
        if (validCand)
5957
162k
        {
5958
162k
          sad = m_pcRdCost->getBvCostMultiplePredsIBC(xPred, yPred, useAmvr);
5959
162k
          m_cDistParam.cur.buf = piRefSrch + cStruct.iRefStride * yPred + xPred;
5960
162k
          sad += m_cDistParam.distFunc(m_cDistParam);
5961
5962
162k
          xIBCSearchMVCandUpdate(sad, xPred, yPred, sadBestCand, cMVCand);
5963
162k
        }
5964
197k
      }
5965
219k
    }
5966
5967
25.4k
    bestX = cMVCand[0].hor;
5968
25.4k
    bestY = cMVCand[0].ver;
5969
25.4k
    rcMv.set(bestX, bestY);
5970
25.4k
    sadBest = sadBestCand[0];
5971
5972
25.4k
    const int boundY = (0 - roiHeight - puPelOffsetY);
5973
447k
    for (int y = std::max(srchRngVerTop, 0 - cuPelY); y <= boundY; ++y)
5974
425k
    {
5975
425k
      if (!searchBvIBC(cu, cuPelX, cuPelY, roiWidth, roiHeight, picWidth, picHeight, 0, y, lcuWidth))
5976
0
      {
5977
0
        continue;
5978
0
      }
5979
5980
425k
      sad = m_pcRdCost->getBvCostMultiplePredsIBC(0, y, useAmvr);
5981
425k
      m_cDistParam.cur.buf = piRefSrch + cStruct.iRefStride * y;
5982
425k
      sad += m_cDistParam.distFunc(m_cDistParam);
5983
5984
425k
      xIBCSearchMVCandUpdate(sad, 0, y, sadBestCand, cMVCand);
5985
425k
      tempSadBest = sadBestCand[0];
5986
425k
      if (sadBestCand[0] <= 3)
5987
2.78k
      {
5988
2.78k
        bestX = cMVCand[0].hor;
5989
2.78k
        bestY = cMVCand[0].ver;
5990
2.78k
        sadBest = sadBestCand[0];
5991
2.78k
        rcMv.set(bestX, bestY);
5992
2.78k
        ruiCost = sadBest;
5993
2.78k
        goto end;
5994
2.78k
      }
5995
425k
    }
5996
5997
22.6k
    const int boundX = std::max(srchRngHorLeft, -cuPelX);
5998
1.45M
    for (int x = 0 - roiWidth - puPelOffsetX; x >= boundX; --x)
5999
1.43M
    {
6000
1.43M
      if (!searchBvIBC(cu, cuPelX, cuPelY, roiWidth, roiHeight, picWidth, picHeight, x, 0, lcuWidth))
6001
807k
      {
6002
807k
        continue;
6003
807k
      }
6004
6005
629k
      sad = m_pcRdCost->getBvCostMultiplePredsIBC(x, 0, useAmvr);
6006
629k
      m_cDistParam.cur.buf = piRefSrch + x;
6007
629k
      sad += m_cDistParam.distFunc(m_cDistParam);
6008
6009
6010
629k
      xIBCSearchMVCandUpdate(sad, x, 0, sadBestCand, cMVCand);
6011
629k
      tempSadBest = sadBestCand[0];
6012
629k
      if (sadBestCand[0] <= 3)
6013
1.27k
      {
6014
1.27k
        bestX = cMVCand[0].hor;
6015
1.27k
        bestY = cMVCand[0].ver;
6016
1.27k
        sadBest = sadBestCand[0];
6017
1.27k
        rcMv.set(bestX, bestY);
6018
1.27k
        ruiCost = sadBest;
6019
1.27k
        goto end;
6020
1.27k
      }
6021
629k
    }
6022
6023
21.3k
    bestX = cMVCand[0].hor;
6024
21.3k
    bestY = cMVCand[0].ver;
6025
21.3k
    sadBest = sadBestCand[0];
6026
21.3k
    if ((!bestX && !bestY) || (sadBest - m_pcRdCost->getBvCostMultiplePredsIBC(bestX, bestY, useAmvr) <= 32))
6027
20.2k
    {
6028
      //chroma refine
6029
20.2k
      bestCandIdx = xIBCSearchMVChromaRefine(cu, roiWidth, roiHeight, cuPelX, cuPelY, sadBestCand, cMVCand);
6030
20.2k
      bestX = cMVCand[bestCandIdx].hor;
6031
20.2k
      bestY = cMVCand[bestCandIdx].ver;
6032
20.2k
      sadBest = sadBestCand[bestCandIdx];
6033
20.2k
      rcMv.set(bestX, bestY);
6034
20.2k
      ruiCost = sadBest;
6035
20.2k
      goto end;
6036
20.2k
    }
6037
6038
1.11k
    if (cu.lwidth() < 16 && cu.lheight() < 16)
6039
25
    {
6040
25
      int stepS = 2;
6041
25
      if (m_pcEncCfg->m_IBCFastMethod > 2)
6042
25
      {
6043
25
        if (m_pcEncCfg->m_IBCFastMethod == 5)
6044
0
        {
6045
0
          stepS = 8;
6046
0
        }
6047
25
        else if ((cu.lwidth() > 4) || (cu.lheight() > 4))
6048
25
        {
6049
25
          stepS = 4;
6050
25
        }
6051
25
      }
6052
6053
25
      const int minCuLog2 = m_pcEncCfg->m_log2MinCodingBlockSize;
6054
25
      const int minCuMask = (1 << minCuLog2) - 1;
6055
25
      bool lastDec = false;
6056
6057
25
      for (int searchStep = 0; searchStep < 3; searchStep++)
6058
25
      {
6059
25
        int delaySy = searchStep ? 1 : 0;
6060
25
        int delaySx = searchStep > 1 ? 1 : 0;
6061
25
        int startY = (std::max(srchRngVerTop, -cuPelY) + delaySy);
6062
25
        int startX = (std::max(srchRngHorLeft, -cuPelX) + delaySx);
6063
25
        int endY = srchRngVerBottom;
6064
25
        int endX = srchRngHorRight;
6065
6066
25
        if (m_pcEncCfg->m_IBCFastMethod > 5)
6067
0
        {
6068
0
          startY = bestY - 4;
6069
0
          endY = bestY + 4;
6070
0
          startX = bestX - 4;
6071
0
          endX = bestX + 4;
6072
0
          stepS = 1;
6073
0
          if (searchStep)
6074
0
          {
6075
0
            break;
6076
0
          }
6077
0
        }
6078
6079
620
        for (int y = startY; y <= endY; y += stepS)
6080
595
        {
6081
595
          if ((y == 0) || ((int)(cuPelY + y + roiHeight) >= picHeight))
6082
355
            continue;
6083
240
          bool firstX = true;
6084
240
          int stepSx = searchStep ? stepS : 1;
6085
26.2k
          for (int x = startX; x <= endX; firstX = false, x += stepSx)
6086
25.9k
          {
6087
25.9k
            if ((x == 0) || ((int)(cuPelX + x + roiWidth) >= picWidth))
6088
12.2k
              continue;
6089
6090
13.7k
            bool isSameAsLast = !firstX && ((cuPelX + x) & minCuMask) > 1;
6091
13.7k
            if (searchStep || (m_pcEncCfg->m_IBCFastMethod > 5))
6092
0
            {
6093
0
              if (!searchBvIBC(cu, cuPelX, cuPelY, roiWidth, roiHeight, picWidth, picHeight, x, y, lcuWidth))
6094
0
              {
6095
0
                continue;
6096
0
              }
6097
0
            }
6098
13.7k
            else if ((isSameAsLast && !lastDec) || (!isSameAsLast && !searchBvIBC(cu, cuPelX, cuPelY, roiWidth, roiHeight, picWidth, picHeight, x, y, lcuWidth)))
6099
3.73k
            {
6100
3.73k
              lastDec = false;
6101
3.73k
              continue;
6102
3.73k
            }
6103
10.0k
            lastDec = true;
6104
6105
10.0k
            sad = m_pcRdCost->getBvCostMultiplePredsIBC(x, y, useAmvr);
6106
10.0k
            m_cDistParam.cur.buf = piRefSrch + cStruct.iRefStride * y + x;
6107
10.0k
            sad += m_cDistParam.distFunc(m_cDistParam);
6108
6109
10.0k
            xIBCSearchMVCandUpdate(sad, x, y, sadBestCand, cMVCand);
6110
6111
6112
10.0k
            if (searchStep && sadBestCand[0] <= 5)
6113
0
            {
6114
              //chroma refine & return
6115
0
              bestCandIdx = xIBCSearchMVChromaRefine(cu, roiWidth, roiHeight, cuPelX, cuPelY, sadBestCand, cMVCand);
6116
0
              bestX = cMVCand[bestCandIdx].hor;
6117
0
              bestY = cMVCand[bestCandIdx].ver;
6118
0
              sadBest = sadBestCand[bestCandIdx];
6119
0
              rcMv.set(bestX, bestY);
6120
0
              ruiCost = sadBest;
6121
0
              goto end;
6122
0
            }
6123
10.0k
          }
6124
240
        }
6125
6126
25
        if ((searchStep < 2) && (m_pcEncCfg->m_IBCFastMethod < 6))
6127
25
        {
6128
25
          if ((m_pcEncCfg->m_IBCFastMethod > 2) && (m_pcEncCfg->m_IBCFastMethod < 5))
6129
25
          {
6130
25
            if ((bestX == cMVCand[0].hor) && (bestY == cMVCand[0].ver))
6131
25
            {
6132
25
              sadBest = sadBestCand[bestCandIdx];
6133
25
              rcMv.set(bestX, bestY);
6134
25
              ruiCost = sadBest;
6135
25
              goto end;
6136
25
            }
6137
25
          }
6138
0
          bestX = cMVCand[0].hor;
6139
0
          bestY = cMVCand[0].ver;
6140
0
          sadBest = sadBestCand[0];
6141
6142
0
          int StopSearch = searchStep ? 32 : 16;
6143
0
          if ((searchStep && (sadBest >= tempSadBest)) || (sadBest - m_pcRdCost->getBvCostMultiplePredsIBC(bestX, bestY, useAmvr) <= StopSearch))
6144
0
          {
6145
            //chroma refine
6146
0
            bestCandIdx = xIBCSearchMVChromaRefine(cu, roiWidth, roiHeight, cuPelX, cuPelY, sadBestCand, cMVCand);
6147
6148
0
            bestX = cMVCand[bestCandIdx].hor;
6149
0
            bestY = cMVCand[bestCandIdx].ver;
6150
0
            sadBest = sadBestCand[bestCandIdx];
6151
0
            rcMv.set(bestX, bestY);
6152
0
            ruiCost = sadBest;
6153
0
            goto end;
6154
0
          }
6155
0
        }
6156
25
      }
6157
25
    }
6158
1.11k
  }
6159
6160
1.08k
  bestCandIdx = xIBCSearchMVChromaRefine(cu, roiWidth, roiHeight, cuPelX, cuPelY, sadBestCand, cMVCand);
6161
6162
1.08k
  bestX = cMVCand[bestCandIdx].hor;
6163
1.08k
  bestY = cMVCand[bestCandIdx].ver;
6164
1.08k
  sadBest = sadBestCand[bestCandIdx];
6165
1.08k
  rcMv.set(bestX, bestY);
6166
1.08k
  ruiCost = sadBest;
6167
6168
25.4k
end:
6169
25.4k
  m_numBVs = 0;
6170
25.4k
  m_numBVs = xMergeCandLists(m_acBVs, m_numBVs, (2 * IBC_NUM_CANDIDATES), m_defaultCachedBvs->m_bvCands, m_defaultCachedBvs->currCnt);
6171
6172
25.4k
  m_defaultCachedBvs->currCnt = 0;
6173
25.4k
  m_defaultCachedBvs->currCnt = xMergeCandLists(m_defaultCachedBvs->m_bvCands, m_defaultCachedBvs->currCnt, IBC_NUM_CANDIDATES, cMVCand, CHROMA_REFINEMENT_CANDIDATES);
6174
25.4k
  m_defaultCachedBvs->currCnt = xMergeCandLists(m_defaultCachedBvs->m_bvCands, m_defaultCachedBvs->currCnt, IBC_NUM_CANDIDATES, m_acBVs, m_numBVs);
6175
6176
228k
  for (unsigned int cand = 0; cand < CHROMA_REFINEMENT_CANDIDATES; cand++)
6177
203k
  {
6178
203k
    if (cMVCand[cand].hor == 0 && cMVCand[cand].ver == 0)
6179
66.1k
    {
6180
66.1k
      continue;
6181
66.1k
    }
6182
137k
    m_ctuRecord[cu.lumaPos()][cu.lumaSize()].bvRecord[cMVCand[cand]] = sadBestCand[cand];
6183
137k
  }
6184
6185
25.4k
  return;
6186
1.08k
}
6187
6188
6189
6190
// based on xMotionEstimation
6191
void InterSearch::xIBCEstimation(CodingUnit& cu, PelUnitBuf& origBuf, Mv* pcMvPred, Mv& rcMv, Distortion& ruiCost )
6192
25.4k
{
6193
25.4k
  const int iPicWidth = cu.cs->slice->pps->picWidthInLumaSamples;
6194
25.4k
  const int iPicHeight = cu.cs->slice->pps->picHeightInLumaSamples;
6195
25.4k
  const unsigned int  lcuWidth = cu.cs->slice->sps->CTUSize;
6196
25.4k
  const int           cuPelX = cu.Y().x;
6197
25.4k
  const int           cuPelY = cu.Y().y;
6198
25.4k
  int                 iRoiWidth = cu.lwidth();
6199
25.4k
  int                 iRoiHeight = cu.lheight();
6200
6201
25.4k
  PelUnitBuf* pBuf = &origBuf;
6202
6203
  //  Search key pattern initialization
6204
25.4k
  CPelBuf  tmpPattern = pBuf->Y();
6205
25.4k
  CPelBuf* pcPatternKey = &tmpPattern;
6206
25.4k
  m_lumaClpRng = cu.cs->slice->clpRngs[COMP_Y];
6207
25.4k
  Picture* refPic = cu.slice->pic;
6208
25.4k
  const CPelBuf refBuf = refPic->getRecoBuf(cu.blocks[COMP_Y]);
6209
6210
25.4k
  TZSearchStruct cStruct; 
6211
25.4k
  cStruct.pcPatternKey  = pcPatternKey;
6212
25.4k
  cStruct.iRefStride    = refBuf.stride;
6213
25.4k
  cStruct.piRefY        = refBuf.buf;
6214
25.4k
  CHECK( cu.imv == IMV_HPEL, "IF_IBC" );
6215
25.4k
  cStruct.imvShift      = cu.imv << 1;
6216
25.4k
  cStruct.subShiftMode  = 0;
6217
25.4k
  cStruct.uiBestSad     = MAX_DISTORTION;
6218
6219
25.4k
  m_pcRdCost->getMotionCostIBC(0);
6220
25.4k
  m_pcRdCost->setPredictorsIBC(pcMvPred);
6221
25.4k
  m_pcRdCost->setCostScale(0);
6222
6223
25.4k
  m_pcRdCost->setDistParam(m_cDistParam, *cStruct.pcPatternKey, cStruct.piRefY, cStruct.iRefStride, m_lumaClpRng.bd, COMP_Y, cStruct.subShiftMode);
6224
25.4k
  bool buffered = false;
6225
25.4k
  if (m_pcEncCfg->m_IBCFastMethod)// IBC_FAST_METHOD_BUFFERBV
6226
25.4k
  {
6227
25.4k
    ruiCost = MAX_UINT;
6228
25.4k
    std::unordered_map<Mv, Distortion>& history = m_ctuRecord[cu.lumaPos()][cu.lumaSize()].bvRecord;
6229
25.4k
    for (std::unordered_map<Mv, Distortion>::iterator p = history.begin(); p != history.end(); p++)
6230
15
    {
6231
15
      const Mv& bv = p->first;
6232
6233
15
      int xBv = bv.hor;
6234
15
      int yBv = bv.ver;
6235
15
      if (searchBvIBC(cu, cuPelX, cuPelY, iRoiWidth, iRoiHeight, iPicWidth, iPicHeight, xBv, yBv, lcuWidth))
6236
15
      {
6237
15
        buffered = true;
6238
15
        Distortion sad = m_pcRdCost->getBvCostMultiplePredsIBC(xBv, yBv, cu.cs->sps->AMVR);
6239
15
        m_cDistParam.cur.buf = cStruct.piRefY + cStruct.iRefStride * yBv + xBv;
6240
15
        sad += m_cDistParam.distFunc(m_cDistParam);
6241
15
        if (sad < ruiCost)
6242
15
        {
6243
15
          rcMv = bv;
6244
15
          ruiCost = sad;
6245
15
        }
6246
0
        else if (sad == ruiCost)
6247
0
        {
6248
          // stabilise the search through the unordered list
6249
0
          if (bv.hor < rcMv.hor
6250
0
            || (bv.hor == rcMv.hor && bv.ver < rcMv.ver))
6251
0
          {
6252
            // update the vector.
6253
0
            rcMv = bv;
6254
0
          }
6255
0
        }
6256
15
      }
6257
15
    }
6258
6259
25.4k
    if (buffered)
6260
15
    {
6261
15
      Mv cMvPredEncOnly[IBC_NUM_CANDIDATES];
6262
15
      int nbPreds = 0;
6263
15
      CU::getIbcMVPsEncOnly(cu, cMvPredEncOnly, nbPreds);
6264
6265
15
      for (unsigned int cand = 0; cand < nbPreds; cand++)
6266
0
      {
6267
0
        int xPred = cMvPredEncOnly[cand].hor;
6268
0
        int yPred = cMvPredEncOnly[cand].ver;
6269
6270
0
        if (searchBvIBC(cu, cuPelX, cuPelY, iRoiWidth, iRoiHeight, iPicWidth, iPicHeight, xPred, yPred, lcuWidth))
6271
0
        {
6272
0
          Distortion sad = m_pcRdCost->getBvCostMultiplePredsIBC(xPred, yPred, cu.cs->sps->AMVR);
6273
0
          m_cDistParam.cur.buf = cStruct.piRefY + cStruct.iRefStride * yPred + xPred;
6274
0
          sad += m_cDistParam.distFunc(m_cDistParam);
6275
0
          if (sad < ruiCost)
6276
0
          {
6277
0
            rcMv.set(xPred, yPred);
6278
0
            ruiCost = sad;
6279
0
          }
6280
0
          else if (sad == ruiCost)
6281
0
          {
6282
            // stabilise the search through the unordered list
6283
0
            if (xPred < rcMv.hor
6284
0
              || (xPred == rcMv.hor && yPred < rcMv.ver))
6285
0
            {
6286
              // update the vector.
6287
0
              rcMv.set(xPred, yPred);
6288
0
            }
6289
0
          }
6290
0
          m_ctuRecord[cu.lumaPos()][cu.lumaSize()].bvRecord[Mv(xPred, yPred)] = sad;
6291
0
        }
6292
0
      }
6293
15
    }
6294
25.4k
  }
6295
6296
25.4k
  if (!buffered)
6297
25.4k
  {
6298
25.4k
    Mv        cMvSrchRngLT;
6299
25.4k
    Mv        cMvSrchRngRB;
6300
6301
    // assume that intra BV is integer-pel precision
6302
25.4k
    xSetIntraSearchRangeIBC(cu, cu.lwidth(), cu.lheight(), cMvSrchRngLT, cMvSrchRngRB);
6303
6304
    //  Do integer search
6305
25.4k
    xIntraPatternSearchIBC(cu, cStruct, rcMv, ruiCost, &cMvSrchRngLT, &cMvSrchRngRB, pcMvPred);
6306
25.4k
  }
6307
25.4k
}
6308
// based on xSetSearchRange
6309
void InterSearch::xSetIntraSearchRangeIBC(CodingUnit& cu, int iRoiWidth, int iRoiHeight, Mv& rcMvSrchRngLT, Mv& rcMvSrchRngRB)
6310
25.4k
{
6311
 // const SPS& sps = *cu.cs->sps;
6312
6313
25.4k
  int srLeft, srRight, srTop, srBottom;
6314
6315
25.4k
  const int cuPelX = cu.Y().x;
6316
25.4k
  const int cuPelY = cu.Y().y;
6317
6318
25.4k
  const int lcuWidth = cu.cs->slice->sps->CTUSize;
6319
25.4k
  const int ctuSizeLog2 = floorLog2(lcuWidth);
6320
25.4k
  int numLeftCTUs = (1 << ((7 - ctuSizeLog2) << 1)) - ((ctuSizeLog2 < 7) ? 1 : 0);
6321
6322
25.4k
  srLeft = -(numLeftCTUs * lcuWidth + (cuPelX % lcuWidth));
6323
25.4k
  srTop = -(cuPelY % lcuWidth);
6324
6325
25.4k
  srRight = lcuWidth - (cuPelX % lcuWidth) - iRoiWidth;
6326
25.4k
  srBottom = lcuWidth - (cuPelY % lcuWidth) - iRoiHeight;
6327
6328
25.4k
  rcMvSrchRngLT.hor=srLeft;
6329
25.4k
  rcMvSrchRngLT.ver=srTop;
6330
25.4k
  rcMvSrchRngRB.hor=srRight;
6331
25.4k
  rcMvSrchRngRB.ver=srBottom;
6332
6333
25.4k
  rcMvSrchRngLT <<= 2;
6334
25.4k
  rcMvSrchRngRB <<= 2;
6335
25.4k
  bool temp = m_clipMvInSubPic;
6336
25.4k
  m_clipMvInSubPic = true;
6337
25.4k
  clipMv(rcMvSrchRngLT,cu.lumaPos(),cu.lumaSize(), *cu.cs->pcv, *cu.cs->pps, m_clipMvInSubPic);
6338
25.4k
  clipMv(rcMvSrchRngRB, cu.lumaPos(),cu.lumaSize(), *cu.cs->pcv, * cu.cs->pps, m_clipMvInSubPic);
6339
25.4k
  m_clipMvInSubPic = temp;
6340
25.4k
  rcMvSrchRngLT >>= 2;
6341
25.4k
  rcMvSrchRngRB >>= 2;
6342
25.4k
}
6343
6344
bool InterSearch::predIBCSearch(CodingUnit& cu, Partitioner& partitioner)
6345
25.4k
{
6346
25.4k
  Mv           cMvSrchRngLT;
6347
25.4k
  Mv           cMvSrchRngRB;
6348
25.4k
  cu.imv = IMV_4PEL;
6349
25.4k
  AMVPInfo amvpInfo4Pel;
6350
25.4k
  CU::fillIBCMvpCand(cu, amvpInfo4Pel);
6351
6352
25.4k
  cu.imv = IMV_OFF;// (Int)cu.cs->sps->getUseIMV(); // set as IMV=0 initially
6353
25.4k
  Mv    cMv, cMvPred[2];
6354
25.4k
  AMVPInfo amvpInfo;
6355
25.4k
  CU::fillIBCMvpCand(cu, amvpInfo);
6356
  // store in full pel accuracy, shift before use in search
6357
25.4k
  cMvPred[0] = amvpInfo.mvCand[0];
6358
25.4k
  cMvPred[0].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT);
6359
25.4k
  cMvPred[1] = amvpInfo.mvCand[1];
6360
25.4k
  cMvPred[1].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT);
6361
6362
25.4k
  int iBvpNum = 2;
6363
25.4k
  int bvpIdxBest = 0;
6364
25.4k
  cMv.setZero();
6365
25.4k
  Distortion cost = 0;
6366
25.4k
  if (cu.cs->sps->maxNumIBCMergeCand == 1)
6367
0
  {
6368
0
    iBvpNum = 1;
6369
0
    cMvPred[1] = cMvPred[0];
6370
0
  }
6371
6372
25.4k
  if (cMv.hor == 0 && cMv.ver == 0)
6373
25.4k
  {
6374
    // if hash search does not work or is not enabled
6375
25.4k
    PelUnitBuf origBuf = cu.cs->getOrgBuf(cu);
6376
25.4k
    xIBCEstimation(cu, origBuf, cMvPred, cMv, cost );
6377
25.4k
  }
6378
6379
25.4k
  if (cMv.hor == 0 && cMv.ver == 0)
6380
2.66k
  {
6381
2.66k
    return false;
6382
2.66k
  }
6383
  /// ibc search
6384
  /////////////////////////////////////////////////////////
6385
22.7k
  unsigned int bitsBVPBest, bitsBVPTemp;
6386
22.7k
  bitsBVPBest = MAX_INT;
6387
22.7k
  m_pcRdCost->setCostScale(0);
6388
6389
68.2k
  for (int bvpIdxTemp = 0; bvpIdxTemp < iBvpNum; bvpIdxTemp++)
6390
45.5k
  {
6391
45.5k
    m_pcRdCost->setPredictor(cMvPred[bvpIdxTemp]);
6392
6393
45.5k
    bitsBVPTemp = m_pcRdCost->getBitsOfVectorWithPredictor(cMv.hor, cMv.ver, 0);
6394
6395
45.5k
    if (bitsBVPTemp < bitsBVPBest)
6396
22.7k
    {
6397
22.7k
      bitsBVPBest = bitsBVPTemp;
6398
22.7k
      bvpIdxBest = bvpIdxTemp;
6399
6400
22.7k
      if (cu.cs->sps->AMVR && cMv != cMvPred[bvpIdxTemp])
6401
22.7k
        cu.imv = IMV_FPEL; // set as full-pel
6402
0
      else
6403
0
        cu.imv = IMV_OFF; // set as fractional-pel
6404
6405
22.7k
    }
6406
6407
45.5k
    unsigned int bitsBVPQP = MAX_UINT;
6408
6409
6410
45.5k
    Mv mvPredQuadPel;
6411
45.5k
    if ((cMv.hor % 4 == 0) && (cMv.ver % 4 == 0) && (cu.cs->sps->AMVR))
6412
45.5k
    {
6413
45.5k
      mvPredQuadPel = amvpInfo4Pel.mvCand[bvpIdxTemp];// cMvPred[bvpIdxTemp];
6414
6415
45.5k
      mvPredQuadPel.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_4PEL);
6416
6417
45.5k
      m_pcRdCost->setPredictor(mvPredQuadPel);
6418
6419
45.5k
      bitsBVPQP = m_pcRdCost->getBitsOfVectorWithPredictor(cMv.hor >> 2, cMv.ver >> 2, 0);
6420
6421
45.5k
    }
6422
45.5k
    mvPredQuadPel.changePrecision(MV_PRECISION_4PEL, MV_PRECISION_INT);
6423
45.5k
    if (bitsBVPQP < bitsBVPBest && cMv != mvPredQuadPel)
6424
22.7k
    {
6425
22.7k
      bitsBVPBest = bitsBVPQP;
6426
22.7k
      bvpIdxBest = bvpIdxTemp;
6427
6428
22.7k
      if (cu.cs->sps->AMVR)
6429
22.7k
        cu.imv = IMV_4PEL;
6430
22.7k
    }
6431
6432
45.5k
  }
6433
6434
22.7k
  cMv.changePrecision( MV_PRECISION_INT, MV_PRECISION_INTERNAL );
6435
22.7k
  cu.mv[REF_PIC_LIST_0][0] = cMv; // store in fractional pel accuracy
6436
6437
22.7k
  cu.mvpIdx[REF_PIC_LIST_0] = bvpIdxBest;
6438
6439
22.7k
  if (cu.imv == IMV_4PEL && cMv != amvpInfo4Pel.mvCand[bvpIdxBest])
6440
22.7k
    cu.mvd[REF_PIC_LIST_0][0] = cMv - amvpInfo4Pel.mvCand[bvpIdxBest];
6441
0
  else
6442
0
    cu.mvd[REF_PIC_LIST_0][0] = cMv - amvpInfo.mvCand[bvpIdxBest];
6443
6444
22.7k
  if (cu.mvd[REF_PIC_LIST_0][0] == Mv(0, 0))
6445
0
    cu.imv = IMV_OFF;
6446
22.7k
  if (cu.imv == IMV_4PEL)
6447
22.7k
    assert((cMv.hor % 16 == 0) && (cMv.ver % 16 == 0));
6448
22.7k
  if (cu.cs->sps->AMVR)
6449
22.7k
    assert(cu.imv > 0 || cu.mvd[REF_PIC_LIST_0][0] == Mv());
6450
6451
22.7k
  cu.refIdx[REF_PIC_LIST_0] = MAX_NUM_REF;
6452
6453
22.7k
  return true;
6454
22.7k
}
6455
6456
6457
static inline bool isYPartBefore( SplitSeries series, const int ctuSizeLog2, const Position& refPos, const Position& pos )
6458
1.49M
{
6459
1.49M
#ifndef NDEBUG
6460
1.49M
  const int refCtuX = refPos.x >> ctuSizeLog2;
6461
1.49M
  const int refCtuY = refPos.y >> ctuSizeLog2;
6462
1.49M
  const int posCtuX = pos.x >> ctuSizeLog2;
6463
1.49M
  const int posCtuY = pos.y >> ctuSizeLog2;
6464
6465
1.49M
  CHECK( refCtuX != posCtuX || refCtuY != posCtuY, "This method can only be applied for positions within the same CTU" );
6466
6467
1.49M
#endif
6468
1.49M
  const int ctuMask = ( 1 << ctuSizeLog2 ) - 1;
6469
6470
1.49M
  const int refX = refPos.x & ctuMask;
6471
1.49M
  const int refY = refPos.y & ctuMask;
6472
1.49M
  const int posX = pos.x & ctuMask;
6473
1.49M
  const int posY = pos.y & ctuMask;
6474
6475
1.49M
  int x = 0, y = 0, w = 1 << ctuSizeLog2, h = 1 << ctuSizeLog2;
6476
  
6477
2.03M
  while( true )
6478
2.03M
  {
6479
2.03M
    PartSplit split = PartSplit( series & SPLIT_MASK );
6480
6481
2.03M
    switch( split )
6482
2.03M
    {
6483
1.97M
    case CU_QUAD_SPLIT:
6484
1.97M
      w >>= 1;
6485
1.97M
      if( posX >= x + w ) x += w;
6486
2.00M
    case CU_HORZ_SPLIT:
6487
2.00M
      h >>= 1;
6488
2.00M
      if( posY >= y + h ) y += h;
6489
2.00M
      break;
6490
6491
31.0k
    case CU_VERT_SPLIT:
6492
31.0k
      w >>= 1;
6493
31.0k
      if( posX >= x + w ) x += w;
6494
31.0k
      goto checkXonly;
6495
6496
0
    case CU_TRIH_SPLIT:
6497
0
      h >>= 2;
6498
0
      if( posY >= y + h ) { y += h; h <<= 1; }
6499
0
      if( posY >= y + h ) { y += h; h >>= 1; }
6500
0
      break;
6501
6502
0
    case CU_TRIV_SPLIT:
6503
0
      w >>= 2;
6504
0
      if( posX >= x + w ) { x += w; w <<= 1; }
6505
0
      if( posX >= x + w ) { x += w; w >>= 1; }
6506
0
      goto checkXonly;
6507
6508
0
    default:
6509
0
      return false;
6510
2.03M
    }
6511
6512
2.00M
    if( refY >= y + h ) return true;
6513
1.50M
    else if( refY < y ) return false;
6514
6515
1.54M
checkXonly:
6516
1.54M
    if( refX >= x + w ) return true;
6517
762k
    else if( refX < x ) return false;
6518
6519
532k
    series >>= SPLIT_DMULT; continue;
6520
1.54M
  }
6521
6522
18.4E
  return false;
6523
1.49M
}
6524
6525
bool InterSearch::searchBvIBC(const CodingUnit& cu, int xPos, int yPos, int width, int height, int picWidth, int picHeight, int xBv, int yBv, int ctuSize) const
6526
2.21M
{
6527
2.21M
  const int ctuSizeLog2 = Log2(ctuSize);
6528
6529
2.21M
  int refRightX  = xPos + xBv + width  - 1;
6530
2.21M
  int refBottomY = yPos + yBv + height - 1;
6531
6532
2.21M
  int refLeftX = xPos + xBv;
6533
2.21M
  int refTopY  = yPos + yBv;
6534
6535
2.21M
  if ((xPos + xBv) < 0)
6536
12.9k
  {
6537
12.9k
    return false;
6538
12.9k
  }
6539
2.20M
  if (refRightX >= picWidth)
6540
0
  {
6541
0
    return false;
6542
0
  }
6543
6544
2.20M
  if ((yPos + yBv) < 0)
6545
0
  {
6546
0
    return false;
6547
0
  }
6548
2.20M
  if (refBottomY >= picHeight)
6549
0
  {
6550
0
    return false;
6551
0
  }
6552
2.20M
  if ((xBv + width) > 0 && (yBv + height) > 0)
6553
174k
  {
6554
174k
    return false;
6555
174k
  }
6556
6557
  // Don't search the above CTU row
6558
2.03M
  if (refTopY >> ctuSizeLog2 < yPos >> ctuSizeLog2)
6559
0
    return false;
6560
6561
  // Don't search the below CTU row
6562
2.03M
  if (refBottomY >> ctuSizeLog2 > yPos >> ctuSizeLog2)
6563
0
  {
6564
0
    return false;
6565
0
  }
6566
6567
2.03M
  unsigned curTileIdx = cu.cs->pps->getTileIdx(cu.lumaPos());
6568
2.03M
  unsigned refTileIdx = cu.cs->pps->getTileIdx(Position(refLeftX, refTopY));
6569
2.03M
  if (curTileIdx != refTileIdx)
6570
0
  {
6571
0
    return false;
6572
0
  }
6573
2.03M
  refTileIdx = cu.cs->pps->getTileIdx(Position(refLeftX, refBottomY));
6574
2.03M
  if (curTileIdx != refTileIdx)
6575
0
  {
6576
0
    return false;
6577
0
  }
6578
2.03M
  refTileIdx = cu.cs->pps->getTileIdx(Position(refRightX, refTopY));
6579
2.03M
  if (curTileIdx != refTileIdx)
6580
0
  {
6581
0
    return false;
6582
0
  }
6583
2.03M
  refTileIdx = cu.cs->pps->getTileIdx(Position(refRightX, refBottomY));
6584
2.03M
  if (curTileIdx != refTileIdx)
6585
0
  {
6586
0
    return false;
6587
0
  }
6588
6589
2.03M
  const Position cuPos{ xPos, yPos };
6590
6591
  //int numLeftCTUs = (1 << ((7 - ctuSizeLog2) << 1)) - ((ctuSizeLog2 < 7) ? 1 : 0);
6592
2.03M
  static const int numLeftCTUsLUT[3] = { 15, 3, 1 };
6593
6594
  // in the same CTU line
6595
2.03M
  const int numLeftCTUs = numLeftCTUsLUT[ctuSizeLog2 - 5];
6596
6597
2.03M
  if( ( refRightX >> ctuSizeLog2 <= xPos >> ctuSizeLog2 ) && ( refLeftX >> ctuSizeLog2 >= ( xPos >> ctuSizeLog2 ) - numLeftCTUs ) )
6598
2.03M
  {
6599
    // in the same CTU, or left CTU
6600
    // if part of ref block is in the left CTU, some area can be referred from the not-yet updated local CTU buffer
6601
2.03M
    if( ( ctuSizeLog2 == 7 ) && ( ( refLeftX >> ctuSizeLog2 ) == ( ( xPos >> ctuSizeLog2 ) - 1 ) ) )
6602
1.03M
    {
6603
      // ref block's collocated block in current CTU
6604
1.03M
      const Position refPosCol64x64{ ( refLeftX + ctuSize ) & ~63, refTopY & ~63 };
6605
1.03M
      if( refPosCol64x64 == Position{ xPos & ~63, yPos & ~63 } )
6606
562k
        return false;
6607
6608
      //CodingUnit* curef = cu.cs->getCU(refPosCol64x64, CH_L, cu.treeType);
6609
      //bool isDecomp = curef && ((cu.cs != curef->cs) || cu.idx < curef->idx);
6610
476k
      bool isDecomp = isYPartBefore( cu.splitSeries, ctuSizeLog2, cuPos, refPosCol64x64 );
6611
476k
      if( isDecomp )
6612
246k
      {
6613
246k
        return false;
6614
246k
      }
6615
476k
    }
6616
2.03M
  }
6617
45
  else
6618
45
    return false;
6619
6620
  // in the same CTU, or valid area from left CTU. Check if the reference block is already coded
6621
1.22M
  const Position refPosBR{ refRightX, refBottomY };
6622
  //CodingUnit* curef = cu.cs->getCU(refPosBR, CH_L, cu.treeType);
6623
  //bool isDecomp = curef && ((cu.cs != curef->cs) || cu.idx < curef->idx);
6624
1.22M
  bool isDecomp = ( ( refPosBR.x >> ctuSizeLog2 ) < ( cuPos.x >> ctuSizeLog2 ) ) || ( refRightX < xPos && refBottomY < yPos ) || isYPartBefore( cu.splitSeries, ctuSizeLog2, cuPos, refPosBR );
6625
6626
1.22M
  return isDecomp;
6627
2.03M
}
6628
6629
} // namespace vvenc
6630
6631
//! \}
6632