Coverage Report

Created: 2026-10-28 06:18

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
5.97k
  : m_modeCtrl                    (nullptr)
190
5.97k
  , m_defaultCachedBvs            (nullptr)
191
5.97k
  , m_pcEncCfg                    (nullptr)
192
5.97k
  , m_pcTrQuant                   (nullptr)
193
5.97k
  , m_iSearchRange                (0)
194
5.97k
  , m_bipredSearchRange           (0)
195
5.97k
  , m_motionEstimationSearchMethod(VVENC_MESEARCH_FULL)
196
5.97k
  , m_motionEstimationSearchMethodSCC( 0 )
197
5.97k
  , m_CABACEstimator              (nullptr)
198
5.97k
  , m_CtxCache                    (nullptr)
199
5.97k
  , m_pTempPel                    (nullptr)
200
5.97k
{
201
17.9k
  for (int i=0; i<MAX_NUM_REF_LIST_ADAPT_SR; i++)
202
11.9k
  {
203
11.9k
    memset (m_aaiAdaptSR[i], 0, MAX_IDX_ADAPT_SR * sizeof (int));
204
11.9k
  }
205
23.8k
  for (int i=0; i<AMVP_MAX_NUM_CANDS+1; i++)
206
17.9k
  {
207
17.9k
    memset (m_auiMVPIdxCost[i], 0, (AMVP_MAX_NUM_CANDS+1) * sizeof (uint32_t) );
208
17.9k
  }
209
5.97k
}
210
211
212
InterSearch::~InterSearch()
213
5.97k
{
214
5.97k
  destroy();
215
5.97k
}
216
217
void InterSearch::init( const VVEncCfg& encCfg, TrQuant* pTrQuant, RdCost* pRdCost, EncModeCtrl* pModeCtrl, CodingStructure **pSaveCS )
218
5.97k
{
219
5.97k
  InterPrediction::init( pRdCost, encCfg.m_internChromaFormat, encCfg.m_CTUSize, encCfg.m_ifpLines );
220
5.97k
  m_numBVs                       = 0;
221
5.97k
  m_pcEncCfg                     = &encCfg;
222
5.97k
  m_pcTrQuant                    = pTrQuant;
223
5.97k
  m_pcRdCost                     = pRdCost;
224
5.97k
  m_modeCtrl                     = pModeCtrl;
225
5.97k
  m_pSaveCS                      = pSaveCS;
226
227
5.97k
  m_iSearchRange                    = encCfg.m_SearchRange;
228
5.97k
  m_bipredSearchRange               = encCfg.m_bipredSearchRange;
229
5.97k
  m_motionEstimationSearchMethod    = vvencMESearchMethod( encCfg.m_motionEstimationSearchMethod );
230
5.97k
  m_motionEstimationSearchMethodSCC = encCfg.m_motionEstimationSearchMethodSCC;
231
232
17.9k
  for( uint32_t iDir = 0; iDir < MAX_NUM_REF_LIST_ADAPT_SR; iDir++ )
233
11.9k
  {
234
83.6k
    for( uint32_t iRefIdx = 0; iRefIdx < MAX_IDX_ADAPT_SR; iRefIdx++ )
235
71.6k
    {
236
71.6k
      m_aaiAdaptSR[iDir][iRefIdx] = m_iSearchRange;
237
71.6k
    }
238
11.9k
  }
239
240
  // initialize motion cost
241
23.8k
  for( int iNum = 0; iNum < AMVP_MAX_NUM_CANDS + 1; iNum++ )
242
17.9k
  {
243
53.7k
    for( int iIdx = 0; iIdx < AMVP_MAX_NUM_CANDS; iIdx++ )
244
35.8k
    {
245
35.8k
      if( iIdx < iNum )
246
17.9k
      {
247
17.9k
        m_auiMVPIdxCost[iIdx][iNum] = xGetMvpIdxBits( iIdx, iNum );
248
17.9k
      }
249
17.9k
      else
250
17.9k
      {
251
17.9k
        m_auiMVPIdxCost[iIdx][iNum] = MAX_UINT;
252
17.9k
      }
253
35.8k
    }
254
17.9k
  }
255
256
5.97k
  const ChromaFormat cform   = encCfg.m_internChromaFormat;
257
5.97k
  const int          ctuSize = encCfg.m_CTUSize;
258
17.9k
  for (uint32_t i = 0; i < NUM_REF_PIC_LIST_01; i++)
259
11.9k
  {
260
11.9k
    m_tmpPredStorage[i].create( UnitArea( cform, Area( 0, 0, ctuSize, ctuSize ) ) );
261
11.9k
  }
262
5.97k
  m_tmpStorageLCU.create( UnitArea( cform, Area( 0, 0, ctuSize, ctuSize ) ) );
263
5.97k
  m_pTempPel = new Pel[ctuSize * ctuSize];
264
5.97k
  m_tmpAffiStorage.create(UnitArea(cform, Area(0, 0, ctuSize, ctuSize + 2)));  // allow overread by 2 samples
265
5.97k
  m_tmpAffiError = new Pel[ctuSize * ctuSize];
266
5.97k
  m_tmpAffiDeri[0] = new Pel[ctuSize * ctuSize];
267
5.97k
  m_tmpAffiDeri[1] = new Pel[ctuSize * ctuSize];
268
269
5.97k
  CompArea chromaArea( COMP_Cb, cform, Area( 0, 0, encCfg.m_CTUSize, encCfg.m_CTUSize ), true );
270
29.8k
  for( int i = 0; i < 4; i++ )
271
23.8k
  {
272
23.8k
    m_orgResiCb[i].create( chromaArea );
273
23.8k
    m_orgResiCr[i].create( chromaArea );
274
23.8k
  }
275
5.97k
}
276
277
void InterSearch::destroy()
278
5.97k
{
279
5.97k
  if ( m_pTempPel )
280
5.97k
  {
281
5.97k
    delete [] m_pTempPel;
282
5.97k
    m_pTempPel = nullptr;
283
5.97k
  }
284
285
17.9k
  for( int i = 0; i < NUM_REF_PIC_LIST_01; i++ )
286
11.9k
  {
287
11.9k
    m_tmpPredStorage[i].destroy();
288
11.9k
  }
289
5.97k
  m_tmpStorageLCU.destroy();
290
5.97k
  m_tmpAffiStorage.destroy();
291
5.97k
  if (m_tmpAffiError != NULL)
292
5.97k
  {
293
5.97k
    delete[] m_tmpAffiError;
294
5.97k
    m_tmpAffiError = nullptr;
295
5.97k
  }
296
5.97k
  if (m_tmpAffiDeri[0] != NULL)
297
5.97k
  {
298
5.97k
    delete[] m_tmpAffiDeri[0];
299
5.97k
    m_tmpAffiDeri[0] = nullptr;
300
5.97k
  }
301
5.97k
  if (m_tmpAffiDeri[1] != NULL)
302
5.97k
  {
303
5.97k
    delete[] m_tmpAffiDeri[1];
304
5.97k
    m_tmpAffiDeri[1] = nullptr;
305
5.97k
  }
306
307
5.97k
  m_pSaveCS  = nullptr;
308
5.97k
}
309
310
void InterSearch::setCtuEncRsrc( CABACWriter* cabacEstimator, CtxCache* ctxCache, ReuseUniMv* pReuseUniMv, BlkUniMvInfoBuffer* pBlkUniMvInfoBuffer, AffineProfList* pAffineProfList, IbcBvCand* pCachedBvs )
311
4.97k
{
312
4.97k
  m_CABACEstimator     = cabacEstimator;
313
4.97k
  m_CtxCache           = ctxCache;
314
4.97k
  m_ReuseUniMv         = pReuseUniMv;
315
4.97k
  m_BlkUniMvInfoBuffer = pBlkUniMvInfoBuffer;
316
4.97k
  m_AffineProfList     = pAffineProfList;
317
4.97k
  m_defaultCachedBvs   = pCachedBvs;
318
4.97k
}
319
320
ReuseUniMv::ReuseUniMv()
321
10.7k
{
322
10.7k
  const int numPos     = MAX_CU_SIZE >> MIN_CU_LOG2;
323
10.7k
  const int maxSizeIdx = MAX_CU_SIZE_IDX-2;
324
75.3k
  for( int wIdx = 0; wIdx < maxSizeIdx; wIdx++ )
325
64.5k
  {
326
452k
    for( int hIdx = 0; hIdx < maxSizeIdx; hIdx++ )
327
387k
    {
328
12.7M
      for( int y = 0; y < numPos; y++ )
329
12.4M
      {
330
409M
        for( int x = 0; x < numPos; x++ )
331
396M
        {
332
396M
          m_reusedUniMVs[ wIdx ][ hIdx ][ x ][ y ] = nullptr;
333
396M
        }
334
12.4M
      }
335
387k
    }
336
64.5k
  }
337
10.7k
}
338
339
ReuseUniMv::~ReuseUniMv()
340
10.7k
{
341
10.7k
  resetReusedUniMvs();
342
10.7k
}
343
344
void ReuseUniMv::resetReusedUniMvs()
345
16.1k
{
346
16.1k
  const int numPos     = MAX_CU_SIZE >> MIN_CU_LOG2;
347
16.1k
  const int maxSizeIdx = MAX_CU_SIZE_IDX-2;
348
113k
  for ( int wIdx = 0; wIdx < maxSizeIdx; wIdx++ )
349
96.8k
  {
350
678k
    for ( int hIdx = 0; hIdx < maxSizeIdx; hIdx++ )
351
581k
    {
352
19.1M
      for ( int y = 0; y < numPos; y++ )
353
18.6M
      {
354
613M
        for ( int x = 0; x < numPos; x++ )
355
595M
        {
356
595M
          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
595M
        }
362
18.6M
      }
363
581k
    }
364
96.8k
  }
365
16.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
17.9k
{
1847
17.9k
  CHECK(iIdx < 0 || iNum < 0 || iIdx >= iNum, "Invalid parameters");
1848
1849
17.9k
  if (iNum == 1)
1850
5.97k
  {
1851
5.97k
    return 0;
1852
5.97k
  }
1853
1854
11.9k
  uint32_t uiLength = 1;
1855
11.9k
  int iTemp = iIdx;
1856
11.9k
  if ( iTemp == 0 )
1857
5.97k
  {
1858
5.97k
    return uiLength;
1859
5.97k
  }
1860
1861
5.97k
  bool bCodeLast = ( iNum-1 > iTemp );
1862
1863
5.97k
  uiLength += (iTemp-1);
1864
1865
5.97k
  if( bCodeLast )
1866
0
  {
1867
0
    uiLength++;
1868
0
  }
1869
1870
5.97k
  return uiLength;
1871
11.9k
}
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
    static_assert( DISTORTION_PRECISION_ADJUSTMENT( 2 ) == 0, "the squared errors of the sub parts are not scaled" );
3305
3306
    //calc distY of 16 sub parts
3307
0
    for( int j = 0; j < numPartY; j++ )
3308
0
    {
3309
0
      for( int i = 0; i < numPartX; i++ )
3310
0
      {
3311
0
        int posX = i * lengthX;
3312
0
        int posY = j * lengthY;
3313
0
        Distortion uiSum = g_pelBufOP.sumSquaredError( orgPel.bufAt( posX, posY ), orgPel.stride, predPel.bufAt( posX, posY ), predPel.stride, lengthX, lengthY );
3314
0
        if( isChroma( compID ) )
3315
0
        {
3316
0
          uiSum = (Distortion)( uiSum * m_pcRdCost->getChromaWeight() );
3317
0
        }
3318
0
        dist[j][i] += uiSum;
3319
0
      }
3320
0
    }
3321
0
  }
3322
3323
  //SSE of a CU
3324
0
  m_estMinDistSbt[NUMBER_SBT_MODE] = 0;
3325
0
  for( int j = 0; j < numPartY; j++ )
3326
0
  {
3327
0
    for( int i = 0; i < numPartX; i++ )
3328
0
    {
3329
0
      m_estMinDistSbt[NUMBER_SBT_MODE] += dist[j][i];
3330
0
    }
3331
0
  }
3332
  //init per-mode dist
3333
0
  for( int i = SBT_VER_H0; i < NUMBER_SBT_MODE; i++ )
3334
0
  {
3335
0
    m_estMinDistSbt[i] = MAX_DISTORTION;
3336
0
  }
3337
3338
  //SBT fast algorithm 1: not try SBT if the residual is too small to compensate bits for encoding residual info
3339
0
  uint64_t minNonZeroResiFracBits = 12 << SCALE_BITS;
3340
0
  if( m_pcRdCost->calcRdCost( 0, m_estMinDistSbt[NUMBER_SBT_MODE] ) < m_pcRdCost->calcRdCost( minNonZeroResiFracBits, 0 ) )
3341
0
  {
3342
0
    m_skipSbtAll = true;
3343
0
    return;
3344
0
  }
3345
3346
  //derive estimated minDist of SBT = zero-residual part distortion + non-zero residual part distortion / 16
3347
0
  int shift = 5;
3348
0
  Distortion distResiPart = 0, distNoResiPart = 0;
3349
3350
0
  if( CU::targetSbtAllowed( SBT_VER_HALF, sbtAllowed ) )
3351
0
  {
3352
0
    int offsetResiPart = 0;
3353
0
    int offsetNoResiPart = numPartX / 2;
3354
0
    distResiPart = distNoResiPart = 0;
3355
0
    assert( numPartX >= 2 );
3356
0
    for( int j = 0; j < numPartY; j++ )
3357
0
    {
3358
0
      for( int i = 0; i < numPartX / 2; i++ )
3359
0
      {
3360
0
        distResiPart   += dist[j][i + offsetResiPart];
3361
0
        distNoResiPart += dist[j][i + offsetNoResiPart];
3362
0
      }
3363
0
    }
3364
0
    m_estMinDistSbt[SBT_VER_H0] = ( distResiPart >> shift ) + distNoResiPart;
3365
0
    m_estMinDistSbt[SBT_VER_H1] = ( distNoResiPart >> shift ) + distResiPart;
3366
0
  }
3367
3368
0
  if( CU::targetSbtAllowed( SBT_HOR_HALF, sbtAllowed ) )
3369
0
  {
3370
0
    int offsetResiPart = 0;
3371
0
    int offsetNoResiPart = numPartY / 2;
3372
0
    assert( numPartY >= 2 );
3373
0
    distResiPart = distNoResiPart = 0;
3374
0
    for( int j = 0; j < numPartY / 2; j++ )
3375
0
    {
3376
0
      for( int i = 0; i < numPartX; i++ )
3377
0
      {
3378
0
        distResiPart   += dist[j + offsetResiPart][i];
3379
0
        distNoResiPart += dist[j + offsetNoResiPart][i];
3380
0
      }
3381
0
    }
3382
0
    m_estMinDistSbt[SBT_HOR_H0] = ( distResiPart >> shift ) + distNoResiPart;
3383
0
    m_estMinDistSbt[SBT_HOR_H1] = ( distNoResiPart >> shift ) + distResiPart;
3384
0
  }
3385
3386
0
  if( CU::targetSbtAllowed( SBT_VER_QUAD, sbtAllowed ) )
3387
0
  {
3388
0
    assert( numPartX == 4 );
3389
0
    m_estMinDistSbt[SBT_VER_Q0] = m_estMinDistSbt[SBT_VER_Q1] = 0;
3390
0
    for( int j = 0; j < numPartY; j++ )
3391
0
    {
3392
0
      m_estMinDistSbt[SBT_VER_Q0] += dist[j][0] + ( ( dist[j][1] + dist[j][2] + dist[j][3] ) << shift );
3393
0
      m_estMinDistSbt[SBT_VER_Q1] += dist[j][3] + ( ( dist[j][0] + dist[j][1] + dist[j][2] ) << shift );
3394
0
    }
3395
0
    m_estMinDistSbt[SBT_VER_Q0] = m_estMinDistSbt[SBT_VER_Q0] >> shift;
3396
0
    m_estMinDistSbt[SBT_VER_Q1] = m_estMinDistSbt[SBT_VER_Q1] >> shift;
3397
0
  }
3398
3399
0
  if( CU::targetSbtAllowed( SBT_HOR_QUAD, sbtAllowed ) )
3400
0
  {
3401
0
    assert( numPartY == 4 );
3402
0
    m_estMinDistSbt[SBT_HOR_Q0] = m_estMinDistSbt[SBT_HOR_Q1] = 0;
3403
0
    for( int i = 0; i < numPartX; i++ )
3404
0
    {
3405
0
      m_estMinDistSbt[SBT_HOR_Q0] += dist[0][i] + ( ( dist[1][i] + dist[2][i] + dist[3][i] ) << shift );
3406
0
      m_estMinDistSbt[SBT_HOR_Q1] += dist[3][i] + ( ( dist[0][i] + dist[1][i] + dist[2][i] ) << shift );
3407
0
    }
3408
0
    m_estMinDistSbt[SBT_HOR_Q0] = m_estMinDistSbt[SBT_HOR_Q0] >> shift;
3409
0
    m_estMinDistSbt[SBT_HOR_Q1] = m_estMinDistSbt[SBT_HOR_Q1] >> shift;
3410
0
  }
3411
3412
  //SBT fast algorithm 5: try N SBT modes with the lowest distortion
3413
0
  Distortion temp[NUMBER_SBT_MODE];
3414
0
  memcpy( temp, m_estMinDistSbt, sizeof( Distortion ) * NUMBER_SBT_MODE );
3415
0
  memset( m_sbtRdoOrder, 255, NUMBER_SBT_MODE );
3416
0
  int startIdx = 0, numRDO;
3417
0
  numRDO = CU::targetSbtAllowed( SBT_VER_HALF, sbtAllowed ) + CU::targetSbtAllowed( SBT_HOR_HALF, sbtAllowed );
3418
0
  numRDO = std::min( ( numRDO << 1 ), SBT_NUM_RDO );
3419
0
  for( int i = startIdx; i < startIdx + numRDO; i++ )
3420
0
  {
3421
0
    Distortion minDist = MAX_DISTORTION;
3422
0
    for( int n = SBT_VER_H0; n <= SBT_HOR_H1; n++ )
3423
0
    {
3424
0
      if( temp[n] < minDist )
3425
0
      {
3426
0
        minDist = temp[n];
3427
0
        m_sbtRdoOrder[i] = n;
3428
0
      }
3429
0
    }
3430
0
    temp[m_sbtRdoOrder[i]] = MAX_DISTORTION;
3431
0
  }
3432
3433
0
  startIdx += numRDO;
3434
0
  numRDO = CU::targetSbtAllowed( SBT_VER_QUAD, sbtAllowed ) + CU::targetSbtAllowed( SBT_HOR_QUAD, sbtAllowed );
3435
0
  numRDO = std::min( ( numRDO << 1 ), SBT_NUM_RDO );
3436
0
  for( int i = startIdx; i < startIdx + numRDO; i++ )
3437
0
  {
3438
0
    Distortion minDist = MAX_DISTORTION;
3439
0
    for( int n = SBT_VER_Q0; n <= SBT_HOR_Q1; n++ )
3440
0
    {
3441
0
      if( temp[n] < minDist )
3442
0
      {
3443
0
        minDist = temp[n];
3444
0
        m_sbtRdoOrder[i] = n;
3445
0
      }
3446
0
    }
3447
0
    temp[m_sbtRdoOrder[i]] = MAX_DISTORTION;
3448
0
  }
