Coverage Report

Created: 2026-09-01 06:57

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
18.6k
  : m_modeCtrl                    (nullptr)
190
18.6k
  , m_defaultCachedBvs            (nullptr)
191
18.6k
  , m_pcEncCfg                    (nullptr)
192
18.6k
  , m_pcTrQuant                   (nullptr)
193
18.6k
  , m_iSearchRange                (0)
194
18.6k
  , m_bipredSearchRange           (0)
195
18.6k
  , m_motionEstimationSearchMethod(VVENC_MESEARCH_FULL)
196
18.6k
  , m_motionEstimationSearchMethodSCC( 0 )
197
18.6k
  , m_CABACEstimator              (nullptr)
198
18.6k
  , m_CtxCache                    (nullptr)
199
18.6k
  , m_pTempPel                    (nullptr)
200
18.6k
{
201
55.9k
  for (int i=0; i<MAX_NUM_REF_LIST_ADAPT_SR; i++)
202
37.3k
  {
203
37.3k
    memset (m_aaiAdaptSR[i], 0, MAX_IDX_ADAPT_SR * sizeof (int));
204
37.3k
  }
205
74.6k
  for (int i=0; i<AMVP_MAX_NUM_CANDS+1; i++)
206
55.9k
  {
207
55.9k
    memset (m_auiMVPIdxCost[i], 0, (AMVP_MAX_NUM_CANDS+1) * sizeof (uint32_t) );
208
55.9k
  }
209
18.6k
}
210
211
212
InterSearch::~InterSearch()
213
18.6k
{
214
18.6k
  destroy();
215
18.6k
}
216
217
void InterSearch::init( const VVEncCfg& encCfg, TrQuant* pTrQuant, RdCost* pRdCost, EncModeCtrl* pModeCtrl, CodingStructure **pSaveCS )
218
18.6k
{
219
18.6k
  InterPrediction::init( pRdCost, encCfg.m_internChromaFormat, encCfg.m_CTUSize, encCfg.m_ifpLines );
220
18.6k
  m_numBVs                       = 0;
221
18.6k
  m_pcEncCfg                     = &encCfg;
222
18.6k
  m_pcTrQuant                    = pTrQuant;
223
18.6k
  m_pcRdCost                     = pRdCost;
224
18.6k
  m_modeCtrl                     = pModeCtrl;
225
18.6k
  m_pSaveCS                      = pSaveCS;
226
227
18.6k
  m_iSearchRange                    = encCfg.m_SearchRange;
228
18.6k
  m_bipredSearchRange               = encCfg.m_bipredSearchRange;
229
18.6k
  m_motionEstimationSearchMethod    = vvencMESearchMethod( encCfg.m_motionEstimationSearchMethod );
230
18.6k
  m_motionEstimationSearchMethodSCC = encCfg.m_motionEstimationSearchMethodSCC;
231
232
55.9k
  for( uint32_t iDir = 0; iDir < MAX_NUM_REF_LIST_ADAPT_SR; iDir++ )
233
37.3k
  {
234
261k
    for( uint32_t iRefIdx = 0; iRefIdx < MAX_IDX_ADAPT_SR; iRefIdx++ )
235
223k
    {
236
223k
      m_aaiAdaptSR[iDir][iRefIdx] = m_iSearchRange;
237
223k
    }
238
37.3k
  }
239
240
  // initialize motion cost
241
74.6k
  for( int iNum = 0; iNum < AMVP_MAX_NUM_CANDS + 1; iNum++ )
242
55.9k
  {
243
167k
    for( int iIdx = 0; iIdx < AMVP_MAX_NUM_CANDS; iIdx++ )
244
111k
    {
245
111k
      if( iIdx < iNum )
246
55.9k
      {
247
55.9k
        m_auiMVPIdxCost[iIdx][iNum] = xGetMvpIdxBits( iIdx, iNum );
248
55.9k
      }
249
55.9k
      else
250
55.9k
      {
251
55.9k
        m_auiMVPIdxCost[iIdx][iNum] = MAX_UINT;
252
55.9k
      }
253
111k
    }
254
55.9k
  }
255
256
18.6k
  const ChromaFormat cform   = encCfg.m_internChromaFormat;
257
18.6k
  const int          ctuSize = encCfg.m_CTUSize;
258
55.9k
  for (uint32_t i = 0; i < NUM_REF_PIC_LIST_01; i++)
259
37.3k
  {
260
37.3k
    m_tmpPredStorage[i].create( UnitArea( cform, Area( 0, 0, ctuSize, ctuSize ) ) );
261
37.3k
  }
262
18.6k
  m_tmpStorageLCU.create( UnitArea( cform, Area( 0, 0, ctuSize, ctuSize ) ) );
263
18.6k
  m_pTempPel = new Pel[ctuSize * ctuSize];
264
18.6k
  m_tmpAffiStorage.create(UnitArea(cform, Area(0, 0, ctuSize, ctuSize + 2)));  // allow overread by 2 samples
265
18.6k
  m_tmpAffiError = new Pel[ctuSize * ctuSize];
266
18.6k
  m_tmpAffiDeri[0] = new Pel[ctuSize * ctuSize];
267
18.6k
  m_tmpAffiDeri[1] = new Pel[ctuSize * ctuSize];
268
269
18.6k
  CompArea chromaArea( COMP_Cb, cform, Area( 0, 0, encCfg.m_CTUSize, encCfg.m_CTUSize ), true );
270
93.2k
  for( int i = 0; i < 4; i++ )
271
74.6k
  {
272
74.6k
    m_orgResiCb[i].create( chromaArea );
273
74.6k
    m_orgResiCr[i].create( chromaArea );
274
74.6k
  }
275
18.6k
}
276
277
void InterSearch::destroy()
278
18.6k
{
279
18.6k
  if ( m_pTempPel )
280
18.6k
  {
281
18.6k
    delete [] m_pTempPel;
282
18.6k
    m_pTempPel = nullptr;
283
18.6k
  }
284
285
55.9k
  for( int i = 0; i < NUM_REF_PIC_LIST_01; i++ )
286
37.3k
  {
287
37.3k
    m_tmpPredStorage[i].destroy();
288
37.3k
  }
289
18.6k
  m_tmpStorageLCU.destroy();
290
18.6k
  m_tmpAffiStorage.destroy();
291
18.6k
  if (m_tmpAffiError != NULL)
292
18.6k
  {
293
18.6k
    delete[] m_tmpAffiError;
294
18.6k
    m_tmpAffiError = nullptr;
295
18.6k
  }
296
18.6k
  if (m_tmpAffiDeri[0] != NULL)
297
18.6k
  {
298
18.6k
    delete[] m_tmpAffiDeri[0];
299
18.6k
    m_tmpAffiDeri[0] = nullptr;
300
18.6k
  }
301
18.6k
  if (m_tmpAffiDeri[1] != NULL)
302
18.6k
  {
303
18.6k
    delete[] m_tmpAffiDeri[1];
304
18.6k
    m_tmpAffiDeri[1] = nullptr;
305
18.6k
  }
306
307
18.6k
  m_pSaveCS  = nullptr;
308
18.6k
}
309
310
void InterSearch::setCtuEncRsrc( CABACWriter* cabacEstimator, CtxCache* ctxCache, ReuseUniMv* pReuseUniMv, BlkUniMvInfoBuffer* pBlkUniMvInfoBuffer, AffineProfList* pAffineProfList, IbcBvCand* pCachedBvs )
311
3.57k
{
312
3.57k
  m_CABACEstimator     = cabacEstimator;
313
3.57k
  m_CtxCache           = ctxCache;
314
3.57k
  m_ReuseUniMv         = pReuseUniMv;
315
3.57k
  m_BlkUniMvInfoBuffer = pBlkUniMvInfoBuffer;
316
3.57k
  m_AffineProfList     = pAffineProfList;
317
3.57k
  m_defaultCachedBvs   = pCachedBvs;
318
3.57k
}
319
320
ReuseUniMv::ReuseUniMv()
321
8.13k
{
322
8.13k
  const int numPos     = MAX_CU_SIZE >> MIN_CU_LOG2;
323
8.13k
  const int maxSizeIdx = MAX_CU_SIZE_IDX-2;
324
56.9k
  for( int wIdx = 0; wIdx < maxSizeIdx; wIdx++ )
325
48.7k
  {
326
341k
    for( int hIdx = 0; hIdx < maxSizeIdx; hIdx++ )
327
292k
    {
328
9.66M
      for( int y = 0; y < numPos; y++ )
329
9.36M
      {
330
309M
        for( int x = 0; x < numPos; x++ )
331
299M
        {
332
299M
          m_reusedUniMVs[ wIdx ][ hIdx ][ x ][ y ] = nullptr;
333
299M
        }
334
9.36M
      }
335
292k
    }
336
48.7k
  }
337
8.13k
}
338
339
ReuseUniMv::~ReuseUniMv()
340
8.13k
{
341
8.13k
  resetReusedUniMvs();
342
8.13k
}
343
344
void ReuseUniMv::resetReusedUniMvs()
345
12.1k
{
346
12.1k
  const int numPos     = MAX_CU_SIZE >> MIN_CU_LOG2;
347
12.1k
  const int maxSizeIdx = MAX_CU_SIZE_IDX-2;
348
85.3k
  for ( int wIdx = 0; wIdx < maxSizeIdx; wIdx++ )
349
73.1k
  {
350
512k
    for ( int hIdx = 0; hIdx < maxSizeIdx; hIdx++ )
351
439k
    {
352
14.4M
      for ( int y = 0; y < numPos; y++ )
353
14.0M
      {
354
463M
        for ( int x = 0; x < numPos; x++ )
355
449M
        {
356
449M
          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
449M
        }
362
14.0M
      }
363
439k
    }
364
73.1k
  }
365
12.1k
}
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
55.9k
{
1847
55.9k
  CHECK(iIdx < 0 || iNum < 0 || iIdx >= iNum, "Invalid parameters");
1848
1849
55.9k
  if (iNum == 1)
1850
18.6k
  {
1851
18.6k
    return 0;
1852
18.6k
  }
1853
1854
37.3k
  uint32_t uiLength = 1;
1855
37.3k
  int iTemp = iIdx;
1856
37.3k
  if ( iTemp == 0 )
1857
18.6k
  {
1858
18.6k
    return uiLength;
1859
18.6k
  }
1860
1861
18.6k
  bool bCodeLast = ( iNum-1 > iTemp );
1862
1863
18.6k
  uiLength += (iTemp-1);
1864
1865
18.6k
  if( bCodeLast )
1866
0
  {
1867
0
    uiLength++;
1868
0
  }
1869
1870
18.6k
  return uiLength;
1871
37.3k
}
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
21.4k
{
3519
21.4k
  const UnitArea& currArea = partitioner.currArea();
3520
21.4k
  const SPS &sps           = *cs.sps;
3521
3522
21.4k
  const uint32_t numValidComp  = getNumberValidComponents( sps.chromaFormatIdc );
3523
21.4k
  const uint32_t numTBlocks    = getNumberValidTBlocks   ( *cs.pcv );
3524
21.4k
  CodingUnit& cu               = *cs.getCU(partitioner.chType, partitioner.treeType);
3525
21.4k
  const unsigned currDepth = partitioner.currTrDepth;
3526
21.4k
  const bool useTS = cs.picture->useTS;
3527
3528
21.4k
  bool bCheckFull  = !partitioner.canSplit( TU_MAX_TR_SPLIT, cs );
3529
21.4k
  if( cu.sbtInfo && partitioner.canSplit( CU::getSbtTuSplit( cu.sbtInfo ), cs ) )
3530
0
  {
3531
0
    bCheckFull = false;
3532
0
  }
3533
21.4k
  bool bCheckSplit = !bCheckFull;
3534
3535
  // get temporary data
3536
21.4k
  CodingStructure *csSplit = nullptr;
3537
21.4k
  CodingStructure *csFull  = nullptr;
3538
21.4k
  if (bCheckSplit)
3539
0
  {
3540
0
    csSplit = &cs;
3541
0
  }
3542
21.4k
  else if (bCheckFull)
3543
21.4k
  {
3544
21.4k
    csFull = &cs;
3545
21.4k
  }
3546
3547
21.4k
  Distortion uiSingleDist         = 0;
3548
21.4k
  Distortion uiSingleDistComp [3] = { 0, 0, 0 };
3549
3550
21.4k
  const TempCtx ctxStart  ( m_CtxCache, m_CABACEstimator->getCtx() );
3551
21.4k
  TempCtx       ctxBest   ( m_CtxCache );
3552
3553
21.4k
  PelUnitBuf    orgResiBuf;
3554
21.4k
  orgResiBuf = m_tmpStorageLCU.getCompactBuf( currArea );
3555
21.4k
  orgResiBuf.copyFrom(cs.getResiBuf(currArea));
3556
3557
21.4k
  if (bCheckFull)
3558
21.4k
  {
3559
21.4k
    TransformUnit& tu = csFull->addTU(CS::getArea(cs, currArea, partitioner.chType, partitioner.treeType), partitioner.chType, &cu);
3560
21.4k
    tu.depth          = currDepth;
3561
21.4k
    tu.mtsIdx[COMP_Y] = MTS_DCT2_DCT2;
3562
21.4k
    tu.checkTuNoResidual( partitioner.currPartIdx() );
3563
3564
21.4k
    double minCost [MAX_NUM_TBLOCKS];
3565
3566
21.4k
    m_CABACEstimator->resetBits();
3567
3568
21.4k
    memset(m_pTempPel, 0, sizeof(Pel) * tu.Y().area()); // not necessary needed for inside of recursion (only at the beginning)
3569
3570
85.9k
    for (uint32_t i = 0; i < numTBlocks; i++)
3571
64.4k
    {
3572
64.4k
      minCost[i] = MAX_DOUBLE;
3573
64.4k
    }
3574
3575
21.4k
    CodingStructure &saveCS = *m_pSaveCS[1];
3576
21.4k
    saveCS.pcv     = cs.pcv;
3577
21.4k
    saveCS.picture = cs.picture;
3578
21.4k
    saveCS.area.repositionTo( currArea );
3579
3580
21.4k
    TransformUnit& bestTU = saveCS.tus.empty() ? saveCS.addTU( currArea, partitioner.chType, nullptr ) : *saveCS.tus.front();
3581
21.4k
    bestTU.initData();
3582
21.4k
    bestTU.UnitArea::operator=( currArea );
3583
3584
85.9k
    for( uint32_t c = 0; c < numTBlocks; c++ )
3585
64.4k
    {
3586
64.4k
      const ComponentID compID    = ComponentID(c);
3587
64.4k
      const CompArea&   compArea  = tu.blocks[compID];
3588
64.4k
      const int channelBitDepth   = sps.bitDepths[toChannelType(compID)];
3589
3590
64.4k
      if( !tu.blocks[compID].valid() )
3591
42.9k
      {
3592
42.9k
        continue;
3593
42.9k
      }
3594
21.4k
      bool tsAllowed = useTS && TU::isTSAllowed(tu, compID) && (isLuma(compID) || (isChroma(compID) && m_pcEncCfg->m_useChromaTS));
3595
21.4k
      if (isChroma(compID) && tsAllowed && (tu.mtsIdx[COMP_Y] != MTS_SKIP))
3596
0
      {
3597
0
        tsAllowed = false;
3598
0
      }
3599
21.4k
      uint8_t nNumTransformCands = 1 + (tsAllowed ? 1 : 0); // DCT + TS = 2 tests
3600
21.4k
      std::vector<TrMode> trModes;
3601
3602
21.4k
      if (nNumTransformCands > 1)
3603
2.92k
      {
3604
2.92k
        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
2.92k
        if ( !tu.noResidual )
3607
2.92k
        {
3608
2.92k
          trModes.push_back(TrMode(1, true));
3609
2.92k
        }
3610
0
        else
3611
0
        {
3612
0
          nNumTransformCands--;
3613
0
        }
3614
2.92k
      }
3615
21.4k
      bool isLast = true;
3616
45.7k
      for (int transformMode = 0; transformMode < nNumTransformCands; transformMode++)
3617
24.2k
      {
3618
24.2k
        const bool isFirstMode = transformMode == 0;
3619
3620
        // copy the original residual into the residual buffer
3621
24.2k
        csFull->getResiBuf(compArea).copyFrom(orgResiBuf.get(compID));
3622
3623
3624
24.2k
        m_CABACEstimator->getCtx() = ctxStart;
3625
24.2k
        m_CABACEstimator->resetBits();
3626
3627
24.2k
        if (bestTU.mtsIdx[compID] == MTS_SKIP && m_pcEncCfg->m_TS)
3628
0
        {
3629
0
          continue;
3630
0
        }
3631
24.2k
        tu.mtsIdx[compID] = transformMode ? trModes[transformMode].first : 0;
3632
3633
24.2k
        const QpParam cQP(tu, compID);  // note: uses tu.transformSkip[compID]
3634
24.2k
        m_pcTrQuant->selectLambda(compID);
3635
3636
24.2k
        if ( sps.jointCbCr && isChroma( compID ) && ( tu.cu->cs->slice->sliceQp > 18 ) )
3637
0
        {
3638
0
          m_pcTrQuant->scaleLambda( 1.05 );
3639
0
        }
3640
24.2k
        TCoeff     currAbsSum = 0;
3641
24.2k
        uint64_t   currCompFracBits = 0;
3642
24.2k
        Distortion currCompDist = 0;
3643
24.2k
        double     currCompCost = 0;
3644
24.2k
        uint64_t   nonCoeffFracBits = 0;
3645
24.2k
        Distortion nonCoeffDist = 0;
3646
24.2k
        double     nonCoeffCost = 0;
3647
3648
24.2k
        if (nNumTransformCands > 1)
3649
5.64k
        {
3650
5.64k
          if (transformMode == 0)
3651
2.92k
          {
3652
2.92k
            m_pcTrQuant->checktransformsNxN(tu, &trModes, 2, compID);
3653
2.92k
            tu.mtsIdx[compID] = trModes[0].first;
3654
2.92k
            if (!trModes[transformMode + 1].second)
3655
200
            {
3656
200
              nNumTransformCands = 1;
3657
200
            }
3658
2.92k
          }
3659
5.64k
          m_pcTrQuant->transformNxN(tu, compID, cQP, currAbsSum, m_CABACEstimator->getCtx(), true);
3660
5.64k
        }
3661
18.5k
        else
3662
18.5k
        {
3663
18.5k
          m_pcTrQuant->transformNxN(tu, compID, cQP, currAbsSum, m_CABACEstimator->getCtx());
3664
18.5k
        }
3665
24.2k
        if (isFirstMode || (currAbsSum == 0))
3666
24.2k
        {
3667
24.2k
          const CPelBuf zeroBuf(m_pTempPel, compArea);
3668
24.2k
          const CPelBuf& orgResi = orgResiBuf.get(compID);
3669
3670
24.2k
          nonCoeffDist = m_pcRdCost->getDistPart(zeroBuf, orgResi, channelBitDepth, compID, DF_SSE); // initialized with zero residual distortion
3671
3672
24.2k
          if (!tu.noResidual)
3673
24.2k
          {
3674
24.2k
            const bool prevCbf = (compID == COMP_Cr ? tu.cbf[COMP_Cb] : false);
3675
24.2k
            m_CABACEstimator->cbf_comp(*tu.cu, false, compArea, currDepth, prevCbf);
3676
24.2k
          }
3677
3678
24.2k
          nonCoeffFracBits = m_CABACEstimator->getEstFracBits();
3679
24.2k
          nonCoeffCost = m_pcRdCost->calcRdCost(nonCoeffFracBits, nonCoeffDist, !m_pcEncCfg->m_lumaLevelToDeltaQPEnabled);
3680
24.2k
        }
3681
3682
24.2k
        if ((puiZeroDist != NULL) && isFirstMode)
3683
21.4k
        {
3684
21.4k
          *puiZeroDist += nonCoeffDist; // initialized with zero residual distortion
3685
21.4k
        }
3686
3687
24.2k
        if (currAbsSum > 0) //if non-zero coefficients are present, a residual needs to be derived for further prediction
3688
203
        {
3689
203
          if (isFirstMode)
3690
203
          {
3691
203
            m_CABACEstimator->getCtx() = ctxStart;
3692
203
            m_CABACEstimator->resetBits();
3693
203
          }
3694
3695
203
          const bool prevCbf = ( compID == COMP_Cr ? tu.cbf[COMP_Cb] : false );
3696
203
          m_CABACEstimator->cbf_comp( *tu.cu, true, compArea, currDepth, prevCbf );
3697
203
          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
203
          CUCtx cuCtx;
3703
203
          cuCtx.isDQPCoded = true;
3704
203
          cuCtx.isChromaQpAdjCoded = true;
3705
203
          m_CABACEstimator->residual_coding(tu, compID, &cuCtx);
3706
203
          m_CABACEstimator->mts_idx(cu, &cuCtx);
3707
3708
203
          currCompFracBits = m_CABACEstimator->getEstFracBits();
3709
3710
203
          PelBuf resiBuf  = csFull->getResiBuf(compArea);
3711
203
          CPelBuf orgResi = orgResiBuf.get(compID);
3712
3713
203
          m_pcTrQuant->invTransformNxN(tu, compID, resiBuf, cQP);
3714
203
          currCompDist = m_pcRdCost->getDistPart(orgResi, resiBuf, channelBitDepth, compID, DF_SSE);
3715
203
          currCompCost = m_pcRdCost->calcRdCost(currCompFracBits, currCompDist, false);
3716
203
        }
3717
24.0k
        else if (transformMode > 0)
3718
2.72k
        {
3719
2.72k
          currCompCost = MAX_DOUBLE;
3720
2.72k
        }
3721
21.2k
        else
3722
21.2k
        {
3723
21.2k
          currCompFracBits = nonCoeffFracBits;
3724
21.2k
          currCompDist     = nonCoeffDist;
3725
21.2k
          currCompCost     = nonCoeffCost;
3726
3727
21.2k
          tu.cbf[compID] = 0;
3728
21.2k
        }
3729
3730
        // evaluate
3731
24.2k
        if ((currCompCost < minCost[compID]) || (transformMode == 1 && currCompCost == minCost[compID]))
3732
21.4k
        {
3733
          // copy component
3734
21.4k
          if (isFirstMode && ((nonCoeffCost < currCompCost) || (currAbsSum == 0))) // check for forced null
3735
21.3k
          {
3736
21.3k
            tu.getCoeffs( compID ).fill( 0 );
3737
21.3k
            csFull->getResiBuf( compArea ).fill( 0 );
3738
21.3k
            tu.cbf[compID]   = 0;
3739
3740
21.3k
            currAbsSum       = 0;
3741
21.3k
            currCompFracBits = nonCoeffFracBits;
3742
21.3k
            currCompDist     = nonCoeffDist;
3743
21.3k
            currCompCost     = nonCoeffCost;
3744
21.3k
          }
3745
3746
21.4k
          uiSingleDistComp[compID] = currCompDist;
3747
21.4k
          minCost[compID]          = currCompCost;
3748
21.4k
          if (transformMode != (nNumTransformCands - 1))
3749
2.72k
          {
3750
2.72k
            bestTU.copyComponentFrom(tu, compID);
3751
2.72k
            saveCS.getResiBuf(compArea).copyFrom(csFull->getResiBuf(compArea));
3752
2.72k
          }
3753
18.7k
          else
3754
18.7k
          {
3755
18.7k
            isLast = false;
3756
18.7k
          }
3757
21.4k
        }
3758
24.2k
        if( tu.noResidual )
3759
0
        {
3760
0
          CHECK( currCompFracBits > 0 || currAbsSum, "currCompFracBits > 0 when tu noResidual" );
3761
0
        }
3762
24.2k
      }
3763
21.4k
      if (isLast)
3764
2.72k
      {
3765
2.72k
        tu.copyComponentFrom(bestTU, compID);
3766
2.72k
        csFull->getResiBuf(compArea).copyFrom(saveCS.getResiBuf(compArea));
3767
2.72k
      }
3768
21.4k
    } // component loop
3769
3770
21.4k
    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
21.4k
    m_CABACEstimator->getCtx() = ctxStart;
3964
21.4k
    m_CABACEstimator->resetBits();
3965
21.4k
    if( !tu.noResidual )
3966
21.4k
    {
3967
21.4k
      static const ComponentID cbf_getComp[3] = { COMP_Cb, COMP_Cr, COMP_Y };
3968
85.9k
      for( unsigned c = 0; c < numTBlocks; c++)
3969
64.4k
      {
3970
64.4k
        const ComponentID compID = numTBlocks>1 ? cbf_getComp[c] : COMP_Y;
3971
64.4k
        if( tu.blocks[compID].valid() )
3972
21.4k
        {
3973
21.4k
          const bool prevCbf = ( compID == COMP_Cr ? TU::getCbfAtDepth( tu, COMP_Cb, currDepth ) : false );
3974
21.4k
          m_CABACEstimator->cbf_comp( *tu.cu, TU::getCbfAtDepth( tu, compID, currDepth ), tu.blocks[compID], currDepth, prevCbf );
3975
21.4k
        }
3976
64.4k
      }
3977
21.4k
    }
3978
3979
85.9k
    for (uint32_t ch = 0; ch < numValidComp; ch++)
3980
64.4k
    {
3981
64.4k
      const ComponentID compID = ComponentID(ch);
3982
64.4k
      if (tu.blocks[compID].valid())
3983
21.4k
      {
3984
21.4k
        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
21.4k
        if( TU::getCbf( tu, compID ) )
3990
131
        {
3991
131
          m_CABACEstimator->residual_coding( tu, compID );
3992
131
        }
3993
21.4k
        uiSingleDist += uiSingleDistComp[compID];
3994
21.4k
      }
3995
64.4k
    }
3996
21.4k
    if( tu.noResidual )
3997
0
    {
3998
0
      CHECK( m_CABACEstimator->getEstFracBits() > 0, "no residual TU's bits shall be 0" );
3999
0
    }
4000
4001
21.4k
    csFull->fracBits += m_CABACEstimator->getEstFracBits();
4002
21.4k
    csFull->dist     += uiSingleDist;
4003
21.4k
    csFull->cost      = m_pcRdCost->calcRdCost(csFull->fracBits, csFull->dist, !m_pcEncCfg->m_lumaLevelToDeltaQPEnabled);
4004
21.4k
  } // check full
4005
4006
  // code sub-blocks
4007
21.4k
  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
21.4k
}
4073
4074
void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &partitioner, const bool skipResidual )
4075
21.4k
{
4076
21.4k
  CodingUnit &cu = *cs.getCU( partitioner.chType, partitioner.treeType );
4077
21.4k
  bool luma      = true;
4078
21.4k
  bool chroma    = cs.pcv->chrFormat != VVENC_CHROMA_400;
4079
21.4k
  if( cu.predMode == MODE_IBC )
4080
21.4k
  {
4081
21.4k
    luma    = !cu.mccNoLuma  ();
4082
21.4k
    chroma &= !cu.mccNoChroma();
4083
21.4k
  }
4084
21.4k
  if( cu.predMode == MODE_INTER )
4085
21.4k
    CHECK( CU::isSepTree(cu), "CU with Inter mode must be in single tree" );
4086
4087
21.4k
  const ChromaFormat format      = cs.area.chromaFormat;;
4088
21.4k
  const int  numValidComponents  = getNumberValidComponents(format);
4089
21.4k
  const SPS &sps                 = *cs.sps;
4090
4091
21.4k
  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
21.4k
  if (luma)
4129
21.4k
  {
4130
21.4k
    cs.getResiBuf(COMP_Y).subtract(cs.getOrgBuf(COMP_Y), cs.getPredBuf(COMP_Y));
4131
21.4k
  }
4132
21.4k
  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
21.4k
  Distortion zeroDistortion = 0;
4139
4140
21.4k
  const TempCtx ctxStart( m_CtxCache, m_CABACEstimator->getCtx() );
4141
4142
21.4k
  xEstimateInterResidualQT(cs, partitioner, &zeroDistortion );
4143
21.4k
  TransformUnit& firstTU = *cs.getTU( partitioner.chType );
4144
4145
21.4k
  cu.rootCbf = false;
4146
21.4k
  m_CABACEstimator->resetBits();
4147
21.4k
  m_CABACEstimator->rqt_root_cbf( cu );
4148
21.4k
  const uint64_t  zeroFracBits = m_CABACEstimator->getEstFracBits();
4149
21.4k
  double zeroCost = m_pcRdCost->calcRdCost( zeroFracBits, zeroDistortion, !m_pcEncCfg->m_lumaLevelToDeltaQPEnabled );
4150
4151
21.4k
  const int  numValidTBlocks   = getNumberValidTBlocks( *cs.pcv );
4152
85.9k
  for (uint32_t i = 0; i < numValidTBlocks; i++)
4153
64.4k
  {
4154
64.4k
    cu.rootCbf |= TU::getCbfAtDepth(firstTU, ComponentID(i), 0);
4155
64.4k
  }
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
21.4k
  if (zeroCost < cs.cost || !cu.rootCbf)
4162
21.3k
  {
4163
21.3k
    cu.sbtInfo = 0;
4164
21.3k
    cu.rootCbf = false;
4165
4166
21.3k
    cs.clearTUs();
4167
4168
    // add a new "empty" TU spanning the whole CU
4169
21.3k
    cs.addEmptyTUs( partitioner, &cu );
4170
21.3k
  }
4171
4172
  // all decisions now made. Fully encode the CU, including the headers:
4173
21.4k
  m_CABACEstimator->getCtx() = ctxStart;
4174
4175
21.4k
  uint64_t finalFracBits = xGetSymbolFracBitsInter( cs, partitioner );
4176
  // we've now encoded the CU, and so have a valid bit cost
4177
21.4k
  if (!cu.rootCbf)
4178
21.3k
  {
4179
21.3k
    if (luma)
4180
21.3k
    {
4181
21.3k
      cs.getResiBuf().bufs[0].fill(0); // Clear the residual image, if we didn't code it.
4182
21.3k
    }
4183
21.3k
    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
21.3k
  }
4189
21.4k
  if (luma)
4190
21.4k
  {
4191
21.4k
    cs.getRecoBuf().bufs[0].reconstruct(cs.getPredBuf().bufs[0], cs.getResiBuf().bufs[0], cs.slice->clpRngs[COMP_Y]);
4192
21.4k
  }
4193
21.4k
  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
21.4k
  Distortion finalDistortion = 0;
4200
4201
85.9k
  for (int comp = 0; comp < numValidComponents; comp++)
4202
64.4k
  {
4203
64.4k
    const ComponentID compID = ComponentID(comp);
4204
64.4k
    if (compID == COMP_Y && !luma)
4205
0
      continue;
4206
64.4k
    if (compID != COMP_Y && !chroma)
4207
42.9k
      continue;
4208
21.4k
    CPelBuf reco = cs.getRecoBuf (compID);
4209
21.4k
    CPelBuf org  = cs.getOrgBuf  (compID);
4210
4211
21.4k
    finalDistortion += m_pcRdCost->getDistPart( org, reco, sps.bitDepths[toChannelType(compID)], compID, DF_SSE );
4212
21.4k
  }
4213
4214
21.4k
  cs.dist     = finalDistortion;
4215
21.4k
  cs.fracBits = finalFracBits;
4216
21.4k
  cs.cost     = m_pcRdCost->calcRdCost(cs.fracBits, cs.dist);
4217
4218
21.4k
  CHECK(cs.tus.size() == 0, "No TUs present");
4219
21.4k
}
4220
4221
uint64_t InterSearch::xGetSymbolFracBitsInter(CodingStructure &cs, Partitioner &partitioner)
4222
21.4k
{
4223
21.4k
  uint64_t fracBits   = 0;
4224
21.4k
  CodingUnit &cu    = *cs.getCU( partitioner.chType, partitioner.treeType );
4225
4226
21.4k
  m_CABACEstimator->resetBits();
4227
4228
21.4k
  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
21.4k
  else
4240
21.4k
  {
4241
21.4k
    CHECK( cu.skip, "Skip flag has to be off at this point!" );
4242
4243
21.4k
    if (cu.Y().valid())
4244
21.4k
    m_CABACEstimator->cu_skip_flag( cu );
4245
21.4k
    m_CABACEstimator->pred_mode   ( cu );
4246
21.4k
    m_CABACEstimator->cu_pred_data( cu );
4247
21.4k
    CUCtx cuCtx;
4248
21.4k
    cuCtx.isDQPCoded = true;
4249
21.4k
    cuCtx.isChromaQpAdjCoded = true;
4250
21.4k
    m_CABACEstimator->cu_residual ( cu, partitioner, cuCtx );
4251
21.4k
    fracBits       += m_CABACEstimator->getEstFracBits();
4252
21.4k
  }
4253
4254
21.4k
  return fracBits;
4255
21.4k
}
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
124k
{
4403
373k
  for (int i = 0; i < 2; i++)
4404
248k
  {
4405
746k
    for (int j = 0; j < 2; j++)
4406
497k
    {
4407
497k
      m_affineMotion.acMvAffine4Para[i][j] = Mv(0, 0);
4408
497k
      m_affineMotion.acMvAffine6Para[i][j] = Mv(0, 0);
4409
497k
    }
4410
248k
    m_affineMotion.acMvAffine6Para[i][2] = Mv(0, 0);
4411
4412
248k
    m_affineMotion.affine4ParaRefIdx[i] = -1;
4413
248k
    m_affineMotion.affine6ParaRefIdx[i] = -1;
4414
248k
  }
4415
124k
  m_affineMotion.affine4ParaAvail = false;
4416
124k
  m_affineMotion.affine6ParaAvail = false;
4417
124k
}
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.66k
{
5717
4.66k
  if( !encCfg.m_bUseASR || slice->isIRAP() )
5718
4.66k
  {
5719
4.66k
    return;
5720
4.66k
  }
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.18M
{
5743
1.18M
  int j = CHROMA_REFINEMENT_CANDIDATES - 1;
5744
5745
1.18M
  if (sad < sadBestCand[CHROMA_REFINEMENT_CANDIDATES - 1])
5746
189k
  {
5747
1.70M
    for (int t = CHROMA_REFINEMENT_CANDIDATES - 1; t >= 0; t--)
5748
1.51M
    {
5749
1.51M
      if (sad < sadBestCand[t])
5750
909k
        j = t;
5751
1.51M
    }
5752
5753
909k
    for (int k = CHROMA_REFINEMENT_CANDIDATES - 1; k > j; k--)
5754
719k
    {
5755
719k
      sadBestCand[k] = sadBestCand[k - 1];
5756
5757
719k
      cMVCand[k].set(cMVCand[k - 1].hor, cMVCand[k - 1].ver);
5758
719k
    }
5759
189k
    sadBestCand[j] = sad;
5760
189k
    cMVCand[j].set(x, y);
5761
189k
  }
5762
1.18M
}
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
20.4k
{
5774
20.4k
  if ((!isChromaEnabled(cu.chromaFormat)) || (!cu.Cb().valid()))
5775
20.4k
  {
5776
20.4k
    return 0;
5777
20.4k
  }
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
20.4k
}
5862
static unsigned int xMergeCandLists(Mv* dst, unsigned int dn, unsigned int dstTotalLength, Mv* src, unsigned int sn)
5863
120k
{
5864
948k
  for (unsigned int cand = 0; cand < sn && dn < dstTotalLength; cand++)
5865
827k
  {
5866
827k
    if (src[cand] == Mv())
5867
61.5k
    {
5868
61.5k
      continue;
5869
61.5k
    }
5870
766k
    bool found = false;
5871
5.82M
    for (int j = 0; j < dn; j++)
5872
5.16M
    {
5873
5.16M
      if (src[cand] == dst[j])
5874
105k
      {
5875
105k
        found = true;
5876
105k
        break;
5877
105k
      }
5878
5.16M
    }
5879
5880
766k
    if (!found)
5881
661k
    {
5882
661k
      dst[dn] = src[cand];
5883
661k
      dn++;
5884
661k
    }
5885
766k
  }
5886
5887
120k
  return dn;
5888
120k
}
5889
void InterSearch::xIntraPatternSearchIBC(CodingUnit& cu, TZSearchStruct& cStruct, Mv& rcMv, Distortion& ruiCost, Mv* pcMvSrchRngLT, Mv* pcMvSrchRngRB, Mv* pcMvPred)
5890
24.0k
{
5891
24.0k
  const int   srchRngHorLeft = pcMvSrchRngLT->hor;
5892
24.0k
  const int   srchRngHorRight = pcMvSrchRngRB->hor;
5893
24.0k
  const int   srchRngVerTop = pcMvSrchRngLT->ver;
5894
24.0k
  const int   srchRngVerBottom = pcMvSrchRngRB->ver;
5895
5896
24.0k
  const unsigned int  lcuWidth = cu.cs->slice->sps->CTUSize;
5897
24.0k
  const int   puPelOffsetX = 0;
5898
24.0k
  const int   puPelOffsetY = 0;
5899
24.0k
  const int   cuPelX = cu.Y().x;
5900
24.0k
  const int   cuPelY = cu.Y().y;
5901
5902
24.0k
  int          roiWidth = cu.lwidth();
5903
24.0k
  int          roiHeight = cu.lheight();
5904
5905
24.0k
  Distortion  sad;
5906
24.0k
  Distortion  sadBest = std::numeric_limits<Distortion>::max();
5907
24.0k
  int         bestX = 0;
5908
24.0k
  int         bestY = 0;
5909
5910
24.0k
  const Pel* piRefSrch = cStruct.piRefY; 
5911
5912
24.0k
  int         bestCandIdx = 0;
5913
5914
24.0k
  Distortion  sadBestCand[CHROMA_REFINEMENT_CANDIDATES];
5915
24.0k
  Mv          cMVCand[CHROMA_REFINEMENT_CANDIDATES];
5916
5917
24.0k
  const bool  useAmvr = cu.cs->sps->AMVR;
5918
5919
5920
216k
  for (int cand = 0; cand < CHROMA_REFINEMENT_CANDIDATES; cand++)
5921
192k
  {
5922
192k
    sadBestCand[cand] = std::numeric_limits<Distortion>::max();
5923
192k
    cMVCand[cand].set(0, 0);
5924
192k
  }
5925
5926
24.0k
  m_pcRdCost->setDistParam(m_cDistParam, *cStruct.pcPatternKey, cStruct.piRefY, cStruct.iRefStride, m_lumaClpRng.bd, COMP_Y, cStruct.subShiftMode);
5927
5928
24.0k
  const int picWidth = cu.cs->slice->pps->picWidthInLumaSamples;
5929
24.0k
  const int picHeight = cu.cs->slice->pps->picHeightInLumaSamples;
5930
5931
5932
24.0k
  {
5933
24.0k
    m_cDistParam.subShift = 0;
5934
24.0k
    Distortion tempSadBest = 0;
5935
5936
24.0k
    int srLeft = srchRngHorLeft, srRight = srchRngHorRight, srTop = srchRngVerTop, srBottom = srchRngVerBottom;
5937
24.0k
    m_numBVs = 0;
5938
24.0k
    m_numBVs = xMergeCandLists(m_acBVs, m_numBVs, (2 * IBC_NUM_CANDIDATES), m_defaultCachedBvs->m_bvCands, m_defaultCachedBvs->currCnt);
5939
5940
24.0k
    Mv cMvPredEncOnly[IBC_NUM_CANDIDATES];
5941
24.0k
    int nbPreds = 0;
5942
24.0k
    CU::getIbcMVPsEncOnly(cu, cMvPredEncOnly, nbPreds);
5943
24.0k
    m_numBVs = xMergeCandLists(m_acBVs, m_numBVs, (2 * IBC_NUM_CANDIDATES), cMvPredEncOnly, nbPreds);
5944
5945
235k
    for (unsigned int cand = 0; cand < m_numBVs; cand++)
5946
211k
    {
5947
211k
      int xPred = m_acBVs[cand].hor;
5948
211k
      int yPred = m_acBVs[cand].ver;
5949
5950
211k
      if (!(xPred == 0 && yPred == 0)
5951
211k
        && !((yPred < srTop) || (yPred > srBottom))
5952
189k
        && !((xPred < srLeft) || (xPred > srRight)))
5953
189k
      {
5954
189k
        bool validCand = searchBvIBC(cu, cuPelX, cuPelY, roiWidth, roiHeight, picWidth, picHeight, xPred, yPred, lcuWidth);
5955
5956
189k
        if (validCand)
5957
156k
        {
5958
156k
          sad = m_pcRdCost->getBvCostMultiplePredsIBC(xPred, yPred, useAmvr);
5959
156k
          m_cDistParam.cur.buf = piRefSrch + cStruct.iRefStride * yPred + xPred;
5960
156k
          sad += m_cDistParam.distFunc(m_cDistParam);
5961
5962
156k
          xIBCSearchMVCandUpdate(sad, xPred, yPred, sadBestCand, cMVCand);
5963
156k
        }
5964
189k
      }
5965
211k
    }
5966
5967
24.0k
    bestX = cMVCand[0].hor;
5968
24.0k
    bestY = cMVCand[0].ver;
5969
24.0k
    rcMv.set(bestX, bestY);
5970
24.0k
    sadBest = sadBestCand[0];
5971
5972
24.0k
    const int boundY = (0 - roiHeight - puPelOffsetY);
5973
428k
    for (int y = std::max(srchRngVerTop, 0 - cuPelY); y <= boundY; ++y)
5974
406k
    {
5975
406k
      if (!searchBvIBC(cu, cuPelX, cuPelY, roiWidth, roiHeight, picWidth, picHeight, 0, y, lcuWidth))
5976
0
      {
5977
0
        continue;
5978
0
      }
5979
5980
406k
      sad = m_pcRdCost->getBvCostMultiplePredsIBC(0, y, useAmvr);
5981
406k
      m_cDistParam.cur.buf = piRefSrch + cStruct.iRefStride * y;
5982
406k
      sad += m_cDistParam.distFunc(m_cDistParam);
5983
5984
406k
      xIBCSearchMVCandUpdate(sad, 0, y, sadBestCand, cMVCand);
5985
406k
      tempSadBest = sadBestCand[0];
5986
406k
      if (sadBestCand[0] <= 3)
5987
2.48k
      {
5988
2.48k
        bestX = cMVCand[0].hor;
5989
2.48k
        bestY = cMVCand[0].ver;
5990
2.48k
        sadBest = sadBestCand[0];
5991
2.48k
        rcMv.set(bestX, bestY);
5992
2.48k
        ruiCost = sadBest;
5993
2.48k
        goto end;
5994
2.48k
      }
5995
406k
    }
5996
5997
21.5k
    const int boundX = std::max(srchRngHorLeft, -cuPelX);
5998
1.38M
    for (int x = 0 - roiWidth - puPelOffsetX; x >= boundX; --x)
5999
1.36M
    {
6000
1.36M
      if (!searchBvIBC(cu, cuPelX, cuPelY, roiWidth, roiHeight, picWidth, picHeight, x, 0, lcuWidth))
6001
752k
      {
6002
752k
        continue;
6003
752k
      }
6004
6005
609k
      sad = m_pcRdCost->getBvCostMultiplePredsIBC(x, 0, useAmvr);
6006
609k
      m_cDistParam.cur.buf = piRefSrch + x;
6007
609k
      sad += m_cDistParam.distFunc(m_cDistParam);
6008
6009
6010
609k
      xIBCSearchMVCandUpdate(sad, x, 0, sadBestCand, cMVCand);
6011
609k
      tempSadBest = sadBestCand[0];
6012
609k
      if (sadBestCand[0] <= 3)
6013
1.06k
      {
6014
1.06k
        bestX = cMVCand[0].hor;
6015
1.06k
        bestY = cMVCand[0].ver;
6016
1.06k
        sadBest = sadBestCand[0];
6017
1.06k
        rcMv.set(bestX, bestY);
6018
1.06k
        ruiCost = sadBest;
6019
1.06k
        goto end;
6020
1.06k
      }
6021
609k
    }
6022
6023
20.5k
    bestX = cMVCand[0].hor;
6024
20.5k
    bestY = cMVCand[0].ver;
6025
20.5k
    sadBest = sadBestCand[0];
6026
20.5k
    if ((!bestX && !bestY) || (sadBest - m_pcRdCost->getBvCostMultiplePredsIBC(bestX, bestY, useAmvr) <= 32))
6027
19.3k
    {
6028
      //chroma refine
6029
19.3k
      bestCandIdx = xIBCSearchMVChromaRefine(cu, roiWidth, roiHeight, cuPelX, cuPelY, sadBestCand, cMVCand);
6030
19.3k
      bestX = cMVCand[bestCandIdx].hor;
6031
19.3k
      bestY = cMVCand[bestCandIdx].ver;
6032
19.3k
      sadBest = sadBestCand[bestCandIdx];
6033
19.3k
      rcMv.set(bestX, bestY);
6034
19.3k
      ruiCost = sadBest;
6035
19.3k
      goto end;
6036
19.3k
    }
6037
6038
1.15k
    if (cu.lwidth() < 16 && cu.lheight() < 16)
6039
28
    {
6040
28
      int stepS = 2;
6041
28
      if (m_pcEncCfg->m_IBCFastMethod > 2)
6042
28
      {
6043
28
        if (m_pcEncCfg->m_IBCFastMethod == 5)
6044
0
        {
6045
0
          stepS = 8;
6046
0
        }
6047
28
        else if ((cu.lwidth() > 4) || (cu.lheight() > 4))
6048
28
        {
6049
28
          stepS = 4;
6050
28
        }
6051
28
      }
6052
6053
28
      const int minCuLog2 = m_pcEncCfg->m_log2MinCodingBlockSize;
6054
28
      const int minCuMask = (1 << minCuLog2) - 1;
6055
28
      bool lastDec = false;
6056
6057
28
      for (int searchStep = 0; searchStep < 3; searchStep++)
6058
28
      {
6059
28
        int delaySy = searchStep ? 1 : 0;
6060
28
        int delaySx = searchStep > 1 ? 1 : 0;
6061
28
        int startY = (std::max(srchRngVerTop, -cuPelY) + delaySy);
6062
28
        int startX = (std::max(srchRngHorLeft, -cuPelX) + delaySx);
6063
28
        int endY = srchRngVerBottom;
6064
28
        int endX = srchRngHorRight;
6065
6066
28
        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
691
        for (int y = startY; y <= endY; y += stepS)
6080
663
        {
6081
663
          if ((y == 0) || ((int)(cuPelY + y + roiHeight) >= picHeight))
6082
403
            continue;
6083
260
          bool firstX = true;
6084
260
          int stepSx = searchStep ? stepS : 1;
6085
31.6k
          for (int x = startX; x <= endX; firstX = false, x += stepSx)
6086
31.4k
          {
6087
31.4k
            if ((x == 0) || ((int)(cuPelX + x + roiWidth) >= picWidth))
6088
12.9k
              continue;
6089
6090
18.4k
            bool isSameAsLast = !firstX && ((cuPelX + x) & minCuMask) > 1;
6091
18.4k
            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
18.4k
            else if ((isSameAsLast && !lastDec) || (!isSameAsLast && !searchBvIBC(cu, cuPelX, cuPelY, roiWidth, roiHeight, picWidth, picHeight, x, y, lcuWidth)))
6099
5.80k
            {
6100
5.80k
              lastDec = false;
6101
5.80k
              continue;
6102
5.80k
            }
6103
12.6k
            lastDec = true;
6104
6105
12.6k
            sad = m_pcRdCost->getBvCostMultiplePredsIBC(x, y, useAmvr);
6106
12.6k
            m_cDistParam.cur.buf = piRefSrch + cStruct.iRefStride * y + x;
6107
12.6k
            sad += m_cDistParam.distFunc(m_cDistParam);
6108
6109
12.6k
            xIBCSearchMVCandUpdate(sad, x, y, sadBestCand, cMVCand);
6110
6111
6112
12.6k
            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
12.6k
          }
6124
260
        }
6125
6126
28
        if ((searchStep < 2) && (m_pcEncCfg->m_IBCFastMethod < 6))
6127
28
        {
6128
28
          if ((m_pcEncCfg->m_IBCFastMethod > 2) && (m_pcEncCfg->m_IBCFastMethod < 5))
6129
28
          {
6130
28
            if ((bestX == cMVCand[0].hor) && (bestY == cMVCand[0].ver))
6131
28
            {
6132
28
              sadBest = sadBestCand[bestCandIdx];
6133
28
              rcMv.set(bestX, bestY);
6134
28
              ruiCost = sadBest;
6135
28
              goto end;
6136
28
            }
6137
28
          }
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
28
      }
6157
28
    }
6158
1.15k
  }
6159
6160
1.12k
  bestCandIdx = xIBCSearchMVChromaRefine(cu, roiWidth, roiHeight, cuPelX, cuPelY, sadBestCand, cMVCand);
6161
6162
1.12k
  bestX = cMVCand[bestCandIdx].hor;
6163
1.12k
  bestY = cMVCand[bestCandIdx].ver;
6164
1.12k
  sadBest = sadBestCand[bestCandIdx];
6165
1.12k
  rcMv.set(bestX, bestY);
6166
1.12k
  ruiCost = sadBest;
6167
6168
24.0k
end:
6169
24.0k
  m_numBVs = 0;
6170
24.0k
  m_numBVs = xMergeCandLists(m_acBVs, m_numBVs, (2 * IBC_NUM_CANDIDATES), m_defaultCachedBvs->m_bvCands, m_defaultCachedBvs->currCnt);
6171
6172
24.0k
  m_defaultCachedBvs->currCnt = 0;
6173
24.0k
  m_defaultCachedBvs->currCnt = xMergeCandLists(m_defaultCachedBvs->m_bvCands, m_defaultCachedBvs->currCnt, IBC_NUM_CANDIDATES, cMVCand, CHROMA_REFINEMENT_CANDIDATES);
6174
24.0k
  m_defaultCachedBvs->currCnt = xMergeCandLists(m_defaultCachedBvs->m_bvCands, m_defaultCachedBvs->currCnt, IBC_NUM_CANDIDATES, m_acBVs, m_numBVs);
6175
6176
216k
  for (unsigned int cand = 0; cand < CHROMA_REFINEMENT_CANDIDATES; cand++)
6177
192k
  {
6178
192k
    if (cMVCand[cand].hor == 0 && cMVCand[cand].ver == 0)
6179
61.5k
    {
6180
61.5k
      continue;
6181
61.5k
    }
6182
130k
    m_ctuRecord[cu.lumaPos()][cu.lumaSize()].bvRecord[cMVCand[cand]] = sadBestCand[cand];
6183
130k
  }
6184
6185
24.0k
  return;
6186
1.12k
}
6187
6188
6189
6190
// based on xMotionEstimation
6191
void InterSearch::xIBCEstimation(CodingUnit& cu, PelUnitBuf& origBuf, Mv* pcMvPred, Mv& rcMv, Distortion& ruiCost )
6192
24.0k
{
6193
24.0k
  const int iPicWidth = cu.cs->slice->pps->picWidthInLumaSamples;
6194
24.0k
  const int iPicHeight = cu.cs->slice->pps->picHeightInLumaSamples;
6195
24.0k
  const unsigned int  lcuWidth = cu.cs->slice->sps->CTUSize;
6196
24.0k
  const int           cuPelX = cu.Y().x;
6197
24.0k
  const int           cuPelY = cu.Y().y;
6198
24.0k
  int                 iRoiWidth = cu.lwidth();
6199
24.0k
  int                 iRoiHeight = cu.lheight();
6200
6201
24.0k
  PelUnitBuf* pBuf = &origBuf;
6202
6203
  //  Search key pattern initialization
6204
24.0k
  CPelBuf  tmpPattern = pBuf->Y();
6205
24.0k
  CPelBuf* pcPatternKey = &tmpPattern;
6206
24.0k
  m_lumaClpRng = cu.cs->slice->clpRngs[COMP_Y];
6207
24.0k
  Picture* refPic = cu.slice->pic;
6208
24.0k
  const CPelBuf refBuf = refPic->getRecoBuf(cu.blocks[COMP_Y]);
6209
6210
24.0k
  TZSearchStruct cStruct; 
6211
24.0k
  cStruct.pcPatternKey  = pcPatternKey;
6212
24.0k
  cStruct.iRefStride    = refBuf.stride;
6213
24.0k
  cStruct.piRefY        = refBuf.buf;
6214
24.0k
  CHECK( cu.imv == IMV_HPEL, "IF_IBC" );
6215
24.0k
  cStruct.imvShift      = cu.imv << 1;
6216
24.0k
  cStruct.subShiftMode  = 0;
6217
24.0k
  cStruct.uiBestSad     = MAX_DISTORTION;
6218
6219
24.0k
  m_pcRdCost->getMotionCostIBC(0);
6220
24.0k
  m_pcRdCost->setPredictorsIBC(pcMvPred);
6221
24.0k
  m_pcRdCost->setCostScale(0);
6222
6223
24.0k
  m_pcRdCost->setDistParam(m_cDistParam, *cStruct.pcPatternKey, cStruct.piRefY, cStruct.iRefStride, m_lumaClpRng.bd, COMP_Y, cStruct.subShiftMode);
6224
24.0k
  bool buffered = false;
6225
24.0k
  if (m_pcEncCfg->m_IBCFastMethod)// IBC_FAST_METHOD_BUFFERBV
6226
24.0k
  {
6227
24.0k
    ruiCost = MAX_UINT;
6228
24.0k
    std::unordered_map<Mv, Distortion>& history = m_ctuRecord[cu.lumaPos()][cu.lumaSize()].bvRecord;
6229
24.0k
    for (std::unordered_map<Mv, Distortion>::iterator p = history.begin(); p != history.end(); p++)
6230
16
    {
6231
16
      const Mv& bv = p->first;
6232
6233
16
      int xBv = bv.hor;
6234
16
      int yBv = bv.ver;
6235
16
      if (searchBvIBC(cu, cuPelX, cuPelY, iRoiWidth, iRoiHeight, iPicWidth, iPicHeight, xBv, yBv, lcuWidth))
6236
16
      {
6237
16
        buffered = true;
6238
16
        Distortion sad = m_pcRdCost->getBvCostMultiplePredsIBC(xBv, yBv, cu.cs->sps->AMVR);
6239
16
        m_cDistParam.cur.buf = cStruct.piRefY + cStruct.iRefStride * yBv + xBv;
6240
16
        sad += m_cDistParam.distFunc(m_cDistParam);
6241
16
        if (sad < ruiCost)
6242
16
        {
6243
16
          rcMv = bv;
6244
16
          ruiCost = sad;
6245
16
        }
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
16
      }
6257
16
    }
6258
6259
24.0k
    if (buffered)
6260
16
    {
6261
16
      Mv cMvPredEncOnly[IBC_NUM_CANDIDATES];
6262
16
      int nbPreds = 0;
6263
16
      CU::getIbcMVPsEncOnly(cu, cMvPredEncOnly, nbPreds);
6264
6265
16
      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
16
    }
6294
24.0k
  }
6295
6296
24.0k
  if (!buffered)
6297
24.0k
  {
6298
24.0k
    Mv        cMvSrchRngLT;
6299
24.0k
    Mv        cMvSrchRngRB;
6300
6301
    // assume that intra BV is integer-pel precision
6302
24.0k
    xSetIntraSearchRangeIBC(cu, cu.lwidth(), cu.lheight(), cMvSrchRngLT, cMvSrchRngRB);
6303
6304
    //  Do integer search
6305
24.0k
    xIntraPatternSearchIBC(cu, cStruct, rcMv, ruiCost, &cMvSrchRngLT, &cMvSrchRngRB, pcMvPred);
6306
24.0k
  }
6307
24.0k
}
6308
// based on xSetSearchRange
6309
void InterSearch::xSetIntraSearchRangeIBC(CodingUnit& cu, int iRoiWidth, int iRoiHeight, Mv& rcMvSrchRngLT, Mv& rcMvSrchRngRB)
6310
24.0k
{
6311
 // const SPS& sps = *cu.cs->sps;
6312
6313
24.0k
  int srLeft, srRight, srTop, srBottom;
6314
6315
24.0k
  const int cuPelX = cu.Y().x;
6316
24.0k
  const int cuPelY = cu.Y().y;
6317
6318
24.0k
  const int lcuWidth = cu.cs->slice->sps->CTUSize;
6319
24.0k
  const int ctuSizeLog2 = floorLog2(lcuWidth);
6320
24.0k
  int numLeftCTUs = (1 << ((7 - ctuSizeLog2) << 1)) - ((ctuSizeLog2 < 7) ? 1 : 0);
6321
6322
24.0k
  srLeft = -(numLeftCTUs * lcuWidth + (cuPelX % lcuWidth));
6323
24.0k
  srTop = -(cuPelY % lcuWidth);
6324
6325
24.0k
  srRight = lcuWidth - (cuPelX % lcuWidth) - iRoiWidth;
6326
24.0k
  srBottom = lcuWidth - (cuPelY % lcuWidth) - iRoiHeight;
6327
6328
24.0k
  rcMvSrchRngLT.hor=srLeft;
6329
24.0k
  rcMvSrchRngLT.ver=srTop;
6330
24.0k
  rcMvSrchRngRB.hor=srRight;
6331
24.0k
  rcMvSrchRngRB.ver=srBottom;
6332
6333
24.0k
  rcMvSrchRngLT <<= 2;
6334
24.0k
  rcMvSrchRngRB <<= 2;
6335
24.0k
  bool temp = m_clipMvInSubPic;
6336
24.0k
  m_clipMvInSubPic = true;
6337
24.0k
  clipMv(rcMvSrchRngLT,cu.lumaPos(),cu.lumaSize(), *cu.cs->pcv, *cu.cs->pps, m_clipMvInSubPic);
6338
24.0k
  clipMv(rcMvSrchRngRB, cu.lumaPos(),cu.lumaSize(), *cu.cs->pcv, * cu.cs->pps, m_clipMvInSubPic);
6339
24.0k
  m_clipMvInSubPic = temp;
6340
24.0k
  rcMvSrchRngLT >>= 2;
6341
24.0k
  rcMvSrchRngRB >>= 2;
6342
24.0k
}
6343
6344
bool InterSearch::predIBCSearch(CodingUnit& cu, Partitioner& partitioner)
6345
24.0k
{
6346
24.0k
  Mv           cMvSrchRngLT;
6347
24.0k
  Mv           cMvSrchRngRB;
6348
24.0k
  cu.imv = IMV_4PEL;
6349
24.0k
  AMVPInfo amvpInfo4Pel;
6350
24.0k
  CU::fillIBCMvpCand(cu, amvpInfo4Pel);
6351
6352
24.0k
  cu.imv = IMV_OFF;// (Int)cu.cs->sps->getUseIMV(); // set as IMV=0 initially
6353
24.0k
  Mv    cMv, cMvPred[2];
6354
24.0k
  AMVPInfo amvpInfo;
6355
24.0k
  CU::fillIBCMvpCand(cu, amvpInfo);
6356
  // store in full pel accuracy, shift before use in search
6357
24.0k
  cMvPred[0] = amvpInfo.mvCand[0];
6358
24.0k
  cMvPred[0].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT);
6359
24.0k
  cMvPred[1] = amvpInfo.mvCand[1];
6360
24.0k
  cMvPred[1].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT);
6361
6362
24.0k
  int iBvpNum = 2;
6363
24.0k
  int bvpIdxBest = 0;
6364
24.0k
  cMv.setZero();
6365
24.0k
  Distortion cost = 0;
6366
24.0k
  if (cu.cs->sps->maxNumIBCMergeCand == 1)
6367
0
  {
6368
0
    iBvpNum = 1;
6369
0
    cMvPred[1] = cMvPred[0];
6370
0
  }
6371
6372
24.0k
  if (cMv.hor == 0 && cMv.ver == 0)
6373
24.0k
  {
6374
    // if hash search does not work or is not enabled
6375
24.0k
    PelUnitBuf origBuf = cu.cs->getOrgBuf(cu);
6376
24.0k
    xIBCEstimation(cu, origBuf, cMvPred, cMv, cost );
6377
24.0k
  }
6378
6379
24.0k
  if (cMv.hor == 0 && cMv.ver == 0)
6380
2.57k
  {
6381
2.57k
    return false;
6382
2.57k
  }
6383
  /// ibc search
6384
  /////////////////////////////////////////////////////////
6385
21.4k
  unsigned int bitsBVPBest, bitsBVPTemp;
6386
21.4k
  bitsBVPBest = MAX_INT;
6387
21.4k
  m_pcRdCost->setCostScale(0);
6388
6389
64.4k
  for (int bvpIdxTemp = 0; bvpIdxTemp < iBvpNum; bvpIdxTemp++)
6390
42.9k
  {
6391
42.9k
    m_pcRdCost->setPredictor(cMvPred[bvpIdxTemp]);
6392
6393
42.9k
    bitsBVPTemp = m_pcRdCost->getBitsOfVectorWithPredictor(cMv.hor, cMv.ver, 0);
6394
6395
42.9k
    if (bitsBVPTemp < bitsBVPBest)
6396
21.4k
    {
6397
21.4k
      bitsBVPBest = bitsBVPTemp;
6398
21.4k
      bvpIdxBest = bvpIdxTemp;
6399
6400
21.4k
      if (cu.cs->sps->AMVR && cMv != cMvPred[bvpIdxTemp])
6401
21.4k
        cu.imv = IMV_FPEL; // set as full-pel
6402
0
      else
6403
0
        cu.imv = IMV_OFF; // set as fractional-pel
6404
6405
21.4k
    }
6406
6407
42.9k
    unsigned int bitsBVPQP = MAX_UINT;
6408
6409
6410
42.9k
    Mv mvPredQuadPel;
6411
42.9k
    if ((cMv.hor % 4 == 0) && (cMv.ver % 4 == 0) && (cu.cs->sps->AMVR))
6412
42.9k
    {
6413
42.9k
      mvPredQuadPel = amvpInfo4Pel.mvCand[bvpIdxTemp];// cMvPred[bvpIdxTemp];
6414
6415
42.9k
      mvPredQuadPel.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_4PEL);
6416
6417
42.9k
      m_pcRdCost->setPredictor(mvPredQuadPel);
6418
6419
42.9k
      bitsBVPQP = m_pcRdCost->getBitsOfVectorWithPredictor(cMv.hor >> 2, cMv.ver >> 2, 0);
6420
6421
42.9k
    }
6422
42.9k
    mvPredQuadPel.changePrecision(MV_PRECISION_4PEL, MV_PRECISION_INT);
6423
42.9k
    if (bitsBVPQP < bitsBVPBest && cMv != mvPredQuadPel)
6424
21.4k
    {
6425
21.4k
      bitsBVPBest = bitsBVPQP;
6426
21.4k
      bvpIdxBest = bvpIdxTemp;
6427
6428
21.4k
      if (cu.cs->sps->AMVR)
6429
21.4k
        cu.imv = IMV_4PEL;
6430
21.4k
    }
6431
6432
42.9k
  }