3449
0
}
3450
3451
uint8_t InterSearch::skipSbtByRDCost( int width, int height, int mtDepth, uint8_t sbtIdx, uint8_t sbtPos, double bestCost, Distortion distSbtOff, double costSbtOff, bool rootCbfSbtOff )
3452
0
{
3453
0
  int sbtMode = CU::getSbtMode( sbtIdx, sbtPos );
3454
3455
  //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);
3456
  //                         if this cost is larger than the best cost, no need to try a specific SBT mode
3457
0
  if( m_pcRdCost->calcRdCost( 11 << SCALE_BITS, m_estMinDistSbt[sbtMode] ) > bestCost )
3458
0
  {
3459
0
    return 0; //early skip type 0
3460
0
  }
3461
3462
0
  if( costSbtOff != MAX_DOUBLE )
3463
0
  {
3464
0
    if( !rootCbfSbtOff )
3465
0
    {
3466
      //SBT fast algorithm 3: skip SBT when the residual is too small (estCost is more accurate than fast algorithm 1, counting PU mode bits)
3467
0
      uint64_t minNonZeroResiFracBits = 10 << SCALE_BITS;
3468
0
      Distortion distResiPart;
3469
0
      if( sbtIdx == SBT_VER_HALF || sbtIdx == SBT_HOR_HALF )
3470
0
      {
3471
0
        distResiPart = (Distortion)( ( ( m_estMinDistSbt[NUMBER_SBT_MODE] - m_estMinDistSbt[sbtMode] ) * 9 ) >> 4 );
3472
0
      }
3473
0
      else
3474
0
      {
3475
0
        distResiPart = (Distortion)( ( ( m_estMinDistSbt[NUMBER_SBT_MODE] - m_estMinDistSbt[sbtMode] ) * 3 ) >> 3 );
3476
0
      }
3477
3478
0
      double estCost = ( costSbtOff - m_pcRdCost->calcRdCost( 0 << SCALE_BITS, distSbtOff ) ) + m_pcRdCost->calcRdCost( minNonZeroResiFracBits, m_estMinDistSbt[sbtMode] + distResiPart );
3479
0
      if( estCost > costSbtOff )
3480
0
      {
3481
0
        return 1;
3482
0
      }
3483
0
      if( estCost > bestCost )
3484
0
      {
3485
0
        return 2;
3486
0
      }
3487
0
    }
3488
0
    else
3489
0
    {
3490
      //SBT fast algorithm 4: skip SBT when an estimated RD cost is larger than the bestCost
3491
0
      double weight = sbtMode > SBT_HOR_H1 ? 0.4 : 0.6;
3492
0
      double estCost = ( ( costSbtOff - m_pcRdCost->calcRdCost( 0 << SCALE_BITS, distSbtOff ) ) * weight ) + m_pcRdCost->calcRdCost( 0 << SCALE_BITS, m_estMinDistSbt[sbtMode] );
3493
0
      if( estCost > bestCost )
3494
0
      {
3495
0
        return 3;
3496
0
      }
3497
0
    }
3498
0
  }
3499
0
  return MAX_UCHAR;
3500
0
}
3501
3502
void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &partitioner, Distortion *puiZeroDist /*= NULL*/)
3503
29.1k
{
3504
29.1k
  const UnitArea& currArea = partitioner.currArea();
3505
29.1k
  const SPS &sps           = *cs.sps;
3506
3507
29.1k
  const uint32_t numValidComp  = getNumberValidComponents( sps.chromaFormatIdc );
3508
29.1k
  const uint32_t numTBlocks    = getNumberValidTBlocks   ( *cs.pcv );
3509
29.1k
  CodingUnit& cu               = *cs.getCU(partitioner.chType, partitioner.treeType);
3510
29.1k
  const unsigned currDepth = partitioner.currTrDepth;
3511
29.1k
  const bool useTS = cs.picture->useTS;
3512
3513
29.1k
  bool bCheckFull  = !partitioner.canSplit( TU_MAX_TR_SPLIT, cs );
3514
29.1k
  if( cu.sbtInfo && partitioner.canSplit( CU::getSbtTuSplit( cu.sbtInfo ), cs ) )
3515
0
  {
3516
0
    bCheckFull = false;
3517
0
  }
3518
29.1k
  bool bCheckSplit = !bCheckFull;
3519
3520
  // get temporary data
3521
29.1k
  CodingStructure *csSplit = nullptr;
3522
29.1k
  CodingStructure *csFull  = nullptr;
3523
29.1k
  if (bCheckSplit)
3524
0
  {
3525
0
    csSplit = &cs;
3526
0
  }
3527
29.1k
  else if (bCheckFull)
3528
29.1k
  {
3529
29.1k
    csFull = &cs;
3530
29.1k
  }
3531
3532
29.1k
  Distortion uiSingleDist         = 0;
3533
29.1k
  Distortion uiSingleDistComp [3] = { 0, 0, 0 };
3534
3535
29.1k
  const TempCtx ctxStart  ( m_CtxCache, m_CABACEstimator->getCtx() );
3536
29.1k
  TempCtx       ctxBest   ( m_CtxCache );
3537
3538
29.1k
  PelUnitBuf    orgResiBuf;
3539
29.1k
  orgResiBuf = m_tmpStorageLCU.getCompactBuf( currArea );
3540
29.1k
  orgResiBuf.copyFrom(cs.getResiBuf(currArea));
3541
3542
29.1k
  if (bCheckFull)
3543
29.1k
  {
3544
29.1k
    TransformUnit& tu = csFull->addTU(CS::getArea(cs, currArea, partitioner.chType, partitioner.treeType), partitioner.chType, &cu);
3545
29.1k
    tu.depth          = currDepth;
3546
29.1k
    tu.mtsIdx[COMP_Y] = MTS_DCT2_DCT2;
3547
29.1k
    tu.checkTuNoResidual( partitioner.currPartIdx() );
3548
3549
29.1k
    double minCost [MAX_NUM_TBLOCKS];
3550
3551
29.1k
    m_CABACEstimator->resetBits();
3552
3553
29.1k
    memset(m_pTempPel, 0, sizeof(Pel) * tu.Y().area()); // not necessary needed for inside of recursion (only at the beginning)
3554
3555
116k
    for (uint32_t i = 0; i < numTBlocks; i++)
3556
87.3k
    {
3557
87.3k
      minCost[i] = MAX_DOUBLE;
3558
87.3k
    }
3559
3560
29.1k
    CodingStructure &saveCS = *m_pSaveCS[1];
3561
29.1k
    saveCS.pcv     = cs.pcv;
3562
29.1k
    saveCS.picture = cs.picture;
3563
29.1k
    saveCS.area.repositionTo( currArea );
3564
3565
29.1k
    TransformUnit& bestTU = saveCS.tus.empty() ? saveCS.addTU( currArea, partitioner.chType, nullptr ) : *saveCS.tus.front();
3566
29.1k
    bestTU.initData();
3567
29.1k
    bestTU.UnitArea::operator=( currArea );
3568
3569
116k
    for( uint32_t c = 0; c < numTBlocks; c++ )
3570
87.3k
    {
3571
87.3k
      const ComponentID compID    = ComponentID(c);
3572
87.3k
      const CompArea&   compArea  = tu.blocks[compID];
3573
87.3k
      const int channelBitDepth   = sps.bitDepths[toChannelType(compID)];
3574
3575
87.3k
      if( !tu.blocks[compID].valid() )
3576
58.2k
      {
3577
58.2k
        continue;
3578
58.2k
      }
3579
29.1k
      bool tsAllowed = useTS && TU::isTSAllowed(tu, compID) && (isLuma(compID) || (isChroma(compID) && m_pcEncCfg->m_useChromaTS));
3580
29.1k
      if (isChroma(compID) && tsAllowed && (tu.mtsIdx[COMP_Y] != MTS_SKIP))
3581
0
      {
3582
0
        tsAllowed = false;
3583
0
      }
3584
29.1k
      uint8_t nNumTransformCands = 1 + (tsAllowed ? 1 : 0); // DCT + TS = 2 tests
3585
29.1k
      TrModeList trModes;
3586
3587
29.1k
      if (nNumTransformCands > 1)
3588
3.70k
      {
3589
3.70k
        trModes.push_back(TrMode(0, true)); //DCT2
3590
        //for a SBT-no-residual TU, the RDO process should be called once, in order to get the RD cost
3591
3.70k
        if ( !tu.noResidual )
3592
3.70k
        {
3593
3.70k
          trModes.push_back(TrMode(1, true));
3594
3.70k
        }
3595
0
        else
3596
0
        {
3597
0
          nNumTransformCands--;
3598
0
        }
3599
3.70k
      }
3600
29.1k
      bool isLast = true;
3601
61.7k
      for (int transformMode = 0; transformMode < nNumTransformCands; transformMode++)
3602
32.5k
      {
3603
32.5k
        const bool isFirstMode = transformMode == 0;
3604
3605
        // copy the original residual into the residual buffer
3606
32.5k
        csFull->getResiBuf(compArea).copyFrom(orgResiBuf.get(compID));
3607
3608
3609
32.5k
        m_CABACEstimator->getCtx() = ctxStart;
3610
32.5k
        m_CABACEstimator->resetBits();
3611
3612
32.5k
        if (bestTU.mtsIdx[compID] == MTS_SKIP && m_pcEncCfg->m_TS)
3613
0
        {
3614
0
          continue;
3615
0
        }
3616
32.5k
        tu.mtsIdx[compID] = transformMode ? trModes[transformMode].first : 0;
3617
3618
32.5k
        const QpParam cQP(tu, compID);  // note: uses tu.transformSkip[compID]
3619
32.5k
        m_pcTrQuant->selectLambda(compID);
3620
3621
32.5k
        if ( sps.jointCbCr && isChroma( compID ) && ( tu.cu->cs->slice->sliceQp > 18 ) )
3622
0
        {
3623
0
          m_pcTrQuant->scaleLambda( 1.05 );
3624
0
        }
3625
32.5k
        TCoeff     currAbsSum = 0;
3626
32.5k
        uint64_t   currCompFracBits = 0;
3627
32.5k
        Distortion currCompDist = 0;
3628
32.5k
        double     currCompCost = 0;
3629
32.5k
        uint64_t   nonCoeffFracBits = 0;
3630
32.5k
        Distortion nonCoeffDist = 0;
3631
32.5k
        double     nonCoeffCost = 0;
3632
3633
32.5k
        if (nNumTransformCands > 1)
3634
7.15k
        {
3635
7.15k
          if (transformMode == 0)
3636
3.70k
          {
3637
3.70k
            m_pcTrQuant->checktransformsNxN(tu, &trModes, 2, compID);
3638
3.70k
            tu.mtsIdx[compID] = trModes[0].first;
3639
3.70k
            if (!trModes[transformMode + 1].second)
3640
248
            {
3641
248
              nNumTransformCands = 1;
3642
248
            }
3643
3.70k
          }
3644
7.15k
          m_pcTrQuant->transformNxN(tu, compID, cQP, currAbsSum, m_CABACEstimator->getCtx(), true);
3645
7.15k
        }
3646
25.4k
        else
3647
25.4k
        {
3648
25.4k
          m_pcTrQuant->transformNxN(tu, compID, cQP, currAbsSum, m_CABACEstimator->getCtx());
3649
25.4k
        }
3650
32.5k
        if (isFirstMode || (currAbsSum == 0))
3651
32.5k
        {
3652
32.5k
          const CPelBuf zeroBuf(m_pTempPel, compArea);
3653
32.5k
          const CPelBuf& orgResi = orgResiBuf.get(compID);
3654
3655
32.5k
          nonCoeffDist = m_pcRdCost->getDistPart(zeroBuf, orgResi, channelBitDepth, compID, DF_SSE); // initialized with zero residual distortion
3656
3657
32.5k
          if (!tu.noResidual)
3658
32.5k
          {
3659
32.5k
            const bool prevCbf = (compID == COMP_Cr ? tu.cbf[COMP_Cb] : false);
3660
32.5k
            m_CABACEstimator->cbf_comp(*tu.cu, false, compArea, currDepth, prevCbf);
3661
32.5k
          }
3662
3663
32.5k
          nonCoeffFracBits = m_CABACEstimator->getEstFracBits();
3664
32.5k
          nonCoeffCost = m_pcRdCost->calcRdCost(nonCoeffFracBits, nonCoeffDist, !m_pcEncCfg->m_lumaLevelToDeltaQPEnabled);
3665
32.5k
        }
3666
3667
32.5k
        if ((puiZeroDist != NULL) && isFirstMode)
3668
29.1k
        {
3669
29.1k
          *puiZeroDist += nonCoeffDist; // initialized with zero residual distortion
3670
29.1k
        }
3671
3672
32.5k
        if (currAbsSum > 0) //if non-zero coefficients are present, a residual needs to be derived for further prediction
3673
239
        {
3674
239
          if (isFirstMode)
3675
239
          {
3676
239
            m_CABACEstimator->getCtx() = ctxStart;
3677
239
            m_CABACEstimator->resetBits();
3678
239
          }
3679
3680
239
          const bool prevCbf = ( compID == COMP_Cr ? tu.cbf[COMP_Cb] : false );
3681
239
          m_CABACEstimator->cbf_comp( *tu.cu, true, compArea, currDepth, prevCbf );
3682
239
          if( compID == COMP_Cr )
3683
0
          {
3684
0
            const int cbfMask = ( tu.cbf[COMP_Cb] ? 2 : 0 ) + 1;
3685
0
            m_CABACEstimator->joint_cb_cr( tu, cbfMask );
3686
0
          }
3687
239
          CUCtx cuCtx;
3688
239
          cuCtx.isDQPCoded = true;
3689
239
          cuCtx.isChromaQpAdjCoded = true;
3690
239
          m_CABACEstimator->residual_coding(tu, compID, &cuCtx);
3691
239
          m_CABACEstimator->mts_idx(cu, &cuCtx);
3692
3693
239
          currCompFracBits = m_CABACEstimator->getEstFracBits();
3694
3695
239
          PelBuf resiBuf  = csFull->getResiBuf(compArea);
3696
239
          CPelBuf orgResi = orgResiBuf.get(compID);
3697
3698
239
          m_pcTrQuant->invTransformNxN(tu, compID, resiBuf, cQP);
3699
239
          currCompDist = m_pcRdCost->getDistPart(orgResi, resiBuf, channelBitDepth, compID, DF_SSE);
3700
239
          currCompCost = m_pcRdCost->calcRdCost(currCompFracBits, currCompDist, false);
3701
239
        }
3702
32.3k
        else if (transformMode > 0)
3703
3.45k
        {
3704
3.45k
          currCompCost = MAX_DOUBLE;
3705
3.45k
        }
3706
28.8k
        else
3707
28.8k
        {
3708
28.8k
          currCompFracBits = nonCoeffFracBits;
3709
28.8k
          currCompDist     = nonCoeffDist;
3710
28.8k
          currCompCost     = nonCoeffCost;
3711
3712
28.8k
          tu.cbf[compID] = 0;
3713
28.8k
        }
3714
3715
        // evaluate
3716
32.5k
        if ((currCompCost < minCost[compID]) || (transformMode == 1 && currCompCost == minCost[compID]))
3717
29.1k
        {
3718
          // copy component
3719
29.1k
          if (isFirstMode && ((nonCoeffCost < currCompCost) || (currAbsSum == 0))) // check for forced null
3720
28.9k
          {
3721
28.9k
            tu.getCoeffs( compID ).fill( 0 );
3722
28.9k
            csFull->getResiBuf( compArea ).fill( 0 );
3723
28.9k
            tu.cbf[compID]   = 0;
3724
3725
28.9k
            currAbsSum       = 0;
3726
28.9k
            currCompFracBits = nonCoeffFracBits;
3727
28.9k
            currCompDist     = nonCoeffDist;
3728
28.9k
            currCompCost     = nonCoeffCost;
3729
28.9k
          }
3730
3731
29.1k
          uiSingleDistComp[compID] = currCompDist;
3732
29.1k
          minCost[compID]          = currCompCost;
3733
29.1k
          if (transformMode != (nNumTransformCands - 1))
3734
3.45k
          {
3735
3.45k
            bestTU.copyComponentFrom(tu, compID);
3736
3.45k
            saveCS.getResiBuf(compArea).copyFrom(csFull->getResiBuf(compArea));
3737
3.45k
          }
3738
25.6k
          else
3739
25.6k
          {
3740
25.6k
            isLast = false;
3741
25.6k
          }
3742
29.1k
        }
3743
32.5k
        if( tu.noResidual )
3744
0
        {
3745
0
          CHECK( currCompFracBits > 0 || currAbsSum, "currCompFracBits > 0 when tu noResidual" );
3746
0
        }
3747
32.5k
      }
3748
29.1k
      if (isLast)
3749
3.45k
      {
3750
3.45k
        tu.copyComponentFrom(bestTU, compID);
3751
3.45k
        csFull->getResiBuf(compArea).copyFrom(saveCS.getResiBuf(compArea));
3752
3.45k
      }
3753
29.1k
    } // component loop
3754
3755
29.1k
    if ( tu.blocks.size()>2 && tu.blocks[COMP_Cb].valid() )
3756
0
    {
3757
0
      const CompArea& cbArea = tu.blocks[COMP_Cb];
3758
0
      const CompArea& crArea = tu.blocks[COMP_Cr];
3759
0
      bool checkJointCbCr = (sps.jointCbCr) && (!tu.noResidual) && (TU::getCbf(tu, COMP_Cb) || TU::getCbf(tu, COMP_Cr));
3760
0
      const int channelBitDepth = sps.bitDepths[toChannelType(COMP_Cb)];
3761
0
      double minCostCbCr = minCost[COMP_Cb] + minCost[COMP_Cr];
3762
0
      bool   isLastBest  = false;
3763
3764
0
      bool checkDCTOnly = m_pcEncCfg->m_useChromaTS && ((TU::getCbf(tu, COMP_Cb) && tu.mtsIdx[COMP_Cb] == MTS_DCT2_DCT2 && !TU::getCbf(tu, COMP_Cr)) ||
3765
0
        (TU::getCbf(tu, COMP_Cr) && tu.mtsIdx[COMP_Cr] == MTS_DCT2_DCT2 && !TU::getCbf(tu, COMP_Cb)) ||
3766
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));
3767
0
      bool checkTSOnly = m_pcEncCfg->m_useChromaTS && ((TU::getCbf(tu, COMP_Cb) && tu.mtsIdx[COMP_Cb] == MTS_SKIP && !TU::getCbf(tu, COMP_Cr)) ||
3768
0
        (TU::getCbf(tu, COMP_Cr) && tu.mtsIdx[COMP_Cr] == MTS_SKIP && !TU::getCbf(tu, COMP_Cb)) ||
3769
0
        (TU::getCbf(tu, COMP_Cb) && tu.mtsIdx[COMP_Cb] == MTS_SKIP && TU::getCbf(tu, COMP_Cr) && tu.mtsIdx[COMP_Cr] == MTS_SKIP));
3770
3771
0
      std::vector<int> jointCbfMasksToTest;
3772
0
      if ( checkJointCbCr )
3773
0
      {
3774
0
        for( int i = 0; i < 4; i++ )
3775
0
        {
3776
0
          m_orgResiCb[i].compactResize(cbArea);
3777
0
          m_orgResiCr[i].compactResize(crArea);
3778
0
        }
3779
0
        m_orgResiCb[0].copyFrom(orgResiBuf.Cb());
3780
0
        m_orgResiCr[0].copyFrom(orgResiBuf.Cr());
3781
3782
0
        jointCbfMasksToTest = m_pcTrQuant->selectICTCandidates(tu, m_orgResiCb, m_orgResiCr);
3783
3784
0
        bestTU.copyComponentFrom(tu, COMP_Cb);
3785
0
        bestTU.copyComponentFrom(tu, COMP_Cr);
3786
0
        saveCS.getResiBuf(cbArea).copyFrom(csFull->getResiBuf(cbArea));
3787
0
        saveCS.getResiBuf(crArea).copyFrom(csFull->getResiBuf(crArea));
3788
0
      }
3789
3790
0
      for (int cbfMask: jointCbfMasksToTest)
3791
0
      {
3792
0
        ComponentID codeCompId = (cbfMask >> 1 ? COMP_Cb : COMP_Cr);
3793
0
        ComponentID otherCompId = (codeCompId == COMP_Cr ? COMP_Cb : COMP_Cr);
3794
0
        bool tsAllowed = useTS && TU::isTSAllowed(tu, codeCompId) && (m_pcEncCfg->m_useChromaTS);
3795
0
        if (tsAllowed && (tu.mtsIdx[COMP_Y] != MTS_SKIP))
3796
0
        {
3797
0
          tsAllowed = false;
3798
0
        }
3799
0
        if (!tsAllowed)
3800
0
        {
3801
0
          checkTSOnly = false;
3802
0
        }
3803
0
        uint8_t     numTransformCands = 1 + (tsAllowed && (!(checkDCTOnly || checkTSOnly)) ? 1 : 0); // DCT + TS = 2 tests
3804
0
        TrModeList trModes;
3805
0
        if (numTransformCands > 1)
3806
0
        {
3807
0
          trModes.push_back(TrMode(0, true)); // DCT2
3808
0
          trModes.push_back(TrMode(1, true));//TS
3809
0
        }
3810
0
        else
3811
0
        {
3812
0
          tu.mtsIdx[codeCompId] = checkTSOnly ? 1 : 0;
3813
0
        }
3814
0
        for (int modeId = 0; modeId < numTransformCands; modeId++)
3815
0
        {
3816
0
          TCoeff     currAbsSum = 0;
3817
0
          uint64_t   currCompFracBits = 0;
3818
0
          Distortion currCompDistCb = 0;
3819
0
          Distortion currCompDistCr = 0;
3820
0
          double     currCompCost = 0;
3821
3822
0
          tu.jointCbCr = (uint8_t)cbfMask;
3823
0
          if (numTransformCands > 1)
3824
0
          {
3825
0
            tu.mtsIdx[codeCompId] = trModes[modeId].first;
3826
0
          }
3827
0
          tu.mtsIdx[otherCompId] = MTS_DCT2_DCT2;
3828
0
          const QpParam cQP(tu, COMP_Cb);  // note: uses tu.transformSkip[compID]
3829
0
          m_pcTrQuant->selectLambda(COMP_Cb);
3830
3831
          // Lambda is loosened for the joint mode with respect to single modes as the same residual is used for both chroma blocks
3832
0
          const int    absIct = abs(TU::getICTMode(tu));
3833
0
          const double lfact = (absIct == 1 || absIct == 3 ? 0.8 : 0.5);
3834
0
          m_pcTrQuant->scaleLambda(lfact);
3835
0
          if (checkJointCbCr && (tu.cu->cs->slice->sliceQp > 18))
3836
0
          {
3837
0
            m_pcTrQuant->scaleLambda(1.05);
3838
0
          }
3839
3840
0
          m_CABACEstimator->getCtx() = ctxStart;
3841
0
          m_CABACEstimator->resetBits();
3842
3843
0
          PelBuf cbResi = csFull->getResiBuf(cbArea);
3844
0
          PelBuf crResi = csFull->getResiBuf(crArea);
3845
0
          cbResi.copyFrom(m_orgResiCb[cbfMask]);
3846
0
          crResi.copyFrom(m_orgResiCr[cbfMask]);
3847
3848
0
          int         codedCbfMask = 0;
3849
0
          ComponentID codeCompId = (tu.jointCbCr >> 1 ? COMP_Cb : COMP_Cr);
3850
0
          ComponentID otherCompId = (codeCompId == COMP_Cr ? COMP_Cb : COMP_Cr);
3851
0
          const QpParam qpCbCr(tu, codeCompId);
3852
3853
0
          tu.getCoeffs(otherCompId).fill(0);   // do we need that?
3854
0
          TU::setCbfAtDepth(tu, otherCompId, tu.depth, false);
3855
3856
0
          PelBuf& codeResi = (codeCompId == COMP_Cr ? crResi : cbResi);
3857
0
          TCoeff  compAbsSum = 0;
3858
0
          if (numTransformCands > 1)
3859
0
          {
3860
0
            if (modeId == 0)
3861
0
            {
3862
0
              m_pcTrQuant->checktransformsNxN(tu, &trModes, 2, codeCompId);
3863
0
              tu.mtsIdx[codeCompId] = trModes[modeId].first;
3864
0
              tu.mtsIdx[otherCompId] = MTS_DCT2_DCT2;
3865
0
              if (!trModes[modeId + 1].second)
3866
0
              {
3867
0
                numTransformCands = 1;
3868
0
              }
3869
0
            }
3870
0
            m_pcTrQuant->transformNxN(tu, codeCompId, qpCbCr, compAbsSum, m_CABACEstimator->getCtx(), true);
3871
0
          }
3872
0
          else
3873
0
          {
3874
0
            m_pcTrQuant->transformNxN(tu, codeCompId, qpCbCr, compAbsSum, m_CABACEstimator->getCtx());
3875
0
          }
3876
0
          if (compAbsSum > 0)
3877
0
          {
3878
0
            m_pcTrQuant->invTransformNxN(tu, codeCompId, codeResi, qpCbCr);
3879
0
            codedCbfMask += (codeCompId == COMP_Cb ? 2 : 1);
3880
0
          }
3881
0
          else
3882
0
          {
3883
0
            codeResi.fill(0);
3884
0
          }
3885
3886
0
          if (tu.jointCbCr == 3 && codedCbfMask == 2)
3887
0
          {
3888
0
            codedCbfMask = 3;
3889
0
            TU::setCbfAtDepth(tu, COMP_Cr, tu.depth, true);
3890
0
          }
3891
0
          if (codedCbfMask && tu.jointCbCr != codedCbfMask)
3892
0
          {
3893
0
            codedCbfMask = 0;
3894
0
          }
3895
0
          currAbsSum = codedCbfMask;
3896
0
          if (!tu.mtsIdx[codeCompId])
3897
0
          {
3898
0
            numTransformCands = (currAbsSum <= 0) ? 1 : numTransformCands;
3899
0
          }
3900
0
          if (currAbsSum > 0)
3901
0
          {
3902
0
            m_CABACEstimator->cbf_comp(*tu.cu, codedCbfMask >> 1, cbArea, currDepth, false);
3903
0
            m_CABACEstimator->cbf_comp(*tu.cu, codedCbfMask & 1, crArea, currDepth, codedCbfMask >> 1);
3904
0
            m_CABACEstimator->joint_cb_cr(tu, codedCbfMask);
3905
0
            if (codedCbfMask >> 1)
3906
0
              m_CABACEstimator->residual_coding(tu, COMP_Cb);
3907
0
            if (codedCbfMask & 1)
3908
0
              m_CABACEstimator->residual_coding(tu, COMP_Cr);
3909
0
            currCompFracBits = m_CABACEstimator->getEstFracBits();
3910
3911
0
            m_pcTrQuant->invTransformICT(tu, cbResi, crResi);
3912
3913
0
            currCompDistCb = m_pcRdCost->getDistPart(orgResiBuf.Cb(), cbResi, channelBitDepth, COMP_Cb, DF_SSE);
3914
0
            currCompDistCr = m_pcRdCost->getDistPart(orgResiBuf.Cr(), crResi, channelBitDepth, COMP_Cr, DF_SSE);
3915
0
            currCompCost = m_pcRdCost->calcRdCost(currCompFracBits, currCompDistCr + currCompDistCb, false);
3916
0
          }
3917
0
          else
3918
0
            currCompCost = MAX_DOUBLE;
3919
3920
          // evaluate
3921
0
          if (currCompCost < minCostCbCr)
3922
0
          {
3923
0
            uiSingleDistComp[COMP_Cb] = currCompDistCb;
3924
0
            uiSingleDistComp[COMP_Cr] = currCompDistCr;
3925
0
            minCostCbCr = currCompCost;
3926
0
            isLastBest = (cbfMask == jointCbfMasksToTest.back()) && (modeId == (numTransformCands - 1));
3927
0
            if (!isLastBest)
3928
0
            {
3929
0
              bestTU.copyComponentFrom(tu, COMP_Cb);
3930
0
              bestTU.copyComponentFrom(tu, COMP_Cr);
3931
0
              saveCS.getResiBuf(cbArea).copyFrom(csFull->getResiBuf(cbArea));
3932
0
              saveCS.getResiBuf(crArea).copyFrom(csFull->getResiBuf(crArea));
3933
0
            }
3934
0
          }
3935
0
        }
3936
3937
0
        if( !isLastBest )
3938
0
        {
3939
          // copy component
3940
0
          tu.copyComponentFrom( bestTU, COMP_Cb );
3941
0
          tu.copyComponentFrom( bestTU, COMP_Cr );
3942
0
          csFull->getResiBuf( cbArea ).copyFrom( saveCS.getResiBuf( cbArea ) );
3943
0
          csFull->getResiBuf( crArea ).copyFrom( saveCS.getResiBuf( crArea ) );
3944
0
        }
3945
0
      }
3946
0
    }
3947
3948
29.1k
    m_CABACEstimator->getCtx() = ctxStart;
3949
29.1k
    m_CABACEstimator->resetBits();
3950
29.1k
    if( !tu.noResidual )
3951
29.1k
    {
3952
29.1k
      static const ComponentID cbf_getComp[3] = { COMP_Cb, COMP_Cr, COMP_Y };
3953
116k
      for( unsigned c = 0; c < numTBlocks; c++)
3954
87.3k
      {
3955
87.3k
        const ComponentID compID = numTBlocks>1 ? cbf_getComp[c] : COMP_Y;
3956
87.3k
        if( tu.blocks[compID].valid() )
3957
29.1k
        {
3958
29.1k
          const bool prevCbf = ( compID == COMP_Cr ? TU::getCbfAtDepth( tu, COMP_Cb, currDepth ) : false );
3959
29.1k
          m_CABACEstimator->cbf_comp( *tu.cu, TU::getCbfAtDepth( tu, compID, currDepth ), tu.blocks[compID], currDepth, prevCbf );
3960
29.1k
        }
3961
87.3k
      }
3962
29.1k
    }
3963
3964
116k
    for (uint32_t ch = 0; ch < numValidComp; ch++)
3965
87.3k
    {
3966
87.3k
      const ComponentID compID = ComponentID(ch);
3967
87.3k
      if (tu.blocks[compID].valid())
3968
29.1k
      {
3969
29.1k
        if( compID == COMP_Cr )
3970
0
        {
3971
0
          const int cbfMask = ( TU::getCbf( tu, COMP_Cb ) ? 2 : 0 ) + ( TU::getCbf( tu, COMP_Cr ) ? 1 : 0 );
3972
0
          m_CABACEstimator->joint_cb_cr(tu, cbfMask);
3973
0
        }
3974
29.1k
        if( TU::getCbf( tu, compID ) )
3975
161
        {
3976
161
          m_CABACEstimator->residual_coding( tu, compID );
3977
161
        }
3978
29.1k
        uiSingleDist += uiSingleDistComp[compID];
3979
29.1k
      }
3980
87.3k
    }
3981
29.1k
    if( tu.noResidual )
3982
0
    {
3983
0
      CHECK( m_CABACEstimator->getEstFracBits() > 0, "no residual TU's bits shall be 0" );
3984
0
    }
3985
3986
29.1k
    csFull->fracBits += m_CABACEstimator->getEstFracBits();
3987
29.1k
    csFull->dist     += uiSingleDist;
3988
29.1k
    csFull->cost      = m_pcRdCost->calcRdCost(csFull->fracBits, csFull->dist, !m_pcEncCfg->m_lumaLevelToDeltaQPEnabled);
3989
29.1k
  } // check full
3990
3991
  // code sub-blocks
3992
29.1k
  if( bCheckSplit )
3993
0
  {
3994
0
    if( bCheckFull )
3995
0
    {
3996
0
      m_CABACEstimator->getCtx() = ctxStart;
3997
0
    }
3998
3999
0
    if( partitioner.canSplit( TU_MAX_TR_SPLIT, cs ) )
4000
0
    {
4001
0
      partitioner.splitCurrArea( TU_MAX_TR_SPLIT, cs );
4002
0
    }
4003
0
    else if( cu.sbtInfo && partitioner.canSplit( CU::getSbtTuSplit( cu.sbtInfo ), cs ) )
4004
0
    {
4005
0
      partitioner.splitCurrArea( CU::getSbtTuSplit( cu.sbtInfo ), cs );
4006
0
    }
4007
0
    else
4008
0
      THROW( "Implicit TU split not available!" );
4009
4010
0
    do
4011
0
    {
4012
0
      xEstimateInterResidualQT(*csSplit, partitioner, bCheckFull ? nullptr : puiZeroDist );
4013
4014
0
      csSplit->cost = m_pcRdCost->calcRdCost( csSplit->fracBits, csSplit->dist );
4015
0
    } while( partitioner.nextPart( *csSplit ) );
4016
4017
0
    partitioner.exitCurrSplit();
4018
4019
0
    unsigned        compCbf[3]  = { 0, 0, 0 };
4020
4021
0
    if( !bCheckFull )
4022
0
    {
4023
0
      for( auto &currTU : csSplit->traverseTUs( currArea, partitioner.chType ) )
4024
0
      {
4025
0
        for( unsigned ch = 0; ch < numTBlocks; ch++ )
4026
0
        {
4027
0
          compCbf[ ch ] |= ( TU::getCbfAtDepth( currTU, ComponentID(ch), currDepth + 1 ) ? 1 : 0 );
4028
0
        }
4029
0
      }
4030
4031
0
      for( auto &currTU : csSplit->traverseTUs( currArea, partitioner.chType ) )
4032
0
      {
4033
0
        TU::setCbfAtDepth   ( currTU, COMP_Y,  currDepth, compCbf[ COMP_Y  ] );
4034
0
        if( currArea.chromaFormat != CHROMA_400 )
4035
0
        {
4036
0
          TU::setCbfAtDepth ( currTU, COMP_Cb, currDepth, compCbf[ COMP_Cb ] );
4037
0
          TU::setCbfAtDepth ( currTU, COMP_Cr, currDepth, compCbf[ COMP_Cr ] );
4038
0
        }
4039
0
      }
4040
4041
0
      m_CABACEstimator->getCtx() = ctxStart;
4042
0
      m_CABACEstimator->resetBits();
4043
4044
      // when compID isn't a channel, code Cbfs:
4045
0
      xEncodeInterResidualQT( *csSplit, partitioner, MAX_NUM_TBLOCKS );
4046
4047
0
      for (uint32_t ch = 0; ch < numValidComp; ch++)
4048
0
      {
4049
0
        const ComponentID compID = ComponentID(ch);
4050
0
        xEncodeInterResidualQT( *csSplit, partitioner, compID );
4051
0
      }
4052
4053
0
      csSplit->fracBits = m_CABACEstimator->getEstFracBits();
4054
0
      csSplit->cost     = m_pcRdCost->calcRdCost(csSplit->fracBits, csSplit->dist);
4055
0
    }
4056
0
  }
4057
29.1k
}
4058
4059
void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &partitioner, const bool skipResidual )
4060
29.1k
{
4061
29.1k
  CodingUnit &cu = *cs.getCU( partitioner.chType, partitioner.treeType );
4062
29.1k
  bool luma      = true;
4063
29.1k
  bool chroma    = cs.pcv->chrFormat != VVENC_CHROMA_400;
4064
29.1k
  if( cu.predMode == MODE_IBC )
4065
29.1k
  {
4066
29.1k
    luma    = !cu.mccNoLuma  ();
4067
29.1k
    chroma &= !cu.mccNoChroma();
4068
29.1k
  }
4069
29.1k
  if( cu.predMode == MODE_INTER )
4070
29.1k
    CHECK( CU::isSepTree(cu), "CU with Inter mode must be in single tree" );
4071
4072
29.1k
  const ChromaFormat format      = cs.area.chromaFormat;;
4073
29.1k
  const int  numValidComponents  = getNumberValidComponents(format);
4074
29.1k
  const SPS &sps                 = *cs.sps;
4075
4076
29.1k
  if( skipResidual ) //  No residual coding : SKIP mode
4077
0
  {
4078
0
    cu.skip    = true;
4079
0
    cu.rootCbf = false;
4080
0
    CHECK( cu.sbtInfo != 0, "sbtInfo shall be 0 if CU has no residual" );
4081
0
    cs.getResiBuf().fill(0);
4082
0
    cs.getRecoBuf().copyFrom(cs.getPredBuf() );
4083
4084
    // add new "empty" TU(s) spanning the whole CU
4085
0
    cs.addEmptyTUs( partitioner, &cu );
4086
0
    Distortion distortion = 0;
4087
4088
0
    for (int comp = 0; comp < numValidComponents; comp++)
4089
0
    {
4090
0
      const ComponentID compID = ComponentID(comp);
4091
0
      if (compID == COMP_Y && !luma)
4092
0
        continue;
4093
0
      if (compID != COMP_Y && !chroma)
4094
0
        continue;
4095
0
      CPelBuf reco = cs.getRecoBuf (compID);
4096
0
      CPelBuf org  = cs.getOrgBuf  (compID);
4097
4098
0
      distortion  += m_pcRdCost->getDistPart( org, reco, sps.bitDepths[ toChannelType( compID ) ], compID, DF_SSE );
4099
0
    }
4100
4101
0
    CodingUnit& cu = *cs.getCU(partitioner.chType, TREE_D);
4102
0
    m_CABACEstimator->resetBits();
4103
0
    m_CABACEstimator->cu_skip_flag  ( cu );
4104
0
    m_CABACEstimator->merge_data(cu);
4105
0
    cs.fracBits = m_CABACEstimator->getEstFracBits();
4106
0
    cs.dist     = distortion;
4107
0
    cs.cost     = m_pcRdCost->calcRdCost(cs.fracBits, cs.dist);
4108
4109
0
    return;
4110
0
  }
4111
4112
  //  Residual coding.
4113
29.1k
  if (luma)
4114
29.1k
  {
4115
29.1k
    cs.getResiBuf(COMP_Y).subtract(cs.getOrgBuf(COMP_Y), cs.getPredBuf(COMP_Y));
4116
29.1k
  }
4117
29.1k
  if (chroma)
4118
0
  {
4119
0
    cs.getResiBuf(COMP_Cb).subtract(cs.getOrgBuf(COMP_Cb), cs.getPredBuf(COMP_Cb));
4120
0
    cs.getResiBuf(COMP_Cr).subtract(cs.getOrgBuf(COMP_Cr), cs.getPredBuf(COMP_Cr));
4121
0
  }
4122
4123
29.1k
  Distortion zeroDistortion = 0;
4124
4125
29.1k
  const TempCtx ctxStart( m_CtxCache, m_CABACEstimator->getCtx() );
4126
4127
29.1k
  xEstimateInterResidualQT(cs, partitioner, &zeroDistortion );
4128
29.1k
  TransformUnit& firstTU = *cs.getTU( partitioner.chType );
4129
4130
29.1k
  cu.rootCbf = false;
4131
29.1k
  m_CABACEstimator->resetBits();
4132
29.1k
  m_CABACEstimator->rqt_root_cbf( cu );
4133
29.1k
  const uint64_t  zeroFracBits = m_CABACEstimator->getEstFracBits();
4134
29.1k
  double zeroCost = m_pcRdCost->calcRdCost( zeroFracBits, zeroDistortion, !m_pcEncCfg->m_lumaLevelToDeltaQPEnabled );
4135
4136
29.1k
  const int  numValidTBlocks   = getNumberValidTBlocks( *cs.pcv );
4137
116k
  for (uint32_t i = 0; i < numValidTBlocks; i++)
4138
87.3k
  {
4139
87.3k
    cu.rootCbf |= TU::getCbfAtDepth(firstTU, ComponentID(i), 0);
4140
87.3k
  }
4141
4142
  // -------------------------------------------------------
4143
  // If a block full of 0's is efficient, then just use 0's.
4144
  // The costs at this point do not include header bits.
4145
4146
29.1k
  if (zeroCost < cs.cost || !cu.rootCbf)
4147
28.9k
  {
4148
28.9k
    cu.sbtInfo = 0;
4149
28.9k
    cu.rootCbf = false;
4150
4151
28.9k
    cs.clearTUs();
4152
4153
    // add a new "empty" TU spanning the whole CU
4154
28.9k
    cs.addEmptyTUs( partitioner, &cu );
4155
28.9k
  }
4156
4157
  // all decisions now made. Fully encode the CU, including the headers:
4158
29.1k
  m_CABACEstimator->getCtx() = ctxStart;
4159
4160
29.1k
  uint64_t finalFracBits = xGetSymbolFracBitsInter( cs, partitioner );
4161
  // we've now encoded the CU, and so have a valid bit cost
4162
29.1k
  if (!cu.rootCbf)
4163
28.9k
  {
4164
28.9k
    if (luma)
4165
28.9k
    {
4166
28.9k
      cs.getResiBuf().bufs[0].fill(0); // Clear the residual image, if we didn't code it.
4167
28.9k
    }
4168
28.9k
    if (chroma && isChromaEnabled(cs.pcv->chrFormat))
4169
0
    {
4170
0
      cs.getResiBuf().bufs[1].fill(0); // Clear the residual image, if we didn't code it.
4171
0
      cs.getResiBuf().bufs[2].fill(0); // Clear the residual image, if we didn't code it.
4172
0
    }
4173
28.9k
  }
4174
29.1k
  if (luma)
4175
29.1k
  {
4176
29.1k
    cs.getRecoBuf().bufs[0].reconstruct(cs.getPredBuf().bufs[0], cs.getResiBuf().bufs[0], cs.slice->clpRngs[COMP_Y]);
4177
29.1k
  }
4178
29.1k
  if (chroma)
4179
0
  {
4180
0
    cs.getRecoBuf().bufs[1].reconstruct(cs.getPredBuf().bufs[1], cs.getResiBuf().bufs[1], cs.slice->clpRngs[COMP_Cb]);
4181
0
    cs.getRecoBuf().bufs[2].reconstruct(cs.getPredBuf().bufs[2], cs.getResiBuf().bufs[2], cs.slice->clpRngs[COMP_Cr]);
4182
0
  }
4183
  // update with clipped distortion and cost (previously unclipped reconstruction values were used)
4184
29.1k
  Distortion finalDistortion = 0;
4185
4186
116k
  for (int comp = 0; comp < numValidComponents; comp++)
4187
87.3k
  {
4188
87.3k
    const ComponentID compID = ComponentID(comp);
4189
87.3k
    if (compID == COMP_Y && !luma)
4190
0
      continue;
4191
87.3k
    if (compID != COMP_Y && !chroma)
4192
58.2k
      continue;
4193
29.1k
    CPelBuf reco = cs.getRecoBuf (compID);
4194
29.1k
    CPelBuf org  = cs.getOrgBuf  (compID);
4195
4196
29.1k
    finalDistortion += m_pcRdCost->getDistPart( org, reco, sps.bitDepths[toChannelType(compID)], compID, DF_SSE );
4197
29.1k
  }
4198
4199
29.1k
  cs.dist     = finalDistortion;
4200
29.1k
  cs.fracBits = finalFracBits;
4201
29.1k
  cs.cost     = m_pcRdCost->calcRdCost(cs.fracBits, cs.dist);
4202
4203
29.1k
  CHECK(cs.tus.size() == 0, "No TUs present");
4204
29.1k
}
4205
4206
uint64_t InterSearch::xGetSymbolFracBitsInter(CodingStructure &cs, Partitioner &partitioner)
4207
29.1k
{
4208
29.1k
  uint64_t fracBits   = 0;
4209
29.1k
  CodingUnit &cu    = *cs.getCU( partitioner.chType, partitioner.treeType );
4210
4211
29.1k
  m_CABACEstimator->resetBits();
4212
4213
29.1k
  if( cu.mergeFlag && !cu.rootCbf )
4214
0
  {
4215
0
    cu.skip = true;
4216
4217
0
    m_CABACEstimator->cu_skip_flag  ( cu );
4218
0
    if (!cu.ciip)
4219
0
    {
4220
0
      m_CABACEstimator->merge_data(cu);
4221
0
    }
4222
0
    fracBits   += m_CABACEstimator->getEstFracBits();
4223
0
  }
4224
29.1k
  else
4225
29.1k
  {
4226
29.1k
    CHECK( cu.skip, "Skip flag has to be off at this point!" );
4227
4228
29.1k
    if (cu.Y().valid())
4229
29.1k
    m_CABACEstimator->cu_skip_flag( cu );
4230
29.1k
    m_CABACEstimator->pred_mode   ( cu );
4231
29.1k
    m_CABACEstimator->cu_pred_data( cu );
4232
29.1k
    CUCtx cuCtx;
4233
29.1k
    cuCtx.isDQPCoded = true;
4234
29.1k
    cuCtx.isChromaQpAdjCoded = true;
4235
29.1k
    m_CABACEstimator->cu_residual ( cu, partitioner, cuCtx );
4236
29.1k
    fracBits       += m_CABACEstimator->getEstFracBits();
4237
29.1k
  }
4238
4239
29.1k
  return fracBits;
4240
29.1k
}
4241
4242
double InterSearch::xGetMEDistortionWeight(uint8_t BcwIdx, RefPicList refPicList)
4243
0
{
4244
0
  if( BcwIdx != BCW_DEFAULT )
4245
0
  {
4246
0
    return fabs( (double)getBcwWeight( BcwIdx, refPicList ) / (double)g_BcwWeightBase );
4247
0
  }
4248
0
  else
4249
0
  {
4250
0
    return 0.5;
4251
0
  }
4252
0
}
4253
4254
bool InterSearch::xReadBufferedUniMv( CodingUnit& cu, RefPicList eRefPicList, int32_t iRefIdx, Mv& pcMvPred, Mv& rcMv, uint32_t& ruiBits, Distortion& ruiCost )
4255
0
{
4256
0
  if( m_uniMotions.isReadMode( (uint32_t)eRefPicList, (uint32_t)iRefIdx ) )
4257
0
  {
4258
0
    m_uniMotions.copyTo(rcMv, ruiCost, (uint32_t)eRefPicList, (uint32_t)iRefIdx);
4259
4260
0
    Mv pred = pcMvPred;
4261
0
    pred.changeTransPrecInternal2Amvr( cu.imv );
4262
0
    m_pcRdCost->setPredictor(pred);
4263
0
    m_pcRdCost->setCostScale(0);
4264
4265
0
    Mv mv = rcMv;
4266
0
    mv.changeTransPrecInternal2Amvr( cu.imv );
4267
0
    uint32_t mvBits = m_pcRdCost->getBitsOfVectorWithPredictor( mv.hor, mv.ver, 0 );
4268
4269
0
    ruiBits += mvBits;
4270
0
    ruiCost += m_pcRdCost->getCost(ruiBits);
4271
0
    return true;
4272
0
  }
4273
0
  return false;
4274
0
}
4275
4276
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 )
4277
0
{
4278
0
  if( m_uniMotions.isReadModeAffine( (uint32_t)eRefPicList, (uint32_t)iRefIdx, cu.affineType ) )
4279
0
  {
4280
0
    m_uniMotions.copyAffineMvTo( acMv, ruiCost, (uint32_t)eRefPicList, (uint32_t)iRefIdx, cu.affineType, mvpIdx );
4281
0
    m_pcRdCost->setCostScale(0);
4282
0
    acMvPred[0] = aamvpi.mvCandLT[mvpIdx];
4283
0
    acMvPred[1] = aamvpi.mvCandRT[mvpIdx];
4284
0
    acMvPred[2] = aamvpi.mvCandLB[mvpIdx];
4285
4286
0
    uint32_t mvBits = 0;
4287
0
    for( int verIdx = 0; verIdx < ( cu.affineType ? 3 : 2 ); verIdx++ )
4288
0
    {
4289
0
      Mv pred = verIdx ? acMvPred[verIdx] + acMv[0] - acMvPred[0] : acMvPred[verIdx];
4290
0
      pred.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
4291
0
      m_pcRdCost->setPredictor(pred);
4292
0
      Mv mv = acMv[verIdx];
4293
0
      mv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
4294
0
      mvBits += m_pcRdCost->getBitsOfVectorWithPredictor( mv.hor, mv.ver, 0 );
4295
0
    }
4296
0
    ruiBits += mvBits;
4297
0
    ruiCost += m_pcRdCost->getCost(ruiBits);
4298
0
    return true;
4299
0
  }
4300
0
  return false;
4301
0
}
4302
4303
void InterSearch::xSymMvdCheckBestMvp(
4304
  CodingUnit& cu,
4305
  CPelUnitBuf& origBuf,
4306
  Mv curMv,
4307
  RefPicList curRefList,
4308
  AMVPInfo amvpInfo[2][MAX_REF_PICS],
4309
  int32_t BcwIdx,
4310
  Mv cMvPredSym[2],
4311
  int32_t mvpIdxSym[2],
4312
  Distortion& bestCost,
4313
  bool skip
4314
)
4315
0
{
4316
0
  RefPicList tarRefList = (RefPicList)(1 - curRefList);
4317
0
  int32_t refIdxCur = cu.slice->symRefIdx[curRefList];
4318
0
  int32_t refIdxTar = cu.slice->symRefIdx[tarRefList];
4319
4320
0
  MvField cCurMvField, cTarMvField;
4321
0
  cCurMvField.setMvField(curMv, refIdxCur);
4322
0
  AMVPInfo& amvpCur = amvpInfo[curRefList][refIdxCur];
4323
0
  AMVPInfo& amvpTar = amvpInfo[tarRefList][refIdxTar];
4324
0
  m_pcRdCost->setCostScale(0);
4325
4326
0
  double fWeight = 0.0;
4327
0
  PelUnitBuf bufTmp;
4328
4329
  // get prediction of eCurRefPicList
4330
0
  PelUnitBuf predBufA = m_tmpPredStorage[curRefList].getCompactBuf( cu );
4331
0
  const Picture* picRefA = cu.slice->getRefPic(curRefList, cCurMvField.refIdx);
4332
0
  Mv mvA = cCurMvField.mv;
4333
0
  xClipMvSearch( mvA, cu.lumaPos(), cu.lumaSize(), *cu.cs->pcv, m_ifpLines );
4334
0
  xPredInterBlk( COMP_Y, cu, picRefA, mvA, predBufA, false, cu.slice->clpRngs[ COMP_Y ], false, false );
4335
4336
0
  bufTmp = m_tmpStorageLCU.getCompactBuf( cu );
4337
0
  bufTmp.copyFrom( origBuf );
4338
0
  bufTmp.removeHighFreq( predBufA, m_pcEncCfg->m_bClipForBiPredMeEnabled, cu.slice->clpRngs/*, getBcwWeight( cu.BcwIdx, tarRefList )*/ );
4339
0
  fWeight = xGetMEDistortionWeight( cu.BcwIdx, tarRefList );
4340
4341
0
  int32_t skipMvpIdx[2];
4342
0
  skipMvpIdx[0] = skip ? mvpIdxSym[0] : -1;
4343
0
  skipMvpIdx[1] = skip ? mvpIdxSym[1] : -1;
4344
4345
0
  for (int i = 0; i < amvpCur.numCand; i++)
4346
0
  {
4347
0
    for (int j = 0; j < amvpTar.numCand; j++)
4348
0
    {
4349
0
      if (skipMvpIdx[curRefList] == i && skipMvpIdx[tarRefList] == j)
4350
0
        continue;
4351
4352
0
      Distortion cost = MAX_DISTORTION;
4353
0
      cTarMvField.setMvField(curMv.getSymmvdMv(amvpCur.mvCand[i], amvpTar.mvCand[j]), refIdxTar);
4354
4355
      // get prediction of eTarRefPicList
4356
0
      PelUnitBuf predBufB = m_tmpPredStorage[tarRefList].getCompactBuf( cu );
4357
0
      const Picture* picRefB = cu.slice->getRefPic(tarRefList, cTarMvField.refIdx);
4358
0
      Mv mvB = cTarMvField.mv;
4359
0
      xClipMvSearch( mvB, cu.lumaPos(), cu.lumaSize(), *cu.cs->pcv, m_ifpLines );
4360
0
      xPredInterBlk( COMP_Y, cu, picRefB, mvB, predBufB, false, cu.slice->clpRngs[ COMP_Y ], false, false );
4361
4362
      // calc distortion
4363
0
      cost = ( Distortion ) floor( fWeight * ( double ) m_pcRdCost->getDistPart( bufTmp.Y(), predBufB.Y(), cu.cs->sps->bitDepths[ CH_L ], COMP_Y, DF_HAD ) );
4364
4365
0
      Mv pred = amvpCur.mvCand[i];
4366
0
      pred.changeTransPrecInternal2Amvr(cu.imv);
4367
0
      m_pcRdCost->setPredictor(pred);
4368
0
      Mv mv = curMv;
4369
0
      mv.changeTransPrecInternal2Amvr(cu.imv);
4370
0
      uint32_t bits = m_pcRdCost->getBitsOfVectorWithPredictor(mv.hor, mv.ver, 0);
4371
0
      bits += m_auiMVPIdxCost[i][AMVP_MAX_NUM_CANDS];
4372
0
      bits += m_auiMVPIdxCost[j][AMVP_MAX_NUM_CANDS];
4373
0
      cost += m_pcRdCost->getCost(bits);
4374
0
      if (cost < bestCost)
4375
0
      {
4376
0
        bestCost = cost;
4377
0
        cMvPredSym[curRefList] = amvpCur.mvCand[i];
4378
0
        cMvPredSym[tarRefList] = amvpTar.mvCand[j];
4379
0
        mvpIdxSym[curRefList] = i;
4380
0
        mvpIdxSym[tarRefList] = j;
4381
0
      }
4382
0
    }
4383
0
  }
4384
0
}
4385
4386
void InterSearch::resetSavedAffineMotion()
4387
166k
{
4388
499k
  for (int i = 0; i < 2; i++)
4389
332k
  {
4390
998k
    for (int j = 0; j < 2; j++)
4391
665k
    {
4392
665k
      m_affineMotion.acMvAffine4Para[i][j] = Mv(0, 0);
4393
665k
      m_affineMotion.acMvAffine6Para[i][j] = Mv(0, 0);
4394
665k
    }
4395
332k
    m_affineMotion.acMvAffine6Para[i][2] = Mv(0, 0);
4396
4397
332k
    m_affineMotion.affine4ParaRefIdx[i] = -1;
4398
332k
    m_affineMotion.affine6ParaRefIdx[i] = -1;
4399
332k
  }
4400
166k
  m_affineMotion.affine4ParaAvail = false;
4401
166k
  m_affineMotion.affine6ParaAvail = false;
4402
166k
}
4403
4404
void InterSearch::storeAffineMotion(Mv acAffineMv[2][3], int16_t affineRefIdx[2], EAffineModel affineType, int BcwIdx)
4405
0
{
4406
0
  if ((BcwIdx == BCW_DEFAULT || !m_affineMotion.affine6ParaAvail) && affineType == AFFINEMODEL_6PARAM)
4407
0
  {
4408
0
    for (int i = 0; i < 2; i++)
4409
0
    {
4410
0
      for (int j = 0; j < 3; j++)
4411
0
      {
4412
0
        m_affineMotion.acMvAffine6Para[i][j] = acAffineMv[i][j];
4413
0
      }
4414
0
      m_affineMotion.affine6ParaRefIdx[i] = affineRefIdx[i];
4415
0
    }
4416
0
    m_affineMotion.affine6ParaAvail = true;
4417
0
  }
4418
4419
0
  if ((BcwIdx == BCW_DEFAULT || !m_affineMotion.affine4ParaAvail) && affineType == AFFINEMODEL_4PARAM)
4420
0
  {
4421
0
    for (int i = 0; i < 2; i++)
4422
0
    {
4423
0
      for (int j = 0; j < 2; j++)
4424
0
      {
4425
0
        m_affineMotion.acMvAffine4Para[i][j] = acAffineMv[i][j];
4426
0
      }
4427
0
      m_affineMotion.affine4ParaRefIdx[i] = affineRefIdx[i];
4428
0
    }
4429
0
    m_affineMotion.affine4ParaAvail = true;
4430
0
  }
4431
0
}
4432
4433
void InterSearch::xPredAffineInterSearch( CodingUnit& cu,
4434
                                          CPelUnitBuf&    origBuf,
4435
                                          int             puIdx,
4436
                                          uint32_t&       lastMode,
4437
                                          Distortion&     affineCost,
4438
                                          Mv              hevcMv[2][MAX_REF_PICS],
4439
                                          Mv              mvAffine4Para[2][MAX_REF_PICS][3],
4440
                                          int             refIdx4Para[2],
4441
                                          uint8_t         BcwIdx,
4442
                                          bool            enforceBcwPred,
4443
                                          uint32_t        BcwIdxBits )