6433
6434
21.4k
  cMv.changePrecision( MV_PRECISION_INT, MV_PRECISION_INTERNAL );
6435
21.4k
  cu.mv[REF_PIC_LIST_0][0] = cMv; // store in fractional pel accuracy
6436
6437
21.4k
  cu.mvpIdx[REF_PIC_LIST_0] = bvpIdxBest;
6438
6439
21.4k
  if (cu.imv == IMV_4PEL && cMv != amvpInfo4Pel.mvCand[bvpIdxBest])
6440
21.4k
    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
21.4k
  if (cu.mvd[REF_PIC_LIST_0][0] == Mv(0, 0))
6445
0
    cu.imv = IMV_OFF;
6446
21.4k
  if (cu.imv == IMV_4PEL)
6447
21.4k
    assert((cMv.hor % 16 == 0) && (cMv.ver % 16 == 0));
6448
21.4k
  if (cu.cs->sps->AMVR)
6449
21.4k
    assert(cu.imv > 0 || cu.mvd[REF_PIC_LIST_0][0] == Mv());
6450
6451
21.4k
  cu.refIdx[REF_PIC_LIST_0] = MAX_NUM_REF;
6452
6453
21.4k
  return true;
6454
21.4k
}
6455
6456
6457
static inline bool isYPartBefore( SplitSeries series, const int ctuSizeLog2, const Position& refPos, const Position& pos )
6458
1.43M
{
6459
1.43M
#ifndef NDEBUG
6460
1.43M
  const int refCtuX = refPos.x >> ctuSizeLog2;
6461
1.43M
  const int refCtuY = refPos.y >> ctuSizeLog2;
6462
1.43M
  const int posCtuX = pos.x >> ctuSizeLog2;
6463
1.43M
  const int posCtuY = pos.y >> ctuSizeLog2;
6464
6465
1.43M
  CHECK( refCtuX != posCtuX || refCtuY != posCtuY, "This method can only be applied for positions within the same CTU" );
6466
6467
1.43M
#endif
6468
1.43M
  const int ctuMask = ( 1 << ctuSizeLog2 ) - 1;
6469
6470
1.43M
  const int refX = refPos.x & ctuMask;
6471
1.43M
  const int refY = refPos.y & ctuMask;
6472
1.43M
  const int posX = pos.x & ctuMask;
6473
1.43M
  const int posY = pos.y & ctuMask;
6474
6475
1.43M
  int x = 0, y = 0, w = 1 << ctuSizeLog2, h = 1 << ctuSizeLog2;
6476
  
6477
1.95M
  while( true )
6478
1.95M
  {
6479
1.95M
    PartSplit split = PartSplit( series & SPLIT_MASK );
6480
6481
1.95M
    switch( split )
6482
1.95M
    {
6483
1.89M
    case CU_QUAD_SPLIT:
6484
1.89M
      w >>= 1;
6485
1.89M
      if( posX >= x + w ) x += w;
6486
1.92M
    case CU_HORZ_SPLIT:
6487
1.92M
      h >>= 1;
6488
1.92M
      if( posY >= y + h ) y += h;
6489
1.92M
      break;
6490
6491
30.8k
    case CU_VERT_SPLIT:
6492
30.8k
      w >>= 1;
6493
30.8k
      if( posX >= x + w ) x += w;
6494
30.8k
      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
1.95M
    }
6511
6512
1.92M
    if( refY >= y + h ) return true;
6513
1.45M
    else if( refY < y ) return false;
6514
6515
1.48M
checkXonly:
6516
1.48M
    if( refX >= x + w ) return true;
6517
741k
    else if( refX < x ) return false;
6518
6519
517k
    series >>= SPLIT_DMULT; continue;
6520
1.48M
  }
6521
6522
18.4E
  return false;
6523
1.43M
}
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.11M
{
6527
2.11M
  const int ctuSizeLog2 = Log2(ctuSize);
6528
6529
2.11M
  int refRightX  = xPos + xBv + width  - 1;
6530
2.11M
  int refBottomY = yPos + yBv + height - 1;
6531
6532
2.11M
  int refLeftX = xPos + xBv;
6533
2.11M
  int refTopY  = yPos + yBv;
6534
6535
2.11M
  if ((xPos + xBv) < 0)
6536
12.4k
  {
6537
12.4k
    return false;
6538
12.4k
  }
6539
2.09M
  if (refRightX >= picWidth)
6540
0
  {
6541
0
    return false;
6542
0
  }
6543
6544
2.09M
  if ((yPos + yBv) < 0)
6545
0
  {
6546
0
    return false;
6547
0
  }
6548
2.09M
  if (refBottomY >= picHeight)
6549
0
  {
6550
0
    return false;
6551
0
  }
6552
2.09M
  if ((xBv + width) > 0 && (yBv + height) > 0)
6553
165k
  {
6554
165k
    return false;
6555
165k
  }
6556
6557
  // Don't search the above CTU row
6558
1.93M
  if (refTopY >> ctuSizeLog2 < yPos >> ctuSizeLog2)
6559
0
    return false;
6560
6561
  // Don't search the below CTU row
6562
1.93M
  if (refBottomY >> ctuSizeLog2 > yPos >> ctuSizeLog2)
6563
0
  {
6564
0
    return false;
6565
0
  }
6566
6567
1.93M
  unsigned curTileIdx = cu.cs->pps->getTileIdx(cu.lumaPos());
6568
1.93M
  unsigned refTileIdx = cu.cs->pps->getTileIdx(Position(refLeftX, refTopY));
6569
1.93M
  if (curTileIdx != refTileIdx)
6570
0
  {
6571
0
    return false;
6572
0
  }
6573
1.93M
  refTileIdx = cu.cs->pps->getTileIdx(Position(refLeftX, refBottomY));
6574
1.93M
  if (curTileIdx != refTileIdx)
6575
0
  {
6576
0
    return false;
6577
0
  }
6578
1.93M
  refTileIdx = cu.cs->pps->getTileIdx(Position(refRightX, refTopY));
6579
1.93M
  if (curTileIdx != refTileIdx)
6580
0
  {
6581
0
    return false;
6582
0
  }
6583
1.93M
  refTileIdx = cu.cs->pps->getTileIdx(Position(refRightX, refBottomY));
6584
1.93M
  if (curTileIdx != refTileIdx)
6585
0
  {
6586
0
    return false;
6587
0
  }
6588
6589
1.93M
  const Position cuPos{ xPos, yPos };
6590
6591
  //int numLeftCTUs = (1 << ((7 - ctuSizeLog2) << 1)) - ((ctuSizeLog2 < 7) ? 1 : 0);
6592
1.93M
  static const int numLeftCTUsLUT[3] = { 15, 3, 1 };
6593
6594
  // in the same CTU line
6595
1.93M
  const int numLeftCTUs = numLeftCTUsLUT[ctuSizeLog2 - 5];
6596
6597
1.93M
  if( ( refRightX >> ctuSizeLog2 <= xPos >> ctuSizeLog2 ) && ( refLeftX >> ctuSizeLog2 >= ( xPos >> ctuSizeLog2 ) - numLeftCTUs ) )
6598
1.93M
  {
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
1.93M
    if( ( ctuSizeLog2 == 7 ) && ( ( refLeftX >> ctuSizeLog2 ) == ( ( xPos >> ctuSizeLog2 ) - 1 ) ) )
6602
978k
    {
6603
      // ref block's collocated block in current CTU
6604
978k
      const Position refPosCol64x64{ ( refLeftX + ctuSize ) & ~63, refTopY & ~63 };
6605
978k
      if( refPosCol64x64 == Position{ xPos & ~63, yPos & ~63 } )
6606
529k
        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
449k
      bool isDecomp = isYPartBefore( cu.splitSeries, ctuSizeLog2, cuPos, refPosCol64x64 );
6611
449k
      if( isDecomp )
6612
225k
      {
6613
225k
        return false;
6614
225k
      }
6615
449k
    }
6616
1.93M
  }
6617
26
  else
6618
26
    return false;
6619
6620
  // in the same CTU, or valid area from left CTU. Check if the reference block is already coded
6621
1.17M
  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.17M
  bool isDecomp = ( ( refPosBR.x >> ctuSizeLog2 ) < ( cuPos.x >> ctuSizeLog2 ) ) || ( refRightX < xPos && refBottomY < yPos ) || isYPartBefore( cu.splitSeries, ctuSizeLog2, cuPos, refPosBR );
6625
6626
1.17M
  return isDecomp;
6627
1.93M
}
6628
6629
} // namespace vvenc
6630
6631
//! \}
6632