4444
0
{
4445
0
  const Slice &slice = *cu.slice;
4446
4447
0
  affineCost = MAX_DISTORTION;
4448
4449
0
  Mv        cMvZero;
4450
0
  Mv        aacMv[2][3];
4451
0
  Mv        cMvBi[2][3];
4452
0
  AffineMVInfo tmp;
4453
4454
0
  int       iNumPredDir = slice.isInterP() ? 1 : 2;
4455
4456
0
  int mvNum = 2;
4457
0
  mvNum = cu.affineType ? 3 : 2;
4458
4459
  // Mvp
4460
0
  Mv        cMvPred[2][MAX_REF_PICS][3];
4461
0
  Mv        cMvPredBi[2][MAX_REF_PICS][3];
4462
0
  int       aaiMvpIdxBi[2][MAX_REF_PICS];
4463
0
  int       aaiMvpIdx[2][MAX_REF_PICS];
4464
0
  int       aaiMvpNum[2][MAX_REF_PICS];
4465
4466
0
  AffineAMVPInfo aacAffineAMVPInfo[2][MAX_REF_PICS];
4467
0
  AffineAMVPInfo affiAMVPInfoTemp[2];
4468
4469
0
  uint32_t      uiMbBits[3] = { 1, 1, 0 };
4470
0
  int           iRefIdx[2] = { 0,0 }; // If un-initialized, may cause SEGV in bi-directional prediction iterative stage.
4471
0
  int           iRefIdxBi[2];
4472
0
  int           iRefStart, iRefEnd;
4473
0
  int           bestBiPRefIdxL1 = 0;
4474
0
  int           bestBiPMvpL1 = 0;
4475
0
  Distortion    biPDistTemp = MAX_DISTORTION;
4476
4477
0
  Distortion    uiCost[2] = { MAX_DISTORTION, MAX_DISTORTION };
4478
0
  Distortion    uiCostBi = MAX_DISTORTION;
4479
0
  Distortion    uiCostTemp;
4480
4481
0
  uint32_t      uiBits[3] = { 0 };
4482
0
  uint32_t      uiBitsTemp;
4483
0
  Distortion    bestBiPDist = MAX_DISTORTION;
4484
4485
0
  Distortion    uiCostTempL0[MAX_NUM_REF];
4486
0
  for (int iNumRef = 0; iNumRef < MAX_NUM_REF; iNumRef++)
4487
0
  {
4488
0
    uiCostTempL0[iNumRef] = MAX_DISTORTION;
4489
0
  }
4490
0
  uint32_t      uiBitsTempL0[MAX_NUM_REF];
4491
4492
0
  Mv            mvValidList1[4];
4493
0
  int           refIdxValidList1 = 0;
4494
0
  uint32_t      bitsValidList1 = MAX_UINT;
4495
0
  Distortion    costValidList1 = MAX_DISTORTION;
4496
0
  Mv            mvHevc[3];
4497
0
  const bool    affineAmvrEnabled = false;
4498
4499
0
  xGetBlkBits(slice.isInterP(), puIdx, lastMode, uiMbBits);
4500
4501
0
  cu.affine = true;
4502
0
  cu.mergeFlag = false;
4503
0
  if (BcwIdx != BCW_DEFAULT)
4504
0
  {
4505
0
    cu.BcwIdx = BcwIdx;
4506
0
  }
4507
4508
  // Uni-directional prediction
4509
0
  for (int iRefList = 0; iRefList < iNumPredDir; iRefList++)
4510
0
  {
4511
0
    RefPicList  refPicList = (iRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0);
4512
0
    cu.interDir = (iRefList ? 2 : 1);
4513
0
    for (int iRefIdxTemp = 0; iRefIdxTemp < slice.numRefIdx[refPicList]; iRefIdxTemp++)
4514
0
    {
4515
      // Get RefIdx bits
4516
0
      uiBitsTemp = uiMbBits[iRefList];
4517
0
      if (slice.numRefIdx[refPicList] > 1)
4518
0
      {
4519
0
        uiBitsTemp += iRefIdxTemp + 1;
4520
0
        if (iRefIdxTemp == slice.numRefIdx[refPicList] - 1)
4521
0
        {
4522
0
          uiBitsTemp--;
4523
0
        }
4524
0
      }
4525
4526
      // Do Affine AMVP
4527
0
      bool foundPred = xEstimateAffineAMVP(cu, affiAMVPInfoTemp[refPicList], origBuf, refPicList, iRefIdxTemp, cMvPred[iRefList][iRefIdxTemp], biPDistTemp);
4528
0
      if( !foundPred )
4529
0
        return;
4530
4531
0
      if (affineAmvrEnabled)
4532
0
      {
4533
0
        biPDistTemp += m_pcRdCost->getCost(xCalcAffineMVBits(cu, cMvPred[iRefList][iRefIdxTemp], cMvPred[iRefList][iRefIdxTemp]));
4534
0
      }
4535
0
      aaiMvpIdx[iRefList][iRefIdxTemp] = cu.mvpIdx[refPicList];
4536
0
      aaiMvpNum[iRefList][iRefIdxTemp] = cu.mvpNum[refPicList];;
4537
0
      if (cu.affineType == AFFINEMODEL_6PARAM && refIdx4Para[iRefList] != iRefIdxTemp)
4538
0
      {
4539
0
        xCopyAffineAMVPInfo(affiAMVPInfoTemp[refPicList], aacAffineAMVPInfo[iRefList][iRefIdxTemp]);
4540
0
        continue;
4541
0
      }
4542
4543
      // set hevc ME result as start search position when it is best than mvp
4544
0
      for (int i = 0; i<3; i++)
4545
0
      {
4546
0
        mvHevc[i] = hevcMv[iRefList][iRefIdxTemp];
4547
0
        mvHevc[i].roundAffinePrecInternal2Amvr(cu.imv);
4548
0
      }
4549
0
      PelUnitBuf predBuf = m_tmpStorageLCU.getCompactBuf(cu);
4550
4551
0
      Distortion uiCandCost = xGetAffineTemplateCost(cu, origBuf, predBuf, mvHevc, aaiMvpIdx[iRefList][iRefIdxTemp],
4552
0
        AMVP_MAX_NUM_CANDS, refPicList, iRefIdxTemp);
4553
4554
0
      if (affineAmvrEnabled)
4555
0
      {
4556
0
        uiCandCost += m_pcRdCost->getCost(xCalcAffineMVBits(cu, mvHevc, cMvPred[iRefList][iRefIdxTemp]));
4557
0
      }
4558
4559
      //check stored affine motion
4560
0
      bool affine4Para = cu.affineType == AFFINEMODEL_4PARAM;
4561
0
      bool savedParaAvail = cu.imv && ((m_affineMotion.affine4ParaRefIdx[iRefList] == iRefIdxTemp && affine4Para && m_affineMotion.affine4ParaAvail) ||
4562
0
        (m_affineMotion.affine6ParaRefIdx[iRefList] == iRefIdxTemp && !affine4Para && m_affineMotion.affine6ParaAvail));
4563
4564
0
      if (savedParaAvail)
4565
0
      {
4566
0
        Mv mvFour[3];
4567
0
        for (int i = 0; i < mvNum; i++)
4568
0
        {
4569
0
          mvFour[i] = affine4Para ? m_affineMotion.acMvAffine4Para[iRefList][i] : m_affineMotion.acMvAffine6Para[iRefList][i];
4570
0
          mvFour[i].roundAffinePrecInternal2Amvr(cu.imv);
4571
0
        }
4572
4573
0
        Distortion candCostInherit = xGetAffineTemplateCost(cu, origBuf, predBuf, mvFour, aaiMvpIdx[iRefList][iRefIdxTemp], AMVP_MAX_NUM_CANDS, refPicList, iRefIdxTemp);
4574
0
        candCostInherit += m_pcRdCost->getCost(xCalcAffineMVBits(cu, mvFour, cMvPred[iRefList][iRefIdxTemp]));
4575
4576
0
        if (candCostInherit < uiCandCost)
4577
0
        {
4578
0
          uiCandCost = candCostInherit;
4579
0
          memcpy(mvHevc, mvFour, 3 * sizeof(Mv));
4580
0
        }
4581
0
      }
4582
4583
0
      if( cu.affineType == AFFINEMODEL_4PARAM && m_AffineProfList->m_affMVListSize && (!cu.cs->sps->BCW || BcwIdx == BCW_DEFAULT ) )
4584
0
      {
4585
0
        int shift = MAX_CU_DEPTH;
4586
0
        for (int i = 0; i < m_AffineProfList->m_affMVListSize; i++)
4587
0
        {
4588
0
          AffineMVInfo *mvInfo = m_AffineProfList->m_affMVList + ((m_AffineProfList->m_affMVListIdx - i - 1 + m_AffineProfList->m_affMVListMaxSize) % (m_AffineProfList->m_affMVListMaxSize));
4589
          //check;
4590
0
          int j = 0;
4591
0
          for (; j < i; j++)
4592
0
          {
4593
0
            AffineMVInfo *prevMvInfo = m_AffineProfList->m_affMVList + ((m_AffineProfList->m_affMVListIdx - j - 1 + m_AffineProfList->m_affMVListMaxSize) % (m_AffineProfList->m_affMVListMaxSize));
4594
0
            if ((mvInfo->affMVs[iRefList][iRefIdxTemp][0] == prevMvInfo->affMVs[iRefList][iRefIdxTemp][0]) &&
4595
0
              (mvInfo->affMVs[iRefList][iRefIdxTemp][1] == prevMvInfo->affMVs[iRefList][iRefIdxTemp][1])
4596
0
              && (mvInfo->x == prevMvInfo->x) && (mvInfo->y == prevMvInfo->y)
4597
0
              && (mvInfo->w == prevMvInfo->w)
4598
0
              )
4599
0
            {
4600
0
              break;
4601
0
            }
4602
0
          }
4603
0
          if (j < i)
4604
0
            continue;
4605
4606
0
          Mv mvTmp[3], *nbMv = mvInfo->affMVs[iRefList][iRefIdxTemp];
4607
0
          int vx, vy;
4608
0
          int dMvHorX, dMvHorY, dMvVerX, dMvVerY;
4609
0
          int mvScaleHor = nbMv[0].hor * (1<< shift);
4610
0
          int mvScaleVer = nbMv[0].ver * (1<< shift);
4611
0
          Mv dMv = nbMv[1] - nbMv[0];
4612
0
          dMvHorX = dMv.hor *(1<<(shift - Log2(mvInfo->w)));
4613
0
          dMvHorY = dMv.ver *(1<< (shift - Log2(mvInfo->w)));
4614
0
          dMvVerX = -dMvHorY;
4615
0
          dMvVerY = dMvHorX;
4616
0
          vx = mvScaleHor + dMvHorX * (cu.Y().x - mvInfo->x) + dMvVerX * (cu.Y().y - mvInfo->y);
4617
0
          vy = mvScaleVer + dMvHorY * (cu.Y().x - mvInfo->x) + dMvVerY * (cu.Y().y - mvInfo->y);
4618
0
          roundAffineMv(vx, vy, shift);
4619
0
          mvTmp[0] = Mv(vx, vy);
4620
0
          mvTmp[0].clipToStorageBitDepth();
4621
0
          clipMv(mvTmp[0], cu.lumaPos(), cu.lumaSize(), *cu.cs->pcv);
4622
0
          mvTmp[0].roundAffinePrecInternal2Amvr(cu.imv);
4623
0
          vx = mvScaleHor + dMvHorX * (cu.Y().x + cu.Y().width - mvInfo->x) + dMvVerX * (cu.Y().y - mvInfo->y);
4624
0
          vy = mvScaleVer + dMvHorY * (cu.Y().x + cu.Y().width - mvInfo->x) + dMvVerY * (cu.Y().y - mvInfo->y);
4625
0
          roundAffineMv(vx, vy, shift);
4626
0
          mvTmp[1] = Mv(vx, vy);
4627
0
          mvTmp[1].clipToStorageBitDepth();
4628
0
          clipMv(mvTmp[1], cu.lumaPos(), cu.lumaSize(), *cu.cs->pcv);
4629
0
          mvTmp[0].roundAffinePrecInternal2Amvr(cu.imv);
4630
0
          mvTmp[1].roundAffinePrecInternal2Amvr(cu.imv);
4631
0
          Distortion tmpCost = xGetAffineTemplateCost(cu, origBuf, predBuf, mvTmp, aaiMvpIdx[iRefList][iRefIdxTemp], AMVP_MAX_NUM_CANDS, refPicList, iRefIdxTemp);
4632
0
          if (affineAmvrEnabled)
4633
0
          {
4634
0
            tmpCost += m_pcRdCost->getCost(xCalcAffineMVBits(cu, mvTmp, cMvPred[iRefList][iRefIdxTemp]));
4635
0
          }
4636
0
          if (tmpCost < uiCandCost)
4637
0
          {
4638
0
            uiCandCost = tmpCost;
4639
0
            std::memcpy(mvHevc, mvTmp, 3 * sizeof(Mv));
4640
0
          }
4641
0
        }
4642
0
      }
4643
0
      if (cu.affineType == AFFINEMODEL_6PARAM)
4644
0
      {
4645
0
        Mv mvFour[3];
4646
0
        mvFour[0] = mvAffine4Para[iRefList][iRefIdxTemp][0];
4647
0
        mvFour[1] = mvAffine4Para[iRefList][iRefIdxTemp][1];
4648
0
        mvAffine4Para[iRefList][iRefIdxTemp][0].roundAffinePrecInternal2Amvr(cu.imv);
4649
0
        mvAffine4Para[iRefList][iRefIdxTemp][1].roundAffinePrecInternal2Amvr(cu.imv);
4650
4651
0
        int shift = MAX_CU_DEPTH;
4652
0
        int vx2 = (mvFour[0].hor * (1<< shift)) - ((mvFour[1].ver - mvFour[0].ver) * (1<< (shift + Log2(cu.lheight()) - Log2(cu.lwidth()))));
4653
0
        int vy2 = (mvFour[0].ver * (1<< shift)) + ((mvFour[1].hor - mvFour[0].hor) * (1<< (shift + Log2(cu.lheight()) - Log2(cu.lwidth()))));
4654
0
        int offset = (1 << (shift - 1));
4655
0
        vx2 = (vx2 + offset - (vx2 >= 0)) >> shift;
4656
0
        vy2 = (vy2 + offset - (vy2 >= 0)) >> shift;
4657
0
        mvFour[2].hor = vx2;
4658
0
        mvFour[2].ver = vy2;
4659
0
        mvFour[2].clipToStorageBitDepth();
4660
0
        mvFour[0].roundAffinePrecInternal2Amvr(cu.imv);
4661
0
        mvFour[1].roundAffinePrecInternal2Amvr(cu.imv);
4662
0
        mvFour[2].roundAffinePrecInternal2Amvr(cu.imv);
4663
0
        Distortion uiCandCostInherit = xGetAffineTemplateCost(cu, origBuf, predBuf, mvFour, aaiMvpIdx[iRefList][iRefIdxTemp], AMVP_MAX_NUM_CANDS, refPicList, iRefIdxTemp);
4664
0
        if (affineAmvrEnabled)
4665
0
        {
4666
0
          uiCandCostInherit += m_pcRdCost->getCost(xCalcAffineMVBits(cu, mvFour, cMvPred[iRefList][iRefIdxTemp]));
4667
0
        }
4668
0
        if (uiCandCostInherit < uiCandCost)
4669
0
        {
4670
0
          uiCandCost = uiCandCostInherit;
4671
0
          for (int i = 0; i < 3; i++)
4672
0
          {
4673
0
            mvHevc[i] = mvFour[i];
4674
0
          }
4675
0
        }
4676
0
      }
4677
4678
0
      if (uiCandCost < biPDistTemp)
4679
0
      {
4680
0
        ::memcpy(tmp.affMVs[iRefList][iRefIdxTemp], mvHevc, sizeof(Mv) * 3);
4681
0
      }
4682
0
      else
4683
0
      {
4684
0
        ::memcpy(tmp.affMVs[iRefList][iRefIdxTemp], cMvPred[iRefList][iRefIdxTemp], sizeof(Mv) * 3);
4685
0
      }
4686
4687
      // GPB list 1, save the best MvpIdx, RefIdx and Cost
4688
0
      if (slice.picHeader->mvdL1Zero && iRefList == 1 && biPDistTemp < bestBiPDist)
4689
0
      {
4690
0
        bestBiPDist = biPDistTemp;
4691
0
        bestBiPMvpL1 = aaiMvpIdx[iRefList][iRefIdxTemp];
4692
0
        bestBiPRefIdxL1 = iRefIdxTemp;
4693
0
      }
4694
4695
      // Update bits
4696
0
      uiBitsTemp += m_auiMVPIdxCost[aaiMvpIdx[iRefList][iRefIdxTemp]][AMVP_MAX_NUM_CANDS];
4697
4698
0
      if (m_pcEncCfg->m_bFastMEForGenBLowDelayEnabled && iRefList == 1)   // list 1
4699
0
      {
4700
0
        if (slice.list1IdxToList0Idx[iRefIdxTemp] >= 0 && (cu.affineType != AFFINEMODEL_6PARAM || slice.list1IdxToList0Idx[iRefIdxTemp] == refIdx4Para[0]))
4701
0
        {
4702
0
          int iList1ToList0Idx = slice.list1IdxToList0Idx[iRefIdxTemp];
4703
0
          ::memcpy(tmp.affMVs[1][iRefIdxTemp], tmp.affMVs[0][iList1ToList0Idx], sizeof(Mv) * 3);
4704
0
          uiCostTemp = uiCostTempL0[iList1ToList0Idx];
4705
4706
0
          uiCostTemp -= m_pcRdCost->getCost(uiBitsTempL0[iList1ToList0Idx]);
4707
0
          uiBitsTemp += xCalcAffineMVBits(cu, tmp.affMVs[iRefList][iRefIdxTemp], cMvPred[iRefList][iRefIdxTemp]);
4708
          /*calculate the correct cost*/
4709
0
          uiCostTemp += m_pcRdCost->getCost(uiBitsTemp);
4710
0
          DTRACE(g_trace_ctx, D_COMMON, " (%d) uiCostTemp=%d\n", DTRACE_GET_COUNTER(g_trace_ctx, D_COMMON), uiCostTemp);
4711
0
        }
4712
0
        else
4713
0
        {
4714
0
          xAffineMotionEstimation(cu, origBuf, refPicList, cMvPred[iRefList][iRefIdxTemp], iRefIdxTemp, tmp.affMVs[iRefList][iRefIdxTemp], 
4715
0
                                  uiBitsTemp, uiCostTemp, aaiMvpIdx[iRefList][iRefIdxTemp], affiAMVPInfoTemp[refPicList]);
4716
0
        }
4717
0
      }
4718
0
      else
4719
0
      {
4720
0
        xAffineMotionEstimation(cu, origBuf, refPicList, cMvPred[iRefList][iRefIdxTemp], iRefIdxTemp, tmp.affMVs[iRefList][iRefIdxTemp], 
4721
0
                                uiBitsTemp, uiCostTemp, aaiMvpIdx[iRefList][iRefIdxTemp], affiAMVPInfoTemp[refPicList]);
4722
0
      }
4723
      
4724
0
      if( slice.sps->BCW && cu.BcwIdx == BCW_DEFAULT && slice.isInterB() )
4725
0
      {
4726
0
        m_uniMotions.setReadModeAffine( true, (uint8_t)iRefList, (uint8_t)iRefIdxTemp, cu.affineType );
4727
0
        m_uniMotions.copyAffineMvFrom( tmp.affMVs[iRefList][iRefIdxTemp], uiCostTemp - m_pcRdCost->getCost(uiBitsTemp), (uint8_t)iRefList, (uint8_t)iRefIdxTemp, cu.affineType,
4728
0
                                       aaiMvpIdx[iRefList][iRefIdxTemp] );
4729
0
      }
4730
4731
      // Set best AMVP Index
4732
0
      xCopyAffineAMVPInfo(affiAMVPInfoTemp[refPicList], aacAffineAMVPInfo[iRefList][iRefIdxTemp]);
4733
0
      if (cu.imv != 2)//|| !m_pcEncCfg->getUseAffineAmvrEncOpt())
4734
0
        xCheckBestAffineMVP(cu, affiAMVPInfoTemp[refPicList], refPicList, tmp.affMVs[iRefList][iRefIdxTemp], cMvPred[iRefList][iRefIdxTemp], aaiMvpIdx[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp);
4735
4736
0
      if (iRefList == 0)
4737
0
      {
4738
0
        uiCostTempL0[iRefIdxTemp] = uiCostTemp;
4739
0
        uiBitsTempL0[iRefIdxTemp] = uiBitsTemp;
4740
0
      }
4741
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]);
4742
0
      if (uiCostTemp < uiCost[iRefList])
4743
0
      {
4744
0
        uiCost[iRefList] = uiCostTemp;
4745
0
        uiBits[iRefList] = uiBitsTemp; // storing for bi-prediction
4746
4747
                                       // set best motion
4748
0
        ::memcpy(aacMv[iRefList], tmp.affMVs[iRefList][iRefIdxTemp], sizeof(Mv) * 3);
4749
0
        iRefIdx[iRefList] = iRefIdxTemp;
4750
0
      }
4751
4752
0
      if (iRefList == 1 && uiCostTemp < costValidList1 && slice.list1IdxToList0Idx[iRefIdxTemp] < 0)
4753
0
      {
4754
0
        costValidList1 = uiCostTemp;
4755
0
        bitsValidList1 = uiBitsTemp;
4756
4757
        // set motion
4758
0
        memcpy(mvValidList1, tmp.affMVs[iRefList][iRefIdxTemp], sizeof(Mv) * 3);
4759
0
        refIdxValidList1 = iRefIdxTemp;
4760
0
      }
4761
0
    } // End refIdx loop
4762
0
  } // end Uni-prediction
4763
4764
0
  if (cu.affineType == AFFINEMODEL_4PARAM)
4765
0
  {
4766
0
    ::memcpy(mvAffine4Para, tmp.affMVs, sizeof(tmp.affMVs));
4767
0
    if (cu.imv == IMV_OFF)
4768
0
    {
4769
0
      m_AffineProfList->insert( tmp, cu.Y());
4770
0
    }
4771
0
  }
4772
4773
  // Bi-directional prediction
4774
0
  if (slice.isInterB() && !CU::isBipredRestriction(cu))
4775
0
  {
4776
0
    cu.interDir = 3;
4777
0
    m_isBi = true;
4778
4779
    // Set as best list0 and list1
4780
0
    iRefIdxBi[0] = iRefIdx[0];
4781
0
    iRefIdxBi[1] = iRefIdx[1];
4782
4783
0
    ::memcpy(cMvBi, aacMv, sizeof(aacMv));
4784
0
    ::memcpy(cMvPredBi, cMvPred, sizeof(cMvPred));
4785
0
    ::memcpy(aaiMvpIdxBi, aaiMvpIdx, sizeof(aaiMvpIdx));
4786
4787
0
    uint32_t uiMotBits[2];
4788
0
    bool doBiPred = true;
4789
4790
0
    if (slice.picHeader->mvdL1Zero) // GPB, list 1 only use Mvp
4791
0
    {
4792
0
      xCopyAffineAMVPInfo(aacAffineAMVPInfo[1][bestBiPRefIdxL1], affiAMVPInfoTemp[REF_PIC_LIST_1]);
4793
0
      cu.mvpIdx[REF_PIC_LIST_1] = bestBiPMvpL1;
4794
0
      aaiMvpIdxBi[1][bestBiPRefIdxL1] = bestBiPMvpL1;
4795
4796
      // Set Mv for list1
4797
0
      Mv pcMvTemp[3] = { affiAMVPInfoTemp[REF_PIC_LIST_1].mvCandLT[bestBiPMvpL1],
4798
0
                         affiAMVPInfoTemp[REF_PIC_LIST_1].mvCandRT[bestBiPMvpL1],
4799
0
                         affiAMVPInfoTemp[REF_PIC_LIST_1].mvCandLB[bestBiPMvpL1] };
4800
0
      ::memcpy(cMvPredBi[1][bestBiPRefIdxL1], pcMvTemp, sizeof(Mv) * 3);
4801
0
      ::memcpy(cMvBi[1], pcMvTemp, sizeof(Mv) * 3);
4802
0
      ::memcpy(tmp.affMVs[1][bestBiPRefIdxL1], pcMvTemp, sizeof(Mv) * 3);
4803
0
      iRefIdxBi[1] = bestBiPRefIdxL1;
4804
4805
0
      if( m_pcEncCfg->m_ifpLines && !xIsAffineMvInRangeFPP( cu, pcMvTemp, m_pcEncCfg->m_ifpLines ) )
4806
0
      {
4807
        // this mvp cannot be used for mv, skip Bi-pred
4808
0
        uiCostBi = MAX_DISTORTION;
4809
0
        doBiPred = false;
4810
0
      }
4811
0
      else
4812
0
      {
4813
4814
        // Get list1 prediction block
4815
0
        CU::setAllAffineMv(cu, cMvBi[1][0], cMvBi[1][1], cMvBi[1][2], REF_PIC_LIST_1);
4816
0
        cu.refIdx[REF_PIC_LIST_1] = iRefIdxBi[1];
4817
4818
0
        PelUnitBuf predBufTmp = m_tmpPredStorage[REF_PIC_LIST_1].getCompactBuf( cu );
4819
0
        motionCompensation(cu, predBufTmp, REF_PIC_LIST_1);
4820
4821
        // Update bits
4822
0
        uiMotBits[0] = uiBits[0] - uiMbBits[0];
4823
0
        uiMotBits[1] = uiMbBits[1];
4824
4825
0
        if (slice.numRefIdx[REF_PIC_LIST_1] > 1)
4826
0
        {
4827
0
          uiMotBits[1] += bestBiPRefIdxL1 + 1;
4828
0
          if (bestBiPRefIdxL1 == slice.numRefIdx[REF_PIC_LIST_1] - 1)
4829
0
          {
4830
0
            uiMotBits[1]--;
4831
0
          }
4832
0
        }
4833
0
        uiMotBits[1] += m_auiMVPIdxCost[aaiMvpIdxBi[1][bestBiPRefIdxL1]][AMVP_MAX_NUM_CANDS];
4834
0
        uiBits[2] = uiMbBits[2] + uiMotBits[0] + uiMotBits[1];
4835
0
      }
4836
0
    }
4837
0
    else
4838
0
    {
4839
0
      uiMotBits[0] = uiBits[0] - uiMbBits[0];
4840
0
      uiMotBits[1] = uiBits[1] - uiMbBits[1];
4841
0
      uiBits[2] = uiMbBits[2] + uiMotBits[0] + uiMotBits[1];
4842
0
    }
4843
4844
0
    if (doBiPred)
4845
0
    {
4846
      // 4-times iteration (default)
4847
0
      int iNumIter = 4;
4848
      // fast encoder setting or GPB: only one iteration
4849
0
      if (m_pcEncCfg->m_fastInterSearchMode == VVENC_FASTINTERSEARCH_MODE3 || m_pcEncCfg->m_fastInterSearchMode == VVENC_FASTINTERSEARCH_MODE2 || slice.picHeader->mvdL1Zero)
4850
0
      {
4851
0
        iNumIter = 1;
4852
0
      }
4853
4854
0
      for (int iIter = 0; iIter < iNumIter; iIter++)
4855
0
      {
4856
        // Set RefList
4857
0
        int iRefList = iIter % 2;
4858
0
        if (m_pcEncCfg->m_fastInterSearchMode == VVENC_FASTINTERSEARCH_MODE3 || m_pcEncCfg->m_fastInterSearchMode == VVENC_FASTINTERSEARCH_MODE2)
4859
0
        {
4860
0
          if (uiCost[0] <= uiCost[1])
4861
0
          {
4862
0
            iRefList = 1;
4863
0
          }
4864
0
          else
4865
0
          {
4866
0
            iRefList = 0;
4867
0
          }
4868
0
        }
4869
0
        else if (iIter == 0)
4870
0
        {
4871
0
          iRefList = 0;
4872
0
        }
4873
4874
        // First iterate, get prediction block of opposite direction
4875
0
        if (iIter == 0 && !slice.picHeader->mvdL1Zero)
4876
0
        {
4877
0
          if( m_pcEncCfg->m_ifpLines && !xIsAffineMvInRangeFPP( cu, aacMv[1 - iRefList], m_pcEncCfg->m_ifpLines ) )
4878
0
          {
4879
0
            continue;
4880
0
          }
4881
4882
0
          CU::setAllAffineMv(cu, aacMv[1 - iRefList][0], aacMv[1 - iRefList][1], aacMv[1 - iRefList][2], RefPicList(1 - iRefList));
4883
0
          cu.refIdx[1 - iRefList] = iRefIdx[1 - iRefList];
4884
4885
0
          PelUnitBuf predBufTmp = m_tmpPredStorage[1 - iRefList].getCompactBuf( cu );
4886
0
          motionCompensation(cu, predBufTmp, RefPicList(1 - iRefList));
4887
0
        }
4888
4889
0
        RefPicList refPicList = (iRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0);
4890
4891
0
        if (slice.picHeader->mvdL1Zero) // GPB, fix List 1, search List 0
4892
0
        {
4893
0
          iRefList = 0;
4894
0
          refPicList = REF_PIC_LIST_0;
4895
0
        }
4896
4897
0
        bool bChanged = false;
4898
4899
0
        iRefStart = 0;
4900
0
        iRefEnd = slice.numRefIdx[refPicList] - 1;
4901
0
        for (int iRefIdxTemp = iRefStart; iRefIdxTemp <= iRefEnd; iRefIdxTemp++)
4902
0
        {
4903
0
          if (cu.affineType == AFFINEMODEL_6PARAM && refIdx4Para[iRefList] != iRefIdxTemp)
4904
0
          {
4905
0
            continue;
4906
0
          }
4907
          // update bits
4908
0
          uiBitsTemp = uiMbBits[2] + uiMotBits[1 - iRefList];
4909
0
          uiBitsTemp += ( (cu.slice->sps->BCW == true) ? BcwIdxBits : 0 );
4910
0
          if (slice.numRefIdx[refPicList] > 1)
4911
0
          {
4912
0
            uiBitsTemp += iRefIdxTemp + 1;
4913
0
            if (iRefIdxTemp == slice.numRefIdx[refPicList] - 1)
4914
0
            {
4915
0
              uiBitsTemp--;
4916
0
            }
4917
0
          }
4918
0
          uiBitsTemp += m_auiMVPIdxCost[aaiMvpIdxBi[iRefList][iRefIdxTemp]][AMVP_MAX_NUM_CANDS];
4919
4920
          // call Affine ME
4921
0
          xAffineMotionEstimation(cu, origBuf, refPicList, cMvPredBi[iRefList][iRefIdxTemp], iRefIdxTemp, tmp.affMVs[iRefList][iRefIdxTemp], 
4922
0
                                  uiBitsTemp, uiCostTemp, aaiMvpIdxBi[iRefList][iRefIdxTemp], aacAffineAMVPInfo[iRefList][iRefIdxTemp], true);
4923
0
          xCopyAffineAMVPInfo(aacAffineAMVPInfo[iRefList][iRefIdxTemp], affiAMVPInfoTemp[refPicList]);
4924
0
          if (cu.imv != 2)
4925
0
          {
4926
0
            xCheckBestAffineMVP(cu, affiAMVPInfoTemp[refPicList], refPicList, tmp.affMVs[iRefList][iRefIdxTemp], cMvPredBi[iRefList][iRefIdxTemp], aaiMvpIdxBi[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp);
4927
0
          }
4928
4929
0
          if (uiCostTemp < uiCostBi)
4930
0
          {
4931
0
            bChanged = true;
4932
0
            ::memcpy(cMvBi[iRefList], tmp.affMVs[iRefList][iRefIdxTemp], sizeof(Mv) * 3);
4933
0
            iRefIdxBi[iRefList] = iRefIdxTemp;
4934
4935
0
            uiCostBi = uiCostTemp;
4936
0
            uiMotBits[iRefList] = uiBitsTemp - uiMbBits[2] - uiMotBits[1 - iRefList];
4937
0
            uiMotBits[iRefList] -= ( (cu.slice->sps->BCW == true) ? BcwIdxBits : 0 );
4938
0
            uiBits[2] = uiBitsTemp;
4939
4940
0
            if (iNumIter != 1) // MC for next iter
4941
0
            {
4942
              //  Set motion
4943
0
              CU::setAllAffineMv(cu, cMvBi[iRefList][0], cMvBi[iRefList][1], cMvBi[iRefList][2], refPicList);
4944
0
              cu.refIdx[refPicList] = iRefIdxBi[refPicList];
4945
0
              PelUnitBuf predBufTmp = m_tmpPredStorage[iRefList].getCompactBuf( cu );
4946
0
              motionCompensation(cu, predBufTmp, refPicList);
4947
0
            }
4948
0
          }
4949
0
        } // for loop-iRefIdxTemp
4950
4951
0
        if (!bChanged)
4952
0
        {
4953
0
          if ((uiCostBi <= uiCost[0] && uiCostBi <= uiCost[1]) || enforceBcwPred)
4954
0
          {
4955
0
            xCopyAffineAMVPInfo(aacAffineAMVPInfo[0][iRefIdxBi[0]], affiAMVPInfoTemp[REF_PIC_LIST_0]);
4956
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);
4957
4958
0
            if (!slice.picHeader->mvdL1Zero)
4959
0
            {
4960
0
              xCopyAffineAMVPInfo(aacAffineAMVPInfo[1][iRefIdxBi[1]], affiAMVPInfoTemp[REF_PIC_LIST_1]);
4961
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);
4962
0
            }
4963
0
          }
4964
0
          break;
4965
0
        }
4966
0
      } // for loop-iter
4967
0
    }
4968
0
    m_isBi = false;
4969
0
  } // if (B_SLICE)
4970
4971
0
  cu.mv [REF_PIC_LIST_0][0] = Mv();
4972
0
  cu.mv [REF_PIC_LIST_1][0] = Mv();
4973
0
  cu.mvd[REF_PIC_LIST_0][0] = cMvZero;
4974
0
  cu.mvd[REF_PIC_LIST_1][0] = cMvZero;
4975
0
  cu.refIdx[REF_PIC_LIST_0] = NOT_VALID;
4976
0
  cu.refIdx[REF_PIC_LIST_1] = NOT_VALID;
4977
0
  cu.mvpIdx[REF_PIC_LIST_0] = NOT_VALID;
4978
0
  cu.mvpIdx[REF_PIC_LIST_1] = NOT_VALID;
4979
0
  cu.mvpNum[REF_PIC_LIST_0] = NOT_VALID;
4980
0
  cu.mvpNum[REF_PIC_LIST_1] = NOT_VALID;
4981
4982
0
  for (int verIdx = 0; verIdx < 3; verIdx++)
4983
0
  {
4984
0
    cu.mvd[REF_PIC_LIST_0][verIdx] = cMvZero;
4985
0
    cu.mvd[REF_PIC_LIST_1][verIdx] = cMvZero;
4986
0
  }
4987
4988
  // Set Motion Field
4989
0
  memcpy(aacMv[1], mvValidList1, sizeof(Mv) * 3);
4990
0
  iRefIdx[1] = refIdxValidList1;
4991
0
  uiBits[1] = bitsValidList1;
4992
0
  uiCost[1] = costValidList1;
4993
4994
0
  if (enforceBcwPred)
4995
0
  {
4996
0
    uiCost[0] = uiCost[1] = MAX_UINT;
4997
0
  }
4998
4999
  // Affine ME result set
5000
0
  if (uiCostBi <= uiCost[0] && uiCostBi <= uiCost[1]) // Bi
5001
0
  {
5002
0
    lastMode = 2;
5003
0
    affineCost = uiCostBi;
5004
0
    cu.interDir = 3;
5005
0
    CU::setAllAffineMv(cu, cMvBi[0][0], cMvBi[0][1], cMvBi[0][2], REF_PIC_LIST_0);
5006
0
    CU::setAllAffineMv(cu, cMvBi[1][0], cMvBi[1][1], cMvBi[1][2], REF_PIC_LIST_1);
5007
0
    cu.refIdx[REF_PIC_LIST_0] = iRefIdxBi[0];
5008
0
    cu.refIdx[REF_PIC_LIST_1] = iRefIdxBi[1];
5009
5010
0
    for (int verIdx = 0; verIdx < mvNum; verIdx++)
5011
0
    {
5012
0
      cu.mvd[REF_PIC_LIST_0][verIdx] = cMvBi[0][verIdx] - cMvPredBi[0][iRefIdxBi[0]][verIdx];
5013
0
      cu.mvd[REF_PIC_LIST_1][verIdx] = cMvBi[1][verIdx] - cMvPredBi[1][iRefIdxBi[1]][verIdx];
5014
0
      if (verIdx != 0)
5015
0
      {
5016
0
        cu.mvd[0][verIdx] = cu.mvd[0][verIdx] - cu.mvd[0][0];
5017
0
        cu.mvd[1][verIdx] = cu.mvd[1][verIdx] - cu.mvd[1][0];
5018
0
      }
5019
0
    }
5020
5021
5022
0
    cu.mvpIdx[REF_PIC_LIST_0] = aaiMvpIdxBi[0][iRefIdxBi[0]];
5023
0
    cu.mvpNum[REF_PIC_LIST_0] = aaiMvpNum[0][iRefIdxBi[0]];
5024
0
    cu.mvpIdx[REF_PIC_LIST_1] = aaiMvpIdxBi[1][iRefIdxBi[1]];
5025
0
    cu.mvpNum[REF_PIC_LIST_1] = aaiMvpNum[1][iRefIdxBi[1]];
5026
0
  }
5027
0
  else if (uiCost[0] <= uiCost[1]) // List 0
5028
0
  {
5029
0
    lastMode = 0;
5030
0
    affineCost = uiCost[0];
5031
0
    cu.interDir = 1;
5032
0
    CU::setAllAffineMv(cu, aacMv[0][0], aacMv[0][1], aacMv[0][2], REF_PIC_LIST_0);
5033
0
    cu.refIdx[REF_PIC_LIST_0] = iRefIdx[0];
5034
5035
0
    for (int verIdx = 0; verIdx < mvNum; verIdx++)
5036
0
    {
5037
0
      cu.mvd[REF_PIC_LIST_0][verIdx] = aacMv[0][verIdx] - cMvPred[0][iRefIdx[0]][verIdx];
5038
0
      if (verIdx != 0)
5039
0
      {
5040
0
        cu.mvd[0][verIdx] = cu.mvd[0][verIdx] - cu.mvd[0][0];
5041
0
      }
5042
0
    }
5043
5044
0
    cu.mvpIdx[REF_PIC_LIST_0] = aaiMvpIdx[0][iRefIdx[0]];
5045
0
    cu.mvpNum[REF_PIC_LIST_0] = aaiMvpNum[0][iRefIdx[0]];
5046
0
  }
5047
0
  else
5048
0
  {
5049
0
    lastMode = 1;
5050
0
    affineCost = uiCost[1];
5051
0
    cu.interDir = 2;
5052
0
    CU::setAllAffineMv(cu, aacMv[1][0], aacMv[1][1], aacMv[1][2], REF_PIC_LIST_1);
5053
0
    cu.refIdx[REF_PIC_LIST_1] = iRefIdx[1];
5054
5055
0
    for (int verIdx = 0; verIdx < mvNum; verIdx++)
5056
0
    {
5057
0
      cu.mvd[REF_PIC_LIST_1][verIdx] = aacMv[1][verIdx] - cMvPred[1][iRefIdx[1]][verIdx];
5058
0
      if (verIdx != 0)
5059
0
      {
5060
0
        cu.mvd[1][verIdx] = cu.mvd[1][verIdx] - cu.mvd[1][0];
5061
0
      }
5062
0
    }
5063
5064
0
    cu.mvpIdx[REF_PIC_LIST_1] = aaiMvpIdx[1][iRefIdx[1]];
5065
0
    cu.mvpNum[REF_PIC_LIST_1] = aaiMvpNum[1][iRefIdx[1]];
5066
0
  }
5067
0
  if (BcwIdx != BCW_DEFAULT)
5068
0
  {
5069
0
    cu.BcwIdx = BCW_DEFAULT;
5070
0
  }
5071
0
}
5072
5073
Distortion InterSearch::xGetAffineTemplateCost(CodingUnit& cu, CPelUnitBuf& origBuf, PelUnitBuf& predBuf, Mv acMvCand[3], int iMVPIdx, int iMVPNum, RefPicList refPicList, int iRefIdx)
5074
0
{
5075
0
  Distortion uiCost = MAX_DISTORTION;
5076
5077
0
  const Picture* picRef = cu.slice->getRefPic(refPicList, iRefIdx);
5078
5079
  // prediction pattern
5080
0
  Mv mv[3];
5081
0
  memcpy(mv, acMvCand, sizeof(mv));
5082
5083
0
  if( m_pcEncCfg->m_ifpLines && !xIsAffineMvInRangeFPP( cu, mv, m_pcEncCfg->m_ifpLines ) )
5084
0
  {
5085
0
    return MAX_DISTORTION>>1;  
5086
0
  }
5087
5088
0
  xPredAffineBlk(COMP_Y, cu, picRef, mv, predBuf, false, cu.slice->clpRngs[COMP_Y], refPicList);
5089
5090
  // calc distortion
5091
0
  uiCost = m_pcRdCost->getDistPart(origBuf.Y(), predBuf.Y(), cu.cs->sps->bitDepths[CH_L], COMP_Y, DF_HAD );
5092
0
  uiCost += m_pcRdCost->getCost(m_auiMVPIdxCost[iMVPIdx][iMVPNum]);
5093
5094
0
  DTRACE(g_trace_ctx, D_COMMON, " (%d) affineTemplateCost=%d\n", DTRACE_GET_COUNTER(g_trace_ctx, D_COMMON), uiCost);
5095
0
  return uiCost;
5096
0
}
5097
5098
void solveEqual(double** dEqualCoeff, int iOrder, double* dAffinePara)
5099
0
{
5100
0
  for (int k = 0; k < iOrder; k++)
5101
0
  {
5102
0
    dAffinePara[k] = 0.;
5103
0
  }
5104
5105
  // row echelon
5106
0
  for (int i = 1; i < iOrder; i++)
5107
0
  {
5108
    // find column max
5109
0
    double temp = fabs(dEqualCoeff[i][i - 1]);
5110
0
    int tempIdx = i;
5111
0
    for (int j = i + 1; j < iOrder + 1; j++)
5112
0
    {
5113
0
      if (fabs(dEqualCoeff[j][i - 1]) > temp)
5114
0
      {
5115
0
        temp = fabs(dEqualCoeff[j][i - 1]);
5116
0
        tempIdx = j;
5117
0
      }
5118
0
    }
5119
5120
    // swap line
5121
0
    if (tempIdx != i)
5122
0
    {
5123
0
      for (int j = 0; j < iOrder + 1; j++)
5124
0
      {
5125
0
        dEqualCoeff[0][j] = dEqualCoeff[i][j];
5126
0
        dEqualCoeff[i][j] = dEqualCoeff[tempIdx][j];
5127
0
        dEqualCoeff[tempIdx][j] = dEqualCoeff[0][j];
5128
0
      }
5129
0
    }
5130
5131
    // elimination first column
5132
0
    if (dEqualCoeff[i][i - 1] == 0.)
5133
0
    {
5134
0
      return;
5135
0
    }
5136
0
    for (int j = i + 1; j < iOrder + 1; j++)
5137
0
    {
5138
0
      for (int k = i; k < iOrder + 1; k++)
5139
0
      {
5140
0
        dEqualCoeff[j][k] = dEqualCoeff[j][k] - dEqualCoeff[i][k] * dEqualCoeff[j][i - 1] / dEqualCoeff[i][i - 1];
5141
0
      }
5142
0
    }
5143
0
  }
5144
5145
0
  if (dEqualCoeff[iOrder][iOrder - 1] == 0.)
5146
0
  {
5147
0
    return;
5148
0
  }
5149
0
  dAffinePara[iOrder - 1] = dEqualCoeff[iOrder][iOrder] / dEqualCoeff[iOrder][iOrder - 1];
5150
0
  for (int i = iOrder - 2; i >= 0; i--)
5151
0
  {
5152
0
    if (dEqualCoeff[i + 1][i] == 0.)
5153
0
    {
5154
0
      for (int k = 0; k < iOrder; k++)
5155
0
      {
5156
0
        dAffinePara[k] = 0.;
5157
0
      }
5158
0
      return;
5159
0
    }
5160
0
    double temp = 0;
5161
0
    for (int j = i + 1; j < iOrder; j++)
5162
0
    {
5163
0
      temp += dEqualCoeff[i + 1][j] * dAffinePara[j];
5164
0
    }
5165
0
    dAffinePara[i] = (dEqualCoeff[i + 1][iOrder] - temp) / dEqualCoeff[i + 1][i];
5166
0
  }
5167
0
}
5168
5169
void InterSearch::xCheckBestAffineMVP(CodingUnit& cu, AffineAMVPInfo &affineAMVPInfo, RefPicList refPicList, Mv acMv[3], Mv acMvPred[3], int& riMVPIdx, uint32_t& ruiBits, Distortion& ruiCost)
5170
0
{
5171
0
  if (affineAMVPInfo.numCand < 2)
5172
0
  {
5173
0
    return;
5174
0
  }
5175
5176
0
  int mvNum = cu.affineType ? 3 : 2;
5177
5178
0
  m_pcRdCost->selectMotionLambda();
5179
0
  m_pcRdCost->setCostScale(0);
5180
5181
0
  int iBestMVPIdx = riMVPIdx;
5182
5183
  // Get origin MV bits
5184
0
  Mv tmpPredMv[3];
5185
0
  int iOrgMvBits = xCalcAffineMVBits(cu, acMv, acMvPred);
5186
0
  iOrgMvBits += m_auiMVPIdxCost[riMVPIdx][AMVP_MAX_NUM_CANDS];
5187
5188
0
  int iBestMvBits = iOrgMvBits;
5189
0
  for (int iMVPIdx = 0; iMVPIdx < affineAMVPInfo.numCand; iMVPIdx++)
5190
0
  {
5191
0
    if (iMVPIdx == riMVPIdx)
5192
0
    {
5193
0
      continue;
5194
0
    }
5195
0
    tmpPredMv[0] = affineAMVPInfo.mvCandLT[iMVPIdx];
5196
0
    tmpPredMv[1] = affineAMVPInfo.mvCandRT[iMVPIdx];
5197
0
    if (mvNum == 3)
5198
0
    {
5199
0
      tmpPredMv[2] = affineAMVPInfo.mvCandLB[iMVPIdx];
5200
0
    }
5201
0
    int iMvBits = xCalcAffineMVBits(cu, acMv, tmpPredMv);
5202
0
    iMvBits += m_auiMVPIdxCost[iMVPIdx][AMVP_MAX_NUM_CANDS];
5203
5204
0
    if (iMvBits < iBestMvBits)
5205
0
    {
5206
0
      iBestMvBits = iMvBits;
5207
0
      iBestMVPIdx = iMVPIdx;
5208
0
    }
5209
0
  }
5210
5211
0
  if (iBestMVPIdx != riMVPIdx)  // if changed
5212
0
  {
5213
0
    acMvPred[0] = affineAMVPInfo.mvCandLT[iBestMVPIdx];
5214
0
    acMvPred[1] = affineAMVPInfo.mvCandRT[iBestMVPIdx];
5215
0
    acMvPred[2] = affineAMVPInfo.mvCandLB[iBestMVPIdx];
5216
0
    riMVPIdx = iBestMVPIdx;
5217
0
    uint32_t uiOrgBits = ruiBits;
5218
0
    ruiBits = uiOrgBits - iOrgMvBits + iBestMvBits;
5219
0
    ruiCost = (ruiCost - m_pcRdCost->getCost(uiOrgBits)) + m_pcRdCost->getCost(ruiBits);
5220
0
  }
5221
0
}
5222
5223
void InterSearch::xAffineMotionEstimation(CodingUnit& cu,
5224
  CPelUnitBuf&    origBuf,
5225
  RefPicList      refPicList,
5226
  Mv              acMvPred[3],
5227
  int             iRefIdxPred,
5228
  Mv              acMv[3],
5229
  uint32_t&       ruiBits,
5230
  Distortion&     ruiCost,
5231
  int&            mvpIdx,
5232
  const AffineAMVPInfo& aamvpi,
5233
  bool            bBi)
5234
0
{
5235
0
  if( cu.cs->sps->BCW && cu.BcwIdx != BCW_DEFAULT && !bBi && xReadBufferedAffineUniMv( cu, refPicList, iRefIdxPred, acMvPred, acMv, ruiBits, ruiCost, mvpIdx, aamvpi ) )
5236
0
  {
5237
0
    return;
5238
0
  }
5239
5240
0
  int bestMvpIdx = mvpIdx;
5241
0
  const int width = cu.Y().width;
5242
0
  const int height = cu.Y().height;
5243
5244
0
  const Picture* refPic = cu.slice->getRefPic(refPicList, iRefIdxPred);
5245
5246
  // Set Origin YUV: pcYuv
5247
0
  CPelUnitBuf*   pBuf = &origBuf;
5248
0
  double        fWeight = 1.0;
5249
5250
0
  CPelUnitBuf  origBufTmpCnst;
5251
5252
  // if Bi, set to ( 2 * Org - ListX )
5253
0
  if (bBi)
5254
0
  {
5255
0
    PelUnitBuf  origBufTmp = m_tmpStorageLCU.getCompactBuf(cu);
5256
    // NOTE: Other buf contains predicted signal from another direction
5257
0
    PelUnitBuf otherBuf = m_tmpPredStorage[1 - (int)refPicList].getCompactBuf( cu );
5258
0
    origBufTmp.copyFrom(origBuf);
5259
0
    origBufTmp.removeHighFreq(otherBuf, m_pcEncCfg->m_bClipForBiPredMeEnabled, cu.slice->clpRngs);
5260
5261
0
    origBufTmpCnst = origBufTmp;
5262
0
    pBuf           = &origBufTmpCnst;
5263
0
    fWeight        = xGetMEDistortionWeight(cu.BcwIdx, refPicList);
5264
0
  }
5265
5266
  // pred YUV
5267
0
  PelUnitBuf  predBuf = m_tmpAffiStorage.getCompactBuf(cu);
5268
5269
  // Set start Mv position, use input mv as started search mv
5270
0
  Mv acMvTemp[3];
5271
0
  ::memcpy(acMvTemp, acMv, sizeof(Mv) * 3);
5272
  // Set delta mv
5273
  // malloc buffer
5274
0
  int iParaNum = cu.affineType ? 7 : 5;
5275
0
  int affineParaNum = iParaNum - 1;
5276
0
  int mvNum = cu.affineType ? 3 : 2;
5277
0
  double **pdEqualCoeff;
5278
0
  pdEqualCoeff = new double *[iParaNum];
5279
0
  for (int i = 0; i < iParaNum; i++)
5280
0
  {
5281
0
    pdEqualCoeff[i] = new double[iParaNum];
5282
0
  }
5283
5284
0
  int64_t  i64EqualCoeff[7][7];
5285
0
  Pel    *piError = m_tmpAffiError;
5286
0
  Pel    *pdDerivate[2];
5287
0
  pdDerivate[0] = m_tmpAffiDeri[0];
5288
0
  pdDerivate[1] = m_tmpAffiDeri[1];
5289
5290
0
  Distortion uiCostBest = MAX_DISTORTION;
5291
0
  uint32_t uiBitsBest = 0;
5292
5293
  // do motion compensation with origin mv
5294
5295
0
  clipMv(acMvTemp[0], cu.lumaPos(), cu.lumaSize(), *cu.cs->pcv);
5296
0
  clipMv(acMvTemp[1], cu.lumaPos(), cu.lumaSize(), *cu.cs->pcv);
5297
0
  if (cu.affineType == AFFINEMODEL_6PARAM)
5298
0
  {
5299
0
    clipMv(acMvTemp[2], cu.lumaPos(), cu.lumaSize(), *cu.cs->pcv);
5300
0
  }
5301
5302
0
  acMvTemp[0].roundAffinePrecInternal2Amvr(cu.imv);
5303
0
  acMvTemp[1].roundAffinePrecInternal2Amvr(cu.imv);
5304
0
  if (cu.affineType == AFFINEMODEL_6PARAM)
5305
0
  {
5306
0
    acMvTemp[2].roundAffinePrecInternal2Amvr(cu.imv);
5307
0
  }
5308
0
  if( !m_pcEncCfg->m_ifpLines || xIsAffineMvInRangeFPP( cu, acMvTemp, m_pcEncCfg->m_ifpLines ) )
5309
0
  {
5310
0
    xPredAffineBlk(COMP_Y, cu, refPic, acMvTemp, predBuf, false, cu.cs->slice->clpRngs[COMP_Y], refPicList);
5311
5312
    // get error
5313
0
    uiCostBest = m_pcRdCost->getDistPart(predBuf.Y(), pBuf->Y(), cu.cs->sps->bitDepths[CH_L], COMP_Y, DF_HAD);
5314
5315
    // get cost with mv
5316
0
    m_pcRdCost->setCostScale(0);
5317
0
    uiBitsBest = ruiBits;
5318
0
    DTRACE(g_trace_ctx, D_COMMON, " (%d) xx uiBitsBest=%d\n", DTRACE_GET_COUNTER(g_trace_ctx, D_COMMON), uiBitsBest);
5319
0
    uiBitsBest += xCalcAffineMVBits(cu, acMvTemp, acMvPred);
5320
0
    DTRACE(g_trace_ctx, D_COMMON, " (%d) yy uiBitsBest=%d\n", DTRACE_GET_COUNTER(g_trace_ctx, D_COMMON), uiBitsBest);
5321
0
    uiCostBest = (Distortion)(floor(fWeight * (double)uiCostBest) + (double)m_pcRdCost->getCost(uiBitsBest));
5322
5323
0
    DTRACE(g_trace_ctx, D_COMMON, " (%d) uiBitsBest=%d, uiCostBest=%d\n", DTRACE_GET_COUNTER(g_trace_ctx, D_COMMON), uiBitsBest, uiCostBest);
5324
5325
0
    ::memcpy(acMv, acMvTemp, sizeof(Mv) * 3);
5326
0
  }
5327
0
  const int predBufStride = predBuf.Y().stride;
5328
0
  Mv prevIterMv[7][3];
5329
0
  int iIterTime;
5330
0
  if (cu.affineType == AFFINEMODEL_6PARAM)
5331
0
  {
5332
0
    iIterTime = bBi ? 3 : 4;
5333
0
  }
5334
0
  else
5335
0
  {
5336
0
    iIterTime = bBi ? 3 : 5;
5337
0
  }
5338
5339
0
  if (!cu.cs->sps->AffineType)// getUseAffineType())
5340
0
  {
5341
0
    iIterTime = bBi ? 5 : 7;
5342
0
  }
5343
5344
0
  for (int iter = 0; iter<iIterTime; iter++)    // iterate loop
5345
0
  {
5346
0
    memcpy(prevIterMv[iter], acMvTemp, sizeof(Mv) * 3);
5347
    /*********************************************************************************
5348
    *                         use gradient to update mv
5349
    *********************************************************************************/
5350
    // get Error Matrix
5351
0
    PelBuf( piError, width, height ).subtract( pBuf->Y(), predBuf.Y() );
5352
5353
    // sobel x direction
5354
    // -1 0 1
5355
    // -2 0 2
5356
    // -1 0 1
5357
0
    Pel* pPred = predBuf.Y().buf;
5358
0
    m_HorizontalSobelFilter(pPred, predBufStride, pdDerivate[0], width, width, height);
5359
5360
    // sobel y direction
5361
    // -1 -2 -1
5362
    //  0  0  0
5363
    //  1  2  1
5364
0
    m_VerticalSobelFilter(pPred, predBufStride, pdDerivate[1], width, width, height);
5365
5366
    // solve delta x and y
5367
0
    for (int row = 0; row < iParaNum; row++)
5368
0
    {
5369
0
      memset(&i64EqualCoeff[row][0], 0, iParaNum * sizeof(int64_t));
5370
0
    }
5371
5372
0
    m_EqualCoeffComputer[cu.affineType]( piError, width, pdDerivate, width, width, height, i64EqualCoeff );
5373
5374
0
    for (int row = 0; row < iParaNum; row++)
5375
0
    {
5376
0
      for (int i = 0; i < iParaNum; i++)
5377
0
      {
5378
0
        pdEqualCoeff[row][i] = (double)i64EqualCoeff[row][i];
5379
0
      }
5380
0
    }
5381
5382
0
    double dAffinePara[6];
5383
0
    double dDeltaMv[6];
5384
0
    Mv acDeltaMv[3];
5385
5386
0
    solveEqual(pdEqualCoeff, affineParaNum, dAffinePara);
5387
5388
    // convert to delta mv
5389
0
    dDeltaMv[0] = dAffinePara[0];
5390
0
    dDeltaMv[2] = dAffinePara[2];
5391
0
    const bool extParams = cu.affineType == AFFINEMODEL_6PARAM;
5392
0
    if (extParams)
5393
0
    {
5394
0
      dDeltaMv[1] = dAffinePara[1] * width + dAffinePara[0];
5395
0
      dDeltaMv[3] = dAffinePara[3] * width + dAffinePara[2];
5396
0
      dDeltaMv[4] = dAffinePara[4] * height + dAffinePara[0];
5397
0
      dDeltaMv[5] = dAffinePara[5] * height + dAffinePara[2];
5398
0
    }
5399
0
    else
5400
0
    {
5401
0
      dDeltaMv[1] = dAffinePara[1] * width + dAffinePara[0];
5402
0
      dDeltaMv[3] = -dAffinePara[3] * width + dAffinePara[2];
5403
0
    }
5404
5405
0
    const int normShiftTab[3] = { MV_PRECISION_QUARTER - MV_PRECISION_INT, MV_PRECISION_SIXTEENTH - MV_PRECISION_INT, MV_PRECISION_QUARTER - MV_PRECISION_INT };
5406
0
    const int stepShiftTab[3] = { MV_PRECISION_INTERNAL - MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL - MV_PRECISION_SIXTEENTH, MV_PRECISION_INTERNAL - MV_PRECISION_QUARTER };
5407
0
    const int multiShift = 1 << normShiftTab[cu.imv];
5408
0
    const int mvShift = stepShiftTab[cu.imv];
5409
5410
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));
5411
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));
5412
0
    if (extParams)
5413
0
    {
5414
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));
5415
0
    }
5416
0
    bool bAllZero = false;
5417
0
    for (int i = 0; i < mvNum; i++)
5418
0
    {
5419
0
      Mv deltaMv = acDeltaMv[i];
5420
0
      if (cu.imv == IMV_4PEL)
5421
0
      {
5422
0
        deltaMv.roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_HALF);
5423
0
      }
5424
0
      if (deltaMv.hor != 0 || deltaMv.ver != 0)
5425
0
      {
5426
0
        bAllZero = false;
5427
0
        break;
5428
0
      }
5429
0
      bAllZero = true;
5430
0
    }
5431
5432
0
    if (bAllZero)
5433
0
      break;
5434
5435
    // do motion compensation with updated mv
5436
0
    for (int i = 0; i < mvNum; i++)
5437
0
    {
5438
0
      acMvTemp[i] += acDeltaMv[i];
5439
0
      acMvTemp[i].hor = Clip3(MV_MIN, MV_MAX, acMvTemp[i].hor);
5440
0
      acMvTemp[i].ver = Clip3(MV_MIN, MV_MAX, acMvTemp[i].ver);
5441
0
      acMvTemp[i].roundAffinePrecInternal2Amvr(cu.imv);
5442
5443
0
      clipMv(acMvTemp[i], cu.lumaPos(), cu.lumaSize(), *cu.cs->pcv);
5444
0
    }
5445
5446
0
    if( !m_pcEncCfg->m_ifpLines || xIsAffineMvInRangeFPP( cu, acMvTemp, m_pcEncCfg->m_ifpLines ) )
5447
0
    {
5448
0
      xPredAffineBlk(COMP_Y, cu, refPic, acMvTemp, predBuf, false, cu.slice->clpRngs[COMP_Y], refPicList);
5449
5450
      // get error
5451
0
      Distortion uiCostTemp = m_pcRdCost->getDistPart(predBuf.Y(), pBuf->Y(), cu.cs->sps->bitDepths[CH_L], COMP_Y, DF_HAD);
5452
0
      DTRACE(g_trace_ctx, D_COMMON, " (%d) uiCostTemp=%d\n", DTRACE_GET_COUNTER(g_trace_ctx, D_COMMON), uiCostTemp);
5453
5454
      // get cost with mv
5455
0
      m_pcRdCost->setCostScale(0);
5456
0
      uint32_t uiBitsTemp = ruiBits;
5457
0
      uiBitsTemp += xCalcAffineMVBits(cu, acMvTemp, acMvPred);
5458
0
      uiCostTemp = (Distortion)(floor(fWeight * (double)uiCostTemp) + (double)m_pcRdCost->getCost(uiBitsTemp));
5459
5460
      // store best cost and mv
5461
0
      if (uiCostTemp < uiCostBest)
5462
0
      {
5463
0
        uiCostBest = uiCostTemp;
5464
0
        uiBitsBest = uiBitsTemp;
5465
0
        memcpy(acMv, acMvTemp, sizeof(Mv) * 3);
5466
0
        mvpIdx = bestMvpIdx;
5467
0
      }
5468
0
      else if(m_pcEncCfg->m_Affine > 1)
5469
0
      {
5470
0
        break;
5471
0
      }
5472
0
    }
5473
0
  }
5474
5475
0
  auto checkCPMVRdCost = [&](Mv ctrlPtMv[3])
5476
0
  {
5477
0
    if( !m_pcEncCfg->m_ifpLines || xIsAffineMvInRangeFPP( cu, ctrlPtMv, m_pcEncCfg->m_ifpLines ) )
5478
0
    {
5479
0
      xPredAffineBlk(COMP_Y, cu, refPic, ctrlPtMv, predBuf, false, cu.slice->clpRngs[COMP_Y], refPicList);
5480
      // get error
5481
0
      Distortion costTemp = m_pcRdCost->getDistPart(predBuf.Y(), pBuf->Y(), cu.cs->sps->bitDepths[CH_L], COMP_Y, DF_HAD);
5482
      // get cost with mv
5483
0
      m_pcRdCost->setCostScale(0);
5484
0
      uint32_t bitsTemp = ruiBits;
5485
0
      bitsTemp += xCalcAffineMVBits(cu, ctrlPtMv, acMvPred);
5486
0
      costTemp = (Distortion)(floor(fWeight * (double)costTemp) + (double)m_pcRdCost->getCost(bitsTemp));
5487
      // store best cost and mv
5488
0
      if (costTemp < uiCostBest)
5489
0
      {
5490
0
        uiCostBest = costTemp;
5491
0
        uiBitsBest = bitsTemp;
5492
0
        ::memcpy(acMv, ctrlPtMv, sizeof(Mv) * 3);
5493
0
      }
5494
0
    }
5495
0
  };
5496
5497
0
  const uint32_t mvShiftTable[3] = { MV_PRECISION_INTERNAL - MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL - MV_PRECISION_INTERNAL, MV_PRECISION_INTERNAL - MV_PRECISION_INT };
5498
0
  const uint32_t mvShift = mvShiftTable[cu.imv];
5499
0
  if (uiCostBest <= AFFINE_ME_LIST_MVP_TH*m_hevcCost)
5500
0
  {
5501
0
    Mv mvPredTmp[3] = { acMvPred[0], acMvPred[1], acMvPred[2] };
5502
0
    Mv mvME[3];
5503
0
    ::memcpy(mvME, acMv, sizeof(Mv) * 3);
5504
0
    Mv dMv = mvME[0] - mvPredTmp[0];
5505
5506
0
    for (int j = 0; j < mvNum; j++)
5507
0
    {
5508
0
      if ((!j && mvME[j] != mvPredTmp[j]) || (j && mvME[j] != (mvPredTmp[j] + dMv)))
5509
0
      {
5510
0
        ::memcpy(acMvTemp, mvME, sizeof(Mv) * 3);
5511
0
        acMvTemp[j] = mvPredTmp[j];
5512
5513
0
        if (j)
5514
0
          acMvTemp[j] += dMv;
5515
5516
0
        checkCPMVRdCost(acMvTemp);
5517
0
      }
5518
0
    }
5519
5520
    //keep the rotation/zoom;
5521
0
    if (mvME[0] != mvPredTmp[0])
5522
0
    {
5523
0
      ::memcpy(acMvTemp, mvME, sizeof(Mv) * 3);
5524
0
      for (int i = 1; i < mvNum; i++)
5525
0
      {
5526
0
        acMvTemp[i] -= dMv;
5527
0
      }
5528
0
      acMvTemp[0] = mvPredTmp[0];
5529
5530
0
      checkCPMVRdCost(acMvTemp);
5531
0
    }
5532
5533
    //keep the translation;
5534
0
    if (cu.affineType == AFFINEMODEL_6PARAM && mvME[1] != (mvPredTmp[1] + dMv) && mvME[2] != (mvPredTmp[2] + dMv))
5535
0
    {
5536
0
      ::memcpy(acMvTemp, mvME, sizeof(Mv) * 3);
5537
5538
0
      acMvTemp[1] = mvPredTmp[1] + dMv;
5539
0
      acMvTemp[2] = mvPredTmp[2] + dMv;
5540
5541
0
      checkCPMVRdCost(acMvTemp);
5542
0
    }
5543
5544
    // 8 nearest neighbor search
5545
0
    int testPos[8][2] = { { -1, 0 },{ 0, -1 },{ 0, 1 },{ 1, 0 },{ -1, -1 },{ -1, 1 },{ 1, 1 },{ 1, -1 } };
5546
0
    const int maxSearchRound = 3;
5547
5548
0
    for (int rnd = 0; rnd < maxSearchRound; rnd++)
5549
0
    {
5550
0
      bool modelChange = false;
5551
      //search the model parameters with finear granularity;
5552
0
      for (int j = 0; j < mvNum; j++)
5553
0
      {
5554
0
        bool loopChange = false;
5555
0
        for (int iter = 0; iter < 2; iter++)
5556
0
        {
5557
0
          if (iter == 1 && !loopChange)
5558
0
          {
5559
0
            break;
5560
0
          }
5561
0
          Mv centerMv[3];
5562
0
          memcpy(centerMv, acMv, sizeof(Mv) * 3);
5563
0
          memcpy(acMvTemp, acMv, sizeof(Mv) * 3);
5564
5565
0
          for (int i = ((iter == 0) ? 0 : 4); i < ((iter == 0) ? 4 : 8); i++)
5566
0
          {
5567
0
            acMvTemp[j].set(centerMv[j].hor + (testPos[i][0] * (1 << mvShift)), centerMv[j].ver + (testPos[i][1] * (1 << mvShift)));
5568
0
            clipMv(acMvTemp[j], cu.lumaPos(), cu.lumaSize(), *cu.cs->pcv);
5569
5570
0
            if( !m_pcEncCfg->m_ifpLines || xIsAffineMvInRangeFPP( cu, acMvTemp, m_pcEncCfg->m_ifpLines ) )
5571
0
            {
5572
0
              xPredAffineBlk(COMP_Y, cu, refPic, acMvTemp, predBuf, false, cu.slice->clpRngs[COMP_Y], refPicList);
5573
5574
0
              Distortion costTemp = m_pcRdCost->getDistPart(predBuf.Y(), pBuf->Y(), cu.cs->sps->bitDepths[CH_L], COMP_Y, DF_HAD);
5575
0
              uint32_t bitsTemp = ruiBits;
5576
0
              bitsTemp += xCalcAffineMVBits(cu, acMvTemp, acMvPred);
5577
0
              costTemp = (Distortion)(floor(fWeight * (double)costTemp) + (double)m_pcRdCost->getCost(bitsTemp));
5578
5579
0
              if (costTemp < uiCostBest)
5580
0
              {
5581
0
                uiCostBest = costTemp;
5582
0
                uiBitsBest = bitsTemp;
5583
0
                ::memcpy(acMv, acMvTemp, sizeof(Mv) * 3);
5584
0
                modelChange = true;
5585
0
                loopChange = true;
5586
0
              }
5587
0
            }
5588
0
          }
5589
0
        }
5590
0
      }
5591
5592
0
      if (!modelChange)
5593
0
      {
5594
0
        break;
5595
0
      }
5596
0
    }
5597
0
  }
5598
0
  acMvPred[0] = aamvpi.mvCandLT[mvpIdx];
5599
0
  acMvPred[1] = aamvpi.mvCandRT[mvpIdx];
5600
0
  acMvPred[2] = aamvpi.mvCandLB[mvpIdx];
5601
5602
  // free buffer
5603
0
  for (int i = 0; i<iParaNum; i++)
5604
0
    delete[]pdEqualCoeff[i];
5605
0
  delete[]pdEqualCoeff;
5606
5607
0
  ruiBits = uiBitsBest;
5608
0
  ruiCost = uiCostBest;
5609
0
  DTRACE(g_trace_ctx, D_COMMON, " (%d) uiBitsBest=%d, uiCostBest=%d\n", DTRACE_GET_COUNTER(g_trace_ctx, D_COMMON), uiBitsBest, uiCostBest);
5610
0
}
5611
5612
bool InterSearch::xEstimateAffineAMVP(CodingUnit& cu, AffineAMVPInfo& affineAMVPInfo, CPelUnitBuf& origBuf, RefPicList refPicList, int iRefIdx, Mv acMvPred[3], Distortion& distBiP)
5613
0
{
5614
0
  Mv         bestMvLT, bestMvRT, bestMvLB;
5615
0
  int        iBestIdx = 0;
5616
0
  Distortion uiBestCost = MAX_DISTORTION;
5617
5618
  // Fill the MV Candidates
5619
0
  CU::fillAffineMvpCand(cu, refPicList, iRefIdx, affineAMVPInfo);
5620
0
  CHECK(affineAMVPInfo.numCand == 0, "Assertion failed.");
5621
5622
0
  PelUnitBuf predBuf = m_tmpStorageLCU.getCompactBuf( cu );
5623
5624
0
  bool stop_check = false;
5625
0
  if (affineAMVPInfo.mvCandLT[0] == affineAMVPInfo.mvCandLT[1])
5626
0
  {
5627
0
    if ((affineAMVPInfo.mvCandRT[0] == affineAMVPInfo.mvCandRT[1]) && (affineAMVPInfo.mvCandLB[0] == affineAMVPInfo.mvCandLB[1]))
5628
0
    {
5629
0
      stop_check = true;
5630
0
    }
5631
0
  }
5632
5633
  // initialize Mvp index & Mvp
5634
0
  iBestIdx = -1;
5635
0
  for (int i = 0; i < affineAMVPInfo.numCand; i++)
5636
0
  {
5637
0
    if (i && stop_check)
5638
0
    {
5639
0
      continue;
5640
0
    }
5641
0
    Mv mv[3] = { affineAMVPInfo.mvCandLT[i], affineAMVPInfo.mvCandRT[i], affineAMVPInfo.mvCandLB[i] };
5642
0
    Distortion uiTmpCost = xGetAffineTemplateCost(cu, origBuf, predBuf, mv, i, AMVP_MAX_NUM_CANDS, refPicList, iRefIdx);
5643
5644
0
    if (uiBestCost > uiTmpCost)
5645
0
    {
5646
0
      uiBestCost = uiTmpCost;
5647
0
      bestMvLT = affineAMVPInfo.mvCandLT[i];
5648
0
      bestMvRT = affineAMVPInfo.mvCandRT[i];
5649
0
      bestMvLB = affineAMVPInfo.mvCandLB[i];
5650
0
      iBestIdx = i;
5651
0
      distBiP  = uiTmpCost;
5652
0
    }
5653
0
  }
5654
5655
0
  if( iBestIdx < 0 )
5656
0
    return false;
5657
5658
  // Setting Best MVP
5659
0
  acMvPred[0] = bestMvLT;
5660
0
  acMvPred[1] = bestMvRT;
5661
0
  acMvPred[2] = bestMvLB;
5662
5663
0
  cu.mvpIdx[refPicList] = iBestIdx;
5664
0
  cu.mvpNum[refPicList] = affineAMVPInfo.numCand;
5665
0
  DTRACE(g_trace_ctx, D_COMMON, "#estAffi=%d \n", affineAMVPInfo.numCand);
5666
0
  return true;
5667
0
}
5668
5669
void InterSearch::xCopyAffineAMVPInfo(AffineAMVPInfo& src, AffineAMVPInfo& dst)
5670
0
{
5671
0
  dst.numCand = src.numCand;
5672
0
  DTRACE(g_trace_ctx, D_COMMON, " (%d) #copyAffi=%d \n", DTRACE_GET_COUNTER(g_trace_ctx, D_COMMON), src.numCand);
5673
0
  ::memcpy(dst.mvCandLT, src.mvCandLT, sizeof(Mv)*src.numCand);
5674
0
  ::memcpy(dst.mvCandRT, src.mvCandRT, sizeof(Mv)*src.numCand);
5675
0
  ::memcpy(dst.mvCandLB, src.mvCandLB, sizeof(Mv)*src.numCand);
5676
0
}
5677
5678
uint32_t InterSearch::xCalcAffineMVBits(CodingUnit& cu, Mv acMvTemp[3], Mv acMvPred[3])
5679
0
{
5680
0
  int mvNum = cu.affineType ? 3 : 2;
5681
0
  m_pcRdCost->setCostScale(0);
5682
0
  uint32_t bitsTemp = 0;
5683
5684
0
  for (int verIdx = 0; verIdx < mvNum; verIdx++)
5685
0
  {
5686
0
    Mv pred = verIdx == 0 ? acMvPred[verIdx] : acMvPred[verIdx] + acMvTemp[0] - acMvPred[0];
5687
0
    pred.changeAffinePrecInternal2Amvr(cu.imv);
5688
0
    m_pcRdCost->setPredictor(pred);
5689
0
    Mv mv = acMvTemp[verIdx];
5690
0
    mv.changeAffinePrecInternal2Amvr(cu.imv);
5691
5692
0
    bitsTemp += m_pcRdCost->getBitsOfVectorWithPredictor(mv.hor, mv.ver, 0);
5693
0
  }
5694
5695
0
  return bitsTemp;
5696
0
}
5697
5698
5699
//! set adaptive search range based on poc difference
5700
void InterSearch::setSearchRange( const Slice* slice, const VVEncCfg& encCfg )
5701
2.17k
{
5702
2.17k
  if( !encCfg.m_bUseASR || slice->isIRAP() )
5703
2.17k
  {
5704
2.17k
    return;
5705
2.17k
  }
5706
5707
0
  int iCurrPOC = slice->poc;
5708
0
  int iRefPOC;
5709
0
  int iGOPSize = encCfg.m_GOPSize;
5710
0
  int iOffset = (iGOPSize >> 1);
5711
0
  int iMaxSR = encCfg.m_SearchRange;
5712
0
  int iNumPredDir = slice->isInterP() ? 1 : 2;
5713
5714
0
  for (int iDir = 0; iDir < iNumPredDir; iDir++)
5715
0
  {
5716
0
    RefPicList  e = ( iDir ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
5717
0
    for (int iRefIdx = 0; iRefIdx < slice->numRefIdx[e]; iRefIdx++)
5718
0
    {
5719
0
      iRefPOC = slice->getRefPic(e, iRefIdx)->getPOC();
5720
0
      int newSearchRange = Clip3(encCfg.m_minSearchWindow, iMaxSR, (iMaxSR*ADAPT_SR_SCALE*abs(iCurrPOC - iRefPOC)+iOffset)/iGOPSize);
5721
0
      m_aaiAdaptSR[iDir][iRefIdx] = newSearchRange;
5722
0
    }
5723
0
  }
5724
0
}
5725
5726
void InterSearch::xIBCSearchMVCandUpdate(Distortion  sad, int x, int y, Distortion* sadBestCand, Mv* cMVCand)
5727
1.60M
{
5728
1.60M
  int j = CHROMA_REFINEMENT_CANDIDATES - 1;
5729
5730
1.60M
  if (sad < sadBestCand[CHROMA_REFINEMENT_CANDIDATES - 1])
5731
253k
  {
5732
2.28M
    for (int t = CHROMA_REFINEMENT_CANDIDATES - 1; t >= 0; t--)
5733
2.02M
    {
5734
2.02M
      if (sad < sadBestCand[t])
5735
1.21M
        j = t;
5736
2.02M
    }
5737
5738
1.21M
    for (int k = CHROMA_REFINEMENT_CANDIDATES - 1; k > j; k--)
5739
962k
    {
5740
962k
      sadBestCand[k] = sadBestCand[k - 1];
5741
5742
962k
      cMVCand[k].set(cMVCand[k - 1].hor, cMVCand[k - 1].ver);
5743
962k
    }
5744
253k
    sadBestCand[j] = sad;
5745
253k
    cMVCand[j].set(x, y);
5746
253k
  }
5747
1.60M
}
5748
5749
int InterSearch::xIBCSearchMVChromaRefine(CodingUnit& cu,
5750
  int         roiWidth,
5751
  int         roiHeight,
5752
  int         cuPelX,
5753
  int         cuPelY,
5754
  Distortion* sadBestCand,
5755
  Mv* cMVCand
5756
5757
)
5758
27.6k
{
5759
27.6k
  if ((!isChromaEnabled(cu.chromaFormat)) || (!cu.Cb().valid()))
5760
27.6k
  {
5761
27.6k
    return 0;
5762
27.6k
  }
5763
5764
0
  int bestCandIdx = 0;
5765
0
  Distortion  sadBest = std::numeric_limits<Distortion>::max();
5766
0
  Distortion  tempSad;
5767
5768
0
  Pel* pRef;
5769
0
  Pel* pOrg;
5770
0
  int refStride, orgStride;
5771
0
  int width, height;
5772
5773
0
  int picWidth = cu.cs->slice->pps->picWidthInLumaSamples;
5774
0
  int picHeight = cu.cs->slice->pps->picHeightInLumaSamples;
5775
5776
0
  UnitArea allCompBlocks(cu.chromaFormat, (Area)cu.block(COMP_Y));
5777
0
  for (int cand = 0; cand < CHROMA_REFINEMENT_CANDIDATES; cand++)
5778
0
  {
5779
0
    if (sadBestCand[cand] == std::numeric_limits<Distortion>::max())
5780
0
    {
5781
0
      continue;
5782
0
    }
5783
5784
0
    if ((!cMVCand[cand].hor) && (!cMVCand[cand].ver))
5785
0
      continue;
5786
5787
0
    if (((int)(cuPelY + cMVCand[cand].ver + roiHeight) >= picHeight) || ((cuPelY + cMVCand[cand].ver) < 0))
5788
0
      continue;
5789
5790
0
    if (((int)(cuPelX + cMVCand[cand].hor + roiWidth) >= picWidth) || ((cuPelX + cMVCand[cand].hor) < 0))
5791
0
      continue;
5792
5793
0
    tempSad = sadBestCand[cand];
5794
5795
0
    cu.mv[0][0] = cMVCand[cand];
5796
0
    cu.mv[0][0].changePrecision(MV_PRECISION_INT, MV_PRECISION_INTERNAL);
5797
0
    cu.interDir = 1;
5798
0
    cu.refIdx[0] = cu.cs->slice->numRefIdx[REF_PIC_LIST_0]; // last idx in the list
5799
5800
0
    PelUnitBuf predBufTmp = m_tmpPredStorage[REF_PIC_LIST_0].getCompactBuf(cu);
5801
0
    motionCompensation(cu, predBufTmp, REF_PIC_LIST_0);
5802
5803
0
    for (unsigned int ch = COMP_Cb; ch < getNumberValidComponents(cu.cs->sps->chromaFormatIdc); ch++)
5804
0
    {
5805
0
      width = roiWidth >> getComponentScaleX(ComponentID(ch), cu.chromaFormat);
5806
0
      height = roiHeight >> getComponentScaleY(ComponentID(ch), cu.chromaFormat);
5807
5808
0
      PelUnitBuf origBuf = cu.cs->getOrgBuf(allCompBlocks);
5809
0
      PelUnitBuf* pBuf = &origBuf;
5810
0
      CPelBuf  tmpPattern = pBuf->get(ComponentID(ch));
5811
0
      pOrg = (Pel*)tmpPattern.buf;
5812
5813
0
      Picture* refPic = cu.slice->pic;
5814
0
      const CPelBuf refBuf = refPic->getRecoBuf(allCompBlocks.blocks[ComponentID(ch)]);
5815
0
      pRef = (Pel*)refBuf.buf;
5816
5817
0
      refStride = refBuf.stride;
5818
0
      orgStride = tmpPattern.stride;
5819
5820
      //ComponentID compID = (ComponentID)ch;
5821
0
      PelUnitBuf* pBufRef = &predBufTmp;
5822
0
      CPelBuf  tmpPatternRef = pBufRef->get(ComponentID(ch));
5823
0
      pRef = (Pel*)tmpPatternRef.buf;
5824
0
      refStride = tmpPatternRef.stride;
5825
5826
5827
0
      tempSad += m_bvSearchOps.sumAbsDiffShifted( pOrg, orgStride, pRef, refStride, width, height, cu.cs->sps->bitDepths[CH_C] - 8 );
5828
0
    }
5829
5830
0
    if (tempSad < sadBest)
5831
0
    {
5832
0
      sadBest = tempSad;
5833
0
      bestCandIdx = cand;
5834
0
    }
5835
0
  }
5836
5837
0
  return bestCandIdx;
5838
27.6k
}
5839
// appends the non-zero candidates of src that are not in dst yet, up to dstTotalLength entries in dst
5840
unsigned InterSearch::xMergeCandLists( Mv* dst, unsigned dn, const unsigned dstTotalLength, const Mv* src, const unsigned sn ) const
5841
162k
{
5842
1.26M
  for( unsigned cand = 0; cand < sn && dn < dstTotalLength; cand++ )
5843
1.10M
  {
5844
1.10M
    if( src[cand] != Mv() && !m_bvSearchOps.containsMv( dst, dn, src[cand] ) )
5845
876k
    {
5846
876k
      dst[dn++] = src[cand];
5847
876k
    }
5848
1.10M
  }
5849
5850
162k
  return dn;
5851
162k
}
5852
5853
const unsigned* InterSearch::xGetBvBitsRow( const int x0, const int xStep, const int count, const int y, const bool useIMV )
5854
29.4k
{
5855
29.4k
  if( count <= 0 )
5856
6.50k
  {
5857
6.50k
    return nullptr;
5858
6.50k
  }
5859
22.9k
  m_bvBits.resize( std::max<size_t>( m_bvBits.size(), count ) );
5860
22.9k
  m_pcRdCost->getBvBitsRowIBC( x0, xStep, count, y, useIMV, m_bvBits.data() );
5861
22.9k
  return m_bvBits.data();
5862
29.4k
}
5863
5864
const unsigned* InterSearch::xGetBvBitsColumn( const int x, const int y0, const int yStep, const int count, const bool useIMV )
5865
32.4k
{
5866
32.4k
  if( count <= 0 )
5867
12.7k
  {
5868
12.7k
    return nullptr;
5869
12.7k
  }
5870
19.6k
  m_bvBits.resize( std::max<size_t>( m_bvBits.size(), count ) );
5871
19.6k
  m_pcRdCost->getBvBitsColumnIBC( x, y0, yStep, count, useIMV, m_bvBits.data() );
5872
19.6k
  return m_bvBits.data();
5873
32.4k
}
5874
5875
void InterSearch::xIntraPatternSearchIBC(CodingUnit& cu, TZSearchStruct& cStruct, Mv& rcMv, Distortion& ruiCost, Mv* pcMvSrchRngLT, Mv* pcMvSrchRngRB, Mv* pcMvPred)
5876
32.4k
{
5877
32.4k
  const int   srchRngHorLeft = pcMvSrchRngLT->hor;
5878
32.4k
  const int   srchRngHorRight = pcMvSrchRngRB->hor;
5879
32.4k
  const int   srchRngVerTop = pcMvSrchRngLT->ver;
5880
32.4k
  const int   srchRngVerBottom = pcMvSrchRngRB->ver;
5881
5882
32.4k
  const unsigned int  lcuWidth = cu.cs->slice->sps->CTUSize;
5883
32.4k
  const int   puPelOffsetX = 0;
5884
32.4k
  const int   puPelOffsetY = 0;
5885
32.4k
  const int   cuPelX = cu.Y().x;
5886
32.4k
  const int   cuPelY = cu.Y().y;
5887
5888
32.4k
  int          roiWidth = cu.lwidth();
5889
32.4k
  int          roiHeight = cu.lheight();
5890
5891
32.4k
  Distortion  sad;
5892
32.4k
  Distortion  sadBest = std::numeric_limits<Distortion>::max();
5893
32.4k
  int         bestX = 0;
5894
32.4k
  int         bestY = 0;
5895
5896
32.4k
  const Pel* piRefSrch = cStruct.piRefY; 
5897
5898
32.4k
  int         bestCandIdx = 0;
5899
5900
32.4k
  Distortion  sadBestCand[CHROMA_REFINEMENT_CANDIDATES];
5901
32.4k
  Mv          cMVCand[CHROMA_REFINEMENT_CANDIDATES];
5902
5903
32.4k
  const bool  useAmvr = cu.cs->sps->AMVR;
5904
5905
5906
291k
  for (int cand = 0; cand < CHROMA_REFINEMENT_CANDIDATES; cand++)
5907
259k
  {
5908
259k
    sadBestCand[cand] = std::numeric_limits<Distortion>::max();
5909
259k
    cMVCand[cand].set(0, 0);
5910
259k
  }
5911
5912
32.4k
  m_pcRdCost->setDistParam(m_cDistParam, *cStruct.pcPatternKey, cStruct.piRefY, cStruct.iRefStride, m_lumaClpRng.bd, COMP_Y, cStruct.subShiftMode);
5913
5914
32.4k
  const int picWidth = cu.cs->slice->pps->picWidthInLumaSamples;
5915
32.4k
  const int picHeight = cu.cs->slice->pps->picHeightInLumaSamples;
5916
5917
5918
32.4k
  {
5919
32.4k
    m_cDistParam.subShift = 0;
5920
32.4k
    Distortion tempSadBest = 0;
5921
5922
32.4k
    int srLeft = srchRngHorLeft, srRight = srchRngHorRight, srTop = srchRngVerTop, srBottom = srchRngVerBottom;
5923
32.4k
    m_numBVs = 0;
5924
32.4k
    m_numBVs = xMergeCandLists(m_acBVs, m_numBVs, (2 * IBC_NUM_CANDIDATES), m_defaultCachedBvs->m_bvCands, m_defaultCachedBvs->currCnt);
5925
5926
32.4k
    Mv cMvPredEncOnly[IBC_NUM_CANDIDATES];
5927
32.4k
    int nbPreds = 0;
5928
32.4k
    CU::getIbcMVPsEncOnly(cu, cMvPredEncOnly, nbPreds);
5929
32.4k
    m_numBVs = xMergeCandLists(m_acBVs, m_numBVs, (2 * IBC_NUM_CANDIDATES), cMvPredEncOnly, nbPreds);
5930
5931
313k
    for (unsigned int cand = 0; cand < m_numBVs; cand++)
5932
280k
    {
5933
280k
      int xPred = m_acBVs[cand].hor;
5934
280k
      int yPred = m_acBVs[cand].ver;
5935
5936
280k
      if (!(xPred == 0 && yPred == 0)
5937
280k
        && !((yPred < srTop) || (yPred > srBottom))
5938
252k
        && !((xPred < srLeft) || (xPred > srRight)))
5939
252k
      {
5940
252k
        bool validCand = searchBvIBC(cu, cuPelX, cuPelY, roiWidth, roiHeight, picWidth, picHeight, xPred, yPred, lcuWidth);
5941
5942
252k
        if (validCand)
5943
208k
        {
5944
208k
          sad = m_pcRdCost->getBvCostMultiplePredsIBC(xPred, yPred, useAmvr);
5945
208k
          m_cDistParam.cur.buf = piRefSrch + cStruct.iRefStride * yPred + xPred;
5946
208k
          sad += m_cDistParam.distFunc(m_cDistParam);
5947
5948
208k
          xIBCSearchMVCandUpdate(sad, xPred, yPred, sadBestCand, cMVCand);
5949
208k
        }
5950
252k
      }
5951
280k
    }
5952
5953
32.4k
    bestX = cMVCand[0].hor;
5954
32.4k
    bestY = cMVCand[0].ver;
5955
32.4k
    rcMv.set(bestX, bestY);
5956
32.4k
    sadBest = sadBestCand[0];
5957
5958
32.4k
    const int boundY = (0 - roiHeight - puPelOffsetY);
5959
32.4k
    const int aboveStartY = std::max(srchRngVerTop, 0 - cuPelY);
5960
32.4k
    const unsigned* bvBitsAbove = xGetBvBitsColumn( 0, aboveStartY, 1, boundY - aboveStartY + 1, useAmvr );
5961
575k
    for (int y = aboveStartY; y <= boundY; ++y)
5962
546k
    {
5963
546k
      if (!searchBvIBC(cu, cuPelX, cuPelY, roiWidth, roiHeight, picWidth, picHeight, 0, y, lcuWidth))
5964
0
      {
5965
0
        continue;
5966
0
      }
5967
5968
546k
      sad = m_pcRdCost->getBvCostIBC( bvBitsAbove[y - aboveStartY] );
5969
546k
      m_cDistParam.cur.buf = piRefSrch + cStruct.iRefStride * y;
5970
546k
      sad += m_cDistParam.distFunc(m_cDistParam);
5971
5972
546k
      xIBCSearchMVCandUpdate(sad, 0, y, sadBestCand, cMVCand);
5973
546k
      tempSadBest = sadBestCand[0];
5974
546k
      if (sadBestCand[0] <= 3)
5975
3.30k
      {
5976
3.30k
        bestX = cMVCand[0].hor;
5977
3.30k
        bestY = cMVCand[0].ver;
5978
3.30k
        sadBest = sadBestCand[0];
5979
3.30k
        rcMv.set(bestX, bestY);
5980
3.30k
        ruiCost = sadBest;
5981
3.30k
        goto end;
5982
3.30k
      }
5983
546k
    }
5984
5985
29.1k
    const int boundX = std::max(srchRngHorLeft, -cuPelX);
5986
29.1k
    const int leftStartX = 0 - roiWidth - puPelOffsetX;
5987
29.1k
    const unsigned* bvBitsLeft = xGetBvBitsRow( leftStartX, -1, leftStartX - boundX + 1, 0, useAmvr );
5988
1.90M
    for (int x = leftStartX; x >= boundX; --x)
5989
1.87M
    {
5990
1.87M
      if (!searchBvIBC(cu, cuPelX, cuPelY, roiWidth, roiHeight, picWidth, picHeight, x, 0, lcuWidth))
5991
1.04M
      {
5992
1.04M
        continue;
5993
1.04M
      }
5994
5995
832k
      sad = m_pcRdCost->getBvCostIBC( bvBitsLeft[leftStartX - x] );
5996
832k
      m_cDistParam.cur.buf = piRefSrch + x;
5997
832k
      sad += m_cDistParam.distFunc(m_cDistParam);
5998
5999
6000
832k
      xIBCSearchMVCandUpdate(sad, x, 0, sadBestCand, cMVCand);
6001
832k
      tempSadBest = sadBestCand[0];
6002
832k
      if (sadBestCand[0] <= 3)
6003
1.44k
      {
6004
1.44k
        bestX = cMVCand[0].hor;
6005
1.44k
        bestY = cMVCand[0].ver;
6006
1.44k
        sadBest = sadBestCand[0];
6007
1.44k
        rcMv.set(bestX, bestY);
6008
1.44k
        ruiCost = sadBest;
6009
1.44k
        goto end;
6010
1.44k
      }
6011
832k
    }
6012
6013
27.6k
    bestX = cMVCand[0].hor;
6014
27.6k
    bestY = cMVCand[0].ver;
6015
27.6k
    sadBest = sadBestCand[0];
6016
27.6k
    if ((!bestX && !bestY) || (sadBest - m_pcRdCost->getBvCostMultiplePredsIBC(bestX, bestY, useAmvr) <= 32))
6017
26.3k
    {
6018
      //chroma refine
6019
26.3k
      bestCandIdx = xIBCSearchMVChromaRefine(cu, roiWidth, roiHeight, cuPelX, cuPelY, sadBestCand, cMVCand);
6020
26.3k
      bestX = cMVCand[bestCandIdx].hor;
6021
26.3k
      bestY = cMVCand[bestCandIdx].ver;
6022
26.3k
      sadBest = sadBestCand[bestCandIdx];
6023
26.3k
      rcMv.set(bestX, bestY);
6024
26.3k
      ruiCost = sadBest;
6025
26.3k
      goto end;
6026
26.3k
    }
6027
6028
1.29k
    if (cu.lwidth() < 16 && cu.lheight() < 16)
6029
34
    {
6030
34
      int stepS = 2;
6031
34
      if (m_pcEncCfg->m_IBCFastMethod > 2)
6032
34
      {
6033
34
        if (m_pcEncCfg->m_IBCFastMethod == 5)
6034
0
        {
6035
0
          stepS = 8;
6036
0
        }
6037
34
        else if ((cu.lwidth() > 4) || (cu.lheight() > 4))
6038
34
        {
6039
34
          stepS = 4;
6040
34
        }
6041
34
      }
6042
6043
34
      const int minCuLog2 = m_pcEncCfg->m_log2MinCodingBlockSize;
6044
34
      const int minCuMask = (1 << minCuLog2) - 1;
6045
34
      bool lastDec = false;
6046
6047
34
      for (int searchStep = 0; searchStep < 3; searchStep++)
6048
34
      {
6049
34
        int delaySy = searchStep ? 1 : 0;
6050
34
        int delaySx = searchStep > 1 ? 1 : 0;
6051
34
        int startY = (std::max(srchRngVerTop, -cuPelY) + delaySy);
6052
34
        int startX = (std::max(srchRngHorLeft, -cuPelX) + delaySx);
6053
34
        int endY = srchRngVerBottom;
6054
34
        int endX = srchRngHorRight;
6055
6056
34
        if (m_pcEncCfg->m_IBCFastMethod > 5)
6057
0
        {
6058
0
          startY = bestY - 4;
6059
0
          endY = bestY + 4;
6060
0
          startX = bestX - 4;
6061
0
          endX = bestX + 4;
6062
0
          stepS = 1;
6063
0
          if (searchStep)
6064
0
          {
6065
0
            break;
6066
0
          }
6067
0
        }
6068
6069
883
        for (int y = startY; y <= endY; y += stepS)
6070
849
        {
6071
849
          if ((y == 0) || ((int)(cuPelY + y + roiHeight) >= picHeight))
6072
461
            continue;
6073
388
          bool firstX = true;
6074
388
          int stepSx = searchStep ? stepS : 1;
6075
388
          const unsigned* bvBitsRow = xGetBvBitsRow( startX, stepSx, ( endX - startX ) / stepSx + 1, y, useAmvr );
6076
43.8k
          for (int x = startX, k = 0; x <= endX; firstX = false, x += stepSx, k++)
6077
43.4k
          {
6078
43.4k
            if ((x == 0) || ((int)(cuPelX + x + roiWidth) >= picWidth))
6079
20.6k
              continue;
6080
6081
22.8k
            bool isSameAsLast = !firstX && ((cuPelX + x) & minCuMask) > 1;
6082
22.8k
            if (searchStep || (m_pcEncCfg->m_IBCFastMethod > 5))
6083
0
            {
6084
0
              if (!searchBvIBC(cu, cuPelX, cuPelY, roiWidth, roiHeight, picWidth, picHeight, x, y, lcuWidth))
6085
0
              {
6086
0
                continue;
6087
0
              }
6088
0
            }
6089
22.8k
            else if ((isSameAsLast && !lastDec) || (!isSameAsLast && !searchBvIBC(cu, cuPelX, cuPelY, roiWidth, roiHeight, picWidth, picHeight, x, y, lcuWidth)))
6090
7.13k
            {
6091
7.13k
              lastDec = false;
6092
7.13k
              continue;
6093
7.13k
            }
6094
15.7k
            lastDec = true;
6095
6096
15.7k
            sad = m_pcRdCost->getBvCostIBC( bvBitsRow[k] );
6097
15.7k
            m_cDistParam.cur.buf = piRefSrch + cStruct.iRefStride * y + x;
6098
15.7k
            sad += m_cDistParam.distFunc(m_cDistParam);
6099
6100
15.7k
            xIBCSearchMVCandUpdate(sad, x, y, sadBestCand, cMVCand);
6101
6102
6103
15.7k
            if (searchStep && sadBestCand[0] <= 5)
6104
0
            {
6105
              //chroma refine & return
6106
0
              bestCandIdx = xIBCSearchMVChromaRefine(cu, roiWidth, roiHeight, cuPelX, cuPelY, sadBestCand, cMVCand);
6107
0
              bestX = cMVCand[bestCandIdx].hor;
6108
0
              bestY = cMVCand[bestCandIdx].ver;
6109
0
              sadBest = sadBestCand[bestCandIdx];
6110
0
              rcMv.set(bestX, bestY);
6111
0
              ruiCost = sadBest;
6112
0
              goto end;
6113
0
            }
6114
15.7k
          }
6115
388
        }
6116
6117
34
        if ((searchStep < 2) && (m_pcEncCfg->m_IBCFastMethod < 6))
6118
34
        {
6119
34
          if ((m_pcEncCfg->m_IBCFastMethod > 2) && (m_pcEncCfg->m_IBCFastMethod < 5))
6120
34
          {
6121
34
            if ((bestX == cMVCand[0].hor) && (bestY == cMVCand[0].ver))
6122
34
            {
6123
34
              sadBest = sadBestCand[bestCandIdx];
6124
34
              rcMv.set(bestX, bestY);
6125
34
              ruiCost = sadBest;
6126
34
              goto end;
6127
34
            }
6128
34
          }
6129
0
          bestX = cMVCand[0].hor;
6130
0
          bestY = cMVCand[0].ver;
6131
0
          sadBest = sadBestCand[0];
6132
6133
0
          int StopSearch = searchStep ? 32 : 16;
6134
0
          if ((searchStep && (sadBest >= tempSadBest)) || (sadBest - m_pcRdCost->getBvCostMultiplePredsIBC(bestX, bestY, useAmvr) <= StopSearch))
6135
0
          {
6136
            //chroma refine
6137
0
            bestCandIdx = xIBCSearchMVChromaRefine(cu, roiWidth, roiHeight, cuPelX, cuPelY, sadBestCand, cMVCand);
6138
6139
0
            bestX = cMVCand[bestCandIdx].hor;
6140
0
            bestY = cMVCand[bestCandIdx].ver;
6141
0
            sadBest = sadBestCand[bestCandIdx];
6142
0
            rcMv.set(bestX, bestY);
6143
0
            ruiCost = sadBest;
6144
0
            goto end;
6145
0
          }
6146
0
        }
6147
34
      }
6148
34
    }
6149
1.29k
  }
6150
6151
1.26k
  bestCandIdx = xIBCSearchMVChromaRefine(cu, roiWidth, roiHeight, cuPelX, cuPelY, sadBestCand, cMVCand);
6152
6153
1.26k
  bestX = cMVCand[bestCandIdx].hor;
6154
1.26k
  bestY = cMVCand[bestCandIdx].ver;
6155
1.26k
  sadBest = sadBestCand[bestCandIdx];
6156
1.26k
  rcMv.set(bestX, bestY);
6157
1.26k
  ruiCost = sadBest;
6158
6159
32.4k
end:
6160
32.4k
  m_numBVs = 0;
6161
32.4k
  m_numBVs = xMergeCandLists(m_acBVs, m_numBVs, (2 * IBC_NUM_CANDIDATES), m_defaultCachedBvs->m_bvCands, m_defaultCachedBvs->currCnt);
6162
6163
32.4k
  m_defaultCachedBvs->currCnt = 0;
6164
32.4k
  m_defaultCachedBvs->currCnt = xMergeCandLists(m_defaultCachedBvs->m_bvCands, m_defaultCachedBvs->currCnt, IBC_NUM_CANDIDATES, cMVCand, CHROMA_REFINEMENT_CANDIDATES);
6165
32.4k
  m_defaultCachedBvs->currCnt = xMergeCandLists(m_defaultCachedBvs->m_bvCands, m_defaultCachedBvs->currCnt, IBC_NUM_CANDIDATES, m_acBVs, m_numBVs);
6166
6167
291k
  for (unsigned int cand = 0; cand < CHROMA_REFINEMENT_CANDIDATES; cand++)
6168
259k
  {
6169
259k
    if (cMVCand[cand].hor == 0 && cMVCand[cand].ver == 0)
6170
82.6k
    {
6171
82.6k
      continue;
6172
82.6k
    }
6173
176k
    m_ctuRecord[cu.lumaPos()][cu.lumaSize()].bvRecord[cMVCand[cand]] = sadBestCand[cand];
6174
176k
  }
6175
6176
32.4k
  return;
6177
1.26k
}
6178
6179
6180
6181
// based on xMotionEstimation
6182
void InterSearch::xIBCEstimation(CodingUnit& cu, PelUnitBuf& origBuf, Mv* pcMvPred, Mv& rcMv, Distortion& ruiCost )
6183
32.4k
{
6184
32.4k
  const int iPicWidth = cu.cs->slice->pps->picWidthInLumaSamples;
6185
32.4k
  const int iPicHeight = cu.cs->slice->pps->picHeightInLumaSamples;
6186
32.4k
  const unsigned int  lcuWidth = cu.cs->slice->sps->CTUSize;
6187
32.4k
  const int           cuPelX = cu.Y().x;
6188
32.4k
  const int           cuPelY = cu.Y().y;
6189
32.4k
  int                 iRoiWidth = cu.lwidth();
6190
32.4k
  int                 iRoiHeight = cu.lheight();
6191
6192
32.4k
  PelUnitBuf* pBuf = &origBuf;
6193
6194
  //  Search key pattern initialization
6195
32.4k
  CPelBuf  tmpPattern = pBuf->Y();
6196
32.4k
  CPelBuf* pcPatternKey = &tmpPattern;
6197
32.4k
  m_lumaClpRng = cu.cs->slice->clpRngs[COMP_Y];
6198
32.4k
  Picture* refPic = cu.slice->pic;
6199
32.4k
  const CPelBuf refBuf = refPic->getRecoBuf(cu.blocks[COMP_Y]);
6200
6201
32.4k
  TZSearchStruct cStruct; 
6202
32.4k
  cStruct.pcPatternKey  = pcPatternKey;
6203
32.4k
  cStruct.iRefStride    = refBuf.stride;
6204
32.4k
  cStruct.piRefY        = refBuf.buf;
6205
32.4k
  CHECK( cu.imv == IMV_HPEL, "IF_IBC" );
6206
32.4k
  cStruct.imvShift      = cu.imv << 1;
6207
32.4k
  cStruct.subShiftMode  = 0;
6208
32.4k
  cStruct.uiBestSad     = MAX_DISTORTION;
6209
6210
32.4k
  m_pcRdCost->getMotionCostIBC(0);
6211
32.4k
  m_pcRdCost->setPredictorsIBC(pcMvPred);
6212
32.4k
  m_pcRdCost->setCostScale(0);
6213
6214
32.4k
  m_pcRdCost->setDistParam(m_cDistParam, *cStruct.pcPatternKey, cStruct.piRefY, cStruct.iRefStride, m_lumaClpRng.bd, COMP_Y, cStruct.subShiftMode);
6215
32.4k
  bool buffered = false;
6216
32.4k
  if (m_pcEncCfg->m_IBCFastMethod)// IBC_FAST_METHOD_BUFFERBV
6217
32.4k
  {
6218
32.4k
    ruiCost = MAX_UINT;
6219
32.4k
    std::unordered_map<Mv, Distortion>& history = m_ctuRecord[cu.lumaPos()][cu.lumaSize()].bvRecord;
6220
32.4k
    for (std::unordered_map<Mv, Distortion>::iterator p = history.begin(); p != history.end(); p++)
6221
19
    {
6222
19
      const Mv& bv = p->first;
6223
6224
19
      int xBv = bv.hor;
6225
19
      int yBv = bv.ver;
6226
19
      if (searchBvIBC(cu, cuPelX, cuPelY, iRoiWidth, iRoiHeight, iPicWidth, iPicHeight, xBv, yBv, lcuWidth))
6227
19
      {
6228
19
        buffered = true;
6229
19
        Distortion sad = m_pcRdCost->getBvCostMultiplePredsIBC(xBv, yBv, cu.cs->sps->AMVR);
6230
19
        m_cDistParam.cur.buf = cStruct.piRefY + cStruct.iRefStride * yBv + xBv;
6231
19
        sad += m_cDistParam.distFunc(m_cDistParam);
6232
19
        if (sad < ruiCost)
6233
19
        {
6234
19
          rcMv = bv;
6235
19
          ruiCost = sad;
6236
19
        }
6237
0
        else if (sad == ruiCost)
6238
0
        {
6239
          // stabilise the search through the unordered list
6240
0
          if (bv.hor < rcMv.hor
6241
0
            || (bv.hor == rcMv.hor && bv.ver < rcMv.ver))
6242
0
          {
6243
            // update the vector.
6244
0
            rcMv = bv;
6245
0
          }
6246
0
        }
6247
19
      }
6248
19
    }
6249
6250
32.4k
    if (buffered)
6251
19
    {
6252
19
      Mv cMvPredEncOnly[IBC_NUM_CANDIDATES];
6253
19
      int nbPreds = 0;
6254
19
      CU::getIbcMVPsEncOnly(cu, cMvPredEncOnly, nbPreds);
6255
6256
19
      for (unsigned int cand = 0; cand < nbPreds; cand++)
6257
0
      {
6258
0
        int xPred = cMvPredEncOnly[cand].hor;
6259
0
        int yPred = cMvPredEncOnly[cand].ver;
6260
6261
0
        if (searchBvIBC(cu, cuPelX, cuPelY, iRoiWidth, iRoiHeight, iPicWidth, iPicHeight, xPred, yPred, lcuWidth))
6262
0
        {
6263
0
          Distortion sad = m_pcRdCost->getBvCostMultiplePredsIBC(xPred, yPred, cu.cs->sps->AMVR);
6264
0
          m_cDistParam.cur.buf = cStruct.piRefY + cStruct.iRefStride * yPred + xPred;
6265
0
          sad += m_cDistParam.distFunc(m_cDistParam);
6266
0
          if (sad < ruiCost)
6267
0
          {
6268
0
            rcMv.set(xPred, yPred);
6269
0
            ruiCost = sad;
6270
0
          }
6271
0
          else if (sad == ruiCost)
6272
0
          {
6273
            // stabilise the search through the unordered list
6274
0
            if (xPred < rcMv.hor
6275
0
              || (xPred == rcMv.hor && yPred < rcMv.ver))
6276
0
            {
6277
              // update the vector.
6278
0
              rcMv.set(xPred, yPred);
6279
0
            }
6280
0
          }
6281
0
          m_ctuRecord[cu.lumaPos()][cu.lumaSize()].bvRecord[Mv(xPred, yPred)] = sad;
6282
0
        }
6283
0
      }
6284
19
    }
6285
32.4k
  }
6286
6287
32.4k
  if (!buffered)
6288
32.4k
  {
6289
32.4k
    Mv        cMvSrchRngLT;
6290
32.4k
    Mv        cMvSrchRngRB;
6291
6292
    // assume that intra BV is integer-pel precision
6293
32.4k
    xSetIntraSearchRangeIBC(cu, cu.lwidth(), cu.lheight(), cMvSrchRngLT, cMvSrchRngRB);
6294
6295
    //  Do integer search
6296
32.4k
    xIntraPatternSearchIBC(cu, cStruct, rcMv, ruiCost, &cMvSrchRngLT, &cMvSrchRngRB, pcMvPred);
6297
32.4k
  }
6298
32.4k
}
6299
// based on xSetSearchRange
6300
void InterSearch::xSetIntraSearchRangeIBC(CodingUnit& cu, int iRoiWidth, int iRoiHeight, Mv& rcMvSrchRngLT, Mv& rcMvSrchRngRB)
6301
32.4k
{
6302
 // const SPS& sps = *cu.cs->sps;
6303
6304
32.4k
  int srLeft, srRight, srTop, srBottom;
6305
6306
32.4k
  const int cuPelX = cu.Y().x;
6307
32.4k
  const int cuPelY = cu.Y().y;
6308
6309
32.4k
  const int lcuWidth = cu.cs->slice->sps->CTUSize;
6310
32.4k
  const int ctuSizeLog2 = floorLog2(lcuWidth);
6311
32.4k
  int numLeftCTUs = (1 << ((7 - ctuSizeLog2) << 1)) - ((ctuSizeLog2 < 7) ? 1 : 0);
6312
6313
32.4k
  srLeft = -(numLeftCTUs * lcuWidth + (cuPelX % lcuWidth));
6314
32.4k
  srTop = -(cuPelY % lcuWidth);
6315
6316
32.4k
  srRight = lcuWidth - (cuPelX % lcuWidth) - iRoiWidth;
6317
32.4k
  srBottom = lcuWidth - (cuPelY % lcuWidth) - iRoiHeight;
6318
6319
32.4k
  rcMvSrchRngLT.hor=srLeft;
6320
32.4k
  rcMvSrchRngLT.ver=srTop;
6321
32.4k
  rcMvSrchRngRB.hor=srRight;
6322
32.4k
  rcMvSrchRngRB.ver=srBottom;
6323
6324
32.4k
  rcMvSrchRngLT <<= 2;
6325
32.4k
  rcMvSrchRngRB <<= 2;
6326
32.4k
  bool temp = m_clipMvInSubPic;
6327
32.4k
  m_clipMvInSubPic = true;
6328
32.4k
  clipMv(rcMvSrchRngLT,cu.lumaPos(),cu.lumaSize(), *cu.cs->pcv, *cu.cs->pps, m_clipMvInSubPic);
6329
32.4k
  clipMv(rcMvSrchRngRB, cu.lumaPos(),cu.lumaSize(), *cu.cs->pcv, * cu.cs->pps, m_clipMvInSubPic);
6330
32.4k
  m_clipMvInSubPic = temp;
6331
32.4k
  rcMvSrchRngLT >>= 2;
6332
32.4k
  rcMvSrchRngRB >>= 2;
6333
32.4k
}
6334
6335
bool InterSearch::predIBCSearch(CodingUnit& cu, Partitioner& partitioner)
6336
32.4k
{
6337
32.4k
  Mv           cMvSrchRngLT;
6338
32.4k
  Mv           cMvSrchRngRB;
6339
32.4k
  cu.imv = IMV_4PEL;
6340
32.4k
  AMVPInfo amvpInfo4Pel;
6341
32.4k
  CU::fillIBCMvpCand(cu, amvpInfo4Pel);
6342
6343
32.4k
  cu.imv = IMV_OFF;// (Int)cu.cs->sps->getUseIMV(); // set as IMV=0 initially
6344
32.4k
  Mv    cMv, cMvPred[2];
6345
32.4k
  AMVPInfo amvpInfo;
6346
32.4k
  CU::fillIBCMvpCand(cu, amvpInfo);
6347
  // store in full pel accuracy, shift before use in search
6348
32.4k
  cMvPred[0] = amvpInfo.mvCand[0];
6349
32.4k
  cMvPred[0].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT);
6350
32.4k
  cMvPred[1] = amvpInfo.mvCand[1];
6351
32.4k
  cMvPred[1].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT);
6352
6353
32.4k
  int iBvpNum = 2;
6354
32.4k
  int bvpIdxBest = 0;
6355
32.4k
  cMv.setZero();
6356
32.4k
  Distortion cost = 0;
6357
32.4k
  if (cu.cs->sps->maxNumIBCMergeCand == 1)
6358
0
  {
6359
0
    iBvpNum = 1;
6360
0
    cMvPred[1] = cMvPred[0];
6361
0
  }
6362
6363
32.4k
  if (cMv.hor == 0 && cMv.ver == 0)
6364
32.4k
  {
6365
    // if hash search does not work or is not enabled
6366
32.4k
    PelUnitBuf origBuf = cu.cs->getOrgBuf(cu);
6367
32.4k
    xIBCEstimation(cu, origBuf, cMvPred, cMv, cost );
6368
32.4k
  }
6369
6370
32.4k
  if (cMv.hor == 0 && cMv.ver == 0)
6371
3.29k
  {
6372
3.29k
    return false;
6373
3.29k
  }
6374
  /// ibc search
6375
  /////////////////////////////////////////////////////////
6376
29.1k
  unsigned int bitsBVPBest, bitsBVPTemp;
6377
29.1k
  bitsBVPBest = MAX_INT;
6378
29.1k
  m_pcRdCost->setCostScale(0);
6379
6380
87.3k
  for (int bvpIdxTemp = 0; bvpIdxTemp < iBvpNum; bvpIdxTemp++)
6381
58.2k
  {
6382
58.2k
    m_pcRdCost->setPredictor(cMvPred[bvpIdxTemp]);
6383
6384
58.2k
    bitsBVPTemp = m_pcRdCost->getBitsOfVectorWithPredictor(cMv.hor, cMv.ver, 0);
6385
6386
58.2k
    if (bitsBVPTemp < bitsBVPBest)
6387
29.1k
    {
6388
29.1k
      bitsBVPBest = bitsBVPTemp;
6389
29.1k
      bvpIdxBest = bvpIdxTemp;
6390
6391
29.1k
      if (cu.cs->sps->AMVR && cMv != cMvPred[bvpIdxTemp])
6392
29.1k
        cu.imv = IMV_FPEL; // set as full-pel
6393
0
      else
6394
0
        cu.imv = IMV_OFF; // set as fractional-pel
6395
6396
29.1k
    }
6397
6398
58.2k
    unsigned int bitsBVPQP = MAX_UINT;
6399
6400
6401
58.2k
    Mv mvPredQuadPel;
6402
58.2k
    if ((cMv.hor % 4 == 0) && (cMv.ver % 4 == 0) && (cu.cs->sps->AMVR))
6403
58.2k
    {
6404
58.2k
      mvPredQuadPel = amvpInfo4Pel.mvCand[bvpIdxTemp];// cMvPred[bvpIdxTemp];
6405
6406
58.2k
      mvPredQuadPel.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_4PEL);
6407
6408
58.2k
      m_pcRdCost->setPredictor(mvPredQuadPel);
6409
6410
58.2k
      bitsBVPQP = m_pcRdCost->getBitsOfVectorWithPredictor(cMv.hor >> 2, cMv.ver >> 2, 0);
6411
6412
58.2k
    }
6413
58.2k
    mvPredQuadPel.changePrecision(MV_PRECISION_4PEL, MV_PRECISION_INT);
6414
58.2k
    if (bitsBVPQP < bitsBVPBest && cMv != mvPredQuadPel)
6415
29.1k
    {
6416
29.1k
      bitsBVPBest = bitsBVPQP;
6417
29.1k
      bvpIdxBest = bvpIdxTemp;
6418
6419
29.1k
      if (cu.cs->sps->AMVR)
6420
29.1k
        cu.imv = IMV_4PEL;
6421
29.1k
    }
6422
6423
58.2k
  }
6424
6425
29.1k
  cMv.changePrecision( MV_PRECISION_INT, MV_PRECISION_INTERNAL );
6426
29.1k
  cu.mv[REF_PIC_LIST_0][0] = cMv; // store in fractional pel accuracy
6427
6428
29.1k
  cu.mvpIdx[REF_PIC_LIST_0] = bvpIdxBest;
6429
6430
29.1k
  if (cu.imv == IMV_4PEL && cMv != amvpInfo4Pel.mvCand[bvpIdxBest])
6431
29.1k
    cu.mvd[REF_PIC_LIST_0][0] = cMv - amvpInfo4Pel.mvCand[bvpIdxBest];
6432
18.4E
  else
6433
18.4E
    cu.mvd[REF_PIC_LIST_0][0] = cMv - amvpInfo.mvCand[bvpIdxBest];
6434
6435
29.1k
  if (cu.mvd[REF_PIC_LIST_0][0] == Mv(0, 0))
6436
0
    cu.imv = IMV_OFF;
6437
29.1k
  if (cu.imv == IMV_4PEL)
6438
29.1k
    assert((cMv.hor % 16 == 0) && (cMv.ver % 16 == 0));
6439
29.1k
  if (cu.cs->sps->AMVR)
6440
29.1k
    assert(cu.imv > 0 || cu.mvd[REF_PIC_LIST_0][0] == Mv());
6441
6442
29.1k
  cu.refIdx[REF_PIC_LIST_0] = MAX_NUM_REF;
6443
6444
29.1k
  return true;
6445
29.1k
}
6446
6447
6448
static inline bool isYPartBefore( SplitSeries series, const int ctuSizeLog2, const Position& refPos, const Position& pos )
6449
1.93M
{
6450
1.93M
#ifndef NDEBUG
6451
1.93M
  const int refCtuX = refPos.x >> ctuSizeLog2;
6452
1.93M
  const int refCtuY = refPos.y >> ctuSizeLog2;
6453
1.93M
  const int posCtuX = pos.x >> ctuSizeLog2;
6454
1.93M
  const int posCtuY = pos.y >> ctuSizeLog2;
6455
6456
1.93M
  CHECK( refCtuX != posCtuX || refCtuY != posCtuY, "This method can only be applied for positions within the same CTU" );
6457
6458
1.93M
#endif
6459
1.93M
  const int ctuMask = ( 1 << ctuSizeLog2 ) - 1;
6460
6461
1.93M
  const int refX = refPos.x & ctuMask;
6462
1.93M
  const int refY = refPos.y & ctuMask;
6463
1.93M
  const int posX = pos.x & ctuMask;
6464
1.93M
  const int posY = pos.y & ctuMask;
6465
6466
1.93M
  int x = 0, y = 0, w = 1 << ctuSizeLog2, h = 1 << ctuSizeLog2;
6467
  
6468
2.59M
  while( true )
6469
2.59M
  {
6470
2.59M
    PartSplit split = PartSplit( series & SPLIT_MASK );
6471
6472
2.59M
    switch( split )
6473
2.59M
    {
6474
2.52M
    case CU_QUAD_SPLIT:
6475
2.52M
      w >>= 1;
6476
2.52M
      if( posX >= x + w ) x += w;
6477
2.55M
    case CU_HORZ_SPLIT:
6478
2.55M
      h >>= 1;
6479
2.55M
      if( posY >= y + h ) y += h;
6480
2.55M
      break;
6481
6482
40.1k
    case CU_VERT_SPLIT:
6483
40.1k
      w >>= 1;
6484
40.1k
      if( posX >= x + w ) x += w;
6485
40.1k
      goto checkXonly;
6486
6487
0
    case CU_TRIH_SPLIT:
6488
0
      h >>= 2;
6489
0
      if( posY >= y + h ) { y += h; h <<= 1; }
6490
0
      if( posY >= y + h ) { y += h; h >>= 1; }
6491
0
      break;
6492
6493
0
    case CU_TRIV_SPLIT:
6494
0
      w >>= 2;
6495
0
      if( posX >= x + w ) { x += w; w <<= 1; }
6496
0
      if( posX >= x + w ) { x += w; w >>= 1; }
6497
0
      goto checkXonly;
6498
6499
0
    default:
6500
0
      return false;
6501
2.59M
    }
6502
6503
2.55M
    if( refY >= y + h ) return true;
6504
1.92M
    else if( refY < y ) return false;
6505
6506
1.96M
checkXonly:
6507
1.96M
    if( refX >= x + w ) return true;
6508
1.00M
    else if( refX < x ) return false;
6509
6510
661k
    series >>= SPLIT_DMULT; continue;
6511
1.96M
  }
6512
6513
262
  return false;
6514
1.93M
}
6515
6516
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
6517
2.88M
{
6518
2.88M
  const int ctuSizeLog2 = Log2(ctuSize);
6519
6520
2.88M
  int refRightX  = xPos + xBv + width  - 1;
6521
2.88M
  int refBottomY = yPos + yBv + height - 1;
6522
6523
2.88M
  int refLeftX = xPos + xBv;
6524
2.88M
  int refTopY  = yPos + yBv;
6525
6526
2.88M
  if ((xPos + xBv) < 0)
6527
15.7k
  {
6528
15.7k
    return false;
6529
15.7k
  }
6530
2.86M
  if (refRightX >= picWidth)
6531
0
  {
6532
0
    return false;
6533
0
  }
6534
6535
2.86M
  if ((yPos + yBv) < 0)
6536
0
  {
6537
0
    return false;
6538
0
  }
6539
2.86M
  if (refBottomY >= picHeight)
6540
0
  {
6541
0
    return false;
6542
0
  }
6543
2.86M
  if ((xBv + width) > 0 && (yBv + height) > 0)
6544
222k
  {
6545
222k
    return false;
6546
222k
  }
6547
6548
  // Don't search the above CTU row
6549
2.64M
  if (refTopY >> ctuSizeLog2 < yPos >> ctuSizeLog2)
6550
0
    return false;
6551
6552
  // Don't search the below CTU row
6553
2.64M
  if (refBottomY >> ctuSizeLog2 > yPos >> ctuSizeLog2)
6554
0
  {
6555
0
    return false;
6556
0
  }
6557
6558
2.64M
  unsigned curTileIdx = cu.cs->pps->getTileIdx(cu.lumaPos());
6559
2.64M
  unsigned refTileIdx = cu.cs->pps->getTileIdx(Position(refLeftX, refTopY));
6560
2.64M
  if (curTileIdx != refTileIdx)
6561
0
  {
6562
0
    return false;
6563
0
  }
6564
2.64M
  refTileIdx = cu.cs->pps->getTileIdx(Position(refLeftX, refBottomY));
6565
2.64M
  if (curTileIdx != refTileIdx)
6566
0
  {
6567
0
    return false;
6568
0
  }
6569
2.64M
  refTileIdx = cu.cs->pps->getTileIdx(Position(refRightX, refTopY));
6570
2.64M
  if (curTileIdx != refTileIdx)
6571
0
  {
6572
0
    return false;
6573
0
  }
6574
2.64M
  refTileIdx = cu.cs->pps->getTileIdx(Position(refRightX, refBottomY));
6575
2.64M
  if (curTileIdx != refTileIdx)
6576
0
  {
6577
0
    return false;
6578
0
  }
6579
6580
2.64M
  const Position cuPos{ xPos, yPos };
6581
6582
  //int numLeftCTUs = (1 << ((7 - ctuSizeLog2) << 1)) - ((ctuSizeLog2 < 7) ? 1 : 0);
6583
2.64M
  static const int numLeftCTUsLUT[3] = { 15, 3, 1 };
6584
6585
  // in the same CTU line
6586
2.64M
  const int numLeftCTUs = numLeftCTUsLUT[ctuSizeLog2 - 5];
6587
6588
2.64M
  if( ( refRightX >> ctuSizeLog2 <= xPos >> ctuSizeLog2 ) && ( refLeftX >> ctuSizeLog2 >= ( xPos >> ctuSizeLog2 ) - numLeftCTUs ) )
6589
2.64M
  {
6590
    // in the same CTU, or left CTU
6591
    // if part of ref block is in the left CTU, some area can be referred from the not-yet updated local CTU buffer
6592
2.64M
    if( ( ctuSizeLog2 == 7 ) && ( ( refLeftX >> ctuSizeLog2 ) == ( ( xPos >> ctuSizeLog2 ) - 1 ) ) )
6593
1.39M
    {
6594
      // ref block's collocated block in current CTU
6595
1.39M
      const Position refPosCol64x64{ ( refLeftX + ctuSize ) & ~63, refTopY & ~63 };
6596
1.39M
      if( refPosCol64x64 == Position{ xPos & ~63, yPos & ~63 } )
6597
753k
        return false;
6598
6599
      //CodingUnit* curef = cu.cs->getCU(refPosCol64x64, CH_L, cu.treeType);
6600
      //bool isDecomp = curef && ((cu.cs != curef->cs) || cu.idx < curef->idx);
6601
637k
      bool isDecomp = isYPartBefore( cu.splitSeries, ctuSizeLog2, cuPos, refPosCol64x64 );
6602
637k
      if( isDecomp )
6603
296k
      {
6604
296k
        return false;
6605
296k
      }
6606
637k
    }
6607
2.64M
  }
6608
80
  else
6609
80
    return false;
6610
6611
  // in the same CTU, or valid area from left CTU. Check if the reference block is already coded
6612
1.59M
  const Position refPosBR{ refRightX, refBottomY };
6613
  //CodingUnit* curef = cu.cs->getCU(refPosBR, CH_L, cu.treeType);
6614
  //bool isDecomp = curef && ((cu.cs != curef->cs) || cu.idx < curef->idx);
6615
1.59M
  bool isDecomp = ( ( refPosBR.x >> ctuSizeLog2 ) < ( cuPos.x >> ctuSizeLog2 ) ) || ( refRightX < xPos && refBottomY < yPos ) || isYPartBefore( cu.splitSeries, ctuSizeLog2, cuPos, refPosBR );
6616
6617
1.59M
  return isDecomp;
6618
2.64M
}
6619
6620
} // namespace vvenc
6621
6622
//! \}
6623