Coverage Report

Created: 2026-06-10 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/vvenc/source/Lib/EncoderLib/EncCu.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     EncCu.cpp
45
    \brief    Coding Unit (CU) encoder class
46
*/
47
48
#include "EncCu.h"
49
#include "EncLib.h"
50
#include "Analyze.h"
51
#include "EncPicture.h"
52
#include "EncModeCtrl.h"
53
#include "BitAllocation.h"
54
#include "EncStage.h"
55
56
#include "CommonLib/dtrace_codingstruct.h"
57
#include "CommonLib/Picture.h"
58
#include "CommonLib/UnitTools.h"
59
#include "CommonLib/dtrace_buffer.h"
60
#include "CommonLib/TimeProfiler.h"
61
#include "CommonLib/SearchSpaceCounter.h"
62
63
#include <mutex>
64
#include <cmath>
65
#include <algorithm>
66
67
//! \ingroup EncoderLib
68
//! \{
69
70
namespace vvenc {
71
72
const MergeIdxPair EncCu::m_GeoModeTest[GEO_MAX_NUM_CANDS] = { MergeIdxPair{0, 1}, MergeIdxPair{1, 0}, MergeIdxPair{0, 2}, MergeIdxPair{1, 2}, MergeIdxPair{2, 0},
73
                                                               MergeIdxPair{2, 1}, MergeIdxPair{0, 3}, MergeIdxPair{1, 3}, MergeIdxPair{2, 3}, MergeIdxPair{3, 0},
74
                                                               MergeIdxPair{3, 1}, MergeIdxPair{3, 2}, MergeIdxPair{0, 4}, MergeIdxPair{1, 4}, MergeIdxPair{2, 4},
75
                                                               MergeIdxPair{3, 4}, MergeIdxPair{4, 0}, MergeIdxPair{4, 1}, MergeIdxPair{4, 2}, MergeIdxPair{4, 3},
76
                                                               MergeIdxPair{0, 5}, MergeIdxPair{1, 5}, MergeIdxPair{2, 5}, MergeIdxPair{3, 5}, MergeIdxPair{4, 5},
77
                                                               MergeIdxPair{5, 0}, MergeIdxPair{5, 1}, MergeIdxPair{5, 2}, MergeIdxPair{5, 3}, MergeIdxPair{5, 4} };
78
79
80
// Shape coefSquareCUsFasterFastMedium (2 x 5 x 2 x 2 x 2): preset (faster and fast + medium) x cusize x nspred x sptype x numcoef
81
82
const double EncCu::coefSquareCUsFasterFastMedium[2][5][2][2][2] = {
83
{{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, },  {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, },  },
84
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, },  {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, },  },
85
{{{-1.00000000, -1.00000000, }, {0.07848505, 0.00225808, }, },  {{-1.00000000, -1.00000000, }, {0.07509575, 0.00204789, }, },  },
86
{{{-1.00000000, -1.00000000, }, {0.10833051, 0.00053144, }, },  {{-1.00000000, -1.00000000, }, {0.08304352, 0.00142876, }, },  },
87
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, },  {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, },  },
88
},
89
{{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, },  {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, },  },
90
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, },  {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, },  },
91
{{{0.06852235, 0.00388054, }, {0.09236045, 0.00084528, }, },  {{0.06955832, 0.00289679, }, {0.09598522, 0.00096187, }, },  },
92
{{{0.07268085, 0.00302796, }, {0.09323753, 0.00050996, }, },  {{0.06123618, 0.00471601, }, {0.09253389, 0.00046826, }, },  },
93
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, },  {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, },  },
94
},
95
};
96
97
// Shape coefSquareCUsSlowSlower (2 x 5 x 2 x 5 x 2 x 2 x 2): preset (Slow + Slower) x cusize x nspred x qtdepth x mtdepth x sptype x numcoef
98
99
const double EncCu::coefSquareCUsSlowSlower[2][5][2][5][2][2][2] = {
100
{{{{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
101
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
102
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
103
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
104
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
105
},
106
{{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
107
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
108
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
109
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
110
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
111
},
112
},
113
{{{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
114
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
115
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
116
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
117
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
118
},
119
{{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
120
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
121
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
122
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
123
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
124
},
125
},
126
{{{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
127
{{{0.06057349, 0.00447803, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
128
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{0.06948736, 0.00327774, }, {0.06396861, 0.00789923, }, }, },
129
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
130
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
131
},
132
{{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
133
{{{0.05526461, 0.00436703, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
134
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{0.05661641, 0.00546358, }, {0.06680048, 0.00670604, }, }, },
135
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
136
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
137
},
138
},
139
{{{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
140
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{0.06556926, 0.00455697, }, {0.06803347, 0.00365396, }, }, },
141
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
142
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
143
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
144
},
145
{{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
146
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{0.06394328, 0.00403533, }, {0.06688063, 0.00272684, }, }, },
147
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
148
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
149
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
150
},
151
},
152
{{{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{0.05533525, 0.00235007, }, {0.07184475, 0.00086154, }, }, },
153
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
154
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
155
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
156
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
157
},
158
{{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
159
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
160
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
161
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
162
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
163
},
164
},
165
},
166
{{{{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
167
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
168
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
169
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
170
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
171
},
172
{{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
173
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
174
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
175
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
176
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
177
},
178
},
179
{{{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
180
{{{0.04770815, 0.00774597, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
181
{{{0.05509813, 0.00812349, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
182
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{0.04719064, 0.01023887, }, {0.04641434, 0.01279769, }, }, },
183
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
184
},
185
{{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
186
{{{0.02777251, 0.00811989, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
187
{{{0.04848973, 0.00628111, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
188
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{0.04924294, 0.00769725, }, {0.04491680, 0.01120645, }, }, },
189
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
190
},
191
},
192
{{{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
193
{{{0.06856533, 0.00418949, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
194
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{0.07059085, 0.00348835, }, {0.06051544, 0.00821365, }, }, },
195
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
196
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
197
},
198
{{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
199
{{{0.07461087, 0.00229937, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
200
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{0.05893714, 0.00513168, }, {0.05809189, 0.00772994, }, }, },
201
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
202
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
203
},
204
},
205
{{{{{0.06922080, 0.00274816, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
206
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{0.06176300, 0.00374356, }, {0.06085891, 0.00361274, }, }, },
207
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
208
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
209
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
210
},
211
{{{{0.06611224, 0.00256748, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
212
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{0.06364765, 0.00282819, }, {0.05888407, 0.00320947, }, }, },
213
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
214
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
215
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
216
},
217
},
218
{{{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{0.05637817, 0.00184637, }, {0.06937475, 0.00091860, }, }, },
219
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
220
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
221
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
222
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
223
},
224
{{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
225
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
226
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
227
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
228
{{{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, {{-1.00000000, -1.00000000, }, {-1.00000000, -1.00000000, }, }, },
229
},
230
},
231
},
232
};
233
234
// ====================================================================================================================
235
EncCu::EncCu()
236
17.7k
  : m_CtxCache          ( nullptr )
237
17.7k
  , m_globalCtuQpVector ( nullptr )
238
17.7k
  , m_wppMutex          ( nullptr )
239
17.7k
  , m_CABACEstimator    ( nullptr )
240
17.7k
{
241
17.7k
}
242
243
void EncCu::initPic( Picture* pic )
244
4.44k
{
245
4.44k
  const ReshapeData& reshapeData = pic->reshapeData;
246
4.44k
  m_cRdCost.setReshapeParams( reshapeData.getReshapeLumaLevelToWeightPLUT(), reshapeData.getChromaWeight() );
247
4.44k
  m_cInterSearch.setSearchRange( pic->cs->slice, *m_pcEncCfg );
248
249
4.44k
  m_wppMutex = (m_pcEncCfg->m_numThreads > 0 ) ? &pic->wppMutex : nullptr;
250
4.44k
}
251
252
void EncCu::initSlice( const Slice* slice )
253
4.44k
{
254
4.44k
  m_cTrQuant.setLambdas( slice->getLambdas() );
255
4.44k
  m_cRdCost.setLambda( slice->getLambdas()[0], slice->sps->bitDepths );
256
4.44k
}
257
258
void EncCu::setCtuEncRsrc( CABACWriter* cabacEstimator, CtxCache* ctxCache, ReuseUniMv* pReuseUniMv, BlkUniMvInfoBuffer* pBlkUniMvInfoBuffer, AffineProfList* pAffineProfList, IbcBvCand* pCachedBvs )
259
3.46k
{
260
3.46k
  m_CABACEstimator = cabacEstimator;
261
3.46k
  m_CtxCache       = ctxCache;
262
3.46k
  m_cIntraSearch.setCtuEncRsrc( cabacEstimator, ctxCache );
263
3.46k
  m_cInterSearch.setCtuEncRsrc( cabacEstimator, ctxCache, pReuseUniMv, pBlkUniMvInfoBuffer, pAffineProfList, pCachedBvs );
264
3.46k
}
265
266
void EncCu::setUpLambda (Slice& slice, const double dLambda, const int iQP, const bool setSliceLambda, const bool saveUnadjusted)
267
7.90k
{
268
  // store lambda
269
7.90k
  m_cRdCost.setLambda( dLambda, slice.sps->bitDepths );
270
271
  // for RDO
272
  // in RdCost there is only one lambda because the luma and chroma bits are not separated, instead we weight the distortion of chroma.
273
7.90k
  double dLambdas[MAX_NUM_COMP] = { dLambda };
274
23.7k
  for( uint32_t compIdx = 1; compIdx < MAX_NUM_COMP; compIdx++ )
275
15.8k
  {
276
15.8k
    const ComponentID compID = ComponentID( compIdx );
277
15.8k
    int chromaQPOffset       = slice.pps->chromaQpOffset[compID] + slice.sliceChromaQpDelta[ compID ];
278
15.8k
    int qpc = slice.sps->chromaQpMappingTable.getMappedChromaQpValue(compID, iQP) + chromaQPOffset;
279
15.8k
    double tmpWeight         = pow( 2.0, ( iQP - qpc ) / 3.0 );  // takes into account of the chroma qp mapping and chroma qp Offset
280
15.8k
    if( m_pcEncCfg->m_DepQuantEnabled/* && !( m_pcEncCfg->getLFNST() ) */)
281
15.8k
    {
282
15.8k
      tmpWeight *= ( m_pcEncCfg->m_GOPSize >= 8 ? pow( 2.0, 0.1/3.0 ) : pow( 2.0, 0.2/3.0 ) );  // increase chroma weight for dependent quantization (in order to reduce bit rate shift from chroma to luma)
283
15.8k
    }
284
15.8k
    m_cRdCost.setDistortionWeight( compID, tmpWeight );
285
15.8k
    dLambdas[compIdx] = dLambda / tmpWeight;
286
15.8k
  }
287
288
  // for RDOQ
289
7.90k
  m_cTrQuant.setLambdas( dLambdas );
290
291
  // for SAO, ALF
292
7.90k
  if (setSliceLambda)
293
4.44k
  {
294
4.44k
    slice.setLambdas( dLambdas );
295
4.44k
  }
296
7.90k
  if( saveUnadjusted )
297
7.90k
  {
298
7.90k
    m_cRdCost.saveUnadjustedLambda();
299
7.90k
  }
300
7.90k
}
301
302
void EncCu::updateLambda(const Slice& slice, const double ctuLambda, const int ctuQP, const int newQP, const bool saveUnadjusted)
303
3.36k
{
304
3.36k
  const double  corrFactor = pow (2.0, double (newQP - ctuQP) / 3.0);
305
3.36k
  const double  newLambda  = ctuLambda * corrFactor;
306
3.36k
  const double* oldLambdas = slice.getLambdas(); // assumes prior setUpLambda (slice, ctuLambda) call!
307
3.36k
  const double  newLambdas[MAX_NUM_COMP] = { oldLambdas[COMP_Y] * corrFactor, oldLambdas[COMP_Cb] * corrFactor, oldLambdas[COMP_Cr] * corrFactor };
308
309
3.36k
  m_cTrQuant.setLambdas ( newLambdas);
310
3.36k
  m_cRdCost.setLambda   ( newLambda, slice.sps->bitDepths);
311
312
3.36k
  if (saveUnadjusted)
313
3.36k
  {
314
3.36k
    m_cRdCost.saveUnadjustedLambda(); // TODO hlm: check if this actually improves the overall quality
315
3.36k
  }
316
3.36k
}
317
318
void EncCu::init( const VVEncCfg& encCfg, const SPS& sps, std::vector<int>* const globalCtuQpVector, Ctx* syncPicCtx, RateCtrl* pRateCtrl )
319
17.7k
{
320
17.7k
  DecCu::init( &m_cTrQuant, &m_cIntraSearch, &m_cInterSearch, encCfg.m_internChromaFormat );
321
17.7k
  m_cRdCost.create     ();
322
17.7k
  m_cRdCost.setCostMode( encCfg.m_costMode );
323
17.7k
  if ( encCfg.m_lumaReshapeEnable || encCfg.m_lumaLevelToDeltaQPEnabled )
324
0
  {
325
0
    m_cRdCost.setReshapeInfo( encCfg.m_lumaReshapeEnable ? encCfg.m_reshapeSignalType : RESHAPE_SIGNAL_PQ, encCfg.m_internalBitDepth[ CH_L ], encCfg.m_internChromaFormat );
326
0
  }
327
328
17.7k
  m_modeCtrl.init     ( encCfg, &m_cRdCost );
329
17.7k
  m_cIntraSearch.init ( encCfg, &m_cTrQuant, &m_cRdCost, &m_SortedPelUnitBufs, m_unitCache );
330
17.7k
  m_cInterSearch.init ( encCfg, &m_cTrQuant, &m_cRdCost, &m_modeCtrl, m_cIntraSearch.getSaveCSBuf() );
331
17.7k
  m_cTrQuant.init     ( nullptr, encCfg.m_RDOQ, encCfg.m_useRDOQTS, false, true, encCfg.m_quantThresholdVal );
332
333
17.7k
  m_syncPicCtx = syncPicCtx;                         ///< context storage for state of contexts at the wavefront/WPP/entropy-coding-sync second CTU of tile-row used for estimation
334
17.7k
  m_pcRateCtrl = pRateCtrl;
335
336
  // Initialise scaling lists: The encoder will only use the SPS scaling lists. The PPS will never be marked present.
337
17.7k
  const int maxLog2TrDynamicRange[ MAX_NUM_CH ] = { sps.getMaxLog2TrDynamicRange(), sps.getMaxLog2TrDynamicRange() };
338
17.7k
  m_cTrQuant.getQuant()->setFlatScalingList( maxLog2TrDynamicRange, sps.bitDepths );
339
340
17.7k
  m_pcEncCfg       = &encCfg;
341
342
17.7k
  m_GeoCostList.init( encCfg.m_maxNumGeoCand );
343
344
17.7k
  unsigned      uiMaxSize    = encCfg.m_CTUSize;
345
17.7k
  ChromaFormat  chromaFormat = encCfg.m_internChromaFormat;
346
347
17.7k
  Area ctuArea = Area( 0, 0, uiMaxSize, uiMaxSize );
348
349
17.7k
  m_mergeItemList.init( encCfg.m_maxMergeRdCandNumTotal, m_pcEncCfg->m_Geo > 1 ? 3 : 1, chromaFormat, uiMaxSize, uiMaxSize );
350
351
231k
  for( int i = 0; i < maxCuDepth; i++ )
352
213k
  {
353
213k
    Area area = Area( 0, 0, uiMaxSize >> ( i >> 1 ), uiMaxSize >> ( ( i + 1 ) >> 1 ) );
354
355
213k
    if( area.width < (1 << MIN_CU_LOG2) || area.height < (1 << MIN_CU_LOG2) )
356
17.7k
    {
357
17.7k
      m_pTempCS[i] = m_pBestCS[i] = nullptr;
358
17.7k
      continue;
359
17.7k
    }
360
361
195k
    m_pTempCS[i] = new CodingStructure( m_unitCache, nullptr );
362
195k
    m_pBestCS[i] = new CodingStructure( m_unitCache, nullptr );
363
364
195k
    m_pTempCS[i]->createForSearch( chromaFormat, area );
365
195k
    m_pBestCS[i]->createForSearch( chromaFormat, area );
366
367
195k
    m_pOrgBuffer[i].create( chromaFormat, area );
368
195k
    m_pRspBuffer[i].create( CHROMA_400, area );
369
195k
  }
370
371
17.7k
  m_pTempCS2 = new CodingStructure( m_unitCache, nullptr );
372
17.7k
  m_pBestCS2 = new CodingStructure( m_unitCache, nullptr );
373
374
17.7k
  m_pTempCS2->createForSearch( chromaFormat, ctuArea );
375
17.7k
  m_pBestCS2->createForSearch( chromaFormat, ctuArea );
376
377
17.7k
  m_cuChromaQpOffsetIdxPlus1 = 0;
378
17.7k
  m_tempQpDiff = 0;
379
17.7k
  m_globalCtuQpVector = globalCtuQpVector;
380
381
17.7k
  m_SortedPelUnitBufs.create( chromaFormat, uiMaxSize, uiMaxSize );
382
383
266k
  for( uint8_t i = 0; i < MAX_TMP_BUFS; i++)
384
248k
  {
385
248k
    m_aTmpStorageLCU[i].create(chromaFormat, Area(0, 0, uiMaxSize, uiMaxSize));
386
248k
  }
387
124k
  for (unsigned ui = 0; ui < MRG_MAX_NUM_CANDS; ui++)
388
106k
  {
389
106k
    m_acMergeTmpBuffer[ui].create(chromaFormat, Area(0, 0, uiMaxSize, uiMaxSize));
390
106k
  }
391
392
17.7k
  const unsigned maxDepth = 2 * MAX_CU_SIZE_IDX;
393
17.7k
  m_CtxBuffer.resize( maxDepth );
394
17.7k
  m_CurrCtx = 0;
395
17.7k
  if( encCfg.m_EDO )
396
17.7k
    m_dbBuffer.create( chromaFormat, Area( 0, 0, uiMaxSize, uiMaxSize ), 0, 8 );
397
398
17.7k
  m_MergeSimpleFlag = 0;
399
17.7k
  m_tileIdx = 0;
400
17.7k
}
401
402
403
void EncCu::destroy()
404
17.7k
{
405
231k
  for( int i = 0; i < maxCuDepth; i++ )
406
213k
  {
407
213k
    if( m_pTempCS[i] )
408
195k
    {
409
195k
      m_pTempCS[i]->destroy();
410
195k
      delete m_pTempCS[i]; m_pTempCS[i] = nullptr;
411
195k
    }
412
413
213k
    if( m_pBestCS[i] )
414
195k
    {
415
195k
      m_pBestCS[i]->destroy();
416
195k
      delete m_pBestCS[i]; m_pBestCS[i] = nullptr;
417
195k
    }
418
419
213k
    m_pOrgBuffer[i].destroy();
420
213k
    m_pRspBuffer[i].destroy();
421
213k
  }
422
423
17.7k
  m_pTempCS2->destroy();
424
17.7k
  m_pBestCS2->destroy();
425
426
17.7k
  delete m_pTempCS2; m_pTempCS2 = nullptr;
427
17.7k
  delete m_pBestCS2; m_pBestCS2 = nullptr;
428
429
17.7k
  m_SortedPelUnitBufs.destroy();
430
431
266k
  for( uint8_t i = 0; i < MAX_TMP_BUFS; i++)
432
248k
  {
433
248k
    m_aTmpStorageLCU[i].destroy();
434
248k
  }
435
124k
  for (unsigned ui = 0; ui < MRG_MAX_NUM_CANDS; ui++)
436
106k
  {
437
106k
    m_acMergeTmpBuffer[ui].destroy();
438
106k
  }
439
440
441
17.7k
  m_dbBuffer.destroy();
442
17.7k
}
443
444
445
EncCu::~EncCu()
446
17.7k
{
447
17.7k
  destroy();
448
17.7k
}
449
450
// ====================================================================================================================
451
// Public member functions
452
// ====================================================================================================================
453
454
void EncCu::encodeCtu( Picture* pic, int (&prevQP)[MAX_NUM_CH], uint32_t ctuXPosInCtus, uint32_t ctuYPosInCtus )
455
3.46k
{
456
3.46k
  CodingStructure&     cs          = *pic->cs;
457
3.46k
  Slice*               slice       = cs.slice;
458
3.46k
  const PreCalcValues& pcv         = *cs.pcv;
459
460
#if ENABLE_MEASURE_SEARCH_SPACE
461
  if( ctuXPosInCtus == 0 && ctuYPosInCtus == 0 )
462
  {
463
    g_searchSpaceAcc.picW = pic->lwidth();
464
    g_searchSpaceAcc.picH = pic->lheight();
465
    g_searchSpaceAcc.addSlice( slice->isIntra(), slice->depth );
466
  }
467
468
#endif
469
3.46k
  const int ctuRsAddr                 = ctuYPosInCtus * pcv.widthInCtus + ctuXPosInCtus;
470
471
3.46k
  const Position pos (ctuXPosInCtus * pcv.maxCUSize, ctuYPosInCtus * pcv.maxCUSize);
472
3.46k
  const UnitArea ctuArea( cs.area.chromaFormat, Area( pos.x, pos.y, pcv.maxCUSize, pcv.maxCUSize ) );
473
3.46k
  DTRACE_UPDATE( g_trace_ctx, std::make_pair( "ctu", ctuRsAddr ) );
474
475
3.46k
  const int tileXPosInCtus = cs.pps->tileColBd[cs.pps->ctuToTileCol[ctuXPosInCtus]];
476
3.46k
  const int tileYPosInCtus = cs.pps->tileRowBd[cs.pps->ctuToTileRow[ctuYPosInCtus]];
477
478
3.46k
  if( ( cs.slice->sliceType != VVENC_I_SLICE || cs.sps->IBC ) && ctuXPosInCtus == tileXPosInCtus )
479
1.95k
  {
480
1.95k
    const int tileRowId = cs.pps->getTileLineId( ctuXPosInCtus, ctuYPosInCtus );
481
1.95k
    cs.motionLutBuf[tileRowId].lut.resize( 0 );
482
1.95k
    cs.motionLutBuf[tileRowId].lutIbc.resize( 0 );
483
1.95k
  }
484
485
3.46k
  if( ( m_pcEncCfg->m_ensureWppBitEqual || m_pcEncCfg->m_entropyCodingSyncEnabled ) && ctuXPosInCtus == tileXPosInCtus )
486
1.95k
  {
487
1.95k
    m_CABACEstimator->initCtxModels( *slice );
488
489
1.95k
    if( m_pcEncCfg->m_entropyCodingSyncEnabled && ( ctuYPosInCtus > tileYPosInCtus ) )
490
0
    {
491
0
      m_CABACEstimator->getCtx() = m_syncPicCtx[slice->pps->getTileLineId( ctuXPosInCtus, ctuYPosInCtus - 1 )];
492
0
    }
493
494
1.95k
    prevQP[CH_L] = prevQP[CH_C] = slice->sliceQp; // hlm: call CU::predictQP() here!
495
1.95k
  }
496
1.51k
  else if( ctuXPosInCtus == tileXPosInCtus && ctuYPosInCtus == tileYPosInCtus )
497
0
  {
498
0
    m_CABACEstimator->initCtxModels( *slice );
499
0
    prevQP[CH_L] = prevQP[CH_C] = slice->sliceQp; // hlm: call CU::predictQP() here!
500
0
  }
501
502
3.46k
  xCompressCtu( cs, ctuArea, ctuRsAddr, prevQP );
503
504
3.46k
  m_CABACEstimator->resetBits();
505
3.46k
  m_CABACEstimator->coding_tree_unit( cs, ctuArea, prevQP, ctuRsAddr, true, true );
506
507
  // Store probabilities of second CTU in line into buffer - used only if wavefront-parallel-processing is enabled.
508
3.46k
  if( ctuXPosInCtus == tileXPosInCtus && m_pcEncCfg->m_entropyCodingSyncEnabled )
509
0
  {
510
0
    m_syncPicCtx[slice->pps->getTileLineId( ctuXPosInCtus, ctuYPosInCtus )] = m_CABACEstimator->getCtx();
511
0
  }
512
513
3.46k
  DTRACE_AREA_CRC( g_trace_ctx, D_CRC, cs, ctuArea );
514
3.46k
}
515
516
// ====================================================================================================================
517
// Protected member functions
518
// ====================================================================================================================
519
520
void EncCu::xCompressCtu( CodingStructure& cs, const UnitArea& area, const unsigned ctuRsAddr, const int prevQP[] )
521
3.46k
{
522
3.46k
  m_tileIdx = cs.pps->getTileIdx( area.lumaPos() );
523
524
3.46k
  m_modeCtrl.initCTUEncoding( *cs.slice, m_tileIdx );
525
526
  // init the partitioning manager
527
3.46k
  Partitioner *partitioner = &m_partitioner;
528
3.46k
  partitioner->initCtu( area, CH_L, *cs.slice );
529
  
530
3.46k
  const Position& lumaPos = area.lumaPos();
531
3.46k
  const bool leftSameTile  = lumaPos.x == 0 || m_tileIdx == cs.pps->getTileIdx( lumaPos.offset(-1, 0) );
532
3.46k
  const bool aboveSameTile = lumaPos.y == 0 || m_tileIdx == cs.pps->getTileIdx( lumaPos.offset( 0,-1) );
533
3.46k
  m_EDO = (!m_pcEncCfg->m_tileParallelCtuEnc || (leftSameTile && aboveSameTile)) ? m_pcEncCfg->m_EDO : 0;
534
  
535
3.46k
  if( m_pcEncCfg->m_IBCMode )
536
3.46k
  {
537
3.46k
    m_cInterSearch.resetCtuRecordIBC();
538
3.46k
  }
539
540
  // init current context pointer
541
3.46k
  m_CurrCtx = m_CtxBuffer.data();
542
543
3.46k
  PelStorage* orgBuffer = &m_pOrgBuffer[0];
544
3.46k
  PelStorage* rspBuffer = &m_pRspBuffer[0];
545
3.46k
  CodingStructure *tempCS =  m_pTempCS [0];
546
3.46k
  CodingStructure *bestCS =  m_pBestCS [0];
547
3.46k
  cs.initSubStructure( *tempCS, partitioner->chType, partitioner->currArea(), false, orgBuffer, rspBuffer );
548
3.46k
  cs.initSubStructure( *bestCS, partitioner->chType, partitioner->currArea(), false, orgBuffer, rspBuffer );
549
3.46k
  PROFILER_SCOPE_AND_STAGE_EXT( 1, _TPROF, P_COMPRESS_CU, tempCS, CH_L );
550
551
  // copy the relevant area
552
3.46k
  UnitArea clippedArea = clipArea( partitioner->currArea(), cs.area );
553
3.46k
  CPelUnitBuf org = cs.picture->getFilteredOrigBuffer().valid() ? cs.picture->getRspOrigBuf( clippedArea ) : cs.picture->getOrigBuf( clippedArea );
554
3.46k
  tempCS->getOrgBuf( clippedArea ).copyFrom( org );
555
3.46k
  const ReshapeData& reshapeData = cs.picture->reshapeData;
556
3.46k
  if( cs.slice->lmcsEnabled && reshapeData.getCTUFlag() )
557
0
  {
558
0
    tempCS->getRspOrgBuf( clippedArea.Y() ).rspSignal( org.get( COMP_Y) , reshapeData.getFwdLUT() );
559
0
  }
560
561
3.46k
  tempCS->currQP[CH_L] = bestCS->currQP[CH_L] =
562
3.46k
  tempCS->baseQP       = bestCS->baseQP       = cs.slice->sliceQp;
563
3.46k
  tempCS->prevQP[CH_L] = bestCS->prevQP[CH_L] = prevQP[CH_L];
564
565
3.46k
  xCompressCU( tempCS, bestCS, *partitioner );
566
  // all signals were already copied during compression if the CTU was split - at this point only the structures are copied to the top level CS
567
  
568
  // Ensure that a coding was found
569
  // Selected mode's RD-cost must be not MAX_DOUBLE.
570
3.46k
  CHECK( bestCS->cus.empty()                                   , "No possible encoding found" );
571
3.46k
  CHECK( bestCS->cus[0]->predMode == NUMBER_OF_PREDICTION_MODES, "No possible encoding found" );
572
3.46k
  CHECK( bestCS->cost             == MAX_DOUBLE                , "No possible encoding found" );
573
574
3.46k
  if ( m_wppMutex ) m_wppMutex->lock();
575
576
3.46k
  cs.useSubStructure( *bestCS, partitioner->chType, TREE_D, CS::getArea( *bestCS, area, partitioner->chType, partitioner->treeType ) );
577
578
3.46k
  if ( m_wppMutex ) m_wppMutex->unlock();
579
580
3.46k
  if( CS::isDualITree( cs ) && isChromaEnabled( cs.pcv->chrFormat ) )
581
3.46k
  {
582
3.46k
    m_CABACEstimator->getCtx() = m_CurrCtx->start;
583
584
3.46k
    partitioner->initCtu( area, CH_C, *cs.slice );
585
586
3.46k
    cs.initSubStructure( *tempCS, partitioner->chType, partitioner->currArea(), false, orgBuffer, rspBuffer );
587
3.46k
    cs.initSubStructure( *bestCS, partitioner->chType, partitioner->currArea(), false, orgBuffer, rspBuffer );
588
3.46k
    tempCS->currQP[CH_C] = bestCS->currQP[CH_C] =
589
3.46k
    tempCS->baseQP       = bestCS->baseQP       = cs.slice->sliceQp;
590
3.46k
    tempCS->prevQP[CH_C] = bestCS->prevQP[CH_C] = prevQP[CH_C];
591
592
3.46k
    xCompressCU( tempCS, bestCS, *partitioner );
593
    
594
    // Ensure that a coding was found
595
    // Selected mode's RD-cost must be not MAX_DOUBLE.
596
3.46k
    CHECK( bestCS->cus.empty()                                   , "No possible encoding found" );
597
3.46k
    CHECK( bestCS->cus[0]->predMode == NUMBER_OF_PREDICTION_MODES, "No possible encoding found" );
598
3.46k
    CHECK( bestCS->cost             == MAX_DOUBLE                , "No possible encoding found" );
599
600
3.46k
    if ( m_wppMutex ) m_wppMutex->lock();
601
602
3.46k
    cs.useSubStructure( *bestCS, partitioner->chType, TREE_D, CS::getArea( *bestCS, area, partitioner->chType, partitioner->treeType ) );
603
604
3.46k
    if ( m_wppMutex ) m_wppMutex->unlock();
605
3.46k
  }
606
607
  // reset context states and uninit context pointer
608
3.46k
  m_CABACEstimator->getCtx() = m_CurrCtx->start;
609
3.46k
  m_CurrCtx                  = 0;
610
3.46k
}
611
612
613
614
bool EncCu::xCheckBestMode( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode, const bool useEDO )
615
259k
{
616
259k
  bool bestCSUpdated = false;
617
618
259k
  if( !tempCS->cus.empty() )
619
157k
  {
620
157k
    if( tempCS->cus.size() == 1 )
621
118k
    {
622
118k
      const CodingUnit& cu = *tempCS->cus.front();
623
118k
      CHECK( cu.skip && !cu.mergeFlag, "Skip flag without a merge flag is not allowed!" );
624
118k
    }
625
626
157k
    DTRACE_BEST_MODE( tempCS, bestCS, m_cRdCost.getLambda(true), useEDO );
627
628
157k
    if( m_modeCtrl.useModeResult( encTestMode, tempCS, partitioner, useEDO ) )
629
142k
    {
630
142k
      std::swap( tempCS, bestCS );
631
      // store temp best CI for next CU coding
632
142k
      m_CurrCtx->best = m_CABACEstimator->getCtx();
633
142k
      bestCSUpdated = true;
634
142k
    }
635
157k
  }
636
637
  // reset context states
638
259k
  m_CABACEstimator->getCtx() = m_CurrCtx->start;
639
259k
  return bestCSUpdated;
640
641
259k
}
642
643
void xCheckFastCuChromaSplitting( CodingStructure*& tempCS, CodingStructure*& bestCS, Partitioner&  partitioner, ComprCUCtx& cuECtx )
644
0
{
645
0
  const uint32_t uiLPelX = tempCS->area.Cb().lumaPos().x;
646
0
  const uint32_t uiTPelY = tempCS->area.Cb().lumaPos().y;
647
648
0
  int lumaw = 0, lumah = 0;
649
0
  bool splitver      = true;
650
0
  bool splithor      = true;
651
0
  bool qtSplitChroma = true;
652
653
0
  if( partitioner.isSepTree( *tempCS ) && isChroma( partitioner.chType ) )
654
0
  {
655
0
    Position lumaRefPos( uiLPelX, uiTPelY );
656
0
    CodingUnit* colLumaCu = bestCS->lumaCS->getCU( lumaRefPos, CH_L, TREE_D );
657
658
0
    if( colLumaCu )
659
0
    {
660
0
      lumah = colLumaCu->Y().height;
661
0
      lumaw = colLumaCu->Y().width;
662
0
    }
663
0
  }
664
0
  else
665
0
  {
666
0
    return;
667
0
  }
668
669
0
  if( partitioner.getImplicitSplit( *tempCS ) != CU_DONT_SPLIT ) return;
670
671
0
  const CPelBuf orgCb = tempCS->getOrgBuf( COMP_Cb );
672
0
  const CPelBuf orgCr = tempCS->getOrgBuf( COMP_Cr );
673
674
0
  int th1 = FCBP_TH1;
675
676
0
  if( ( lumaw >> getChannelTypeScaleX( CH_C, tempCS->area.chromaFormat ) ) == orgCb.width )
677
0
  {
678
0
    if( ( bestCS->cost < ( th1*orgCb.width*orgCb.height ) ) )
679
0
    {
680
0
      splitver      = false;
681
0
      qtSplitChroma = false;
682
0
    }
683
0
  }
684
685
0
  if( ( lumah >> getChannelTypeScaleY( CH_C, tempCS->area.chromaFormat ) ) == orgCb.height )
686
0
  {
687
0
    if( ( bestCS->cost < ( th1*orgCb.width*orgCb.height ) ) )
688
0
    {
689
0
      splithor      = false;
690
0
      qtSplitChroma = false;
691
0
    }
692
0
  }
693
694
0
  cuECtx.doHorChromaSplit = splithor;
695
0
  cuECtx.doVerChromaSplit = splitver;
696
0
  cuECtx.doQtChromaSplit  = qtSplitChroma;
697
698
0
  if( orgCb.width == orgCb.height )
699
0
  {
700
0
    int varh_cb, varv_cb;
701
0
    int varh_cr, varv_cr;
702
703
0
    orgCb.calcVarianceSplit( orgCb, orgCb.width, varh_cb, varv_cb );
704
0
    orgCr.calcVarianceSplit( orgCr, orgCr.width, varh_cr, varv_cr );
705
706
0
    if( ( varh_cr*FCBP_TH2 < varv_cr * 100 ) && ( varh_cb*FCBP_TH2 < varv_cb * 100 ) )
707
0
    {
708
0
      cuECtx.doVerChromaSplit = false;
709
0
    }
710
0
    else if( ( varv_cr*FCBP_TH2 < varh_cr * 100 ) && ( varv_cb*FCBP_TH2 < varh_cb * 100 ) )
711
0
    {
712
0
      cuECtx.doHorChromaSplit = false;
713
0
    }
714
0
  }
715
0
}
716
717
void EncCu::xCompressCU( CodingStructure*& tempCS, CodingStructure*& bestCS, Partitioner& partitioner )
718
119k
{
719
119k
  const Area& lumaArea = tempCS->area.Y();
720
721
119k
  Slice&   slice      = *tempCS->slice;
722
119k
  const PPS &pps      = *tempCS->pps;
723
119k
  const SPS &sps      = *tempCS->sps;
724
119k
  const uint32_t uiLPelX  = tempCS->area.Y().lumaPos().x;
725
119k
  const uint32_t uiTPelY  = tempCS->area.Y().lumaPos().y;
726
119k
  const bool isBimEnabled = (m_pcEncCfg->m_blockImportanceMapping && !bestCS->picture->m_picShared->m_ctuBimQpOffset.empty());
727
728
119k
  m_modeCtrl.initBlk( tempCS->area, slice.pic->poc );
729
119k
  m_CABACEstimator->determineNeighborCus( *tempCS, partitioner.currArea(), partitioner.chType, partitioner.treeType );
730
731
119k
  if ((m_pcEncCfg->m_usePerceptQPA || isBimEnabled) && pps.useDQP && isLuma (partitioner.chType) && partitioner.currQgEnable())
732
6.83k
  {
733
6.83k
    const PreCalcValues &pcv = *pps.pcv;
734
6.83k
    Picture* const pic = bestCS->picture;
735
6.83k
    const uint32_t ctuRsAddr = getCtuAddr (partitioner.currQgPos, pcv);
736
737
6.83k
    if (partitioner.currSubdiv == 0) // CTU-level QP adaptation
738
3.46k
    {
739
3.46k
      if (m_pcEncCfg->m_usePerceptQPA)
740
3.46k
      {
741
3.46k
        if (m_pcEncCfg->m_internalUsePerceptQPATempFiltISlice == 2)
742
0
        {
743
0
          m_tempQpDiff = pic->ctuAdaptedQP[ctuRsAddr] - BitAllocation::applyQPAdaptationSubCtu (&slice, m_pcEncCfg, lumaArea, m_pcRateCtrl->getMinNoiseLevels());
744
0
        }
745
746
3.46k
        if ((!slice.isIntra()) && (pcv.maxCUSize > 64) && // sub-CTU QPA behavior - Museum fix
747
0
            (uiLPelX + (pcv.maxCUSize >> 1) < (m_pcEncCfg->m_PadSourceWidth)) &&
748
0
            (uiTPelY + (pcv.maxCUSize >> 1) < (m_pcEncCfg->m_PadSourceHeight)))
749
0
        {
750
0
          const uint32_t h = lumaArea.height >> 1;
751
0
          const uint32_t w = lumaArea.width  >> 1;
752
0
          const int adQPTL = BitAllocation::applyQPAdaptationSubCtu (&slice, m_pcEncCfg, Area (uiLPelX + 0, uiTPelY + 0, w, h), m_pcRateCtrl->getMinNoiseLevels());
753
0
          const int adQPTR = BitAllocation::applyQPAdaptationSubCtu (&slice, m_pcEncCfg, Area (uiLPelX + w, uiTPelY + 0, w, h), m_pcRateCtrl->getMinNoiseLevels());
754
0
          const int adQPBL = BitAllocation::applyQPAdaptationSubCtu (&slice, m_pcEncCfg, Area (uiLPelX + 0, uiTPelY + h, w, h), m_pcRateCtrl->getMinNoiseLevels());
755
0
          const int adQPBR = BitAllocation::applyQPAdaptationSubCtu (&slice, m_pcEncCfg, Area (uiLPelX + w, uiTPelY + h, w, h), m_pcRateCtrl->getMinNoiseLevels());
756
757
0
          tempCS->currQP[partitioner.chType] = tempCS->baseQP =
758
0
          bestCS->currQP[partitioner.chType] = bestCS->baseQP = std::min (std::min (adQPTL, adQPTR), std::min (adQPBL, adQPBR));
759
760
0
          if (m_pcEncCfg->m_internalUsePerceptQPATempFiltISlice == 2)
761
0
          {
762
0
            if ((m_globalCtuQpVector->size() > ctuRsAddr) && (slice.TLayer == 0) && // last CTU row of non-Intra key-frame
763
0
                (m_pcEncCfg->m_IntraPeriod == 2 * m_pcEncCfg->m_GOPSize) && (ctuRsAddr >= pcv.widthInCtus) && (uiTPelY + pcv.maxCUSize > m_pcEncCfg->m_PadSourceHeight))
764
0
            {
765
0
              m_globalCtuQpVector->at (ctuRsAddr) = m_globalCtuQpVector->at (ctuRsAddr - pcv.widthInCtus); // copy the pumping reducing QP offset from the top CTU neighbor
766
0
              tempCS->currQP[partitioner.chType] = tempCS->baseQP =
767
0
              bestCS->currQP[partitioner.chType] = bestCS->baseQP = tempCS->baseQP - m_globalCtuQpVector->at (ctuRsAddr);
768
0
            }
769
0
            tempCS->currQP[partitioner.chType] = tempCS->baseQP =
770
0
            bestCS->currQP[partitioner.chType] = bestCS->baseQP = Clip3 (0, MAX_QP, tempCS->baseQP + m_tempQpDiff);
771
0
          }
772
0
        }
773
3.46k
        else
774
3.46k
        {
775
3.46k
          tempCS->currQP[partitioner.chType] = tempCS->baseQP =
776
3.46k
          bestCS->currQP[partitioner.chType] = bestCS->baseQP = pic->ctuAdaptedQP[ctuRsAddr];
777
3.46k
        }
778
779
3.46k
        setUpLambda (slice, pic->ctuQpaLambda[ctuRsAddr], pic->ctuAdaptedQP[ctuRsAddr], false, true);
780
3.46k
      }
781
0
      else // isBimEnabled without QPA
782
0
      {
783
0
        const int baseQp         = tempCS->baseQP;
784
0
        const unsigned bimQpSize = (unsigned) bestCS->picture->m_picShared->m_ctuBimQpOffset.size();
785
0
        uint32_t ctuAddr         = ctuRsAddr;
786
787
0
        if (bimQpSize != pcv.sizeInCtus) // re-calculate correct address of BIM CTU QP offset
788
0
        {
789
0
          const unsigned bimCtuSize  = m_pcEncCfg->m_bimCtuSize;
790
0
          const unsigned bimCtuWidth = (pcv.lumaWidth + bimCtuSize - 1) / bimCtuSize;
791
792
0
          ctuAddr = getCtuAddrFromCtuSize (partitioner.currQgPos, Log2 (bimCtuSize), bimCtuWidth);
793
0
          CHECK (ctuAddr >= bimQpSize, "ctuAddr exceeds size of m_ctuBimQpOffset");
794
0
        }
795
0
        tempCS->currQP[partitioner.chType] = tempCS->baseQP =
796
0
        bestCS->currQP[partitioner.chType] = bestCS->baseQP = Clip3 (-sps.qpBDOffset[CH_L], MAX_QP, tempCS->baseQP + pic->m_picShared->m_ctuBimQpOffset[ctuAddr]);
797
798
0
        updateLambda (slice, slice.getLambdas()[0], baseQp, tempCS->baseQP, true);
799
0
      }
800
3.46k
    }
801
3.36k
    else if (m_pcEncCfg->m_usePerceptQPA && slice.isIntra()) // currSubdiv 2 - use sub-CTU QPA
802
3.36k
    {
803
3.36k
      CHECK ((partitioner.currArea().lwidth() >= pcv.maxCUSize) || (partitioner.currArea().lheight() >= pcv.maxCUSize), "sub-CTU delta-QP error");
804
3.36k
      tempCS->currQP[partitioner.chType] = tempCS->baseQP = BitAllocation::applyQPAdaptationSubCtu (&slice, m_pcEncCfg, lumaArea, m_pcRateCtrl->getMinNoiseLevels());
805
806
3.36k
      if (m_pcEncCfg->m_internalUsePerceptQPATempFiltISlice == 2)
807
0
      {
808
0
        tempCS->currQP[partitioner.chType] = tempCS->baseQP = Clip3 (0, MAX_QP, tempCS->baseQP + m_tempQpDiff);
809
0
      }
810
811
3.36k
      updateLambda (slice, pic->ctuQpaLambda[ctuRsAddr], pic->ctuAdaptedQP[ctuRsAddr], tempCS->baseQP, true);
812
3.36k
    }
813
6.83k
  }
814
815
119k
  if (partitioner.currQtDepth == 0)
816
6.93k
  {
817
6.93k
    m_MergeSimpleFlag = 0;
818
6.93k
  }
819
119k
  m_modeCtrl.initCULevel( partitioner, *tempCS, m_MergeSimpleFlag );
820
119k
  m_sbtCostSave[0] = m_sbtCostSave[1] = MAX_DOUBLE;
821
822
119k
  m_CurrCtx->start = m_CABACEstimator->getCtx();
823
824
119k
  m_cuChromaQpOffsetIdxPlus1 = 0;
825
826
119k
  if( slice.chromaQpAdjEnabled && partitioner.currQgChromaEnable() )
827
0
  {
828
    // TODO M0133 : double check encoder decisions with respect to chroma QG detection and actual encode
829
0
    int cuChromaQpOffsetSubdiv = slice.isIntra() ? slice.picHeader->cuChromaQpOffsetSubdivIntra : slice.picHeader->cuChromaQpOffsetSubdivInter;
830
0
    int lgMinCuSize = sps.log2MinCodingBlockSize +
831
0
      std::max<int>(0, floorLog2(sps.CTUSize) - sps.log2MinCodingBlockSize - int((cuChromaQpOffsetSubdiv + 1) / 2));
832
0
    m_cuChromaQpOffsetIdxPlus1 = ( ( uiLPelX >> lgMinCuSize ) + ( uiTPelY >> lgMinCuSize ) ) % ( pps.chromaQpOffsetListLen + 1 );
833
0
  }
834
835
119k
  DTRACE_UPDATE( g_trace_ctx, std::make_pair( "cux", uiLPelX ) );
836
119k
  DTRACE_UPDATE( g_trace_ctx, std::make_pair( "cuy", uiTPelY ) );
837
119k
  DTRACE_UPDATE( g_trace_ctx, std::make_pair( "cuw", tempCS->area.lwidth() ) );
838
119k
  DTRACE_UPDATE( g_trace_ctx, std::make_pair( "cuh", tempCS->area.lheight() ) );
839
119k
  DTRACE( g_trace_ctx, D_COMMON, "@(%4d,%4d) [%2dx%2d]\n", tempCS->area.lx(), tempCS->area.ly(), tempCS->area.lwidth(), tempCS->area.lheight() );
840
841
119k
  if( tempCS->slice->checkLDC )
842
119k
  {
843
119k
    m_bestBcwCost[0] = m_bestBcwCost[1] = std::numeric_limits<double>::max();
844
119k
    m_bestBcwIdx[0] = m_bestBcwIdx[1] = -1;
845
119k
  }
846
847
119k
  m_cInterSearch.resetSavedAffineMotion();
848
119k
  {
849
119k
    const ComprCUCtx &cuECtx      = *m_modeCtrl.comprCUCtx;
850
119k
    const CodingStructure& cs     = *tempCS;
851
119k
    const PartSplit implicitSplit = partitioner.getImplicitSplit( cs );
852
119k
    const bool isBoundary         = implicitSplit != CU_DONT_SPLIT;
853
119k
    const bool lossless           = false;
854
119k
    int qp                        = cs.baseQP;
855
856
#if ENABLE_MEASURE_SEARCH_SPACE
857
    if( !isBoundary )
858
    {
859
      g_searchSpaceAcc.addPartition( partitioner.currArea(), partitioner.isSepTree( *tempCS ) ? partitioner.chType : MAX_NUM_CH );
860
    }
861
862
#endif
863
119k
    if( ! isBoundary )
864
75.2k
    {
865
75.2k
      if (pps.useDQP && partitioner.isSepTree (*tempCS) && isChroma (partitioner.chType))
866
52.1k
      {
867
52.1k
        const ChromaFormat chromaFm = tempCS->area.chromaFormat;
868
52.1k
        const Position chromaCentral (tempCS->area.Cb().chromaPos().offset (tempCS->area.Cb().chromaSize().width >> 1, tempCS->area.Cb().chromaSize().height >> 1));
869
52.1k
        const Position lumaRefPos (chromaCentral.x << getChannelTypeScaleX (CH_C, chromaFm), chromaCentral.y << getChannelTypeScaleY (CH_C, chromaFm));
870
52.1k
        const CodingUnit* colLumaCu = bestCS->lumaCS->getCU (lumaRefPos, CH_L, TREE_D);
871
        // update qp
872
52.1k
        qp = colLumaCu->qp;
873
52.1k
      }
874
875
75.2k
      m_cIntraSearch.reset();
876
877
75.2k
      bool isReuseCU = m_modeCtrl.isReusingCuValid( cs, partitioner, qp );
878
879
75.2k
      bool checkIbc = m_pcEncCfg->m_IBCMode && bestCS->picture->useIBC && (partitioner.chType == CH_L);
880
75.2k
      if ((m_pcEncCfg->m_IBCFastMethod>3) && (cs.area.lwidth() * cs.area.lheight()) > (16 * 16))
881
0
      {
882
0
        checkIbc = false;
883
0
      }
884
75.2k
      if( isReuseCU )
885
0
      {
886
0
        xReuseCachedResult( tempCS, bestCS, partitioner );
887
0
      }
888
75.2k
      else
889
75.2k
      {
890
        // add first pass modes
891
75.2k
        if ( !slice.isIntra() && !slice.isIRAP() && !( cs.area.lwidth() == 4 && cs.area.lheight() == 4 ) && !partitioner.isConsIntra() )
892
0
        {
893
          // add inter modes
894
0
          EncTestMode encTestModeSkip = { ETM_MERGE_SKIP, ETO_STANDARD, qp, lossless };
895
0
          if (m_modeCtrl.tryMode(encTestModeSkip, cs, partitioner))
896
0
          {
897
0
            xCheckRDCostUnifiedMerge(tempCS, bestCS, partitioner, encTestModeSkip);
898
899
0
            CodingUnit* cu = bestCS->getCU(partitioner.chType, partitioner.treeType);
900
0
            if (cu)
901
0
              cu->mmvdSkip = cu->skip == false ? false : cu->mmvdSkip;
902
0
          }
903
0
          EncTestMode encTestMode = { ETM_INTER_ME, ETO_STANDARD, qp, lossless };
904
0
          if (m_modeCtrl.tryMode(encTestMode, cs, partitioner))
905
0
          {
906
0
            xCheckRDCostInter(tempCS, bestCS, partitioner, encTestMode);
907
0
          }
908
909
0
          if (m_pcEncCfg->m_AMVRspeed)
910
0
          {
911
0
            double bestIntPelCost = MAX_DOUBLE;
912
913
0
            EncTestMode encTestMode = {ETM_INTER_IMV, ETO_STANDARD, qp, lossless};
914
0
            if( m_modeCtrl.tryMode( encTestMode, cs, partitioner ) )
915
0
            {
916
0
              const bool skipAltHpelIF = ( int( ( encTestMode.opts & ETO_IMV ) >> ETO_IMV_SHIFT ) == 4 ) && ( bestIntPelCost > 1.25 * bestCS->cost );
917
0
              if (!skipAltHpelIF)
918
0
              {
919
0
                xCheckRDCostInterIMV(tempCS, bestCS, partitioner, encTestMode );
920
0
              }
921
0
            }
922
0
          }
923
0
        }
924
925
75.2k
        if (checkIbc && !partitioner.isConsInter())
926
23.1k
        {
927
23.1k
          EncTestMode encTestModeIBCMerge = { ETM_IBC_MERGE, ETO_STANDARD, qp, lossless };
928
23.1k
          if ((m_pcEncCfg->m_IBCFastMethod < 4) && (partitioner.chType == CH_L) && m_modeCtrl.tryMode(encTestModeIBCMerge, cs, partitioner))
929
23.1k
          {
930
23.1k
            xCheckRDCostIBCModeMerge2Nx2N(tempCS, bestCS, partitioner, encTestModeIBCMerge);
931
23.1k
          }
932
933
23.1k
          EncTestMode encTestModeIBC = { ETM_IBC, ETO_STANDARD, qp, lossless };
934
23.1k
          if (m_modeCtrl.tryMode(encTestModeIBC, cs, partitioner))
935
23.1k
          {
936
23.1k
            xCheckRDCostIBCMode(tempCS, bestCS, partitioner, encTestModeIBC);
937
23.1k
          }
938
23.1k
        }
939
75.2k
        if( m_EDO && bestCS->cost != MAX_DOUBLE )
940
20.6k
        {
941
20.6k
          xCalDebCost(*bestCS, partitioner);
942
20.6k
        }
943
944
        // add intra modes
945
75.2k
        EncTestMode encTestMode( {ETM_INTRA, ETO_STANDARD, qp, lossless} );
946
75.2k
        if( !partitioner.isConsInter() && m_modeCtrl.tryMode( encTestMode, cs, partitioner ) )
947
75.2k
        {
948
75.2k
          xCheckRDCostIntra( tempCS, bestCS, partitioner, encTestMode );
949
75.2k
        }
950
75.2k
      } // reusing cu
951
952
75.2k
      m_modeCtrl.beforeSplit( partitioner );
953
954
75.2k
      if (cuECtx.bestCS && ((cuECtx.bestCostNoImv == (MAX_DOUBLE * .5) || cuECtx.isReusingCu) && !slice.isIntra()) )
955
0
      {
956
0
        m_cInterSearch.loadGlobalUniMvs( lumaArea, *pps.pcv );
957
0
      }
958
959
75.2k
      if (!cs.slice->isIntra() && (partitioner.chType == CH_L) && ( m_pcEncCfg->m_qtbttSpeedUpMode & 2) && (partitioner.currQtDepth < 3) && bestCS->cus.size())
960
0
      {
961
0
        int flagDbefore = (bestCS->cus[0]->mergeFlag && !bestCS->cus[0]->mmvdMergeFlag && !bestCS->cus[0]->ispMode && !bestCS->cus[0]->geo) ? 1 : 0;
962
0
        if (partitioner.currQtDepth == 0)
963
0
        {
964
0
          m_MergeSimpleFlag = flagDbefore;
965
0
        }
966
0
        else
967
0
        {
968
0
          int markFlag = (partitioner.currQtDepth == 1) ? 1 : 3;
969
0
          m_MergeSimpleFlag = (flagDbefore << partitioner.currQtDepth) | (m_MergeSimpleFlag & markFlag);
970
0
        }
971
0
      }
972
75.2k
    } //boundary
973
974
119k
    if( ( m_pcEncCfg->m_IntraPeriod == 1 ) && ( partitioner.chType == CH_C ) )
975
0
    {
976
0
      xCheckFastCuChromaSplitting( tempCS, bestCS, partitioner, *m_modeCtrl.comprCUCtx );
977
0
    }
978
    //////////////////////////////////////////////////////////////////////////
979
    // split modes
980
119k
    EncTestMode lastTestMode;
981
982
119k
    if( cuECtx.qtBeforeBt )
983
19.1k
    {
984
19.1k
      EncTestMode encTestMode( { ETM_SPLIT_QT, ETO_STANDARD, qp, false } );
985
19.1k
      if( m_modeCtrl.trySplit( encTestMode, cs, partitioner, lastTestMode ) )
986
12.4k
      {
987
12.4k
        lastTestMode = encTestMode;
988
12.4k
        xCheckModeSplit( tempCS, bestCS, partitioner, encTestMode );
989
12.4k
      }
990
19.1k
    }
991
992
119k
    if( partitioner.canSplit( CU_HORZ_SPLIT, cs ) )
993
63.8k
    {
994
      // add split modes
995
63.8k
      EncTestMode encTestMode( { ETM_SPLIT_BT_H, ETO_STANDARD, qp, false } );
996
63.8k
      if( m_modeCtrl.trySplit( encTestMode, cs, partitioner, lastTestMode ) )
997
63.8k
      {
998
63.8k
        lastTestMode = encTestMode;
999
63.8k
        xCheckModeSplit( tempCS, bestCS, partitioner, encTestMode );
1000
63.8k
      }
1001
63.8k
    }
1002
1003
119k
    if( partitioner.canSplit( CU_VERT_SPLIT, cs ) )
1004
59.7k
    {
1005
      // add split modes
1006
59.7k
      EncTestMode encTestMode( { ETM_SPLIT_BT_V, ETO_STANDARD, qp, false } );
1007
59.7k
      if( m_modeCtrl.trySplit( encTestMode, cs, partitioner, lastTestMode ) )
1008
59.7k
      {
1009
59.7k
        lastTestMode = encTestMode;
1010
59.7k
        xCheckModeSplit( tempCS, bestCS, partitioner, encTestMode );
1011
59.7k
      }
1012
59.7k
    }
1013
1014
119k
    if( partitioner.canSplit( CU_TRIH_SPLIT, cs ) )
1015
26.4k
    {
1016
      // add split modes
1017
26.4k
      EncTestMode encTestMode( { ETM_SPLIT_TT_H, ETO_STANDARD, qp, false } );
1018
26.4k
      if( m_modeCtrl.trySplit( encTestMode, cs, partitioner, lastTestMode ) )
1019
1.40k
      {
1020
1.40k
        lastTestMode = encTestMode;
1021
1.40k
        xCheckModeSplit( tempCS, bestCS, partitioner, encTestMode );
1022
1.40k
      }
1023
26.4k
    }
1024
1025
119k
    if( partitioner.canSplit( CU_TRIV_SPLIT, cs ) )
1026
21.0k
    {
1027
      // add split modes
1028
21.0k
      EncTestMode encTestMode( { ETM_SPLIT_TT_V, ETO_STANDARD, qp, false } );
1029
21.0k
      if( m_modeCtrl.trySplit( encTestMode, cs, partitioner, lastTestMode ) )
1030
1.08k
      {
1031
1.08k
        lastTestMode = encTestMode;
1032
1.08k
        xCheckModeSplit( tempCS, bestCS, partitioner, encTestMode );
1033
1.08k
      }
1034
21.0k
    }
1035
1036
119k
    if( !cuECtx.qtBeforeBt )
1037
100k
    {
1038
100k
      EncTestMode encTestMode( { ETM_SPLIT_QT, ETO_STANDARD, qp, false } );
1039
100k
      if( m_modeCtrl.trySplit( encTestMode, cs, partitioner, lastTestMode ) )
1040
25.0k
      {
1041
25.0k
        lastTestMode = encTestMode;
1042
25.0k
        xCheckModeSplit( tempCS, bestCS, partitioner, encTestMode );
1043
25.0k
      }
1044
100k
    }
1045
119k
  }
1046
1047
119k
  if( bestCS->cus.empty() )
1048
0
  {
1049
0
    m_modeCtrl.finishCULevel( partitioner );
1050
0
    return;
1051
0
  }
1052
1053
  //////////////////////////////////////////////////////////////////////////
1054
  // Finishing CU
1055
  // set context states
1056
119k
  m_CABACEstimator->getCtx() = m_CurrCtx->best;
1057
1058
  // QP from last processed CU for further processing
1059
  //copy the qp of the last non-chroma CU
1060
119k
  int numCUInThisNode = (int)bestCS->cus.size();
1061
119k
  if( numCUInThisNode > 1 && bestCS->cus.back()->chType == CH_C && !CS::isDualITree( *bestCS ) )
1062
0
  {
1063
0
    CHECK( bestCS->cus[numCUInThisNode-2]->chType != CH_L, "wrong chType" );
1064
0
    bestCS->prevQP[partitioner.chType] = bestCS->cus[numCUInThisNode-2]->qp;
1065
0
  }
1066
119k
  else
1067
119k
  {
1068
119k
    bestCS->prevQP[partitioner.chType] = bestCS->cus.back()->qp;
1069
119k
  }
1070
119k
  if( ( !slice.isIntra() || slice.sps->IBC )
1071
119k
    && partitioner.chType == CH_L
1072
47.4k
    && bestCS->cus.size() == 1 && ( bestCS->cus.back()->predMode == MODE_INTER || bestCS->cus.back()->predMode == MODE_IBC )
1073
0
    && bestCS->area.Y() == (*bestCS->cus.back()).Y() )
1074
0
  {
1075
0
    const CodingUnit& cu = *bestCS->cus.front();
1076
0
    bool isIbcSmallBlk = CU::isIBC(cu) && (cu.lwidth() * cu.lheight() <= 16);
1077
0
    if (!cu.affine && !cu.geo && !isIbcSmallBlk)
1078
0
    {
1079
0
      const MotionInfo &mi = cu.getMotionInfo();
1080
0
      HPMVInfo hMi( mi, ( mi.interDir() == 3 ) ? cu.BcwIdx : BCW_DEFAULT, cu.imv == IMV_HPEL, CU::isIBC( cu ) );
1081
0
      cu.cs->addMiToLut( CU::isIBC( cu ) ? cu.cs->motionLut.lutIbc : cu.cs->motionLut.lut, hMi );
1082
0
    }
1083
0
  }
1084
1085
119k
  m_modeCtrl.finishCULevel( partitioner );
1086
119k
  if( m_cIntraSearch.getSaveCuCostInSCIPU() && bestCS->cus.size() == 1 )
1087
0
  {
1088
0
    m_cIntraSearch.saveCuAreaCostInSCIPU( Area( partitioner.currArea().lumaPos(), partitioner.currArea().lumaSize() ), bestCS->cost );
1089
0
  }
1090
1091
  // Assert if Best prediction mode is NONE
1092
  // Selected mode's RD-cost must be not MAX_DOUBLE.
1093
119k
  CHECK( bestCS->cus.empty()                                   , "No possible encoding found" );
1094
119k
  CHECK( bestCS->cus[0]->predMode == NUMBER_OF_PREDICTION_MODES, "No possible encoding found" );
1095
119k
  CHECK( bestCS->cost             == MAX_DOUBLE                , "No possible encoding found" );
1096
119k
}
1097
1098
1099
void EncCu::xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode )
1100
163k
{
1101
163k
  const ModeType modeTypeParent  = partitioner.modeType;
1102
163k
  const TreeType treeTypeParent  = partitioner.treeType;
1103
163k
  const ChannelType chTypeParent = partitioner.chType;
1104
1105
163k
  int signalModeConsVal = CS::signalModeCons( *tempCS, partitioner.currArea(), getPartSplit(encTestMode), modeTypeParent);
1106
163k
  int numRoundRdo = signalModeConsVal == LDT_MODE_TYPE_SIGNAL ? 2 : 1;
1107
163k
  bool skipInterPass = false;
1108
326k
  for( int i = 0; i < numRoundRdo; i++ )
1109
163k
  {
1110
    //change cons modes
1111
163k
    if( signalModeConsVal == LDT_MODE_TYPE_SIGNAL )
1112
0
    {
1113
0
      CHECK( numRoundRdo != 2, "numRoundRdo shall be 2 - [LDT_MODE_TYPE_SIGNAL]" );
1114
0
      partitioner.modeType = (i == 0) ? MODE_TYPE_INTER : MODE_TYPE_INTRA;
1115
0
    }
1116
163k
    else if( signalModeConsVal == LDT_MODE_TYPE_INFER )
1117
0
    {
1118
0
      CHECK( numRoundRdo != 1, "numRoundRdo shall be 1 - [LDT_MODE_TYPE_INFER]" );
1119
0
      partitioner.modeType = MODE_TYPE_INTRA;
1120
0
    }
1121
163k
    else if( signalModeConsVal == LDT_MODE_TYPE_INHERIT )
1122
163k
    {
1123
163k
      CHECK( numRoundRdo != 1, "numRoundRdo shall be 1 - [LDT_MODE_TYPE_INHERIT]" );
1124
163k
      partitioner.modeType = modeTypeParent;
1125
163k
    }
1126
1127
    //for lite intra encoding fast algorithm, set the status to save inter coding info
1128
163k
    if( modeTypeParent == MODE_TYPE_ALL && partitioner.modeType == MODE_TYPE_INTER )
1129
0
    {
1130
0
      m_cIntraSearch.setSaveCuCostInSCIPU( true );
1131
0
      m_cIntraSearch.setNumCuInSCIPU( 0 );
1132
0
    }
1133
163k
    else if( modeTypeParent == MODE_TYPE_ALL && partitioner.modeType != MODE_TYPE_INTER )
1134
163k
    {
1135
163k
      m_cIntraSearch.setSaveCuCostInSCIPU( false );
1136
163k
      if( partitioner.modeType == MODE_TYPE_ALL )
1137
163k
      {
1138
163k
        m_cIntraSearch.setNumCuInSCIPU( 0 );
1139
163k
      }
1140
163k
    }
1141
1142
163k
    xCheckModeSplitInternal( tempCS, bestCS, partitioner, encTestMode, modeTypeParent, skipInterPass );
1143
    //recover cons modes
1144
163k
    partitioner.modeType = modeTypeParent;
1145
163k
    partitioner.treeType = treeTypeParent;
1146
163k
    partitioner.chType = chTypeParent;
1147
163k
    if( modeTypeParent == MODE_TYPE_ALL )
1148
163k
    {
1149
163k
      m_cIntraSearch.setSaveCuCostInSCIPU( false );
1150
163k
      if( numRoundRdo == 2 && partitioner.modeType == MODE_TYPE_INTRA )
1151
0
      {
1152
0
        m_cIntraSearch.initCuAreaCostInSCIPU();
1153
0
      }
1154
163k
    }
1155
163k
    if( skipInterPass )
1156
0
    {
1157
0
      break;
1158
0
    }
1159
163k
  }
1160
163k
}
1161
1162
void EncCu::xCheckModeSplitInternal(CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode, const ModeType modeTypeParent, bool& skipInterPass )
1163
163k
{
1164
163k
  const int qp                     = encTestMode.qp;
1165
163k
  const int oldPrevQp              = tempCS->prevQP[partitioner.chType];
1166
163k
  const auto oldMotionLut          = tempCS->motionLut;
1167
163k
  const ReshapeData& reshapeData   = tempCS->picture->reshapeData;
1168
                                   
1169
163k
  const PartSplit split            = getPartSplit( encTestMode );
1170
163k
  const ModeType  modeTypeChild    = partitioner.modeType;
1171
1172
163k
  CHECK( !( split == CU_QUAD_SPLIT || split == CU_HORZ_SPLIT || split == CU_VERT_SPLIT
1173
163k
         || split == CU_TRIH_SPLIT || split == CU_TRIV_SPLIT ), "invalid split type" );
1174
1175
163k
  tempCS->initStructData( qp );
1176
1177
163k
  m_CABACEstimator->getCtx()       = m_CurrCtx->start;
1178
1179
163k
  const uint16_t split_ctx_size    = Ctx::SplitFlag.size() + Ctx::SplitQtFlag.size() + Ctx::SplitHvFlag.size() + Ctx::Split12Flag.size() + Ctx::ModeConsFlag.size();
1180
163k
  const TempCtx  ctxSplitFlags     ( m_CtxCache, SubCtx( CtxSet( Ctx::SplitFlag(), split_ctx_size ), m_CABACEstimator->getCtx() ) );
1181
1182
163k
  m_CABACEstimator->determineNeighborCus( *tempCS, partitioner.currArea(), partitioner.chType, partitioner.treeType );
1183
163k
  m_CABACEstimator->resetBits           ();
1184
163k
  m_CABACEstimator->split_cu_mode       ( split, *tempCS, partitioner );
1185
163k
  partitioner     . modeType            = modeTypeParent;
1186
163k
  m_CABACEstimator->mode_constraint     ( split, *tempCS, partitioner, modeTypeChild );
1187
163k
  partitioner     . modeType            = modeTypeChild;
1188
1189
163k
  const int64_t splitBits   = m_CABACEstimator->getEstFracBits();
1190
1191
163k
  const bool chromaNotSplit = modeTypeParent == MODE_TYPE_ALL && modeTypeChild == MODE_TYPE_INTRA;
1192
163k
  const bool isChromaTooBig = isChromaEnabled( tempCS->pps->pcv->chrFormat ) && tempCS->area.Y().maxDim() > tempCS->sps->getMaxTbSize();
1193
163k
  bool       skipSplitTest  = chromaNotSplit && isChromaTooBig;
1194
1195
163k
  if( !skipSplitTest )
1196
163k
  {
1197
163k
    double         a = -1, b = -1;
1198
163k
    const unsigned w       = partitioner.currArea().lwidth();
1199
163k
    const unsigned h       = partitioner.currArea().lheight();
1200
163k
    const bool contextCond = w == h && tempCS->slice->sliceType == VVENC_B_SLICE && isLuma( partitioner.chType ) && m_pcEncCfg->m_splitCostThrParamId >= 0 && m_pcEncCfg->m_splitCostThrParamId <= 3;
1201
1202
163k
    if( contextCond )
1203
0
    {
1204
0
      uint8_t nsPredInd = m_modeCtrl.comprCUCtx->bestNsPredMode.type == ETM_INTRA;
1205
0
      uint8_t szInd     = getLog2( w ) - 3;
1206
0
      uint8_t splitInd  = split == CU_QUAD_SPLIT ? 1 : 0;
1207
0
      if ( m_pcEncCfg->m_splitCostThrParamId <= 1 )
1208
0
      {
1209
0
        a = coefSquareCUsFasterFastMedium[m_pcEncCfg->m_splitCostThrParamId][szInd][nsPredInd][splitInd][0];
1210
0
        b = coefSquareCUsFasterFastMedium[m_pcEncCfg->m_splitCostThrParamId][szInd][nsPredInd][splitInd][1];
1211
0
      }
1212
0
      else
1213
0
      {
1214
0
        uint8_t mtInd = (partitioner.currMtDepth == 0);
1215
0
        a = coefSquareCUsSlowSlower[m_pcEncCfg->m_splitCostThrParamId - 2][szInd][nsPredInd][partitioner.currQtDepth][mtInd][splitInd][0];
1216
0
        b = coefSquareCUsSlowSlower[m_pcEncCfg->m_splitCostThrParamId - 2][szInd][nsPredInd][partitioner.currQtDepth][mtInd][splitInd][1];
1217
0
      }
1218
0
    }
1219
1220
163k
    if( a > -1 && b > -1 )
1221
0
    {
1222
0
      const double bestNsCost    = m_modeCtrl.comprCUCtx->bestCostBeforeSplit == MAX_DOUBLE ? -1 : m_modeCtrl.comprCUCtx->bestCostBeforeSplit;
1223
0
      const double factor        = 1.0 + b * exp( a * qp );
1224
0
      const double predSplitCost = bestNsCost / factor + splitBits;
1225
0
      skipSplitTest              = bestNsCost >= 0 && predSplitCost >= bestNsCost;
1226
0
    }
1227
163k
    else
1228
163k
    {
1229
163k
      int numChild = 3;
1230
163k
      if( split == CU_VERT_SPLIT || split == CU_HORZ_SPLIT ) numChild--;
1231
39.9k
      else if( split == CU_QUAD_SPLIT ) numChild++;
1232
1233
163k
      int64_t approxBits = m_pcEncCfg->m_qtbttSpeedUp > 0 ? numChild << SCALE_BITS : 0;
1234
1235
163k
      const double factor     = ( tempCS->currQP[partitioner.chType] > 30                              ? 1.1  : 1.075 ) +
1236
163k
                                (   m_pcEncCfg->m_qtbttSpeedUp > 0                                     ? 0.01 : 0.0   ) +
1237
163k
                                ( ( m_pcEncCfg->m_qtbttSpeedUp > 0 && isChroma( partitioner.chType ) ) ? 0.2  : 0.0   );
1238
       
1239
163k
      const double baseCost   = bestCS->cost + bestCS->costDbOffset;
1240
163k
      const double predCost   = baseCost / factor + splitBits + approxBits;
1241
163k
      skipSplitTest           = predCost >= baseCost;
1242
163k
    }
1243
163k
  }
1244
1245
163k
  if( skipSplitTest )
1246
101k
  {
1247
101k
    m_CABACEstimator->getCtx() = SubCtx( CtxSet( Ctx::SplitFlag(), split_ctx_size ), ctxSplitFlags );
1248
101k
    xCheckBestMode( tempCS, bestCS, partitioner, encTestMode );
1249
101k
    return;
1250
101k
  }
1251
1252
61.6k
  if( partitioner.treeType == TREE_D )
1253
61.6k
  {
1254
61.6k
    if( chromaNotSplit )
1255
0
    {
1256
0
      CHECK( partitioner.chType != CH_L, "chType must be luma" );
1257
0
      partitioner.treeType = TREE_L;
1258
0
    }
1259
61.6k
    else
1260
61.6k
    {
1261
61.6k
      partitioner.treeType = TREE_D;
1262
61.6k
    }
1263
61.6k
  }
1264
1265
61.6k
  partitioner.splitCurrArea( split, *tempCS );
1266
61.6k
  bool qgEnableChildren = partitioner.currQgEnable(); // QG possible at children level
1267
1268
61.6k
  m_CurrCtx++;
1269
1270
61.6k
  AffineMVInfo tmpMVInfo;
1271
61.6k
  bool isAffMVInfoSaved = m_cInterSearch.m_AffineProfList->savePrevAffMVInfo( 0, tmpMVInfo );
1272
1273
61.6k
  BlkUniMvInfo tmpUniMvInfo;
1274
61.6k
  bool         isUniMvInfoSaved = false;
1275
61.6k
  if( !tempCS->slice->isIntra() )
1276
0
  {
1277
0
    m_cInterSearch.m_BlkUniMvInfoBuffer->savePrevUniMvInfo( tempCS->area.Y(), tmpUniMvInfo, isUniMvInfoSaved );
1278
0
  }
1279
1280
61.6k
  DeriveCtx deriveCtx = m_CABACEstimator->getDeriveCtx();
1281
1282
61.6k
  do
1283
158k
  {
1284
158k
    const auto &subCUArea  = partitioner.currArea();
1285
1286
158k
    if( tempCS->picture->Y().contains( subCUArea.lumaPos() ) )
1287
112k
    {
1288
112k
      PelStorage* orgBuffer =  &m_pOrgBuffer[partitioner.currDepth];
1289
112k
      PelStorage* rspBuffer =  &m_pRspBuffer[partitioner.currDepth];
1290
112k
      CodingStructure *tempSubCS = m_pTempCS[partitioner.currDepth];
1291
112k
      CodingStructure *bestSubCS = m_pBestCS[partitioner.currDepth];
1292
1293
112k
      tempCS->initSubStructure( *tempSubCS, partitioner.chType, subCUArea, false, orgBuffer, rspBuffer );
1294
112k
      tempCS->initSubStructure( *bestSubCS, partitioner.chType, subCUArea, false, orgBuffer, rspBuffer );
1295
1296
      // copy org buffer, need to be done after initSubStructure because of reshaping!
1297
112k
      orgBuffer->copyFrom( tempCS->getOrgBuf( subCUArea ) );
1298
112k
      if( tempCS->slice->lmcsEnabled && reshapeData.getCTUFlag() )
1299
0
      {
1300
0
        rspBuffer->Y().copyFrom( tempCS->getRspOrgBuf( subCUArea.Y() ) );
1301
0
      }
1302
1303
112k
      tempSubCS->bestParent = bestSubCS->bestParent = bestCS;
1304
1305
112k
      xCompressCU(tempSubCS, bestSubCS, partitioner );
1306
1307
112k
      tempSubCS->bestParent = bestSubCS->bestParent = nullptr;
1308
1309
112k
      if( bestSubCS->cost == MAX_DOUBLE )
1310
0
      {
1311
0
        CHECK( split == CU_QUAD_SPLIT, "Split decision reusing cannot skip quad split" );
1312
0
        tempCS->cost = MAX_DOUBLE;
1313
0
        tempCS->costDbOffset = 0;
1314
0
        m_CurrCtx--;
1315
0
        partitioner.exitCurrSplit();
1316
0
        xCheckBestMode( tempCS, bestCS, partitioner, encTestMode );
1317
0
        if( partitioner.chType == CH_L )
1318
0
        {
1319
0
          tempCS->motionLut = oldMotionLut;
1320
0
        }
1321
1322
0
        m_CABACEstimator->getDeriveCtx() = deriveCtx;
1323
0
        return;
1324
0
      }
1325
1326
112k
      tempCS->useSubStructure( *bestSubCS, partitioner.chType, TREE_D, CS::getArea( *tempCS, subCUArea, partitioner.chType, partitioner.treeType ), partitioner.hasNextPart() || chromaNotSplit );
1327
1328
112k
      if( partitioner.currQgEnable() )
1329
6.73k
      {
1330
6.73k
        tempCS->prevQP[partitioner.chType] = bestSubCS->prevQP[partitioner.chType];
1331
6.73k
      }
1332
112k
      if( partitioner.isConsInter() )
1333
0
      {
1334
0
        for( int i = 0; i < bestSubCS->cus.size(); i++ )
1335
0
        {
1336
0
          CHECK( bestSubCS->cus[i]->predMode != MODE_INTER, "all CUs must be inter mode in an Inter coding region (SCIPU)" );
1337
0
        }
1338
0
      }
1339
112k
      else if( partitioner.isConsIntra() )
1340
0
      {
1341
0
        for( int i = 0; i < bestSubCS->cus.size(); i++ )
1342
0
        {
1343
0
          CHECK( bestSubCS->cus[i]->predMode == MODE_INTER, "all CUs must not be inter mode in an Intra coding region (SCIPU)" );
1344
0
        }
1345
0
      }
1346
1347
112k
      tempSubCS->releaseIntermediateData();
1348
112k
      bestSubCS->releaseIntermediateData();
1349
112k
      if( !tempCS->slice->isIntra() && partitioner.isConsIntra() )
1350
0
      {
1351
0
        tempCS->cost = m_cRdCost.calcRdCost( tempCS->fracBits, tempCS->dist );
1352
0
        if( tempCS->cost > bestCS->cost )
1353
0
        {
1354
0
          tempCS->cost = MAX_DOUBLE;
1355
0
          tempCS->costDbOffset = 0;
1356
0
          m_CurrCtx--;
1357
0
          partitioner.exitCurrSplit();
1358
0
          if( partitioner.chType == CH_L )
1359
0
          {
1360
0
            tempCS->motionLut = oldMotionLut;
1361
0
          }
1362
1363
0
          m_CABACEstimator->getDeriveCtx() = deriveCtx;
1364
0
          return;
1365
0
        }
1366
0
      }
1367
112k
    }
1368
158k
  } while( partitioner.nextPart( *tempCS ) );
1369
1370
61.6k
  partitioner.exitCurrSplit();
1371
1372
61.6k
  m_CurrCtx--;
1373
1374
61.6k
  m_CABACEstimator->getDeriveCtx() = deriveCtx;
1375
1376
61.6k
  if( chromaNotSplit )
1377
0
  {
1378
    //Note: In local dual tree region, the chroma CU refers to the central luma CU's QP.
1379
    //If the luma CU QP shall be predQP (no residual in it and before it in the QG), it must be revised to predQP before encoding the chroma CU
1380
    //Otherwise, the chroma CU uses predQP+deltaQP in encoding but is decoded as using predQP, thus causing encoder-decoded mismatch on chroma qp.
1381
0
    if( tempCS->pps->useDQP )
1382
0
    {
1383
      //find parent CS that including all coded CUs in the QG before this node
1384
0
      CodingStructure* qgCS = tempCS;
1385
0
      bool deltaQpCodedBeforeThisNode = false;
1386
0
      if( partitioner.currArea().lumaPos() != partitioner.currQgPos )
1387
0
      {
1388
0
        int numParentNodeToQgCS = 0;
1389
0
        while( qgCS->area.lumaPos() != partitioner.currQgPos )
1390
0
        {
1391
0
          CHECK( qgCS->parent == nullptr, "parent of qgCS shall exsit" );
1392
0
          qgCS = qgCS->parent;
1393
0
          numParentNodeToQgCS++;
1394
0
        }
1395
1396
        //check whether deltaQP has been coded (in luma CU or luma&chroma CU) before this node
1397
0
        CodingStructure* parentCS = tempCS->parent;
1398
0
        for( int i = 0; i < numParentNodeToQgCS; i++ )
1399
0
        {
1400
          //checking each parent
1401
0
          CHECK( parentCS == nullptr, "parentCS shall exsit" );
1402
0
          for( const auto &cu : parentCS->cus )
1403
0
          {
1404
0
            if( cu->rootCbf && !isChroma( cu->chType ) )
1405
0
            {
1406
0
              deltaQpCodedBeforeThisNode = true;
1407
0
              break;
1408
0
            }
1409
0
          }
1410
0
          parentCS = parentCS->parent;
1411
0
        }
1412
0
      }
1413
1414
      //revise luma CU qp before the first luma CU with residual in the SCIPU to predQP
1415
0
      if( !deltaQpCodedBeforeThisNode )
1416
0
      {
1417
        //get pred QP of the QG
1418
0
        const CodingUnit* cuFirst = qgCS->getCU( CH_L, TREE_D );
1419
0
        CHECK( cuFirst->lumaPos() != partitioner.currQgPos, "First cu of the Qg is wrong" );
1420
0
        int predQp = CU::predictQP( *cuFirst, qgCS->prevQP[CH_L] );
1421
1422
        //revise to predQP
1423
0
        int firstCuHasResidual = (int)tempCS->cus.size();
1424
0
        for( int i = 0; i < tempCS->cus.size(); i++ )
1425
0
        {
1426
0
          if( tempCS->cus[i]->rootCbf )
1427
0
          {
1428
0
            firstCuHasResidual = i;
1429
0
            break;
1430
0
          }
1431
0
        }
1432
1433
0
        for( int i = 0; i < firstCuHasResidual; i++ )
1434
0
        {
1435
0
          tempCS->cus[i]->qp = predQp;
1436
0
        }
1437
0
      }
1438
0
    }
1439
0
    partitioner.chType   = CH_C;
1440
0
    partitioner.treeType = TREE_C;
1441
1442
0
    m_CurrCtx++;
1443
1444
0
    CodingStructure *tempCSChroma = m_pTempCS2;
1445
0
    CodingStructure *bestCSChroma = m_pBestCS2;
1446
1447
0
    tempCS->initSubStructure( *tempCSChroma, partitioner.chType, partitioner.currArea(), false );
1448
0
    tempCS->initSubStructure( *bestCSChroma, partitioner.chType, partitioner.currArea(), false );
1449
0
    tempCSChroma->lumaCS = tempCS;
1450
0
    bestCSChroma->lumaCS = tempCS;
1451
0
    xCompressCU( tempCSChroma, bestCSChroma, partitioner );
1452
1453
    //attach chromaCS to luma CS and update cost
1454
0
    tempCS->useSubStructure( *bestCSChroma, partitioner.chType, TREE_D, CS::getArea( *bestCSChroma, partitioner.currArea(), partitioner.chType, partitioner.treeType ), false );
1455
1456
    //release tmp resource
1457
0
    tempCSChroma->releaseIntermediateData();
1458
0
    bestCSChroma->releaseIntermediateData();
1459
1460
0
    m_CurrCtx--;
1461
    //recover luma tree status
1462
0
    partitioner.chType = CH_L;
1463
0
    partitioner.treeType = TREE_D;
1464
0
    partitioner.modeType = MODE_TYPE_ALL;
1465
0
  }
1466
1467
  // Finally, add split-signaling bits for RD-cost check
1468
61.6k
  tempCS->fracBits += splitBits; // split bits
1469
61.6k
  tempCS->cost      = m_cRdCost.calcRdCost( tempCS->fracBits, tempCS->dist );
1470
61.6k
  partitioner.modeType = modeTypeParent;
1471
1472
  // Check Delta QP bits for splitted structure
1473
61.6k
  if( !qgEnableChildren ) // check at deepest QG level only
1474
59.0k
    xCheckDQP( *tempCS, partitioner, true );
1475
1476
  // If the configuration being tested exceeds the maximum number of bytes for a slice / slice-segment, then
1477
  // a proper RD evaluation cannot be performed. Therefore, termination of the
1478
  // slice/slice-segment must be made prior to this CTU.
1479
  // This can be achieved by forcing the decision to be that of the rpcTempCU.
1480
  // The exception is each slice / slice-segment must have at least one CTU.
1481
61.6k
  if( bestCS->cost == MAX_DOUBLE )
1482
43.8k
  {
1483
43.8k
    bestCS->costDbOffset = 0;
1484
43.8k
  }
1485
1486
61.6k
  if( tempCS->cus.size() > 0 && modeTypeParent == MODE_TYPE_ALL && modeTypeChild == MODE_TYPE_INTER )
1487
0
  {
1488
0
    int areaSizeNoResiCu = 0;
1489
0
    for( int k = 0; k < tempCS->cus.size(); k++ )
1490
0
    {
1491
0
      areaSizeNoResiCu += (tempCS->cus[k]->rootCbf == false) ? tempCS->cus[k]->lumaSize().area() : 0;
1492
0
    }
1493
0
    if( areaSizeNoResiCu >= (tempCS->area.lumaSize().area() >> 1) )
1494
0
    {
1495
0
      skipInterPass = true;
1496
0
    }
1497
0
  }
1498
1499
  // RD check for sub partitioned coding structure.
1500
61.6k
  xCheckBestMode( tempCS, bestCS, partitioner, encTestMode, m_EDO );
1501
1502
61.6k
  if( isAffMVInfoSaved )
1503
0
  {
1504
0
    m_cInterSearch.m_AffineProfList->addAffMVInfo(tmpMVInfo);
1505
0
  }
1506
1507
61.6k
  if( !tempCS->slice->isIntra() && isUniMvInfoSaved )
1508
0
  {
1509
0
    m_cInterSearch.m_BlkUniMvInfoBuffer->addUniMvInfo(tmpUniMvInfo);
1510
0
  }
1511
1512
61.6k
  tempCS->motionLut = oldMotionLut;
1513
61.6k
  tempCS->releaseIntermediateData();
1514
61.6k
  tempCS->prevQP[partitioner.chType] = oldPrevQp;
1515
61.6k
}
1516
1517
1518
void EncCu::xCheckRDCostIntra( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode )
1519
75.2k
{
1520
75.2k
  PROFILER_SCOPE_AND_STAGE_EXT( 1, _TPROF, P_INTRA, tempCS, partitioner.chType );
1521
1522
75.2k
  tempCS->initStructData( encTestMode.qp, false ); // clear motion buffer
1523
1524
75.2k
  CodingUnit &cu      = tempCS->addCU( CS::getArea( *tempCS, tempCS->area, partitioner.chType, partitioner.treeType ), partitioner.chType );
1525
1526
75.2k
  partitioner.setCUData( cu );
1527
75.2k
  cu.slice            = tempCS->slice;
1528
75.2k
  cu.tileIdx          = m_tileIdx;
1529
75.2k
  cu.skip             = false;
1530
75.2k
  cu.mmvdSkip         = false;
1531
75.2k
  cu.predMode         = MODE_INTRA;
1532
75.2k
  cu.chromaQpAdj      = m_cuChromaQpOffsetIdxPlus1;
1533
75.2k
  cu.qp               = encTestMode.qp;
1534
75.2k
  cu.ispMode          = NOT_INTRA_SUBPARTITIONS;
1535
75.2k
  cu.initPuData();
1536
1537
75.2k
  m_cIntraSearch.m_ispTestedModes[0].init(0, 0, 1);
1538
75.2k
  if (m_pcEncCfg->m_FastIntraTools)
1539
75.2k
  {
1540
75.2k
    m_modeCtrl.comprCUCtx->intraWasTested = false;
1541
75.2k
    m_cIntraSearch.m_ispTestedModes[0].relatedCuIsValid = m_modeCtrl.comprCUCtx->relatedCuIsValid;
1542
75.2k
    if (!bestCS->cus.empty())
1543
20.6k
    {
1544
20.6k
      if ((bestCS->cus[0]->mergeFlag || bestCS->cus[0]->imv || bestCS->cus[0]->affine) && (!bestCS->cus[0]->ciip))
1545
20.6k
      {
1546
20.6k
        m_cIntraSearch.m_ispTestedModes[0].bestBefore[0] = -1;
1547
20.6k
      }
1548
20.6k
    }
1549
75.2k
    if (!bestCS->slice->isIntra())
1550
0
    {
1551
0
      const Position posBL = cu.Y().bottomLeft();
1552
0
      const Position posTR = cu.Y().topRight();
1553
0
      for (int i = 0; i < 2; i++)
1554
0
      {
1555
0
        const CodingUnit* neigh = i ? cu.cs->getCURestricted(posTR.offset(0, -1), cu, CH_L) :cu.cs->getCURestricted(posBL.offset(-1, 0), cu, CH_L);
1556
0
        m_cIntraSearch.m_ispTestedModes[0].bestBefore[i+1] = -1;
1557
0
        if (neigh != nullptr)
1558
0
        {
1559
0
          int bestMode = neigh->firstTU->mtsIdx[0] ? 4 : 0;
1560
0
          bestMode |= neigh->lfnstIdx ? 2 : 0;
1561
0
          bestMode |= neigh->ispMode ? 1 : 0;
1562
0
          m_cIntraSearch.m_ispTestedModes[0].bestBefore[i+1] = bestMode;
1563
0
        }
1564
0
      }
1565
0
    }
1566
75.2k
  }
1567
1568
75.2k
  tempCS->interHad    = m_modeCtrl.comprCUCtx->interHad;
1569
75.2k
  double maxCostAllowedForChroma = MAX_DOUBLE;
1570
75.2k
  if( isLuma( partitioner.chType ) )
1571
23.1k
  {
1572
23.1k
    if (!tempCS->slice->isIntra() && bestCS)
1573
0
    {
1574
0
      m_cIntraSearch.estIntraPredLumaQT(cu, partitioner, bestCS->cost);
1575
0
    }
1576
23.1k
    else
1577
23.1k
    {
1578
23.1k
      m_cIntraSearch.estIntraPredLumaQT(cu, partitioner);
1579
23.1k
    }
1580
23.1k
    if (m_pcEncCfg->m_FastIntraTools)
1581
23.1k
    {
1582
23.1k
      if (m_cIntraSearch.m_ispTestedModes[0].intraWasTested)
1583
23.1k
      {
1584
23.1k
        m_modeCtrl.comprCUCtx->intraWasTested = m_cIntraSearch.m_ispTestedModes[0].intraWasTested;
1585
23.1k
      }
1586
23.1k
    }
1587
1588
23.1k
    if( !partitioner.isSepTree( *tempCS ) )
1589
0
    {
1590
0
      tempCS->lumaCost = m_cRdCost.calcRdCost( tempCS->fracBits, tempCS->dist );
1591
0
    }
1592
23.1k
    if (m_pcEncCfg->m_usePbIntraFast && tempCS->dist == MAX_DISTORTION && tempCS->interHad == 0)
1593
0
    {
1594
      // JEM assumes only perfect reconstructions can from now on beat the inter mode
1595
0
      m_modeCtrl.comprCUCtx->interHad = 0;
1596
0
      return;
1597
0
    }
1598
23.1k
  }
1599
1600
75.2k
  if( tempCS->area.chromaFormat != CHROMA_400 && ( partitioner.chType == CH_C || !CU::isSepTree(cu) ) )
1601
52.1k
  {
1602
52.1k
    bool useIntraSubPartitions = cu.ispMode != NOT_INTRA_SUBPARTITIONS;
1603
52.1k
    Partitioner subTuPartitioner = partitioner;
1604
52.1k
    if ((m_pcEncCfg->m_ISP >= 3) && (!partitioner.isSepTree(*tempCS) && useIntraSubPartitions))
1605
0
    {
1606
0
      maxCostAllowedForChroma = bestCS->cost < MAX_DOUBLE ? bestCS->cost - tempCS->lumaCost : MAX_DOUBLE;
1607
0
    }
1608
52.1k
    m_cIntraSearch.estIntraPredChromaQT(
1609
52.1k
      cu, (!useIntraSubPartitions || (CU::isSepTree(cu) && !isLuma(CH_C))) ? partitioner : subTuPartitioner,
1610
52.1k
      maxCostAllowedForChroma);
1611
52.1k
    if ((m_pcEncCfg->m_ISP >= 3) && useIntraSubPartitions && !cu.ispMode)
1612
0
    {
1613
0
      return;
1614
0
    }
1615
52.1k
  }
1616
1617
75.2k
  cu.rootCbf = false;
1618
1619
301k
  for (uint32_t t = 0; t < getNumberValidTBlocks(*cu.cs->pcv); t++)
1620
225k
  {
1621
225k
    cu.rootCbf |= cu.firstTU->cbf[t] != 0;
1622
225k
  }
1623
1624
  // Get total bits for current mode: encode CU
1625
75.2k
  m_CABACEstimator->resetBits();
1626
1627
75.2k
  if ((!cu.cs->slice->isIntra() || cu.cs->slice->sps->IBC) && cu.Y().valid())
1628
23.1k
  {
1629
23.1k
    m_CABACEstimator->cu_skip_flag(cu);
1630
23.1k
  }
1631
75.2k
  m_CABACEstimator->pred_mode(cu);
1632
75.2k
  m_CABACEstimator->cu_pred_data(cu);
1633
1634
  // Encode Coefficients
1635
75.2k
  CUCtx cuCtx;
1636
75.2k
  cuCtx.isDQPCoded = true;
1637
75.2k
  cuCtx.isChromaQpAdjCoded = true;
1638
75.2k
  m_CABACEstimator->cu_residual(cu, partitioner, cuCtx);
1639
1640
75.2k
  tempCS->fracBits = m_CABACEstimator->getEstFracBits();
1641
75.2k
  tempCS->cost = m_cRdCost.calcRdCost(tempCS->fracBits, tempCS->dist);
1642
1643
75.2k
  xEncodeDontSplit(*tempCS, partitioner);
1644
1645
75.2k
  xCheckDQP(*tempCS, partitioner);
1646
1647
75.2k
  if( m_EDO )
1648
75.2k
  {
1649
75.2k
    xCalDebCost(*tempCS, partitioner);
1650
75.2k
  }
1651
1652
75.2k
  DTRACE_MODE_COST(*tempCS, m_cRdCost.getLambda(true));
1653
75.2k
  xCheckBestMode(tempCS, bestCS, partitioner, encTestMode, m_EDO);
1654
1655
75.2k
  STAT_COUNT_CU_MODES( partitioner.chType == CH_L, g_cuCounters1D[CU_MODES_TESTED][0][!tempCS->slice->isIntra() + tempCS->slice->depth] );
1656
75.2k
  STAT_COUNT_CU_MODES( partitioner.chType == CH_L && !tempCS->slice->isIntra(), g_cuCounters2D[CU_MODES_TESTED][Log2( tempCS->area.lheight() )][Log2( tempCS->area.lwidth() )] );
1657
75.2k
}
1658
1659
void EncCu::xCheckDQP( CodingStructure& cs, Partitioner& partitioner, bool bKeepCtx )
1660
154k
{
1661
154k
  if( !cs.pps->useDQP )
1662
0
  {
1663
0
    return;
1664
0
  }
1665
1666
154k
  if (partitioner.isSepTree(cs) && isChroma(partitioner.chType))
1667
87.6k
  {
1668
87.6k
    return;
1669
87.6k
  }
1670
1671
67.3k
  if( !partitioner.currQgEnable() ) // do not consider split or leaf/not leaf QG condition (checked by caller)
1672
60.4k
  {
1673
60.4k
    return;
1674
60.4k
  }
1675
1676
6.89k
  CodingUnit* cuFirst = cs.getCU( partitioner.chType, partitioner.treeType );
1677
1678
6.89k
  CHECK( bKeepCtx && cs.cus.size() <= 1 && partitioner.getImplicitSplit( cs ) == CU_DONT_SPLIT, "bKeepCtx should only be set in split case" );
1679
6.89k
  CHECK( !bKeepCtx && cs.cus.size() > 1, "bKeepCtx should never be set for non-split case" );
1680
6.89k
  CHECK( !cuFirst, "No CU available" );
1681
1682
6.89k
  bool hasResidual = false;
1683
6.89k
  for( const auto &cu : cs.cus )
1684
18.6k
  {
1685
    //not include the chroma CU because chroma CU is decided based on corresponding luma QP and deltaQP is not signaled at chroma CU
1686
18.6k
    if( cu->rootCbf && !isChroma( cu->chType ))
1687
1.11k
    {
1688
1.11k
      hasResidual = true;
1689
1.11k
      break;
1690
1.11k
    }
1691
18.6k
  }
1692
1693
6.89k
  int predQP = CU::predictQP( *cuFirst, cs.prevQP[partitioner.chType] );
1694
1695
6.89k
  if( hasResidual )
1696
1.11k
  {
1697
1.11k
    TempCtx ctxTemp( m_CtxCache );
1698
1.11k
    if( !bKeepCtx ) ctxTemp = SubCtx( Ctx::DeltaQP, m_CABACEstimator->getCtx() );
1699
1700
1.11k
    m_CABACEstimator->resetBits();
1701
1.11k
    m_CABACEstimator->cu_qp_delta( *cuFirst, predQP, cuFirst->qp );
1702
1703
1.11k
    cs.fracBits += m_CABACEstimator->getEstFracBits(); // dQP bits
1704
1.11k
    cs.cost      = m_cRdCost.calcRdCost(cs.fracBits, cs.dist);
1705
1706
1707
1.11k
    if( !bKeepCtx ) m_CABACEstimator->getCtx() = SubCtx( Ctx::DeltaQP, ctxTemp );
1708
1709
    // NOTE: reset QPs for CUs without residuals up to first coded CU
1710
1.11k
    for( const auto &cu : cs.cus )
1711
1.12k
    {
1712
      //not include the chroma CU because chroma CU is decided based on corresponding luma QP and deltaQP is not signaled at chroma CU
1713
1.12k
      if( cu->rootCbf && !isChroma( cu->chType ))
1714
1.11k
      {
1715
1.11k
        break;
1716
1.11k
      }
1717
7
      cu->qp = predQP;
1718
7
    }
1719
1.11k
  }
1720
5.77k
  else
1721
5.77k
  {
1722
    // No residuals: reset CU QP to predicted value
1723
5.77k
    for( const auto &cu : cs.cus )
1724
17.4k
    {
1725
17.4k
      cu->qp = predQP;
1726
17.4k
    }
1727
5.77k
  }
1728
6.89k
}
1729
1730
CodingUnit *EncCu::getCuForInterPrediction( CodingStructure *cs, const EncTestMode& encTestMode )
1731
0
{
1732
0
  CodingUnit *cu = cs->getCU( CH_L, TREE_D );
1733
1734
0
  if( cu == nullptr )
1735
0
  {
1736
0
    CHECK( cs->getCU( CH_L, TREE_D ) != nullptr, "Wrong CU/PU setting in CS" );
1737
0
    cu = &cs->addCU( cs->area, CH_L );
1738
0
  }
1739
1740
0
  cu->slice       = cs->slice;
1741
0
  cu->tileIdx     = m_tileIdx;
1742
0
  cu->skip        = false;
1743
0
  cu->mmvdSkip    = false;
1744
0
  cu->mmvdMergeFlag
1745
0
                  = false;
1746
0
  cu->geo         = false;
1747
0
  cu->predMode    = MODE_INTER;
1748
0
  cu->chromaQpAdj = m_cuChromaQpOffsetIdxPlus1;
1749
0
  cu->qp          = encTestMode.qp;
1750
0
  cu->affine      = false;
1751
0
  cu->multiRefIdx = 0;
1752
0
  cu->mipFlag     = false;
1753
0
  cu->ciip        = false;
1754
1755
0
  return cu;
1756
0
}
1757
1758
int getDmvrMvdNum( const CodingUnit &cu )
1759
0
{
1760
0
  const int dx = std::max<int>( cu.lwidth()  >> DMVR_SUBCU_SIZE_LOG2, 1 );
1761
0
  const int dy = std::max<int>( cu.lheight() >> DMVR_SUBCU_SIZE_LOG2, 1 );
1762
0
  return dx * dy;
1763
0
}
1764
1765
void EncCu::xCheckRDCostUnifiedMerge( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, EncTestMode &encTestMode )
1766
0
{
1767
0
  const Slice &slice = *tempCS->slice;
1768
1769
0
  CHECK( slice.sliceType == VVENC_I_SLICE, "Merge modes not available for I-slices" );
1770
1771
0
  tempCS->initStructData( encTestMode.qp );
1772
1773
0
  MergeCtx          mergeCtx, gpmMergeCtx;
1774
0
  AffineMergeCtx    affineMergeCtx;
1775
0
  GeoComboCostList &comboList = m_comboList;
1776
0
  const SPS        &sps       = *tempCS->sps;
1777
1778
0
  if( sps.SbtMvp )
1779
0
  {
1780
0
    const Size bufSize           = g_miScaling.scale( tempCS->area.lumaSize() );
1781
0
    affineMergeCtx.subPuMvpMiBuf = MotionBuf        ( m_subPuMiBuf, bufSize );
1782
0
  }
1783
1784
0
  m_mergeBestSATDCost = MAX_DOUBLE;
1785
1786
0
  CodingUnit *cu = getCuForInterPrediction( tempCS, encTestMode );
1787
0
  partitioner.setCUData            ( *cu );
1788
0
  CU::getInterMergeCandidates      ( *cu, mergeCtx, 0 );
1789
0
  if( sps.MMVD )
1790
0
    CU::getInterMMVDMergeCandidates( *cu, mergeCtx );
1791
1792
0
  bool sameMV[MRG_MAX_NUM_CANDS] = { false, };
1793
0
  if( m_pcEncCfg->m_useFastMrg >= 2 )
1794
0
  {
1795
0
    for( int m = 0; m < mergeCtx.numValidMergeCand - 1; m++ )
1796
0
    {
1797
0
      if( !sameMV[m] )
1798
0
      {
1799
0
        for( int n = m + 1; n < mergeCtx.numValidMergeCand; n++ )
1800
0
        {
1801
0
          sameMV[n] |= mergeCtx.mvFieldNeighbours[m][0] == mergeCtx.mvFieldNeighbours[n][0]
1802
0
                    && mergeCtx.mvFieldNeighbours[m][1] == mergeCtx.mvFieldNeighbours[n][1];
1803
0
        }
1804
0
      }
1805
0
    }
1806
0
  }
1807
1808
0
  MergeBufVector mrgPredBufNoCiip;
1809
0
  MergeBufVector geoBuffer;
1810
0
  const double  sqrtLambdaForFirstPass = m_cRdCost.getMotionLambda() * FRAC_BITS_SCALE;
1811
1812
0
  const UnitArea localUnitArea( cu->chromaFormat, Area( 0, 0, cu->Y().width, cu->Y().height ) );
1813
0
  for( int i = 0; i < mergeCtx.numValidMergeCand; i++ )
1814
0
  {
1815
0
    mrgPredBufNoCiip.push_back( m_acMergeTmpBuffer[i].getCompactBuf( localUnitArea ) );
1816
0
  }
1817
1818
0
  int numMergeSatdCand = std::min( bestCS->area.lumaSize().area() >= 64 ? m_pcEncCfg->m_mergeRdCandQuotaRegular : m_pcEncCfg->m_mergeRdCandQuotaRegularSmallBlk, mergeCtx.numValidMergeCand );
1819
1820
0
  bool isCiipEnabled  = sps.CIIP && bestCS->area.lumaSize().area() >= 64 && bestCS->area.lumaSize().maxDim() < MAX_CU_SIZE;
1821
0
       isCiipEnabled &= m_pcEncCfg->m_CIIP <= 1 || !m_modeCtrl.getBlkInfo( tempCS->area ).isSkip; //5
1822
1823
0
  if( isCiipEnabled )
1824
0
  {
1825
0
    numMergeSatdCand += std::min( m_pcEncCfg->m_mergeRdCandQuotaCiip, mergeCtx.numValidMergeCand );
1826
0
  }
1827
1828
0
  const bool affineMrgAvail = ( m_pcEncCfg->m_Affine <= 2 || slice.TLayer <= 3 || m_pcEncCfg->m_SbTMVP )
1829
0
                           && ( m_pcEncCfg->m_Affine || sps.SbtMvp ) && m_pcEncCfg->m_maxNumAffineMergeCand && bestCS->area.Y().minDim() >= 8;
1830
1831
0
  if( affineMrgAvail )
1832
0
  {
1833
0
    CU::getAffineMergeCand( *cu, affineMergeCtx );
1834
0
    numMergeSatdCand += std::min( m_pcEncCfg->m_mergeRdCandQuotaSubBlk, affineMergeCtx.numValidMergeCand );
1835
0
  }
1836
1837
0
  int numSatdCandPreGeo = std::min( numMergeSatdCand, m_pcEncCfg->m_maxMergeRdCandNumTotal );
1838
0
  bool toAddGpmCand     = false;
1839
0
  if( sps.GEO && slice.isInterB() // base checks
1840
0
      && cu->lumaSize().minDim() >= GEO_MIN_CU_SIZE  && cu->lumaSize().maxDim() <= GEO_MAX_CU_SIZE && cu->lumaSize().maxDim() < 8 * cu->lumaSize().minDim() // size checks
1841
0
      && !( m_pcEncCfg->m_Geo > 2 && slice.TLayer <= 1 ) ) // speedups
1842
0
  {
1843
0
    cu->mergeFlag            = true;
1844
0
    cu->geo                  = true;
1845
0
    CU::getGeoMergeCandidates( *cu, gpmMergeCtx );
1846
0
    toAddGpmCand             = prepareGpmComboList( gpmMergeCtx, localUnitArea, sqrtLambdaForFirstPass, comboList, geoBuffer, *cu );
1847
0
    numMergeSatdCand        += toAddGpmCand ? std::min( m_pcEncCfg->m_mergeRdCandQuotaGpm, ( int ) comboList.list.size() ) : 0;
1848
0
  }
1849
1850
0
  numMergeSatdCand  = std::min( numMergeSatdCand, m_pcEncCfg->m_maxMergeRdCandNumTotal );
1851
1852
  // 1. Pass: get SATD-cost for selected candidates and reduce their count
1853
0
  m_mergeItemList.resetList( numMergeSatdCand );
1854
0
  const TempCtx ctxStart   ( m_CtxCache, m_CABACEstimator->getCtx() );
1855
0
  const DFunc   dfunc      = encTestMode.lossless ? DF_SAD : ( m_pcEncCfg->m_fastHad ? DF_HAD_fast : DF_HAD );
1856
0
  DistParam     distParam  = m_cRdCost.setDistParam( tempCS->getOrgBuf().Y(), tempCS->getOrgBuf().Y(), sps.bitDepths[CH_L], dfunc );
1857
0
  m_uiSadBestForQPA        = MAX_DISTORTION;
1858
1859
0
  addRegularCandsToPruningList( mergeCtx, localUnitArea, sqrtLambdaForFirstPass, ctxStart, distParam, *cu, sameMV, mrgPredBufNoCiip );
1860
1861
  // add CIIP candidates directly after adding regular cands
1862
0
  if( isCiipEnabled )
1863
0
  {
1864
0
    addCiipCandsToPruningList( mergeCtx, localUnitArea, sqrtLambdaForFirstPass, ctxStart, distParam, *cu, sameMV );
1865
0
  }
1866
1867
0
  if( sps.MMVD && !!m_mergeItemList.size() && !( m_pcEncCfg->m_useFastMrg >= 2 && m_mergeItemList.size() <= 1 ) )
1868
0
  {
1869
0
    addMmvdCandsToPruningList( mergeCtx, localUnitArea, sqrtLambdaForFirstPass, ctxStart, distParam, *cu );
1870
0
  }
1871
1872
0
  if( affineMergeCtx.numValidMergeCand > 0 )
1873
0
  {
1874
0
    addAffineCandsToPruningList( affineMergeCtx, localUnitArea, sqrtLambdaForFirstPass, ctxStart, distParam, *cu );
1875
0
  }
1876
1877
0
  if( m_pcEncCfg->m_useFastMrg > 0 && m_mergeItemList.size() > 0 )
1878
0
  {
1879
0
    m_mergeBestSATDCost    = m_mergeItemList.getMergeItemInList( 0 )->cost;
1880
0
    const double threshold = m_mergeBestSATDCost * MRG_FAST_RATIO[tempCS->picture->useFastMrg];
1881
0
    const   int shrinkSize = std::min( numSatdCandPreGeo, ( int ) updateRdCheckingNum( m_mergeItemList, threshold, numMergeSatdCand ) );
1882
0
    m_mergeItemList        . shrinkList( shrinkSize );
1883
0
  }
1884
0
  else
1885
0
  {
1886
0
    m_mergeItemList        . shrinkList( numSatdCandPreGeo );
1887
0
  }
1888
1889
0
  if( toAddGpmCand )
1890
0
  {
1891
0
    addGpmCandsToPruningList( gpmMergeCtx, localUnitArea, sqrtLambdaForFirstPass, ctxStart, comboList, geoBuffer, distParam, *cu );
1892
0
  }
1893
1894
0
  if(    m_pcEncCfg->m_internalUsePerceptQPATempFiltISlice == 2 && m_uiSadBestForQPA < MAX_DISTORTION && slice.TLayer == 0 // non-Intra key-frame
1895
0
      && m_pcEncCfg->m_salienceBasedOpt
1896
0
      && m_pcEncCfg->m_usePerceptQPA && partitioner.currQgEnable() && partitioner.currSubdiv == 0 ) // CTU-level luma quantization group
1897
0
  {
1898
0
    CHECK( bestCS->cost < MAX_DOUBLE, "This has to be the first test performed!" );
1899
1900
0
    const Picture *pic         = slice.pic;
1901
0
    const bool     isBIM       = m_pcEncCfg->m_RCNumPasses != 2 && m_pcEncCfg->m_blockImportanceMapping && !pic->m_picShared->m_ctuBimQpOffset.empty();
1902
0
    const uint32_t rsAddr      = getCtuAddr( partitioner.currQgPos, *pic->cs->pcv );
1903
0
    const int      pumpReducQP = BitAllocation::getCtuPumpingReducingQP( &slice, tempCS->getOrgBuf( COMP_Y ), m_uiSadBestForQPA, *m_globalCtuQpVector, rsAddr,
1904
0
                                                                         m_pcEncCfg->m_QP, isBIM );
1905
1906
0
    if( pumpReducQP != 0 ) // subtract QP offset, reduces Intra-period pumping or overcoding
1907
0
    {
1908
0
      encTestMode.qp = Clip3( 0, MAX_QP, encTestMode.qp - pumpReducQP );
1909
0
      tempCS->currQP[partitioner.chType] = tempCS->baseQP =
1910
0
      bestCS->currQP[partitioner.chType] = bestCS->baseQP = Clip3( 0, MAX_QP, tempCS->baseQP - pumpReducQP );
1911
1912
0
      updateLambda( slice, pic->ctuQpaLambda[rsAddr], pic->ctuAdaptedQP[rsAddr], tempCS->baseQP, true );
1913
0
    }
1914
0
  }
1915
1916
  // Try to limit number of candidates using SATD-costs
1917
0
  if( m_pcEncCfg->m_useFastMrg > 0 && m_mergeItemList.size() > 0 )
1918
0
  {
1919
    // shrink GEO list as well
1920
0
    const double threshold = m_mergeItemList.getMergeItemInList( 0 )->cost * MRG_FAST_RATIO[0];
1921
0
    numMergeSatdCand       = updateRdCheckingNum( m_mergeItemList, threshold, numMergeSatdCand );
1922
0
    m_mergeBestSATDCost    = m_mergeItemList.size() != 0 ? m_mergeItemList.getMergeItemInList( 0 )->cost : MAX_DOUBLE;
1923
0
  }
1924
0
  else
1925
0
  {
1926
0
    numMergeSatdCand       = std::min<int>( numMergeSatdCand, ( int ) m_mergeItemList.size() );
1927
0
  }
1928
1929
  // 2. Pass: RD checking 
1930
0
  tempCS->initStructData( encTestMode.qp );
1931
0
  m_CABACEstimator->getCtx() = ctxStart;
1932
1933
0
  double bestEndCost                            =   MAX_DOUBLE;
1934
0
  bool bestIsSkip                               =   false;
1935
0
  PelUnitBuf ciipBuf                            =   m_aTmpStorageLCU[1].getCompactBuf( *cu );
1936
0
  bool ciipChromaDone                           =   false;
1937
0
  bool isRegularTestedAsSkip[MRG_MAX_NUM_CANDS] = { false, };
1938
0
  bool geoWasTested                             =   false;
1939
0
  int  stopCand                                 =   numMergeSatdCand;
1940
1941
0
  CHECK( numMergeSatdCand > 0 && m_mergeItemList.size() == 0, "Empty merge item list is not expected" );
1942
1943
0
  for( uint32_t noResidualPass = 0; noResidualPass < 2; noResidualPass++ )
1944
0
  {
1945
0
    const bool forceNoResidual = noResidualPass == 1;
1946
0
    for( uint32_t mrgHadIdx = 0; mrgHadIdx < stopCand; mrgHadIdx++ )
1947
0
    {
1948
0
      auto mergeItem = m_mergeItemList.getMergeItemInList( mrgHadIdx );
1949
0
      CHECK( mergeItem == nullptr, "Wrong merge item" );
1950
1951
0
      const bool isCiip = mergeItem->mergeItemType == MergeItem::MergeItemType::CIIP;
1952
0
      const bool isGeo  = mergeItem->mergeItemType == MergeItem::MergeItemType::GPM;
1953
0
      const bool isRglr = mergeItem->mergeItemType == MergeItem::MergeItemType::REGULAR;
1954
0
      const bool isMmvd = mergeItem->mergeItemType == MergeItem::MergeItemType::MMVD;
1955
1956
0
      if( noResidualPass != 0 && isCiip && isRegularTestedAsSkip[mergeItem->mergeIdx] )
1957
0
      {
1958
0
        continue;
1959
0
      }
1960
1961
0
      if( noResidualPass ? mergeItem->noResidual : bestIsSkip )
1962
0
      {
1963
0
        continue;
1964
0
      }
1965
1966
0
      if( isGeo )
1967
0
      {
1968
0
        if( m_pcEncCfg->m_Geo > 2 && geoWasTested && !bestCS->cus.empty() && !bestCS->getCU( partitioner.chType, partitioner.treeType )->geo )
1969
0
        {
1970
0
          continue;
1971
0
        }
1972
1973
0
        geoWasTested = true;
1974
0
      }
1975
1976
0
      cu = getCuForInterPrediction( tempCS, encTestMode );
1977
0
      partitioner.setCUData( *cu );
1978
0
      const bool resetCiip2Regular = mergeItem->exportMergeInfo( *cu, forceNoResidual );
1979
1980
0
      if( isRglr || resetCiip2Regular )
1981
0
      {
1982
0
        if( CU::checkDMVRCondition( *cu ) ) std::copy_n( m_subPuMvOffset[mergeItem->mergeIdx].data(), getDmvrMvdNum( *cu ), cu->mvdL0SubPu );
1983
0
      }
1984
1985
0
      if( isMmvd && mergeItem->noBdofRefine )
1986
0
      {
1987
        // no BDOF refinement was made for the luma prediction, need to have luma prediction again
1988
0
        mergeItem->lumaPredReady = false;
1989
0
      }
1990
1991
0
      PelUnitBuf *predBuf1   = nullptr, *predBuf2 = isCiip ? &ciipBuf : nullptr;
1992
0
      PelUnitBuf  dstPredBuf = tempCS->getPredBuf( *cu );
1993
1994
0
      if( isGeo )
1995
0
      {
1996
0
        predBuf1 = &geoBuffer[cu->geoMergeIdx[0]];
1997
0
        predBuf2 = &geoBuffer[cu->geoMergeIdx[1]];
1998
0
      }
1999
2000
0
      if( resetCiip2Regular )
2001
0
      {
2002
0
        dstPredBuf.copyFrom( mrgPredBufNoCiip[mergeItem->mergeIdx] );
2003
0
      }
2004
0
      else
2005
0
      {
2006
0
        if( isCiip && !resetCiip2Regular && isChromaEnabled( cu->chromaFormat ) && cu->chromaSize().width > 2 )
2007
0
        {
2008
0
          if( !ciipChromaDone )
2009
0
          {
2010
0
            cu->intraDir[0] = PLANAR_IDX;
2011
0
            cu->intraDir[1] = DM_CHROMA_IDX;
2012
2013
0
            m_cIntraSearch  . initIntraPatternChType( *cu, cu->Cb() );
2014
0
            m_cIntraSearch  . predIntraAng          ( COMP_Cb, ciipBuf.Cb(), *cu );
2015
0
            m_cIntraSearch  . initIntraPatternChType( *cu, cu->Cr() );
2016
0
            m_cIntraSearch  . predIntraAng          ( COMP_Cr, ciipBuf.Cr(), *cu );
2017
2018
0
            ciipChromaDone  = true;
2019
0
          }
2020
0
        }
2021
2022
0
        if(  mergeItem->lumaPredReady ||  mergeItem->chromaPredReady )
2023
0
          dstPredBuf.copyFrom( mergeItem->getPredBuf( localUnitArea ), mergeItem->lumaPredReady, mergeItem->chromaPredReady );
2024
0
        if( !mergeItem->lumaPredReady || !mergeItem->chromaPredReady )
2025
0
          generateMergePrediction( localUnitArea, mergeItem, *cu, !mergeItem->lumaPredReady, !mergeItem->chromaPredReady, dstPredBuf, true, forceNoResidual, predBuf1, predBuf2 );
2026
0
      }
2027
2028
0
      if( !cu->mmvdSkip && !cu->ciip && !cu->affine && !cu->geo && noResidualPass != 0 )
2029
0
      {
2030
0
        CHECK( mergeItem->mergeIdx >= mergeCtx.numValidMergeCand, "out of normal merge" );
2031
0
        isRegularTestedAsSkip[mergeItem->mergeIdx] = true;
2032
0
      }
2033
2034
0
      xEncodeInterResidual( tempCS, bestCS, partitioner, encTestMode, noResidualPass, noResidualPass == 0 ? &mergeItem->noResidual : nullptr );
2035
2036
0
      if( m_pcEncCfg->m_useFastMrg >= 2 )
2037
0
      {
2038
0
        if( cu->ciip && bestCS->cost == MAX_DOUBLE && mrgHadIdx + 1 == numMergeSatdCand )
2039
0
        {
2040
0
          numMergeSatdCand = ( unsigned ) m_mergeItemList.size();
2041
0
        }
2042
      
2043
0
        if( mrgHadIdx > 0 && tempCS->cost >= bestEndCost && !cu->ciip && !isGeo )
2044
0
        {
2045
0
          stopCand = mrgHadIdx + 1;
2046
0
        }
2047
      
2048
0
        if( noResidualPass == 0 )
2049
0
        {
2050
0
          bestEndCost = std::min( bestEndCost, tempCS->cost );
2051
0
        }
2052
0
      }
2053
2054
0
      if( m_pcEncCfg->m_useFastDecisionForMerge && !bestIsSkip && !cu->ciip )
2055
0
      {
2056
0
        bestIsSkip = !bestCS->cus.empty() && bestCS->getCU( partitioner.chType, partitioner.treeType )->rootCbf == 0;
2057
0
      }
2058
2059
0
      tempCS->initStructData( encTestMode.qp );
2060
0
    }   // end loop mrgHadIdx
2061
0
  }
2062
0
}
2063
2064
unsigned int EncCu::updateRdCheckingNum( MergeItemList &mergeItemList, double threshold, unsigned int numMergeSatdCand )
2065
0
{
2066
0
  for( uint32_t i = 0; i < mergeItemList.size(); i++ )
2067
0
  {
2068
0
    const auto mergeItem = mergeItemList.getMergeItemInList( i );
2069
0
    if( mergeItem == nullptr || mergeItem->cost > threshold )
2070
0
    {
2071
0
      numMergeSatdCand = i;
2072
0
      break;
2073
0
    }
2074
0
  }
2075
0
  return std::min( numMergeSatdCand, ( unsigned ) mergeItemList.size() );
2076
0
}
2077
2078
void EncCu::generateMergePrediction( const UnitArea &unitArea, MergeItem *mergeItem, CodingUnit &pu, bool luma, bool chroma,
2079
                                     PelUnitBuf &dstBuf, bool finalRd, bool forceNoResidual, PelUnitBuf *predBuf1, PelUnitBuf *predBuf2 )
2080
0
{
2081
0
  CHECK( ( luma && mergeItem->lumaPredReady ) || ( chroma && mergeItem->chromaPredReady ), "Prediction has been avaiable" );
2082
2083
0
  pu.mcControl = ( !luma ? 4 : 0 ) | ( !chroma ? 2 : 0 );
2084
2085
0
  switch( mergeItem->mergeItemType )
2086
0
  {
2087
0
  case MergeItem::MergeItemType::REGULAR:
2088
    // here predBuf1 is predBufNoCiip
2089
0
    pu.mvRefine = true;
2090
0
    m_cInterSearch.motionCompensation( pu, dstBuf, REF_PIC_LIST_X );
2091
0
    pu.mvRefine = false;
2092
0
    if( predBuf1 != nullptr )
2093
0
    {
2094
0
      predBuf1->copyFrom( dstBuf, luma, chroma );
2095
0
    }
2096
0
    break;
2097
2098
0
  case MergeItem::MergeItemType::CIIP:
2099
0
    m_cInterSearch.motionCompensation( pu, dstBuf, REF_PIC_LIST_X );
2100
2101
0
    if( luma )
2102
0
    {
2103
0
      const ReshapeData& reshapeData = pu.cs->picture->reshapeData;
2104
0
      if( pu.cs->slice->lmcsEnabled && reshapeData.getCTUFlag() )
2105
0
      {
2106
0
        dstBuf.Y().rspSignal( reshapeData.getFwdLUT() );
2107
0
      }
2108
      // generate intrainter Y prediction
2109
0
      dstBuf.Y().weightCiip( predBuf2->Y(), mergeItem->numCiipIntra );
2110
0
    }
2111
2112
0
    if( chroma )
2113
0
    {
2114
0
      if( pu.chromaSize().width > 2 )
2115
0
      {
2116
0
        dstBuf.Cb().weightCiip( predBuf2->Cb(), mergeItem->numCiipIntra );
2117
0
        dstBuf.Cr().weightCiip( predBuf2->Cr(), mergeItem->numCiipIntra );
2118
0
      }
2119
0
    }
2120
2121
0
    break;
2122
2123
0
  case MergeItem::MergeItemType::MMVD:
2124
0
    pu.mcControl           |= finalRd ? 0 : ( pu.mmvdMergeIdx.pos.step > 2 || m_pcEncCfg->m_MMVD > 1 ) ? 1 : 0;
2125
0
    mergeItem->noBdofRefine = pu.mccNoBdof() && pu.cs->sps->BDOF && !pu.cs->picHeader->disBdofFlag;
2126
0
    m_cInterSearch.motionCompensation( pu, dstBuf, REF_PIC_LIST_X );
2127
0
    break;
2128
2129
0
  case MergeItem::MergeItemType::SBTMVP:
2130
0
    m_cInterSearch.motionCompensation( pu, dstBuf, REF_PIC_LIST_X );
2131
0
    break;
2132
2133
0
  case MergeItem::MergeItemType::AFFINE:
2134
0
    m_cInterSearch.motionCompensation( pu, dstBuf, REF_PIC_LIST_X );
2135
0
    break;
2136
2137
0
  case MergeItem::MergeItemType::GPM:
2138
    // here predBuf1 and predBuf2 point to geoBuffer[mergeCand0] and geoBuffer[mergeCand1], respectively
2139
0
    CHECK( predBuf1 == nullptr || predBuf2 == nullptr, "Invalid input buffer to GPM" );
2140
0
    m_cInterSearch.weightedGeoBlk( pu.slice->clpRngs, pu, pu.geoSplitDir, luma && chroma ? MAX_NUM_CH : luma ? CH_L : CH_C, dstBuf, *predBuf1, *predBuf2 );
2141
0
    break;
2142
2143
0
  default:
2144
0
    THROW("Wrong merge item type");
2145
0
  }
2146
2147
0
  auto mergeItemPredBuf = mergeItem->getPredBuf( unitArea );
2148
2149
0
  if( dstBuf.Y().buf == mergeItemPredBuf.Y().buf )
2150
0
  {
2151
    // dst is the internal buffer
2152
0
    mergeItem->lumaPredReady   |= luma;
2153
0
    mergeItem->chromaPredReady |= chroma;
2154
0
  }
2155
0
  else if( finalRd && !forceNoResidual )
2156
0
  {
2157
    // at final RD stage, with and without residuals are both checked
2158
    // it makes sense to buffer the prediction
2159
0
    mergeItemPredBuf.copyFrom( dstBuf, luma, chroma );
2160
0
    mergeItem->lumaPredReady   |= luma;
2161
0
    mergeItem->chromaPredReady |= chroma;
2162
0
  }
2163
0
}
2164
2165
void EncCu::addRegularCandsToPruningList( const MergeCtx &mergeCtx, const UnitArea &localUnitArea, double sqrtLambdaForFirstPassIntra, const TempCtx &ctxStart,
2166
                                          DistParam& distParam, CodingUnit& pu, bool* sameMv, MergeBufVector& regularPred )
2167
0
{
2168
0
  pu.geo = pu.affine
2169
0
         = pu.mmvdMergeFlag = pu.mmvdSkip
2170
0
         = pu.ciip
2171
0
         = false;
2172
2173
0
  for( uint32_t uiMergeCand = 0; uiMergeCand < mergeCtx.numValidMergeCand; uiMergeCand++ )
2174
0
  {
2175
0
    if( sameMv[uiMergeCand] ) continue;
2176
2177
0
    mergeCtx.setMergeInfo   ( pu, uiMergeCand );
2178
2179
0
    if( m_pcEncCfg->m_ifpLines && // what about DMVR?
2180
0
        ( ( pu.refIdx[L0] >= 0 && !CU::isMvInRangeFPP( pu.ly(), pu.lheight(), pu.mv[L0][0].ver, m_pcEncCfg->m_ifpLines, *pu.cs->pcv ) ) ||
2181
0
          ( pu.refIdx[L1] >= 0 && !CU::isMvInRangeFPP( pu.ly(), pu.lheight(), pu.mv[L1][0].ver, m_pcEncCfg->m_ifpLines, *pu.cs->pcv ) ) ) )
2182
0
    {
2183
0
      continue;
2184
0
    }
2185
2186
0
    pu.interDir             = mergeCtx.interDirNeighbours[uiMergeCand];
2187
0
    pu.BcwIdx               = pu.interDir == 3 ? mergeCtx.BcwIdx[uiMergeCand] : BCW_DEFAULT;
2188
0
    pu.imv                  = mergeCtx.useAltHpelIf[uiMergeCand] ? IMV_HPEL : IMV_OFF;
2189
0
    CU::spanMotionInfo      ( pu );
2190
2191
0
    MergeItem *regularMerge = m_mergeItemList.allocateNewMergeItem();
2192
0
    regularMerge->importMergeInfo( mergeCtx, uiMergeCand, MergeItem::MergeItemType::REGULAR, pu );
2193
0
    auto dstBuf             = regularMerge->getPredBuf( localUnitArea );
2194
0
    generateMergePrediction ( localUnitArea, regularMerge, pu, true, true, dstBuf, false, false, &regularPred[uiMergeCand], nullptr );
2195
0
    regularMerge->cost      = calcLumaCost4MergePrediction( ctxStart, dstBuf, sqrtLambdaForFirstPassIntra, pu, distParam );
2196
0
    if( CU::checkDMVRCondition( pu ) ) std::copy_n( pu.mvdL0SubPu, getDmvrMvdNum( pu ), m_subPuMvOffset[uiMergeCand].data() );
2197
0
    m_mergeItemList         . insertMergeItemToList( regularMerge );
2198
0
  }
2199
0
}
2200
2201
void EncCu::addCiipCandsToPruningList( const MergeCtx &mergeCtx, const UnitArea &localUnitArea, double sqrtLambdaForFirstPassIntra, const TempCtx &ctxStart, DistParam &distParam, CodingUnit &pu, bool* sameMv )
2202
0
{
2203
0
  const ReshapeData& reshapeData  = pu.cs->picture->reshapeData;
2204
0
  int                numCiipIntra = -1;
2205
0
  PelUnitBuf         rspBuffer    = m_aTmpStorageLCU[0].getCompactBuf( pu );
2206
0
  PelUnitBuf         ciipBuf      = m_aTmpStorageLCU[1].getCompactBuf( pu );
2207
2208
0
  pu.ciip        = true;
2209
0
  pu.intraDir[0] = PLANAR_IDX;
2210
0
  pu.geo         = pu.affine
2211
0
                 = pu.mmvdMergeFlag = pu.mmvdSkip
2212
0
                 = false;
2213
0
  m_cIntraSearch . initIntraPatternChType        ( pu, pu.Y() );
2214
0
  m_cIntraSearch . predIntraAng                  ( COMP_Y, ciipBuf.Y(), pu );
2215
0
  numCiipIntra   = m_cIntraSearch.getNumIntraCiip( pu );
2216
2217
0
  int nonCiipMrgCnds[MRG_MAX_NUM_CANDS] = { 0, };
2218
0
  int numNonCiipCnds                    =   0;
2219
0
  for( ; numNonCiipCnds < m_mergeItemList.size(); numNonCiipCnds++ ) nonCiipMrgCnds[numNonCiipCnds] = m_mergeItemList.getMergeItemInList( numNonCiipCnds )->mergeIdx;
2220
2221
0
  for( int i = 0; i < numNonCiipCnds; i++ )
2222
0
  {
2223
0
    const unsigned int uiMergeCand = nonCiipMrgCnds[i];
2224
2225
0
    if( sameMv[uiMergeCand] ) continue;
2226
2227
0
    mergeCtx.setMergeInfo     ( pu, uiMergeCand );
2228
2229
0
    if( m_pcEncCfg->m_ifpLines && 
2230
0
        ( ( pu.refIdx[L0] >= 0 && !CU::isMvInRangeFPP( pu.ly(), pu.lheight(), pu.mv[L0][0].ver, m_pcEncCfg->m_ifpLines, *pu.cs->pcv ) ) ||
2231
0
          ( pu.refIdx[L1] >= 0 && !CU::isMvInRangeFPP( pu.ly(), pu.lheight(), pu.mv[L1][0].ver, m_pcEncCfg->m_ifpLines, *pu.cs->pcv ) ) ) )
2232
0
    {
2233
0
      continue;
2234
0
    }
2235
2236
0
    pu.interDir               = mergeCtx.interDirNeighbours[uiMergeCand];
2237
0
    pu.BcwIdx                 = pu.interDir == 3 ? mergeCtx.BcwIdx[uiMergeCand] : BCW_DEFAULT;
2238
0
    pu.imv                    = mergeCtx.useAltHpelIf[uiMergeCand] ? IMV_HPEL : IMV_OFF;
2239
0
    CU::spanMotionInfo        ( pu );
2240
2241
0
    MergeItem* ciipMerge      = m_mergeItemList.allocateNewMergeItem();
2242
0
    ciipMerge->importMergeInfo( mergeCtx, uiMergeCand, MergeItem::MergeItemType::CIIP, pu );
2243
0
    ciipMerge->numCiipIntra   = numCiipIntra;
2244
0
    auto dstBuf               = ciipMerge->getPredBuf( localUnitArea );
2245
0
    generateMergePrediction   ( localUnitArea, ciipMerge, pu, true, false, dstBuf, false, false, nullptr, &ciipBuf );
2246
2247
0
    if( pu.cs->slice->lmcsEnabled && reshapeData.getCTUFlag() )
2248
0
    {
2249
      // distortion is calculated in the original domain
2250
0
      rspBuffer.Y()           . rspSignal( dstBuf.Y(), reshapeData.getInvLUT() );
2251
0
      ciipMerge->cost         = calcLumaCost4MergePrediction( ctxStart, rspBuffer, sqrtLambdaForFirstPassIntra, pu, distParam );
2252
0
    }
2253
0
    else
2254
0
    {
2255
0
      ciipMerge->cost         = calcLumaCost4MergePrediction( ctxStart, dstBuf, sqrtLambdaForFirstPassIntra, pu, distParam );
2256
0
    }
2257
0
    if( !m_mergeItemList      . insertMergeItemToList( ciipMerge ) && m_pcEncCfg->m_CIIP > 1 )
2258
0
    {
2259
0
      break;
2260
0
    }
2261
0
  }
2262
0
}
2263
2264
void EncCu::addMmvdCandsToPruningList( const MergeCtx &mergeCtx, const UnitArea &localUnitArea, double sqrtLambdaForFirstPassIntra, const TempCtx& ctxStart,
2265
                                       DistParam& distParam, CodingUnit& pu )
2266
0
{
2267
0
  pu.mmvdSkip              = true;
2268
0
  pu.affine                = pu.geo
2269
0
                           = pu.ciip
2270
0
                           = false;
2271
2272
0
  int       mmvdTestNum    = mergeCtx.numValidMergeCand > 1 ? MmvdIdx::ADD_NUM : MmvdIdx::ADD_NUM >> 1;
2273
0
  int       bestDir        = 0;
2274
0
  size_t    curListSize    = m_mergeItemList.size();
2275
0
  double    bestCostMerge  = m_mergeItemList.getMergeItemInList( curListSize - 1 )->cost;
2276
0
  double    bestCostOffset = MAX_DOUBLE;
2277
0
  int       shiftCandStart = 0;
2278
2279
0
  if( m_pcEncCfg->m_MMVD == 4 )
2280
0
  {
2281
0
    const int cnd1idx = m_mergeItemList.size() == 1 ? 0 : 1;
2282
0
    const int mrgCnd0 = m_mergeItemList.getMergeItemInList(       0 )->mergeIdx;
2283
0
    const int mrgCnd1 = m_mergeItemList.getMergeItemInList( cnd1idx )->mergeIdx;
2284
2285
0
    if( mrgCnd0 > 1 && mrgCnd1 > 1 )
2286
0
    {
2287
0
      mmvdTestNum = 0;
2288
0
    }
2289
0
    else if( mrgCnd0 > 1 || mrgCnd1 > 1 )
2290
0
    {
2291
0
      int shiftCand = mrgCnd0 < 2 ? mrgCnd0 : mrgCnd1;
2292
2293
0
      if( shiftCand )
2294
0
      {
2295
0
        shiftCandStart = MMVD_MAX_REFINE_NUM;
2296
0
      }
2297
0
      else
2298
0
      {
2299
0
        mmvdTestNum    = MMVD_MAX_REFINE_NUM;
2300
0
      }
2301
0
    }
2302
0
  }
2303
2304
0
  for( int mmvdMergeCand = shiftCandStart; mmvdMergeCand < mmvdTestNum; mmvdMergeCand++ )
2305
0
  {
2306
0
    MmvdIdx mmvdIdx;
2307
0
    mmvdIdx.val = mmvdMergeCand;
2308
2309
0
    if( mmvdIdx.pos.step >= m_pcEncCfg->m_MmvdDisNum )
2310
0
    {
2311
0
      continue;
2312
0
    }
2313
2314
0
    if( m_pcEncCfg->m_MMVD > 1 )
2315
0
    {
2316
0
      int checkMMVD = xCheckMMVDCand( mmvdIdx, bestDir, mmvdTestNum, bestCostOffset, bestCostMerge, m_mergeItemList.getMergeItemInList( curListSize - 1 )->cost );
2317
0
      mmvdMergeCand = mmvdIdx.val;
2318
2319
0
      if( checkMMVD )
2320
0
      {
2321
0
        if( checkMMVD == 2 )
2322
0
        {
2323
0
          break;
2324
0
        }
2325
0
        continue;
2326
0
      }
2327
0
    }
2328
2329
0
    mergeCtx.setMmvdMergeCandiInfo( pu, mmvdIdx );
2330
2331
0
    if( m_pcEncCfg->m_ifpLines &&
2332
0
        ( ( pu.refIdx[L0] >= 0 && !CU::isMvInRangeFPP( pu.ly(), pu.lheight(), pu.mv[L0][0].ver, m_pcEncCfg->m_ifpLines, *pu.cs->pcv ) ) ||
2333
0
          ( pu.refIdx[L1] >= 0 && !CU::isMvInRangeFPP( pu.ly(), pu.lheight(), pu.mv[L1][0].ver, m_pcEncCfg->m_ifpLines, *pu.cs->pcv ) ) ) )
2334
0
    {
2335
      // skip candidate
2336
0
      continue;
2337
0
    }
2338
2339
0
    pu.interDir               = mergeCtx.interDirNeighbours[mmvdIdx.pos.baseIdx];
2340
0
    pu.BcwIdx                 = pu.interDir == 3 ? mergeCtx.BcwIdx[mmvdIdx.pos.baseIdx] : BCW_DEFAULT;
2341
0
    pu.imv                    = mergeCtx.useAltHpelIf[mmvdIdx.pos.baseIdx] ? IMV_HPEL : IMV_OFF;
2342
0
    CU::spanMotionInfo        ( pu );
2343
2344
0
    MergeItem *mmvdMerge      = m_mergeItemList.allocateNewMergeItem();
2345
0
    mmvdMerge->importMergeInfo( mergeCtx, mmvdIdx.val, MergeItem::MergeItemType::MMVD, pu );
2346
0
    auto dstBuf               = mmvdMerge->getPredBuf( localUnitArea );
2347
0
    generateMergePrediction   ( localUnitArea, mmvdMerge, pu, true, false, dstBuf, false, false, nullptr, nullptr );
2348
0
    mmvdMerge->cost           = calcLumaCost4MergePrediction( ctxStart, dstBuf, sqrtLambdaForFirstPassIntra, pu, distParam );
2349
0
    m_mergeItemList           . insertMergeItemToList( mmvdMerge );
2350
2351
0
    if( m_pcEncCfg->m_MMVD > 1 && mmvdMerge->cost < bestCostOffset )
2352
0
    {
2353
0
      bestCostOffset          = mmvdMerge->cost;
2354
0
      int CandCur             = mmvdIdx.val - MMVD_MAX_REFINE_NUM * mmvdIdx.pos.baseIdx;
2355
0
      if( CandCur < 4 )
2356
0
        bestDir               = CandCur;
2357
0
    }
2358
0
  }
2359
2360
0
  if( m_pcEncCfg->m_useFastMrg >= 2 )
2361
0
  {
2362
0
    m_mergeItemList           . shrinkList( curListSize );
2363
0
  }
2364
0
}
2365
2366
void EncCu::addAffineCandsToPruningList( AffineMergeCtx &affineMergeCtx, const UnitArea &localUnitArea, double sqrtLambdaForFirstPass,
2367
                                         const TempCtx& ctxStart, DistParam& distParam, CodingUnit& pu)
2368
0
{
2369
0
  bool sameMV[AFFINE_MRG_MAX_NUM_CANDS + 1]
2370
0
                      = { false, };
2371
0
  size_t curListSize  = m_mergeItemList.size();
2372
2373
0
  pu.mergeFlag = true;
2374
0
  pu.affine    = true;
2375
0
  pu.imv       = IMV_OFF;
2376
0
  pu.geo       = pu.mmvdMergeFlag = pu.mmvdSkip
2377
0
               = pu.ciip
2378
0
               = false;
2379
2380
0
  if( m_pcEncCfg->m_Affine > 1 )
2381
0
  {
2382
0
    for( int m = 0; m < affineMergeCtx.numValidMergeCand; m++ )
2383
0
    {
2384
0
      if( pu.cs->slice->TLayer > 3 && affineMergeCtx.mergeType[m] != MRG_TYPE_SUBPU_ATMVP )
2385
0
      {
2386
0
        sameMV[m] = m != 0;
2387
0
      }
2388
0
      else if( !sameMV[m + 1] )
2389
0
      {
2390
0
        for( int n = m + 1; n < affineMergeCtx.numValidMergeCand; n++ )
2391
0
        {
2392
0
          sameMV[n] |= affineMergeCtx.mvFieldNeighbours[m][0][0] == affineMergeCtx.mvFieldNeighbours[n][0][0]
2393
0
                    && affineMergeCtx.mvFieldNeighbours[m][1][0] == affineMergeCtx.mvFieldNeighbours[n][1][0];
2394
0
        }
2395
0
      }
2396
0
    }
2397
0
  }
2398
2399
0
  for( uint32_t mergeIdx = 0; mergeIdx < affineMergeCtx.numValidMergeCand; mergeIdx++ )
2400
0
  {
2401
0
    if( ( affineMergeCtx.mergeType[mergeIdx] != MRG_TYPE_SUBPU_ATMVP && m_pcEncCfg->m_Affine == 0 ) || sameMV[mergeIdx] )
2402
0
    {
2403
0
      continue;
2404
0
    }
2405
2406
0
    pu.mergeType              = affineMergeCtx.mergeType[mergeIdx];
2407
0
    pu.affineType             = affineMergeCtx.affineType[mergeIdx];
2408
0
    pu.interDir               = affineMergeCtx.interDirNeighbours[mergeIdx];
2409
0
    pu.BcwIdx                 = pu.interDir == 3 ? affineMergeCtx.BcwIdx[mergeIdx] : BCW_DEFAULT;
2410
2411
    // generate motion buf for IFP
2412
0
    if( affineMergeCtx.mergeType[mergeIdx] == MRG_TYPE_SUBPU_ATMVP )
2413
0
    {
2414
0
      pu.refIdx[L0]           = affineMergeCtx.mvFieldNeighbours[mergeIdx][L0][0].refIdx;
2415
0
      pu.refIdx[L1]           = affineMergeCtx.mvFieldNeighbours[mergeIdx][L1][0].refIdx;
2416
0
      pu.mv    [L0][0]        = affineMergeCtx.mvFieldNeighbours[mergeIdx][L0][0].mv;
2417
0
      pu.mv    [L1][0]        = affineMergeCtx.mvFieldNeighbours[mergeIdx][L1][0].mv;
2418
0
      CU::spanMotionInfo      ( pu, &affineMergeCtx );
2419
0
    }
2420
0
    else
2421
0
    {
2422
0
      CU::setAllAffineMvField ( pu, affineMergeCtx.mvFieldNeighbours[mergeIdx][L0], L0 );
2423
0
      CU::setAllAffineMvField ( pu, affineMergeCtx.mvFieldNeighbours[mergeIdx][L1], L1 );
2424
0
      CU::spanMotionInfo      ( pu );
2425
0
    }
2426
2427
0
    if( m_pcEncCfg->m_ifpLines && !CU::isMotionBufInRangeFPP( pu, m_pcEncCfg->m_ifpLines ) )
2428
0
    {
2429
0
      continue;
2430
0
    }
2431
2432
0
    MergeItem *mergeItem   = m_mergeItemList.allocateNewMergeItem();
2433
0
    mergeItem->importMergeInfo( affineMergeCtx, mergeIdx, affineMergeCtx.mergeType[mergeIdx] == MRG_TYPE_SUBPU_ATMVP ? MergeItem::MergeItemType::SBTMVP : MergeItem::MergeItemType::AFFINE, pu );
2434
0
    auto dstBuf            = mergeItem->getPredBuf( localUnitArea );
2435
0
    generateMergePrediction( localUnitArea, mergeItem, pu, true, false, dstBuf, false, false, nullptr, nullptr );
2436
0
    mergeItem->cost        = calcLumaCost4MergePrediction( ctxStart, dstBuf, sqrtLambdaForFirstPass, pu, distParam );
2437
0
    m_mergeItemList        . insertMergeItemToList( mergeItem );
2438
0
  }
2439
0
  if( m_pcEncCfg->m_useFastMrg >= 2 )
2440
0
  {
2441
0
    m_mergeItemList        . shrinkList( curListSize );
2442
0
  }
2443
0
}
2444
2445
void EncCu::addGpmCandsToPruningList( const MergeCtx &mergeCtx, const UnitArea &localUnitArea, double sqrtLambdaForFirstPass,
2446
                                      const TempCtx& ctxStart, const GeoComboCostList& comboList, MergeBufVector& geoBuffer, DistParam& distParam, CodingUnit& pu)
2447
0
{
2448
0
  int geoNumMrgSadCand    = std::min( GEO_MAX_TRY_WEIGHTED_SAD, ( int ) comboList.list.size() );
2449
0
  geoNumMrgSadCand        = std::min( geoNumMrgSadCand, m_pcEncCfg->m_Geo > 2 ? 10 : GEO_MAX_TRY_WEIGHTED_SAD );
2450
0
  double bestGeoCost      = MAX_DOUBLE / 2.0;
2451
0
  MergeItem* best2geo[2]  = { nullptr, nullptr };
2452
2453
0
  pu.mergeFlag = true;
2454
0
  pu.geo       = true;
2455
0
  pu.mergeType = MRG_TYPE_DEFAULT_N;
2456
0
  pu.BcwIdx    = BCW_DEFAULT;
2457
0
  pu.interDir  = 3;
2458
0
  pu.imv       = IMV_OFF;
2459
0
  pu.affine    = pu.mmvdMergeFlag = pu.mmvdSkip
2460
0
               = pu.ciip
2461
0
               = false;
2462
2463
0
  for( int candidateIdx = 0; candidateIdx < geoNumMrgSadCand; candidateIdx++ )
2464
0
  {
2465
0
    const int          splitDir     = comboList.list[candidateIdx].splitDir;
2466
0
    const MergeIdxPair mergeIdxPair { comboList.list[candidateIdx].mergeIdx0, comboList.list[candidateIdx].mergeIdx1 };
2467
0
    const int          gpmIndex     = MergeItem::getGpmUnfiedIndex( splitDir, mergeIdxPair );
2468
2469
0
    pu.mergeIdx            = gpmIndex;
2470
0
    pu.geoMergeIdx         = mergeIdxPair;
2471
0
    pu.geoSplitDir         = splitDir;
2472
0
    CU::spanGeoMotionInfo  ( pu, mergeCtx, pu.geoSplitDir, pu.geoMergeIdx[0], pu.geoMergeIdx[1] );
2473
2474
0
    MergeItem *mergeItem   = m_mergeItemList.allocateNewMergeItem();
2475
0
    mergeItem->importMergeInfo( mergeCtx, gpmIndex, MergeItem::MergeItemType::GPM, pu );
2476
0
    auto dstBuf            = mergeItem->getPredBuf( localUnitArea );
2477
0
    generateMergePrediction( localUnitArea, mergeItem, pu, true, false, dstBuf, false, false, &geoBuffer[mergeIdxPair[0]], &geoBuffer[mergeIdxPair[1]] );
2478
0
    mergeItem->cost        = calcLumaCost4MergePrediction( ctxStart, dstBuf, sqrtLambdaForFirstPass, pu, distParam );
2479
0
    bestGeoCost            = std::min( mergeItem->cost, bestGeoCost );
2480
2481
0
    if( mergeItem->cost > MRG_FAST_RATIO[0] * bestGeoCost || mergeItem->cost > m_mergeBestSATDCost )
2482
0
    {
2483
0
      m_mergeItemList      . giveBackMergeItem( mergeItem );
2484
2485
0
      if( m_pcEncCfg->m_Geo > 2 ) break;
2486
0
    }
2487
0
    else if( m_pcEncCfg->m_Geo < 2 )
2488
0
    {
2489
0
      m_mergeItemList      . insertMergeItemToList( mergeItem );
2490
0
    }
2491
0
    else
2492
0
    {
2493
0
      if( ( m_mergeItemList.size() > 0 && m_mergeItemList.getMergeItemInList( m_mergeItemList.size() - 1 )->cost <= mergeItem->cost ) ||
2494
0
        ( best2geo[1] && best2geo[1]->cost <= mergeItem->cost ) )
2495
0
      {
2496
0
        m_mergeItemList    . giveBackMergeItem( mergeItem );
2497
0
      }
2498
0
      else
2499
0
      {
2500
0
        if( !best2geo[0] || mergeItem->cost < best2geo[0]->cost )
2501
0
        {
2502
0
          if( best2geo[1] )
2503
0
            m_mergeItemList. giveBackMergeItem( best2geo[1] );
2504
2505
0
          best2geo[1] = best2geo[0]; best2geo[0] = mergeItem;
2506
0
        }
2507
0
        else
2508
0
        {
2509
0
          if( best2geo[1] ) 
2510
0
            m_mergeItemList. giveBackMergeItem( best2geo[1] );
2511
2512
0
          best2geo[1] = mergeItem;
2513
0
        }
2514
0
      }
2515
0
    }
2516
0
  }
2517
2518
0
  if( best2geo[0] )
2519
0
    m_mergeItemList        . insertMergeItemToList( best2geo[0] );
2520
0
  if( best2geo[1] )
2521
0
    m_mergeItemList        . insertMergeItemToList( best2geo[1] );
2522
0
}
2523
2524
bool EncCu::prepareGpmComboList( const MergeCtx &mergeCtx, const UnitArea &localUnitArea, double sqrtLambdaForFirstPass,
2525
                                 GeoComboCostList& comboList, MergeBufVector& geoBuffer, CodingUnit& pu )
2526
0
{
2527
0
          sqrtLambdaForFirstPass /= FRAC_BITS_SCALE;
2528
0
  const int bitsForPartitionIdx   = floorLog2(GEO_NUM_PARTITION_MODE);
2529
0
  const int maxNumMergeCandidates = std::min( ( int ) pu.cs->sps->maxNumGeoCand, MRG_MAX_NUM_CANDS );
2530
0
  DistParam distParam;
2531
  // the second arguments to setDistParam is dummy and will be updated before being used
2532
0
  DistParam  distParamWholeBlk     = m_cRdCost.setDistParam( pu.cs->getOrgBuf().Y(), pu.cs->getOrgBuf().Y(), pu.cs->sps->bitDepths[ CH_L ], DF_SAD );
2533
0
  Distortion bestWholeBlkSad       = MAX_UINT64;
2534
0
  double     bestWholeBlkCost      = MAX_DOUBLE;
2535
0
  const ClpRng&  lclpRng           = pu.slice->clpRngs[COMP_Y];
2536
0
  const unsigned rshift            = std::max<int>( 2, ( IF_INTERNAL_PREC - lclpRng.bd ) );
2537
0
  const int      offset            = ( 1 << ( rshift - 1 ) ) + IF_INTERNAL_OFFS;
2538
0
  const int      numSamples        = pu.Y().area();
2539
0
  Distortion sadWholeBlk            [GEO_MAX_NUM_UNI_CANDS];
2540
0
  int        pocMrg                 [GEO_MAX_NUM_UNI_CANDS];
2541
0
  Mv         mergeMv                [GEO_MAX_NUM_UNI_CANDS];
2542
0
  bool       isSkipThisCand         [GEO_MAX_NUM_UNI_CANDS]
2543
0
                                   = { false, };
2544
0
  bool       sameMV                 [MRG_MAX_NUM_CANDS]
2545
0
                                   = { false, };
2546
0
  MergeBufVector geoTempBuf;
2547
2548
0
  if( m_pcEncCfg->m_Geo > 2 )
2549
0
  {
2550
0
    for( int m = 0; m < maxNumMergeCandidates; m++ )
2551
0
    {
2552
0
      if( !sameMV[m] )
2553
0
      {
2554
0
        for( int n = m + 1; n < maxNumMergeCandidates; n++ )
2555
0
        {
2556
0
          sameMV[n] |= mergeCtx.mvFieldNeighbours[m][0] == mergeCtx.mvFieldNeighbours[n][0]
2557
0
                    && mergeCtx.mvFieldNeighbours[m][1] == mergeCtx.mvFieldNeighbours[n][1];
2558
0
        }
2559
0
      }
2560
0
    }
2561
0
  }
2562
2563
0
  for( uint8_t mergeCand = 0; mergeCand < maxNumMergeCandidates; mergeCand++ )
2564
0
  {
2565
0
    geoBuffer .push_back ( m_aTmpStorageLCU[2                         + mergeCand].getCompactBuf( localUnitArea ) );
2566
0
    geoTempBuf.push_back ( m_aTmpStorageLCU[2 + GEO_MAX_NUM_UNI_CANDS + mergeCand].getCompactBuf( localUnitArea ) );
2567
2568
0
    const int  listIdx    = mergeCtx.mvFieldNeighbours[mergeCand][0]      .refIdx == -1 ? 1 : 0;
2569
0
    const auto refPicList = RefPicList(listIdx);
2570
0
    const int  refIdx     = mergeCtx.mvFieldNeighbours[mergeCand][listIdx].refIdx;
2571
2572
0
    pocMrg [mergeCand]    = pu.cs->slice->getRefPic( refPicList, refIdx )->poc;
2573
0
    mergeMv[mergeCand]    = mergeCtx.mvFieldNeighbours[mergeCand][listIdx].mv;
2574
2575
0
    for( int i = 0; i < mergeCand; i++ )
2576
0
    {
2577
0
      if( pocMrg[mergeCand] == pocMrg[i] && mergeMv[mergeCand] == mergeMv[i] )
2578
0
      {
2579
0
        isSkipThisCand[mergeCand] = true;
2580
0
        break;
2581
0
      }
2582
0
    }
2583
2584
0
    if( sameMV[mergeCand] )
2585
0
    {
2586
0
      continue;
2587
0
    }
2588
2589
0
    if( m_pcEncCfg->m_ifpLines ) 
2590
0
    {
2591
0
      bool isOutOfRange  = !CU::isMvInRangeFPP( pu.ly(), pu.lheight(), mergeCtx.mvFieldNeighbours[mergeCand][0].mv.ver, m_pcEncCfg->m_ifpLines, *pu.cs->pcv );
2592
0
           isOutOfRange |= !CU::isMvInRangeFPP( pu.ly(), pu.lheight(), mergeCtx.mvFieldNeighbours[mergeCand][1].mv.ver, m_pcEncCfg->m_ifpLines, *pu.cs->pcv );
2593
2594
      // use sameMV to surpress processing of this cand later on...
2595
0
      sameMV[mergeCand] |= isOutOfRange;
2596
2597
0
      if( isOutOfRange )
2598
0
        continue;
2599
0
    }
2600
2601
0
    mergeCtx.setMergeInfo            ( pu, mergeCand );
2602
0
    CU::spanMotionInfo               ( pu );
2603
0
    m_cInterSearch.motionCompensation( pu, geoBuffer[mergeCand], REF_PIC_LIST_X );
2604
2605
0
    g_pelBufOP.roundGeo( geoBuffer[mergeCand].Y().buf, geoTempBuf[mergeCand].Y().buf, numSamples, rshift, offset, lclpRng );
2606
2607
0
    distParamWholeBlk.cur  = geoTempBuf[mergeCand].Y();
2608
0
    sadWholeBlk[mergeCand] = distParamWholeBlk.distFunc( distParamWholeBlk );
2609
2610
0
    if( sadWholeBlk[mergeCand] < bestWholeBlkSad )
2611
0
    {
2612
0
      bestWholeBlkSad  = sadWholeBlk[mergeCand];
2613
0
      int bitsCand     = mergeCand + 1;
2614
0
      bestWholeBlkCost = ( double ) bestWholeBlkSad + ( double ) bitsCand * sqrtLambdaForFirstPass;
2615
0
    }
2616
0
  }
2617
2618
0
  bool allCandsAreSame = true;
2619
0
  for( uint8_t mergeCand = 1; mergeCand < maxNumMergeCandidates; mergeCand++ )
2620
0
  {
2621
0
    allCandsAreSame &= isSkipThisCand[mergeCand];
2622
0
  }
2623
0
  if( allCandsAreSame )
2624
0
  {
2625
0
    return false;
2626
0
  }
2627
2628
0
  const int wIdx = floorLog2( pu.lwidth() )  - GEO_MIN_CU_LOG2;
2629
0
  const int hIdx = floorLog2( pu.lheight() ) - GEO_MIN_CU_LOG2;
2630
2631
0
  for( int splitDir = 0; splitDir < GEO_NUM_PARTITION_MODE; )
2632
0
  {
2633
0
    int maskStride = 0, maskStride2 = 0;
2634
0
    int stepX = 1;
2635
0
    Pel *sadMask;
2636
0
    int16_t angle = g_GeoParams[splitDir][0];
2637
    
2638
0
    if( g_angle2mirror[angle] == 2 )
2639
0
    {
2640
0
      maskStride  = -GEO_WEIGHT_MASK_SIZE;
2641
0
      maskStride2 = -( int ) pu.lwidth();
2642
0
      sadMask     = &g_globalGeoEncSADmask[g_angle2mask[g_GeoParams[splitDir][0]]]
2643
0
                      [( GEO_WEIGHT_MASK_SIZE - 1 - g_weightOffset[hIdx][wIdx][splitDir][1] ) * GEO_WEIGHT_MASK_SIZE
2644
0
                                                  + g_weightOffset[hIdx][wIdx][splitDir][0]
2645
0
                      ];
2646
0
    }
2647
0
    else if( g_angle2mirror[angle] == 1 )
2648
0
    {
2649
0
      stepX       = -1;
2650
0
      maskStride2 = pu.lwidth();
2651
0
      maskStride  = GEO_WEIGHT_MASK_SIZE;
2652
0
      sadMask     = &g_globalGeoEncSADmask[g_angle2mask[g_GeoParams[splitDir][0]]]
2653
0
                      [     GEO_WEIGHT_MASK_SIZE *     g_weightOffset[hIdx][wIdx][splitDir][1]
2654
0
                        + ( GEO_WEIGHT_MASK_SIZE - 1 - g_weightOffset[hIdx][wIdx][splitDir][0] )
2655
0
                      ];
2656
0
    }
2657
0
    else
2658
0
    {
2659
0
      maskStride  = GEO_WEIGHT_MASK_SIZE;
2660
0
      maskStride2 = -( int ) pu.lwidth();
2661
0
      sadMask     = &g_globalGeoEncSADmask[g_angle2mask[g_GeoParams[splitDir][0]]]
2662
0
                      [   g_weightOffset[hIdx][wIdx][splitDir][1] * GEO_WEIGHT_MASK_SIZE
2663
0
                        + g_weightOffset[hIdx][wIdx][splitDir][0]
2664
0
                      ];
2665
0
    }
2666
2667
0
    m_cRdCost.setDistParamGeo ( distParam, pu.cs->getOrgBuf().Y(),
2668
0
                                nullptr, 0,
2669
0
                                sadMask, maskStride, stepX, maskStride2,
2670
0
                                pu.cs->sps->bitDepths[CH_L], COMP_Y );
2671
2672
0
    for( uint8_t mergeCand = 0; mergeCand < maxNumMergeCandidates; mergeCand++ )
2673
0
    {
2674
0
      if( sameMV[mergeCand] )
2675
0
      {
2676
0
        continue;
2677
0
      }
2678
2679
0
      distParam.cur.buf         = geoTempBuf[mergeCand].Y().buf;
2680
0
      distParam.cur.stride      = geoTempBuf[mergeCand].Y().stride;
2681
0
      const Distortion sadLarge = distParam.distFunc( distParam );
2682
0
      const Distortion sadSmall = sadWholeBlk[mergeCand] - sadLarge;
2683
2684
0
      const int bitsCand        = mergeCand + 1;
2685
2686
0
      const double cost0        = ( double ) sadLarge + ( double ) bitsCand * sqrtLambdaForFirstPass;
2687
0
      const double cost1        = ( double ) sadSmall + ( double ) bitsCand * sqrtLambdaForFirstPass;
2688
2689
0
      m_GeoCostList.insert( splitDir, 0, mergeCand, cost0 );
2690
0
      m_GeoCostList.insert( splitDir, 1, mergeCand, cost1 );
2691
0
    }
2692
2693
0
    if( m_pcEncCfg->m_Geo == 4 )
2694
0
    {
2695
0
      if( splitDir == 1 )
2696
0
      {
2697
0
        splitDir += 7;
2698
0
      }
2699
0
      else if( splitDir == 35 || ( splitDir + 1 ) % 4 != 0 )
2700
0
      {
2701
0
        splitDir++;
2702
0
      }
2703
0
      else
2704
0
      {
2705
0
        splitDir += 5;
2706
0
      }
2707
0
    }
2708
0
    else
2709
0
    {
2710
0
      splitDir++;
2711
0
    }
2712
0
  }
2713
2714
0
  comboList.list.clear();
2715
2716
0
  for( int splitDir = 0; splitDir < GEO_NUM_PARTITION_MODE; )
2717
0
  {
2718
0
    for( int geoMotionIdx = 0; geoMotionIdx < maxNumMergeCandidates * ( maxNumMergeCandidates - 1 ); geoMotionIdx++ )
2719
0
    {
2720
0
      const MergeIdxPair mergeIdxPair = m_GeoModeTest[geoMotionIdx];
2721
2722
0
      if( sameMV[mergeIdxPair[0]] || sameMV[mergeIdxPair[1]] )
2723
0
      {
2724
0
        continue;
2725
0
      }
2726
2727
0
      double tempCost = m_GeoCostList.getCost( splitDir, mergeIdxPair[0], mergeIdxPair[1] );
2728
2729
0
      if( tempCost > bestWholeBlkCost )
2730
0
      {
2731
0
        continue;
2732
0
      }
2733
2734
0
      tempCost = tempCost + ( double ) bitsForPartitionIdx * sqrtLambdaForFirstPass;
2735
0
      comboList.list.push_back( GeoMergeCombo{ splitDir, mergeIdxPair[0], mergeIdxPair[1], tempCost } );
2736
0
    }
2737
2738
0
    if( m_pcEncCfg->m_Geo == 4 )
2739
0
    {
2740
0
      if( splitDir == 1 )
2741
0
      {
2742
0
        splitDir += 7;
2743
0
      }
2744
0
      else if( splitDir == 35 || ( splitDir + 1 ) % 4 != 0 )
2745
0
      {
2746
0
        splitDir++;
2747
0
      }
2748
0
      else
2749
0
      {
2750
0
        splitDir += 5;
2751
0
      }
2752
0
    }
2753
0
    else
2754
0
    {
2755
0
      splitDir++;
2756
0
    }
2757
0
  }
2758
2759
0
  if( comboList.list.empty() )
2760
0
  {
2761
0
    return false;
2762
0
  }
2763
2764
0
  comboList.sortByCost();
2765
0
  return true;
2766
0
}
2767
2768
double EncCu::calcLumaCost4MergePrediction( const TempCtx &ctxStart, const PelUnitBuf &predBuf, double lambda, CodingUnit &cu, DistParam &distParam )
2769
0
{
2770
0
  distParam.cur = predBuf.Y();
2771
0
  auto dist     = distParam.distFunc(distParam);
2772
2773
0
  m_CABACEstimator->getCtx() = ctxStart;
2774
0
  auto fracBits = xCalcPuMeBits( cu );
2775
2776
0
  double cost   = ( double ) dist + ( double ) fracBits * lambda;
2777
2778
0
  m_uiSadBestForQPA = std::min( dist, m_uiSadBestForQPA );
2779
2780
0
  return cost;
2781
0
}
2782
2783
//////////////////////////////////////////////////////////////////////////////////////////////
2784
// ibc merge/skip mode check
2785
void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure*& tempCS, CodingStructure*& bestCS, Partitioner& partitioner, const EncTestMode& encTestMode)
2786
23.1k
{
2787
23.1k
  assert(partitioner.chType != CH_C); // chroma IBC is derived
2788
23.1k
  if (tempCS->area.lwidth() == 128 || tempCS->area.lheight() == 128) // disable IBC mode larger than 64x64
2789
0
  {
2790
0
    return;
2791
0
  }
2792
2793
23.1k
  if ((m_pcEncCfg->m_IBCFastMethod > 1) && !bestCS->slice->isIntra() && (bestCS->cus.size() != 0))
2794
0
  {
2795
0
    if (bestCS->getCU(partitioner.chType, partitioner.treeType)->skip)
2796
0
    {
2797
0
      return;
2798
0
    }
2799
0
  }
2800
2801
23.1k
  const SPS& sps = *tempCS->sps;
2802
2803
23.1k
  tempCS->initStructData(encTestMode.qp);
2804
23.1k
  MergeCtx mergeCtx;
2805
2806
23.1k
  {
2807
    // first get merge candidates
2808
23.1k
    CodingUnit cu(tempCS->area);
2809
23.1k
    cu.cs = tempCS;
2810
23.1k
    cu.predMode = MODE_IBC;
2811
23.1k
    cu.slice = tempCS->slice;
2812
23.1k
    cu.tileIdx = m_tileIdx;
2813
23.1k
    cu.initPuData();
2814
23.1k
    cu.cs = tempCS;
2815
23.1k
    cu.mmvdSkip = false;
2816
23.1k
    cu.mmvdMergeFlag = false;
2817
23.1k
    cu.geo = false;
2818
23.1k
    CU::getIBCMergeCandidates(cu, mergeCtx);
2819
23.1k
  }
2820
23.1k
  int candHasNoResidual[MRG_MAX_NUM_CANDS];
2821
161k
  for (unsigned int ui = 0; ui < mergeCtx.numValidMergeCand; ui++)
2822
138k
  {
2823
138k
    candHasNoResidual[ui] = 0;
2824
138k
  }
2825
2826
23.1k
  bool                                        bestIsSkip = false;
2827
23.1k
  unsigned                                    numMrgSATDCand = mergeCtx.numValidMergeCand;
2828
23.1k
  static_vector<unsigned, MRG_MAX_NUM_CANDS>  RdModeList(MRG_MAX_NUM_CANDS);
2829
161k
  for (unsigned i = 0; i < MRG_MAX_NUM_CANDS; i++)
2830
138k
  {
2831
138k
    RdModeList[i] = i;
2832
138k
  }
2833
2834
  //{
2835
23.1k
  static_vector<double, MRG_MAX_NUM_CANDS>  candCostList(MRG_MAX_NUM_CANDS, MAX_DOUBLE);
2836
  // 1. Pass: get SATD-cost for selected candidates and reduce their count
2837
23.1k
  {
2838
23.1k
    const double sqrtLambdaForFirstPass = m_cRdCost.getMotionLambda();
2839
2840
23.1k
    CodingUnit& cu = tempCS->addCU(CS::getArea(*tempCS, tempCS->area, partitioner.chType,partitioner.treeType), partitioner.chType);
2841
2842
23.1k
    partitioner.setCUData(cu);
2843
23.1k
    cu.slice = tempCS->slice;
2844
23.1k
    cu.tileIdx = m_tileIdx;
2845
23.1k
    cu.skip = false;
2846
23.1k
    cu.predMode = MODE_IBC;
2847
23.1k
    cu.chromaQpAdj = m_cuChromaQpOffsetIdxPlus1;
2848
23.1k
    cu.qp = encTestMode.qp;
2849
23.1k
    cu.mmvdSkip = false;
2850
23.1k
    cu.geo = false;
2851
23.1k
    DistParam distParam;
2852
23.1k
    cu.initPuData();
2853
23.1k
    cu.mmvdMergeFlag = false;
2854
23.1k
    Picture* refPic = cu.slice->pic;
2855
23.1k
    const UnitArea localUnitArea(tempCS->area.chromaFormat, Area(cu.blocks[COMP_Y].x, cu.blocks[COMP_Y].y, tempCS->area.Y().width, tempCS->area.Y().height));
2856
23.1k
    const CompArea& compArea = localUnitArea.block(COMP_Y);
2857
23.1k
    const CPelBuf refBuf = refPic->getRecoBuf(compArea);
2858
23.1k
    const Pel* piRefSrch = refBuf.buf;
2859
23.1k
    const ReshapeData& reshapeData = cu.cs->picture->reshapeData;
2860
23.1k
    if (cu.cs->slice->lmcsEnabled && reshapeData.getCTUFlag())
2861
0
    {
2862
0
      PelBuf tmpLmcs = m_aTmpStorageLCU[0].getCompactBuf(cu.Y());
2863
0
      tmpLmcs.rspSignal(tempCS->getOrgBuf().Y(), reshapeData.getFwdLUT());
2864
0
      distParam = m_cRdCost.setDistParam( tmpLmcs, refBuf, sps.bitDepths[CH_L], DF_HAD);
2865
0
    }
2866
23.1k
    else
2867
23.1k
    {
2868
23.1k
      distParam = m_cRdCost.setDistParam(tempCS->getOrgBuf(COMP_Y), refBuf, sps.bitDepths[CH_L], DF_HAD);
2869
23.1k
    }
2870
23.1k
    int refStride = refBuf.stride;
2871
2872
23.1k
    int numValidBv = mergeCtx.numValidMergeCand;
2873
161k
    for (unsigned int mergeCand = 0; mergeCand < mergeCtx.numValidMergeCand; mergeCand++)
2874
138k
    {
2875
138k
      mergeCtx.setMergeInfo(cu, mergeCand); // set bv info in merge mode
2876
138k
      const int cuPelX = cu.Y().x;
2877
138k
      const int cuPelY = cu.Y().y;
2878
138k
      int roiWidth     = cu.lwidth();
2879
138k
      int roiHeight    = cu.lheight();
2880
138k
      const int picWidth  = cu.cs->slice->pps->picWidthInLumaSamples;
2881
138k
      const int picHeight = cu.cs->slice->pps->picHeightInLumaSamples;
2882
138k
      const unsigned int lcuWidth = cu.cs->slice->sps->CTUSize;
2883
2884
138k
      Mv bv = cu.mv[0][0];
2885
138k
      bv.changePrecision( MV_PRECISION_INTERNAL, MV_PRECISION_INT);
2886
138k
      int xPred = bv.hor;
2887
138k
      int yPred = bv.ver;
2888
      
2889
138k
      if( !m_cInterSearch.searchBvIBC( cu, cuPelX, cuPelY, roiWidth, roiHeight, picWidth, picHeight, xPred, yPred, lcuWidth ) ) // not valid bv derived
2890
138k
      {
2891
138k
        numValidBv--;
2892
138k
        continue;
2893
138k
      }
2894
0
      CU::spanMotionInfo(cu);
2895
0
      distParam.cur.buf = piRefSrch + refStride * yPred + xPred;
2896
2897
0
      Distortion sad = distParam.distFunc(distParam);
2898
0
      unsigned int bitsCand = mergeCand + 1;
2899
0
      if (mergeCand == tempCS->sps->maxNumIBCMergeCand - 1)
2900
0
      {
2901
0
        bitsCand--;
2902
0
      }
2903
0
      double cost = (double)sad + (double)bitsCand * sqrtLambdaForFirstPass;
2904
2905
0
      updateCandList( mergeCand, cost, RdModeList, candCostList, numMrgSATDCand );
2906
0
    }
2907
2908
    // Try to limit number of candidates using SATD-costs
2909
23.1k
    if (numValidBv)
2910
0
    {
2911
0
      numMrgSATDCand = numValidBv;
2912
0
      for (unsigned int i = 1; i < numValidBv; i++)
2913
0
      {
2914
0
        if (candCostList[i] > MRG_FAST_RATIO[0] * candCostList[0])
2915
0
        {
2916
0
          numMrgSATDCand = i;
2917
0
          break;
2918
0
        }
2919
0
      }
2920
0
    }
2921
23.1k
    else
2922
23.1k
    {
2923
23.1k
      tempCS->dist = 0;
2924
23.1k
      tempCS->fracBits = 0;
2925
23.1k
      tempCS->cost = MAX_DOUBLE;
2926
23.1k
      tempCS->costDbOffset = 0;
2927
23.1k
      tempCS->initStructData(encTestMode.qp);
2928
23.1k
      return;
2929
23.1k
    }
2930
2931
0
    tempCS->initStructData(encTestMode.qp);
2932
0
  }
2933
  //}
2934
2935
2936
0
  const unsigned int iteration = 2;
2937
 // m_bestModeUpdated = tempCS->cost = bestCS->cost = false;
2938
  // 2. Pass: check candidates using full RD test
2939
0
  for (unsigned int numResidualPass = 0; numResidualPass < iteration; numResidualPass++)
2940
0
  {
2941
0
    for (unsigned int mrgHADIdx = 0; mrgHADIdx < numMrgSATDCand; mrgHADIdx++)
2942
0
    {
2943
0
      unsigned int mergeCand = RdModeList[mrgHADIdx];
2944
0
      if (!(numResidualPass == 1 && candHasNoResidual[mergeCand] == 1))
2945
0
      {
2946
0
        if (!(bestIsSkip && (numResidualPass == 0)))
2947
0
        {
2948
0
          {
2949
2950
            // first get merge candidates
2951
0
            CodingUnit& cu = tempCS->addCU(CS::getArea(*tempCS, tempCS->area, (const ChannelType)partitioner.chType,partitioner.treeType), (const ChannelType)partitioner.chType);
2952
2953
0
            partitioner.setCUData(cu);
2954
0
            cu.slice = tempCS->slice;
2955
0
            cu.tileIdx = m_tileIdx;
2956
0
            cu.skip = false;
2957
0
            cu.predMode = MODE_IBC;
2958
0
            cu.chromaQpAdj = m_cuChromaQpOffsetIdxPlus1;
2959
0
            cu.qp = encTestMode.qp;
2960
0
            cu.sbtInfo = 0;
2961
0
            cu.initPuData();
2962
0
            cu.intraDir[0] = DC_IDX; // set intra pred for ibc block
2963
0
            cu.intraDir[1] = PLANAR_IDX; // set intra pred for ibc block
2964
0
            cu.mmvdSkip = false;
2965
0
            cu.mmvdMergeFlag = false;
2966
0
            cu.geo = false;
2967
0
            mergeCtx.setMergeInfo(cu, mergeCand);
2968
0
            CU::spanMotionInfo(cu);
2969
2970
0
            assert(mergeCtx.mrgTypeNeighbours[mergeCand] == MRG_TYPE_IBC);
2971
0
            const bool chroma = !CU::isSepTree(cu);
2972
2973
            //  MC
2974
0
            cu.mcControl = chroma ? 0: 2;
2975
0
            m_cInterSearch.motionCompensationIBC(cu, tempCS->getPredBuf());
2976
0
            m_CABACEstimator->getCtx() = m_CurrCtx->start;
2977
2978
0
            m_cInterSearch.encodeResAndCalcRdInterCU(*tempCS, partitioner, (numResidualPass != 0));
2979
0
            cu.mcControl = 0;
2980
0
            xEncodeDontSplit(*tempCS, partitioner);
2981
0
            xCheckDQP(*tempCS, partitioner);
2982
0
            xCheckBestMode(tempCS, bestCS, partitioner, encTestMode);
2983
2984
0
            tempCS->initStructData(encTestMode.qp);
2985
0
          }
2986
2987
0
          if (m_pcEncCfg->m_useFastDecisionForMerge && !bestIsSkip)
2988
0
          {
2989
0
            if (bestCS->getCU(partitioner.chType, partitioner.treeType) == NULL)
2990
0
              bestIsSkip = 0;
2991
0
            else
2992
0
              bestIsSkip = bestCS->getCU(partitioner.chType, partitioner.treeType)->rootCbf == 0;
2993
0
          }
2994
0
        }
2995
0
      }
2996
0
    }
2997
0
  }
2998
0
}
2999
3000
void EncCu::xCheckRDCostIBCMode(CodingStructure*& tempCS, CodingStructure*& bestCS, Partitioner& partitioner,
3001
  const EncTestMode& encTestMode)
3002
23.1k
{
3003
23.1k
  if (tempCS->area.lwidth() == 128 || tempCS->area.lheight() == 128)   // disable IBC mode larger than 64x64
3004
0
  {
3005
0
    return;
3006
0
  }
3007
23.1k
  if ((m_pcEncCfg->m_IBCFastMethod > 1) && !bestCS->slice->isIntra() && (bestCS->cus.size() != 0))
3008
0
  {
3009
0
    if (bestCS->getCU(partitioner.chType, partitioner.treeType)->skip)
3010
0
    {
3011
0
      return;
3012
0
    }
3013
0
  }
3014
3015
23.1k
  tempCS->initStructData(encTestMode.qp);
3016
3017
23.1k
  CodingUnit& cu = tempCS->addCU(CS::getArea(*tempCS, tempCS->area, partitioner.chType, partitioner.treeType), partitioner.chType);
3018
3019
23.1k
  partitioner.setCUData(cu);
3020
23.1k
  cu.slice = tempCS->slice;
3021
23.1k
  cu.tileIdx = m_tileIdx;
3022
23.1k
  cu.skip = false;
3023
23.1k
  cu.predMode = MODE_IBC;
3024
23.1k
  cu.chromaQpAdj = m_cuChromaQpOffsetIdxPlus1;
3025
23.1k
  cu.qp = encTestMode.qp;
3026
23.1k
  cu.initPuData();
3027
23.1k
  cu.imv = IMV_OFF;
3028
23.1k
  cu.sbtInfo = 0;
3029
23.1k
  cu.mmvdSkip = false;
3030
23.1k
  cu.mmvdMergeFlag = false;
3031
3032
23.1k
  cu.intraDir[0] = DC_IDX; // set intra pred for ibc block
3033
23.1k
  cu.intraDir[1] = PLANAR_IDX; // set intra pred for ibc block
3034
3035
23.1k
  cu.interDir = 1; // use list 0 for IBC mode
3036
23.1k
  cu.refIdx[REF_PIC_LIST_0] = MAX_NUM_REF; // last idx in the list
3037
23.1k
  bool bValid = m_cInterSearch.predIBCSearch(cu, partitioner);
3038
3039
23.1k
  if (bValid)
3040
20.6k
  {
3041
20.6k
    CU::spanMotionInfo(cu);
3042
20.6k
    const bool chroma = !CU::isSepTree(cu);
3043
    //  MC
3044
20.6k
    cu.mcControl = chroma ? 0 : 2;
3045
20.6k
    m_cInterSearch.motionCompensationIBC(cu, tempCS->getPredBuf());
3046
3047
20.6k
    m_cInterSearch.encodeResAndCalcRdInterCU(*tempCS, partitioner, false);
3048
20.6k
    cu.mcControl = 0;
3049
3050
20.6k
    xEncodeDontSplit(*tempCS, partitioner);
3051
20.6k
    xCheckDQP(*tempCS, partitioner);
3052
20.6k
    xCheckBestMode(tempCS, bestCS, partitioner, encTestMode);
3053
20.6k
  } // bValid
3054
2.49k
  else
3055
2.49k
  {
3056
2.49k
    tempCS->dist = 0;
3057
2.49k
    tempCS->fracBits = 0;
3058
2.49k
    tempCS->cost = MAX_DOUBLE;
3059
2.49k
    tempCS->costDbOffset = 0;
3060
2.49k
  }
3061
23.1k
}
3062
3063
void EncCu::xCheckRDCostInter( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode )
3064
0
{
3065
0
  PROFILER_SCOPE_AND_STAGE_EXT( 1, _TPROF, P_INTER_MVD, tempCS, partitioner.chType );
3066
0
  tempCS->initStructData( encTestMode.qp );
3067
3068
0
  m_cInterSearch.setAffineModeSelected( false );
3069
3070
0
  m_cInterSearch.resetBufferedUniMotions();
3071
3072
0
  int bcwLoopNum = BCW_NUM;
3073
3074
0
  if( tempCS->area.Y().area() < BCW_SIZE_CONSTRAINT || !tempCS->slice->isInterB() || !tempCS->sps->BCW )
3075
0
  {
3076
0
    bcwLoopNum = 1;
3077
0
  }
3078
  
3079
0
  double curBestCost = bestCS->cost;
3080
0
  double equBcwCost = MAX_DOUBLE;
3081
3082
0
  for( int bcwLoopIdx = 0; bcwLoopIdx < bcwLoopNum; bcwLoopIdx++ )
3083
0
  {
3084
0
    if( m_pcEncCfg->m_BCW == 2 )
3085
0
    {
3086
0
      bool isBestInter   = m_modeCtrl.getBlkInfo( bestCS->area ).isInter;
3087
0
      uint8_t bestBcwIdx = m_modeCtrl.getBlkInfo( bestCS->area).BcwIdx;
3088
3089
0
      if( isBestInter && g_BcwSearchOrder[bcwLoopIdx] != BCW_DEFAULT && g_BcwSearchOrder[bcwLoopIdx] != bestBcwIdx )
3090
0
      {
3091
0
        continue;
3092
0
      }
3093
0
    }
3094
    
3095
0
    if( !tempCS->slice->checkLDC )
3096
0
    {
3097
0
      if( bcwLoopIdx != 0 && bcwLoopIdx != 3 && bcwLoopIdx != 4 )
3098
0
      {
3099
0
        continue;
3100
0
      }
3101
0
    }
3102
  
3103
0
    CodingUnit &cu      = tempCS->addCU( tempCS->area, partitioner.chType );
3104
3105
0
    partitioner.setCUData( cu );
3106
0
    cu.slice            = tempCS->slice;
3107
0
    cu.tileIdx          = m_tileIdx;
3108
0
    cu.skip             = false;
3109
0
    cu.mmvdSkip         = false;
3110
0
    cu.predMode         = MODE_INTER;
3111
0
    cu.chromaQpAdj      = m_cuChromaQpOffsetIdxPlus1;
3112
0
    cu.qp               = encTestMode.qp;
3113
0
    cu.initPuData();
3114
3115
0
    cu.BcwIdx = g_BcwSearchOrder[bcwLoopIdx];
3116
0
    uint8_t bcwIdx = cu.BcwIdx;
3117
0
    bool testBcw = (bcwIdx != BCW_DEFAULT);
3118
3119
0
    bool StopInterRes = (m_pcEncCfg->m_FastInferMerge >> 3) & 1;
3120
0
    StopInterRes &= bestCS->slice->TLayer > (m_pcEncCfg->m_maxTLayer - (m_pcEncCfg->m_FastInferMerge & 7));
3121
0
    double bestCostInter = StopInterRes ? m_mergeBestSATDCost : MAX_DOUBLE;
3122
3123
0
    bool stopTest = m_cInterSearch.predInterSearch(cu, partitioner, bestCostInter);
3124
3125
0
    if (StopInterRes && (bestCostInter != m_mergeBestSATDCost))
3126
0
    {
3127
0
      int L = (cu.slice->TLayer <= 2) ? 0 : (cu.slice->TLayer - 2);
3128
0
      if ((bestCostInter > MRG_FAST_RATIOMYV[L] * m_mergeBestSATDCost))
3129
0
      {
3130
0
        stopTest = true;
3131
0
      }
3132
0
    }
3133
3134
0
    if( !stopTest )
3135
0
    {
3136
0
      bcwIdx   = CU::getValidBcwIdx(cu);
3137
0
      stopTest = testBcw && bcwIdx == BCW_DEFAULT;
3138
0
    }
3139
    
3140
0
    if( stopTest )
3141
0
    {
3142
0
      tempCS->initStructData(encTestMode.qp);
3143
0
      continue;
3144
0
    }
3145
3146
0
    CHECK(!(testBcw || (!testBcw && bcwIdx == BCW_DEFAULT)), " !( bTestBcw || (!bTestBcw && bcwIdx == BCW_DEFAULT ) )");
3147
        
3148
0
    xEncodeInterResidual(tempCS, bestCS, partitioner, encTestMode, 0, 0, &equBcwCost);
3149
    
3150
0
    if( bcwIdx == BCW_DEFAULT )
3151
0
    {
3152
0
      m_cInterSearch.setAffineModeSelected( bestCS->cus.front()->affine && !bestCS->cus.front()->mergeFlag );
3153
0
    }
3154
3155
0
    tempCS->initStructData(encTestMode.qp);
3156
  
3157
0
    double skipTH = MAX_DOUBLE;
3158
0
    skipTH = (m_pcEncCfg->m_BCW == 2 ? 1.05 : MAX_DOUBLE);
3159
0
    if( equBcwCost > curBestCost * skipTH )
3160
0
    {
3161
0
      break;
3162
0
    }
3163
3164
0
    if( m_pcEncCfg->m_BCW == 2 )
3165
0
    {
3166
0
      if( ( cu.interDir != 3 && testBcw == 0 && ! m_pcEncCfg->m_picReordering )
3167
0
         || ( g_BcwSearchOrder[bcwLoopIdx] == BCW_DEFAULT && xIsBcwSkip( cu ) ) )
3168
0
      {
3169
0
        break;
3170
0
      }
3171
0
    }
3172
0
  }
3173
0
  STAT_COUNT_CU_MODES( partitioner.chType == CH_L, g_cuCounters1D[CU_MODES_TESTED][0][!tempCS->slice->isIntra() + tempCS->slice->depth] );
3174
0
  STAT_COUNT_CU_MODES( partitioner.chType == CH_L && !tempCS->slice->isIntra(), g_cuCounters2D[CU_MODES_TESTED][Log2( tempCS->area.lheight() )][Log2( tempCS->area.lwidth() )] );
3175
0
}
3176
3177
void EncCu::xCheckRDCostInterIMV(CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode)
3178
0
{
3179
0
  PROFILER_SCOPE_AND_STAGE_EXT( 1, _TPROF, P_INTER_MVD_IMV, tempCS, partitioner.chType );
3180
0
  bool Test_AMVR = m_pcEncCfg->m_AMVRspeed ? true: false;
3181
0
  if (m_pcEncCfg->m_AMVRspeed > 2 && m_pcEncCfg->m_AMVRspeed < 5 && !bestCS->cus.empty() && bestCS->getCU(partitioner.chType, partitioner.treeType)->skip)
3182
0
  {
3183
0
    Test_AMVR = false;
3184
0
  }
3185
0
  else if (m_pcEncCfg->m_AMVRspeed > 4 && !bestCS->cus.empty() && bestCS->getCU(partitioner.chType, partitioner.treeType)->mergeFlag && !bestCS->getCU(partitioner.chType, partitioner.treeType)->ciip)
3186
0
  {
3187
0
    Test_AMVR = false;
3188
0
  }
3189
0
  bool Do_Limit = !bestCS->cus.empty() && (m_pcEncCfg->m_AMVRspeed == 4 || m_pcEncCfg->m_AMVRspeed == 6) ? true : false;
3190
0
  bool Do_OnceRes = !bestCS->cus.empty() && (m_pcEncCfg->m_AMVRspeed == 7) ? true : false;
3191
3192
0
  if( Test_AMVR )
3193
0
  {
3194
0
    double Fpel_cost    = m_pcEncCfg->m_AMVRspeed == 1 ? MAX_DOUBLE*0.5 : MAX_DOUBLE;
3195
0
    double costCurStart = m_pcEncCfg->m_AMVRspeed == 1 ? m_modeCtrl.comprCUCtx->bestCostNoImv : bestCS->cost;
3196
0
    double costCur      = MAX_DOUBLE;
3197
0
    double bestCostIMV  = MAX_DOUBLE;
3198
3199
0
    if (Do_OnceRes)
3200
0
    {
3201
0
      costCurStart = xCalcDistortion(bestCS, partitioner.chType, bestCS->sps->bitDepths[CH_L], 0);
3202
0
      Fpel_cost = costCurStart;
3203
0
      tempCS->initSubStructure(*m_pTempCS2, partitioner.chType, partitioner.currArea(), false);
3204
0
    }
3205
3206
0
    CodingStructure *tempCSbest = m_pTempCS2;
3207
3208
0
    m_cInterSearch.setAffineModeSelected( false );
3209
3210
0
    m_cInterSearch.resetBufferedUniMotions();
3211
3212
0
    int bcwLoopNum = (tempCS->slice->isInterB() ? BCW_NUM : 1);
3213
0
    bcwLoopNum = (tempCS->sps->BCW ? bcwLoopNum : 1);
3214
3215
0
    if( tempCS->area.lwidth() * tempCS->area.lheight() < BCW_SIZE_CONSTRAINT )
3216
0
    {
3217
0
      bcwLoopNum = 1;
3218
0
    }
3219
3220
0
    for (int i = 1; i <= IMV_HPEL; i++)
3221
0
    {
3222
0
      double curBestCost = bestCS->cost;
3223
0
      double equBcwCost  = MAX_DOUBLE;
3224
3225
0
      for( int bcwLoopIdx = 0; bcwLoopIdx < bcwLoopNum; bcwLoopIdx++ )
3226
0
      {
3227
0
        if( m_pcEncCfg->m_BCW == 2 )
3228
0
        {
3229
0
          bool isBestInter   = m_modeCtrl.getBlkInfo( bestCS->area ).isInter;
3230
0
          uint8_t bestBcwIdx = m_modeCtrl.getBlkInfo( bestCS->area).BcwIdx;
3231
3232
0
          if( isBestInter && g_BcwSearchOrder[bcwLoopIdx] != BCW_DEFAULT && g_BcwSearchOrder[bcwLoopIdx] != bestBcwIdx )
3233
0
          {
3234
0
            continue;
3235
0
          }
3236
          
3237
0
          if( tempCS->slice->checkLDC && g_BcwSearchOrder[bcwLoopIdx] != BCW_DEFAULT
3238
0
            && (m_bestBcwIdx[0] >= 0 && g_BcwSearchOrder[bcwLoopIdx] != m_bestBcwIdx[0])
3239
0
            && (m_bestBcwIdx[1] >= 0 && g_BcwSearchOrder[bcwLoopIdx] != m_bestBcwIdx[1]))
3240
0
          {
3241
0
            continue;
3242
0
          }
3243
0
        }
3244
3245
0
        if( !tempCS->slice->checkLDC )
3246
0
        {
3247
0
          if( bcwLoopIdx != 0 && bcwLoopIdx != 3 && bcwLoopIdx != 4 )
3248
0
          {
3249
0
            continue;
3250
0
          }
3251
0
        }
3252
3253
0
        bool testBcw;
3254
0
        uint8_t bcwIdx;
3255
0
        bool isEqualUni = false;
3256
3257
0
        if (i > IMV_FPEL)
3258
0
        {
3259
0
          bool nextimv = false;
3260
0
          double stopCost = i == IMV_HPEL ? 1.25 : 1.06;
3261
0
          if (Fpel_cost > stopCost * costCurStart)
3262
0
          {
3263
0
            nextimv = true;
3264
0
          }
3265
0
          if ( m_pcEncCfg->m_AMVRspeed == 1 )
3266
0
          {
3267
0
            costCurStart = bestCS->cost;
3268
0
          }
3269
0
          if (nextimv)
3270
0
          {
3271
0
            continue;
3272
0
          }
3273
0
        }
3274
3275
0
        bool Do_Search = Do_OnceRes ? false : true;
3276
3277
0
        if (Do_Limit)
3278
0
        {
3279
0
          Do_Search = i == IMV_FPEL ? true : false;
3280
3281
0
          if (i == IMV_HPEL)
3282
0
          {
3283
0
            if (bestCS->slice->TLayer > 3)
3284
0
            {
3285
0
              continue;
3286
0
            }
3287
0
            if (bestCS->getCU(partitioner.chType, partitioner.treeType)->imv != 0)
3288
0
            {
3289
0
              Do_Search = true; //do_est
3290
0
            }
3291
0
          }
3292
0
          if (bestCS->getCU(partitioner.chType, partitioner.treeType)->mmvdMergeFlag || bestCS->getCU(partitioner.chType, partitioner.treeType)->geo)
3293
0
          {
3294
0
            Do_Search = true;
3295
0
          }
3296
0
        }
3297
0
        tempCS->initStructData(encTestMode.qp);
3298
3299
0
        if (!Do_Search)
3300
0
        {
3301
0
          tempCS->copyStructure(*bestCS, partitioner.chType, TREE_D);
3302
0
        }
3303
0
        tempCS->dist = 0;
3304
0
        tempCS->fracBits = 0;
3305
0
        tempCS->cost = MAX_DOUBLE;
3306
0
        CodingUnit &cu = (Do_Search) ? tempCS->addCU(tempCS->area, partitioner.chType) : *tempCS->getCU(partitioner.chType, partitioner.treeType);
3307
0
        if (Do_Search)
3308
0
        {
3309
0
          partitioner.setCUData(cu);
3310
0
          cu.slice = tempCS->slice;
3311
0
          cu.tileIdx = m_tileIdx;
3312
0
          cu.skip = false;
3313
0
          cu.mmvdSkip = false;
3314
0
          cu.predMode = MODE_INTER;
3315
0
          cu.chromaQpAdj = m_cuChromaQpOffsetIdxPlus1;
3316
0
          cu.qp = encTestMode.qp;
3317
3318
0
          cu.initPuData();
3319
3320
0
          cu.imv = i;
3321
3322
0
          cu.BcwIdx = g_BcwSearchOrder[bcwLoopIdx];
3323
0
          bcwIdx    = cu.BcwIdx;
3324
0
          testBcw   = (bcwIdx != BCW_DEFAULT);
3325
3326
0
          cu.interDir = 10;
3327
          
3328
0
          double bestCostInter = MAX_DOUBLE;
3329
0
          m_cInterSearch.predInterSearch(cu, partitioner, bestCostInter);
3330
          
3331
0
          if ( cu.interDir <= 3 )
3332
0
          {
3333
0
            bcwIdx = CU::getValidBcwIdx(cu);
3334
0
          }
3335
0
          else
3336
0
          {
3337
0
            continue;
3338
0
          }
3339
          
3340
0
          if( testBcw && bcwIdx == BCW_DEFAULT ) // Enabled Bcw but the search results is uni.
3341
0
          {
3342
0
            continue;
3343
0
          }
3344
0
          CHECK(!(testBcw || (!testBcw && bcwIdx == BCW_DEFAULT)), " !( bTestBcw || (!bTestBcw && bcwIdx == BCW_DEFAULT ) )");
3345
3346
0
          if( m_pcEncCfg->m_BCW == 2 )
3347
0
          {
3348
0
            if( cu.interDir != 3 && testBcw == 0 )
3349
0
            {
3350
0
              isEqualUni = true;
3351
0
            }
3352
0
          }
3353
3354
0
          if (!CU::hasSubCUNonZeroMVd(cu))
3355
0
          {
3356
0
            continue;
3357
0
          }
3358
0
        }
3359
0
        else
3360
0
        {
3361
0
          cu.smvdMode = 0;
3362
0
          cu.affine = false;
3363
0
          cu.imv = i ;
3364
0
          CU::resetMVDandMV2Int(cu);
3365
0
          if (!CU::hasSubCUNonZeroMVd(cu))
3366
0
          {
3367
0
            continue;
3368
0
          }
3369
3370
0
          cu.BcwIdx = g_BcwSearchOrder[bcwLoopIdx];
3371
3372
0
          cu.mvRefine = true;
3373
0
          m_cInterSearch.motionCompensation(cu, tempCS->getPredBuf() );
3374
0
          cu.mvRefine = false;
3375
0
        }
3376
3377
0
        if( Do_OnceRes )
3378
0
        {
3379
0
          costCur = xCalcDistortion(tempCS, partitioner.chType, tempCS->sps->bitDepths[CH_L], cu.imv );
3380
0
          if (costCur < bestCostIMV)
3381
0
          {
3382
0
            bestCostIMV = costCur;
3383
0
            tempCSbest->getPredBuf().copyFrom(tempCS->getPredBuf());
3384
0
            tempCSbest->clearCUs();
3385
0
            tempCSbest->clearTUs();
3386
0
            tempCSbest->copyStructure(*tempCS, partitioner.chType, TREE_D);
3387
0
          }
3388
0
          if (i > IMV_FPEL)
3389
0
          {
3390
0
            costCurStart = costCurStart > costCur ? costCur : costCurStart;
3391
0
          }
3392
0
        }
3393
0
        else
3394
0
        {
3395
0
          xEncodeInterResidual(tempCS, bestCS, partitioner, encTestMode, 0, 0, &equBcwCost);
3396
0
          costCur = tempCS->cost;
3397
3398
0
          if (i > IMV_FPEL)
3399
0
          {
3400
0
            costCurStart = bestCS->cost;
3401
0
          }
3402
0
        }
3403
3404
0
        if (i == IMV_FPEL)
3405
0
        {
3406
0
           Fpel_cost = costCur;
3407
0
        }
3408
3409
0
        double skipTH = MAX_DOUBLE;
3410
0
        skipTH = (m_pcEncCfg->m_BCW == 2 ? 1.05 : MAX_DOUBLE);
3411
0
        if( equBcwCost > curBestCost * skipTH )
3412
0
        {
3413
0
          break;
3414
0
        }
3415
3416
0
        if( m_pcEncCfg->m_BCW == 2 )
3417
0
        {
3418
0
          if( isEqualUni == true && ! m_pcEncCfg->m_picReordering )
3419
0
          {
3420
0
            break;
3421
0
          }
3422
0
          if( g_BcwSearchOrder[bcwLoopIdx] == BCW_DEFAULT && xIsBcwSkip( cu ) )
3423
0
          {
3424
0
            break;
3425
0
          }
3426
0
        }
3427
0
      }
3428
0
    }
3429
3430
0
    if (Do_OnceRes && (bestCostIMV != MAX_DOUBLE))
3431
0
    {
3432
0
      CodingStructure* CSCandBest = tempCSbest;
3433
0
      tempCS->initStructData(bestCS->currQP[partitioner.chType]);
3434
0
      tempCS->copyStructure(*CSCandBest, partitioner.chType, TREE_D);
3435
0
      tempCS->getPredBuf().copyFrom(tempCSbest->getPredBuf());
3436
0
      tempCS->dist = 0;
3437
0
      tempCS->fracBits = 0;
3438
0
      tempCS->cost = MAX_DOUBLE;
3439
3440
0
      xEncodeInterResidual(tempCS, bestCS, partitioner, encTestMode, 0, 0, NULL);
3441
0
    }
3442
3443
0
    tempCS->initStructData(encTestMode.qp);
3444
0
  }
3445
0
  STAT_COUNT_CU_MODES( partitioner.chType == CH_L, g_cuCounters1D[CU_MODES_TESTED][0][!tempCS->slice->isIntra() + tempCS->slice->depth] );
3446
0
  STAT_COUNT_CU_MODES( partitioner.chType == CH_L && !tempCS->slice->isIntra(), g_cuCounters2D[CU_MODES_TESTED][Log2( tempCS->area.lheight() )][Log2( tempCS->area.lwidth() )] );
3447
0
}
3448
3449
void EncCu::xCalDebCost( CodingStructure &cs, Partitioner &partitioner )
3450
95.9k
{
3451
95.9k
  PROFILER_SCOPE_AND_STAGE_EXT( 1, _TPROF, P_DEBLOCK_FILTER, &cs, partitioner.chType );
3452
95.9k
  if ( cs.slice->deblockingFilterDisable )
3453
0
  {
3454
0
    return;
3455
0
  }
3456
3457
95.9k
  const ChromaFormat format = cs.area.chromaFormat;
3458
95.9k
  CodingUnit*            cu = cs.getCU(partitioner.chType, partitioner.treeType);
3459
95.9k
  const Position    lumaPos = cu->Y().valid() ? cu->Y().pos() : recalcPosition( format, cu->chType, CH_L, cu->blocks[cu->chType].pos() );
3460
95.9k
  bool    topEdgeAvai = lumaPos.y > 0 && ((lumaPos.y % 4) == 0);
3461
95.9k
  bool   leftEdgeAvai = lumaPos.x > 0 && ((lumaPos.x % 4) == 0);
3462
3463
95.9k
  if( ! ( topEdgeAvai || leftEdgeAvai ))
3464
19.9k
  {
3465
19.9k
    return;
3466
19.9k
  }
3467
3468
75.9k
  ComponentID compStr = ( CU::isSepTree(*cu) && !isLuma( partitioner.chType ) ) ? COMP_Cb : COMP_Y;
3469
75.9k
  ComponentID compEnd = (( CU::isSepTree(*cu) && isLuma( partitioner.chType )) || cu->chromaFormat == VVENC_CHROMA_400 ) ? COMP_Y : COMP_Cr;
3470
75.9k
  const UnitArea currCsArea = clipArea( CS::getArea( cs, cs.area, partitioner.chType, partitioner.treeType ), *cs.picture );
3471
3472
75.9k
  PelStorage&  picDbBuf = m_dbBuffer; //th we could reduce the buffer size and do some relocate
3473
3474
  //deblock neighbour pixels
3475
75.9k
  const Size     lumaSize = cu->Y().valid() ? cu->Y().size() : recalcSize( format, cu->chType, CH_L, cu->blocks[cu->chType].size() );
3476
3477
75.9k
  int verOffset = lumaPos.y > 7 ? 8 : 4;
3478
75.9k
  int horOffset = lumaPos.x > 7 ? 8 : 4;
3479
3480
75.9k
  LoopFilter::calcFilterStrengths( *cu, true );
3481
3482
75.9k
  if( m_EDO == 2 && CS::isDualITree( cs ) && isLuma( partitioner.chType ) )
3483
42.0k
  {
3484
42.0k
    m_cLoopFilter.getMaxFilterLength( *cu, verOffset, horOffset );
3485
3486
42.0k
    if( 0== (verOffset + horOffset) )
3487
0
    {
3488
0
      return;
3489
0
    }
3490
3491
42.0k
    topEdgeAvai  &= verOffset != 0;
3492
42.0k
    leftEdgeAvai &= horOffset != 0;
3493
42.0k
  }
3494
3495
75.9k
  const UnitArea  areaTop  = UnitArea( format, Area( lumaPos.x,             lumaPos.y - verOffset, lumaSize.width, verOffset       ) );
3496
75.9k
  const UnitArea  areaLeft = UnitArea( format, Area( lumaPos.x - horOffset, lumaPos.y,             horOffset,      lumaSize.height ) );
3497
3498
185k
  for ( int compIdx = compStr; compIdx <= compEnd; compIdx++ )
3499
109k
  {
3500
109k
    ComponentID compId = (ComponentID)compIdx;
3501
3502
    //Copy current CU's reco to Deblock Pic Buffer
3503
109k
    const ReshapeData& reshapeData = cs.picture->reshapeData;
3504
109k
    const CompArea&  compArea = currCsArea.block( compId );
3505
109k
    CompArea         locArea  = compArea;
3506
109k
    locArea.x -= cu->blocks[compIdx].x;
3507
109k
    locArea.y -= cu->blocks[compIdx].y;
3508
109k
    PelBuf dbReco = picDbBuf.getBuf( locArea );
3509
109k
    if (cs.slice->lmcsEnabled && isLuma(compId) )
3510
0
    {
3511
0
      if ((!cs.sps->LFNST) && (!cs.sps->MTS) && (!cs.sps->ISP)&& reshapeData.getCTUFlag())
3512
0
      {
3513
0
        PelBuf rspReco = cs.getRspRecoBuf();
3514
0
        dbReco.copyFrom( rspReco );
3515
0
      }
3516
0
      else
3517
0
      {
3518
0
        PelBuf reco = cs.getRecoBuf( compId );
3519
0
        dbReco.rspSignal( reco, reshapeData.getInvLUT() );
3520
0
      }
3521
0
    }
3522
109k
    else
3523
109k
    {
3524
109k
      PelBuf reco = cs.getRecoBuf( compId );
3525
109k
      dbReco.copyFrom( reco );
3526
109k
    }
3527
    //left neighbour
3528
109k
    if ( leftEdgeAvai )
3529
76.5k
    {
3530
76.5k
      const CompArea&  compArea = areaLeft.block(compId);
3531
76.5k
      CompArea         locArea = compArea;
3532
76.5k
      locArea.x -= cu->blocks[compIdx].x;
3533
76.5k
      locArea.y -= cu->blocks[compIdx].y;
3534
76.5k
      PelBuf dbReco = picDbBuf.getBuf( locArea );
3535
76.5k
      if (cs.slice->lmcsEnabled && isLuma(compId))
3536
0
      {
3537
0
        dbReco.rspSignal( cs.picture->getRecoBuf( compArea ), reshapeData.getInvLUT() );
3538
0
      }
3539
76.5k
      else
3540
76.5k
      {
3541
76.5k
        dbReco.copyFrom( cs.picture->getRecoBuf( compArea ) );
3542
76.5k
      }
3543
76.5k
    }
3544
    //top neighbour
3545
109k
    if ( topEdgeAvai )
3546
79.5k
    {
3547
79.5k
      const CompArea&  compArea = areaTop.block( compId );
3548
79.5k
      CompArea         locArea = compArea;
3549
79.5k
      locArea.x -= cu->blocks[compIdx].x;
3550
79.5k
      locArea.y -= cu->blocks[compIdx].y;
3551
79.5k
      PelBuf dbReco = picDbBuf.getBuf( locArea );
3552
79.5k
      if (cs.slice->lmcsEnabled && isLuma(compId))
3553
0
      {
3554
0
        dbReco.rspSignal( cs.picture->getRecoBuf( compArea ), reshapeData.getInvLUT() );
3555
0
      }
3556
79.5k
      else
3557
79.5k
      {
3558
79.5k
        dbReco.copyFrom( cs.picture->getRecoBuf( compArea ) );
3559
79.5k
      }
3560
79.5k
    }
3561
109k
  }
3562
3563
75.9k
  ChannelType dbChType = CU::isSepTree(*cu) ? partitioner.chType : MAX_NUM_CH;
3564
3565
75.9k
  CHECK( CU::isSepTree(*cu) && !cu->Y().valid() && partitioner.chType == CH_L, "xxx" );
3566
3567
75.9k
  if( cu->Y() .valid() ) m_cLoopFilter.setOrigin( CH_L, cu->lumaPos() );
3568
75.9k
  if( cu->chromaFormat != VVENC_CHROMA_400 && cu->Cb().valid() ) m_cLoopFilter.setOrigin( CH_C, cu->chromaPos() );
3569
3570
  //deblock
3571
75.9k
  if( leftEdgeAvai )
3572
55.7k
  {
3573
55.7k
    m_cLoopFilter.loopFilterCu( *cu, dbChType, EDGE_VER, m_dbBuffer );
3574
55.7k
  }
3575
3576
75.9k
  if( topEdgeAvai )
3577
57.2k
  {
3578
57.2k
    m_cLoopFilter.loopFilterCu( *cu, dbChType, EDGE_HOR, m_dbBuffer );
3579
57.2k
  }
3580
3581
  //calculate difference between DB_before_SSE and DB_after_SSE for neighbouring CUs
3582
75.9k
  Distortion distBeforeDb = 0, distAfterDb = 0, distCur = 0;
3583
185k
  for (int compIdx = compStr; compIdx <= compEnd; compIdx++)
3584
109k
  {
3585
109k
    ComponentID compId = (ComponentID)compIdx;
3586
109k
    {
3587
109k
      CompArea compArea = currCsArea.block( compId );
3588
109k
      CompArea         locArea  = compArea;
3589
109k
      locArea.x -= cu->blocks[compIdx].x;
3590
109k
      locArea.y -= cu->blocks[compIdx].y;
3591
109k
      CPelBuf reco      = picDbBuf.getBuf( locArea );
3592
109k
      CPelBuf org       = cs.getOrgBuf( compId );
3593
109k
      distCur += xGetDistortionDb( cs, org, reco, compArea, false );
3594
109k
    }
3595
3596
109k
    if ( leftEdgeAvai )
3597
76.5k
    {
3598
76.5k
      const CompArea&  compArea = areaLeft.block( compId );
3599
76.5k
      CompArea         locArea  = compArea;
3600
76.5k
      locArea.x -= cu->blocks[compIdx].x;
3601
76.5k
      locArea.y -= cu->blocks[compIdx].y;
3602
76.5k
      CPelBuf org    = cs.picture->getOrigBuf( compArea );
3603
76.5k
      if ( cs.picture->getFilteredOrigBuffer().valid() )
3604
0
      {
3605
0
        org = cs.picture->getRspOrigBuf( compArea );
3606
0
      }
3607
76.5k
      CPelBuf reco   = cs.picture->getRecoBuf( compArea );
3608
76.5k
      CPelBuf recoDb = picDbBuf.getBuf( locArea );
3609
76.5k
      distBeforeDb  += xGetDistortionDb( cs, org, reco,   compArea, true );
3610
76.5k
      distAfterDb   += xGetDistortionDb( cs, org, recoDb, compArea, false  );
3611
76.5k
    }
3612
3613
109k
    if ( topEdgeAvai )
3614
79.5k
    {
3615
79.5k
      const CompArea&  compArea = areaTop.block( compId );
3616
79.5k
      CompArea         locArea  = compArea;
3617
79.5k
      locArea.x -= cu->blocks[compIdx].x;
3618
79.5k
      locArea.y -= cu->blocks[compIdx].y;
3619
79.5k
      CPelBuf org    = cs.picture->getOrigBuf( compArea );
3620
79.5k
      if ( cs.picture->getFilteredOrigBuffer().valid() )
3621
0
      {
3622
0
        org = cs.picture->getRspOrigBuf( compArea );
3623
0
      }
3624
79.5k
      CPelBuf reco   = cs.picture->getRecoBuf( compArea );
3625
79.5k
      CPelBuf recoDb = picDbBuf.getBuf( locArea );
3626
79.5k
      distBeforeDb  += xGetDistortionDb( cs, org, reco,   compArea, true );
3627
79.5k
      distAfterDb   += xGetDistortionDb( cs, org, recoDb, compArea, false  );
3628
79.5k
    }
3629
109k
  }
3630
3631
  //updated cost
3632
75.9k
  int64_t distTmp = distCur - cs.dist + distAfterDb - distBeforeDb;
3633
75.9k
  cs.costDbOffset = distTmp < 0 ? -m_cRdCost.calcRdCost( 0, -distTmp ) : m_cRdCost.calcRdCost( 0, distTmp );
3634
75.9k
}
3635
3636
Distortion EncCu::xGetDistortionDb(CodingStructure &cs, CPelBuf& org, CPelBuf& reco, const CompArea& compArea, bool beforeDb)
3637
421k
{
3638
421k
  Distortion dist;
3639
421k
  const ReshapeData& reshapeData = cs.picture->reshapeData;
3640
421k
  const ComponentID compID = compArea.compID;
3641
421k
  if( (cs.slice->lmcsEnabled && reshapeData.getCTUFlag()) || m_pcEncCfg->m_lumaLevelToDeltaQPEnabled)
3642
0
  {
3643
0
    if ( compID == COMP_Y && !m_pcEncCfg->m_lumaLevelToDeltaQPEnabled)
3644
0
    {
3645
0
      CPelBuf tmpReco;
3646
0
      if( beforeDb )
3647
0
      {
3648
0
        PelBuf tmpLmcs = m_aTmpStorageLCU[0].getCompactBuf( compArea );
3649
0
        tmpLmcs.rspSignal( reco, reshapeData.getInvLUT() );
3650
0
        tmpReco = tmpLmcs;
3651
0
      }
3652
0
      else
3653
0
      {
3654
0
        tmpReco = reco;
3655
0
      }
3656
0
      dist = m_cRdCost.getDistPart( org, tmpReco, cs.sps->bitDepths[CH_L], compID, DF_SSE_WTD, &org );
3657
0
    }
3658
0
    else if( m_EDO == 2)
3659
0
    {
3660
      // use the correct luma area to scale chroma
3661
0
      const int csx = getComponentScaleX( compID, cs.area.chromaFormat );
3662
0
      const int csy = getComponentScaleY( compID, cs.area.chromaFormat );
3663
0
      CompArea lumaArea = CompArea( COMP_Y, cs.area.chromaFormat, Area( compArea.x << csx, compArea.y << csy, compArea.width << csx, compArea.height << csy), true);
3664
0
      CPelBuf orgLuma = cs.picture->getFilteredOrigBuffer().valid() ? cs.picture->getRspOrigBuf( lumaArea ): cs.picture->getOrigBuf( lumaArea );
3665
0
      dist = m_cRdCost.getDistPart( org, reco, cs.sps->bitDepths[toChannelType( compID )], compID, DF_SSE_WTD, &orgLuma );
3666
0
    }
3667
0
    else
3668
0
    {
3669
0
      const int csx = getComponentScaleX( compID, cs.area.chromaFormat );
3670
0
      const int csy = getComponentScaleY( compID, cs.area.chromaFormat );
3671
0
      CompArea lumaArea = compArea.compID ? CompArea( COMP_Y, cs.area.chromaFormat, Area( compArea.x << csx, compArea.y << csy, compArea.width << csx, compArea.height << csy), true) : cs.area.blocks[COMP_Y];
3672
0
      CPelBuf orgLuma = cs.picture->getFilteredOrigBuffer().valid() ? cs.picture->getRspOrigBuf( lumaArea ): cs.picture->getOrigBuf( lumaArea );
3673
//      CPelBuf orgLuma = cs.picture->getFilteredOrigBuffer().valid() ? cs.picture->getRspOrigBuf( cs.area.blocks[COMP_Y] ): cs.picture->getOrigBuf( cs.area.blocks[COMP_Y] );
3674
0
      dist = m_cRdCost.getDistPart( org, reco, cs.sps->bitDepths[toChannelType( compID )], compID, DF_SSE_WTD, &orgLuma );
3675
0
    }
3676
0
    return dist;
3677
0
  }
3678
3679
421k
  if ( cs.slice->lmcsEnabled && cs.slice->isIntra() && compID == COMP_Y && !beforeDb ) //intra slice
3680
0
  {
3681
0
    PelBuf tmpLmcs = m_aTmpStorageLCU[0].getCompactBuf( compArea );
3682
0
    tmpLmcs.rspSignal( reco, reshapeData.getFwdLUT() );
3683
0
    dist = m_cRdCost.getDistPart( org, tmpLmcs, cs.sps->bitDepths[CH_L], compID, DF_SSE );
3684
0
    return dist;
3685
0
  }
3686
421k
  dist = m_cRdCost.getDistPart(org, reco, cs.sps->bitDepths[toChannelType(compID)], compID, DF_SSE);
3687
421k
  return dist;
3688
421k
}
3689
3690
bool checkValidMvs( const CodingUnit& cu)
3691
0
{
3692
  // clang-format off
3693
0
  const int affineShiftTab[3] =
3694
0
  {
3695
0
    MV_PRECISION_INTERNAL - MV_PRECISION_QUARTER,
3696
0
    MV_PRECISION_INTERNAL - MV_PRECISION_SIXTEENTH,
3697
0
    MV_PRECISION_INTERNAL - MV_PRECISION_INT
3698
0
  };
3699
3700
0
  const int normalShiftTab[NUM_IMV_MODES] =
3701
0
  {
3702
0
    MV_PRECISION_INTERNAL - MV_PRECISION_QUARTER,
3703
0
    MV_PRECISION_INTERNAL - MV_PRECISION_INT,
3704
0
    MV_PRECISION_INTERNAL - MV_PRECISION_4PEL,
3705
0
    MV_PRECISION_INTERNAL - MV_PRECISION_HALF,
3706
0
  };
3707
  // clang-format on
3708
3709
0
  int mvShift;
3710
3711
0
  for (int refList = 0; refList < NUM_REF_PIC_LIST_01; refList++)
3712
0
  {
3713
0
    if (cu.refIdx[refList] >= 0)
3714
0
    {
3715
0
      if (!cu.affine)
3716
0
      {
3717
0
        mvShift = normalShiftTab[cu.imv];
3718
0
        Mv signaledmvd(cu.mvd[refList][0].hor >> mvShift, cu.mvd[refList][0].ver >> mvShift);
3719
0
        if (!((signaledmvd.hor >= MVD_MIN) && (signaledmvd.hor <= MVD_MAX)) || !((signaledmvd.ver >= MVD_MIN) && (signaledmvd.ver <= MVD_MAX)))
3720
0
          return false;
3721
0
      }
3722
0
      else
3723
0
      {
3724
0
        for (int ctrlP = 1 + (cu.affineType == AFFINEMODEL_6PARAM); ctrlP >= 0; ctrlP--)
3725
0
        {
3726
0
          mvShift = affineShiftTab[cu.imv];
3727
0
          Mv signaledmvd(cu.mvd[refList][ctrlP].hor >> mvShift, cu.mvd[refList][ctrlP].ver >> mvShift);
3728
0
          if (!((signaledmvd.hor >= MVD_MIN) && (signaledmvd.hor <= MVD_MAX)) || !((signaledmvd.ver >= MVD_MIN) && (signaledmvd.ver <= MVD_MAX)))
3729
0
            return false;;
3730
0
        }
3731
0
      }
3732
0
    }
3733
0
  }
3734
  // avoid MV exceeding 18-bit dynamic range
3735
0
  const int maxMv = 1 << 17;
3736
0
  if (!cu.affine && !cu.mergeFlag)
3737
0
  {
3738
0
    if(    ( cu.refIdx[ 0 ] >= 0 && ( cu.mv[ 0 ][ 0 ].getAbsHor() >= maxMv || cu.mv[ 0 ][ 0 ].getAbsVer() >= maxMv ) )
3739
0
        || ( cu.refIdx[ 1 ] >= 0 && ( cu.mv[ 1 ][ 0 ].getAbsHor() >= maxMv || cu.mv[ 1 ][ 0 ].getAbsVer() >= maxMv ) ) )
3740
0
    {
3741
0
      return false;
3742
0
    }
3743
0
  }
3744
0
  if( cu.affine && !cu.mergeFlag )
3745
0
  {
3746
0
    for( int refList = 0; refList < NUM_REF_PIC_LIST_01; refList++ )
3747
0
    {
3748
0
      if( cu.refIdx[ refList ] >= 0 )
3749
0
      {
3750
0
        for( int ctrlP = 1 + ( cu.affineType == AFFINEMODEL_6PARAM ); ctrlP >= 0; ctrlP-- )
3751
0
        {
3752
0
          if( cu.mv[ refList ][ ctrlP ].getAbsHor() >= maxMv || cu.mv[ refList ][ ctrlP ].getAbsVer() >= maxMv )
3753
0
          {
3754
0
            return false;
3755
0
          }
3756
0
        }
3757
0
      }
3758
0
    }
3759
0
  }
3760
0
  return true;
3761
0
}
3762
3763
3764
void EncCu::xEncodeInterResidual( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode, int residualPass, bool* bestHasNonResi, double* equBcwCost )
3765
0
{
3766
0
  if( residualPass == 1 && encTestMode.lossless )
3767
0
  {
3768
0
    return;
3769
0
  }
3770
3771
0
  CodingUnit*            cu        = tempCS->getCU( partitioner.chType, partitioner.treeType );
3772
0
  double   bestCostInternal        = MAX_DOUBLE;
3773
3774
0
  if( !checkValidMvs( *cu ) )
3775
0
    return;
3776
3777
0
  double  currBestCost = MAX_DOUBLE;
3778
3779
  // For SBT
3780
0
  double     bestCost          = bestCS->cost;
3781
0
  double     bestCostBegin     = bestCS->cost;
3782
0
  const CodingUnit* prevBestCU = bestCS->getCU( partitioner.chType, partitioner.treeType );
3783
0
  uint8_t    prevBestSbt       = ( prevBestCU == nullptr ) ? 0 : prevBestCU->sbtInfo;
3784
0
  Distortion sbtOffDist        = 0;
3785
0
  bool       sbtOffRootCbf     = 0;
3786
0
  double     sbtOffCost        = MAX_DOUBLE;
3787
0
  uint8_t    currBestSbt       = 0;
3788
0
  uint8_t    histBestSbt       = MAX_UCHAR;
3789
0
  Distortion curPuSse          = MAX_DISTORTION;
3790
0
  uint8_t    numRDOTried       = 0;
3791
0
  bool       doPreAnalyzeResi  = false;
3792
0
  const bool mtsAllowed        =   tempCS->sps->MTSInter && cu->Y().maxDim() <= MTS_INTER_MAX_CU_SIZE;
3793
0
  const uint8_t sbtAllowed     = ( tempCS->pps->picWidthInLumaSamples < SBT_FAST64_WIDTH_THRESHOLD || m_pcEncCfg->m_SBT > 1 ) && cu->Y().maxDim() > 32 ? 0 : CU::checkAllowedSbt(*cu);
3794
3795
0
  if( sbtAllowed )
3796
0
  {
3797
    //SBT resolution-dependent fast algorithm: not try size-64 SBT in RDO for low-resolution sequences (now resolution below HD)
3798
0
    doPreAnalyzeResi = ( sbtAllowed || mtsAllowed ) && residualPass == 0;
3799
0
    m_cInterSearch.getBestSbt( tempCS, cu, histBestSbt, curPuSse, sbtAllowed, doPreAnalyzeResi, mtsAllowed );
3800
0
  }
3801
3802
0
  cu->skip    = false;
3803
0
  cu->sbtInfo = 0;
3804
3805
0
  const bool skipResidual = residualPass == 1;
3806
0
  if( skipResidual || histBestSbt == MAX_UCHAR || !CU::isSbtMode( histBestSbt ) )
3807
0
  {
3808
0
    m_cInterSearch.encodeResAndCalcRdInterCU( *tempCS, partitioner, skipResidual );
3809
0
    xEncodeDontSplit( *tempCS, partitioner );
3810
0
    xCheckDQP       ( *tempCS, partitioner );
3811
3812
0
    if( NULL != bestHasNonResi && (bestCostInternal > tempCS->cost) )
3813
0
    {
3814
0
      bestCostInternal = tempCS->cost;
3815
0
      if( !cu->ciip )
3816
0
        *bestHasNonResi = !cu->rootCbf;
3817
0
    }
3818
3819
0
    if( cu->rootCbf == false )
3820
0
    {
3821
0
      if( cu->ciip )
3822
0
      {
3823
0
        tempCS->cost = MAX_DOUBLE;
3824
0
        tempCS->costDbOffset = 0;
3825
0
        return;
3826
0
      }
3827
0
    }
3828
0
    currBestCost = tempCS->cost;
3829
0
    if( sbtAllowed )
3830
0
    {
3831
0
      sbtOffCost    = tempCS->cost;
3832
0
      sbtOffDist    = tempCS->dist;
3833
0
      sbtOffRootCbf = cu->rootCbf;
3834
0
      currBestSbt   = cu->firstTU->mtsIdx[COMP_Y] > MTS_SKIP ? SBT_OFF_MTS : SBT_OFF_DCT;
3835
0
      numRDOTried  += mtsAllowed ? 2 : 1;
3836
0
    }
3837
3838
0
    DTRACE_MODE_COST( *tempCS, m_cRdCost.getLambda( true ) );
3839
0
    xCheckBestMode( tempCS, bestCS, partitioner, encTestMode );
3840
3841
0
    STAT_COUNT_CU_MODES( partitioner.chType == CH_L, g_cuCounters1D[CU_RD_TESTS][0][!tempCS->slice->isIntra() + tempCS->slice->depth] );
3842
0
    STAT_COUNT_CU_MODES( partitioner.chType == CH_L && !tempCS->slice->isIntra(), g_cuCounters2D[CU_RD_TESTS][Log2( tempCS->area.lheight() )][Log2( tempCS->area.lwidth() )] );
3843
0
  }
3844
3845
0
  if( sbtAllowed && ( m_pcEncCfg->m_SBT == 1 || sbtOffRootCbf ) )
3846
0
  {
3847
0
    bool swapped = false; // avoid unwanted data copy
3848
0
    uint8_t numSbtRdo = CU::numSbtModeRdo( sbtAllowed );
3849
    //early termination if all SBT modes are not allowed
3850
    //normative
3851
0
    if( !sbtAllowed || skipResidual )
3852
0
    {
3853
0
      numSbtRdo = 0;
3854
0
    }
3855
    //fast algorithm
3856
0
    if( ( histBestSbt != MAX_UCHAR && !CU::isSbtMode( histBestSbt ) ) || m_cInterSearch.getSkipSbtAll() )
3857
0
    {
3858
0
      numSbtRdo = 0;
3859
0
    }
3860
0
    if( bestCost != MAX_DOUBLE && sbtOffCost != MAX_DOUBLE )
3861
0
    {
3862
0
      double th = 1.07;
3863
0
      if( !( prevBestSbt == 0 || m_sbtCostSave[0] == MAX_DOUBLE ) )
3864
0
      {
3865
0
        assert( m_sbtCostSave[1] <= m_sbtCostSave[0] );
3866
0
        th *= ( m_sbtCostSave[0] / m_sbtCostSave[1] );
3867
0
      }
3868
0
      if( sbtOffCost > bestCost * th )
3869
0
      {
3870
0
        numSbtRdo = 0;
3871
0
      }
3872
0
    }
3873
0
    if( !sbtOffRootCbf && sbtOffCost != MAX_DOUBLE )
3874
0
    {
3875
0
      double th = Clip3( 0.05, 0.55, ( 27 - cu->qp ) * 0.02 + 0.35 );
3876
0
      if( sbtOffCost < m_cRdCost.calcRdCost( ( cu->lwidth() * cu->lheight() ) << SCALE_BITS, 0 ) * th )
3877
0
      {
3878
0
        numSbtRdo = 0;
3879
0
      }
3880
0
    }
3881
3882
0
    if( histBestSbt != MAX_UCHAR && numSbtRdo != 0 )
3883
0
    {
3884
0
      numSbtRdo = 1;
3885
0
      m_cInterSearch.initSbtRdoOrder( CU::getSbtMode( CU::getSbtIdx( histBestSbt ), CU::getSbtPos( histBestSbt ) ) );
3886
0
    }
3887
3888
0
    for( int sbtModeIdx = 0; sbtModeIdx < numSbtRdo; sbtModeIdx++ )
3889
0
    {
3890
0
      uint8_t sbtMode = m_cInterSearch.getSbtRdoOrder( sbtModeIdx );
3891
0
      uint8_t sbtIdx = CU::getSbtIdxFromSbtMode( sbtMode );
3892
0
      uint8_t sbtPos = CU::getSbtPosFromSbtMode( sbtMode );
3893
3894
      //fast algorithm (early skip, save & load)
3895
0
      if( histBestSbt == MAX_UCHAR )
3896
0
      {
3897
0
        uint8_t skipCode = m_cInterSearch.skipSbtByRDCost( cu->lwidth(), cu->lheight(), cu->mtDepth, sbtIdx, sbtPos, bestCS->cost, sbtOffDist, sbtOffCost, sbtOffRootCbf );
3898
0
        if( skipCode != MAX_UCHAR )
3899
0
        {
3900
0
          continue;
3901
0
        }
3902
3903
0
        if( sbtModeIdx > 0 )
3904
0
        {
3905
0
          uint8_t prevSbtMode = m_cInterSearch.getSbtRdoOrder( sbtModeIdx - 1 );
3906
          //make sure the prevSbtMode is the same size as the current SBT mode (otherwise the estimated dist may not be comparable)
3907
0
          if( CU::isSameSbtSize( prevSbtMode, sbtMode ) )
3908
0
          {
3909
0
            Distortion currEstDist = m_cInterSearch.getEstDistSbt( sbtMode );
3910
0
            Distortion prevEstDist = m_cInterSearch.getEstDistSbt( prevSbtMode );
3911
0
            if( currEstDist > prevEstDist * 1.15 )
3912
0
            {
3913
0
              continue;
3914
0
            }
3915
0
          }
3916
0
        }
3917
0
      }
3918
3919
      //init tempCS and TU
3920
0
      if( bestCost == bestCS->cost ) //The first EMT pass didn't become the bestCS, so we clear the TUs generated
3921
0
      {
3922
0
        tempCS->clearTUs();
3923
0
      }
3924
0
      else if( !swapped )
3925
0
      {
3926
0
        tempCS->initStructData( encTestMode.qp );
3927
0
        tempCS->copyStructure( *bestCS, partitioner.chType, partitioner.treeType );
3928
0
        tempCS->getPredBuf().copyFrom( bestCS->getPredBuf() );
3929
0
        bestCost = bestCS->cost;
3930
0
        cu = tempCS->getCU( partitioner.chType, partitioner.treeType );
3931
0
        swapped = true;
3932
0
      }
3933
0
      else
3934
0
      {
3935
0
        tempCS->clearTUs();
3936
0
        bestCost = bestCS->cost;
3937
0
        cu = tempCS->getCU( partitioner.chType, partitioner.treeType );
3938
0
      }
3939
3940
      //we need to restart the distortion for the new tempCS, the bit count and the cost
3941
0
      tempCS->dist     = 0;
3942
0
      tempCS->fracBits = 0;
3943
0
      tempCS->cost     = MAX_DOUBLE;
3944
0
      cu->skip         = false;
3945
3946
3947
      //set SBT info
3948
0
      cu->sbtInfo = (sbtPos << 4) + sbtIdx;
3949
3950
      //try residual coding
3951
0
      m_cInterSearch.encodeResAndCalcRdInterCU( *tempCS, partitioner, skipResidual );
3952
0
      numRDOTried++;
3953
3954
0
      xEncodeDontSplit( *tempCS, partitioner );
3955
0
      xCheckDQP( *tempCS, partitioner );
3956
3957
0
      if( NULL != bestHasNonResi && ( bestCostInternal > tempCS->cost ) )
3958
0
      {
3959
0
        bestCostInternal = tempCS->cost;
3960
0
        if( !( cu->ciip ) )
3961
0
          *bestHasNonResi = !cu->rootCbf;
3962
0
      }
3963
3964
0
      if( tempCS->cost < currBestCost )
3965
0
      {
3966
0
        currBestSbt = cu->sbtInfo;
3967
0
        currBestCost = tempCS->cost;
3968
0
      }
3969
0
      else if( m_pcEncCfg->m_SBT > 2 )
3970
0
      {
3971
0
        sbtModeIdx = numSbtRdo;
3972
0
      }
3973
3974
0
      DTRACE_MODE_COST( *tempCS, m_cRdCost.getLambda( true ) );
3975
0
      xCheckBestMode( tempCS, bestCS, partitioner, encTestMode );
3976
0
      STAT_COUNT_CU_MODES( partitioner.chType == CH_L, g_cuCounters1D[CU_RD_TESTS][0][!tempCS->slice->isIntra() + tempCS->slice->depth] );
3977
0
      STAT_COUNT_CU_MODES( partitioner.chType == CH_L && !tempCS->slice->isIntra(), g_cuCounters2D[CU_RD_TESTS][Log2( tempCS->area.lheight() )][Log2( tempCS->area.lwidth() )] );
3978
0
    }
3979
3980
0
    if( bestCostBegin != bestCS->cost )
3981
0
    {
3982
0
      m_sbtCostSave[0] = sbtOffCost;
3983
0
      m_sbtCostSave[1] = currBestCost;
3984
0
    }
3985
3986
0
    if( histBestSbt == MAX_UCHAR && doPreAnalyzeResi && numRDOTried > 1 )
3987
0
    {
3988
0
      auto slsSbt = static_cast<CacheBlkInfoCtrl&>( m_modeCtrl );
3989
0
      int slShift = 4 + std::min( Log2( cu->lwidth() ) + Log2( cu->lheight() ), 9 );
3990
0
      slsSbt.saveBestSbt( cu->cs->area, (uint32_t)( curPuSse >> slShift ), currBestSbt );
3991
0
    }
3992
    
3993
0
    if( ETM_INTER_ME == encTestMode.type )
3994
0
    {
3995
0
      if( equBcwCost != NULL )
3996
0
      {
3997
0
        if( tempCS->cost < ( *equBcwCost ) && cu->BcwIdx == BCW_DEFAULT )
3998
0
        {
3999
0
          ( *equBcwCost ) = tempCS->cost;
4000
0
        }
4001
0
      }
4002
0
      else
4003
0
      {
4004
0
        CHECK( equBcwCost == NULL, "equBcwCost == NULL" );
4005
0
      }
4006
0
      if( tempCS->slice->checkLDC && !cu->imv && cu->BcwIdx != BCW_DEFAULT && tempCS->cost < m_bestBcwCost[1] )
4007
0
      {
4008
0
        if( tempCS->cost < m_bestBcwCost[0] )
4009
0
        {
4010
0
          m_bestBcwCost[1] = m_bestBcwCost[0];
4011
0
          m_bestBcwCost[0] = tempCS->cost;
4012
0
          m_bestBcwIdx[1] = m_bestBcwIdx[0];
4013
0
          m_bestBcwIdx[0] = cu->BcwIdx;
4014
0
        }
4015
0
        else
4016
0
        {
4017
0
          m_bestBcwCost[1] = tempCS->cost;
4018
0
          m_bestBcwIdx[1] = cu->BcwIdx;
4019
0
        }
4020
0
      }
4021
0
    }
4022
0
  }
4023
4024
0
  tempCS->cost = currBestCost;
4025
0
}
4026
4027
void EncCu::xEncodeDontSplit( CodingStructure &cs, Partitioner &partitioner )
4028
95.9k
{
4029
95.9k
  m_CABACEstimator->resetBits();
4030
4031
95.9k
  m_CABACEstimator->split_cu_mode( CU_DONT_SPLIT, cs, partitioner );
4032
95.9k
  if( partitioner.treeType == TREE_C )
4033
95.9k
    CHECK( m_CABACEstimator->getEstFracBits() != 0, "must be 0 bit" );
4034
4035
95.9k
  cs.fracBits += m_CABACEstimator->getEstFracBits(); // split bits
4036
95.9k
  cs.cost      = m_cRdCost.calcRdCost( cs.fracBits, cs.dist );
4037
95.9k
}
4038
4039
void EncCu::xReuseCachedResult( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner )
4040
0
{
4041
0
  EncTestMode cachedMode;
4042
4043
0
  if( ! m_modeCtrl.setCsFrom( *tempCS, cachedMode, partitioner ) )
4044
0
  {
4045
0
    THROW( "Should never happen!" );
4046
0
  }
4047
4048
0
  CodingUnit& cu = *tempCS->cus.front();
4049
0
  partitioner.setCUData( cu );
4050
4051
0
  if( CU::isIntra( cu ) )
4052
0
  {
4053
0
    if( isLuma( cu.chType ) )
4054
0
    {
4055
0
      cu.getMotionBuf().memset( -1 ); // clear motion buf
4056
0
    }
4057
0
    xReconIntraQT( cu );
4058
0
  }
4059
0
  else
4060
0
  {
4061
0
    xDeriveCUMV( cu );
4062
0
    xReconInter( cu );
4063
0
  }
4064
4065
0
  m_CABACEstimator->getCtx() = m_CurrCtx->start;
4066
0
  m_CABACEstimator->resetBits();
4067
4068
0
  CUCtx cuCtx;
4069
0
  cuCtx.isDQPCoded = true;
4070
0
  cuCtx.isChromaQpAdjCoded = true;
4071
0
  m_CABACEstimator->coding_unit( cu, partitioner, cuCtx );
4072
4073
0
  tempCS->fracBits = m_CABACEstimator->getEstFracBits();
4074
0
  tempCS->cost     = m_cRdCost.calcRdCost( tempCS->fracBits, tempCS->dist );
4075
4076
0
  xEncodeDontSplit( *tempCS,         partitioner );
4077
0
  xCheckDQP       ( *tempCS,         partitioner );
4078
0
  xCheckBestMode  (  tempCS, bestCS, partitioner, cachedMode, m_EDO );
4079
0
}
4080
4081
uint64_t EncCu::xCalcPuMeBits( const CodingUnit &cu )
4082
0
{
4083
0
  CHECK( !cu.mergeFlag, "Should only be used for merge!" );
4084
0
  CHECK( CU::isIBC( cu ), "Shound not be used for IBC" );
4085
4086
0
  m_CABACEstimator->resetBits();
4087
0
  m_CABACEstimator->merge_flag(cu);
4088
0
  if( cu.mergeFlag )
4089
0
  {
4090
0
    m_CABACEstimator->merge_data( cu );
4091
0
  }
4092
0
  return m_CABACEstimator->getEstFracBits();
4093
0
}
4094
4095
double EncCu::xCalcDistortion(CodingStructure *&cur_CS, ChannelType chType, int BitDepth, int imv)
4096
0
{
4097
0
  const auto currDist1 = m_cRdCost.getDistPart(cur_CS->getOrgBuf( COMP_Y ), cur_CS->getPredBuf( COMP_Y ), BitDepth, COMP_Y, m_pcEncCfg->m_fastHad ? DF_HAD_fast : DF_HAD );
4098
0
  unsigned int uiMvBits = 0;
4099
0
  unsigned imvShift = imv == IMV_HPEL ? 1 : (imv << 1);
4100
0
  const CodingUnit& cu = *cur_CS->getCU( chType, TREE_D);
4101
0
  if (cu.interDir != 2)
4102
0
  {
4103
0
    uiMvBits += m_cRdCost.getBitsOfVectorWithPredictor(cu.mvd[0][0].hor, cu.mvd[0][0].ver, imvShift + MV_FRACTIONAL_BITS_DIFF);
4104
0
  }
4105
0
  if (cu.interDir != 1)
4106
0
  {
4107
0
    uiMvBits += m_cRdCost.getBitsOfVectorWithPredictor(cu.mvd[1][0].hor, cu.mvd[1][0].ver, imvShift + MV_FRACTIONAL_BITS_DIFF);
4108
0
  }
4109
0
  return (double(currDist1) + (double)m_cRdCost.getCost(uiMvBits));
4110
0
}
4111
4112
int EncCu::xCheckMMVDCand(MmvdIdx& mmvdMergeCand, int& bestDir, int tempNum, double& bestCostOffset, double& bestCostMerge, double bestCostList )
4113
0
{
4114
0
  int baseIdx = mmvdMergeCand.val / MMVD_MAX_REFINE_NUM;
4115
0
  int CandCur = mmvdMergeCand.val - MMVD_MAX_REFINE_NUM * baseIdx;
4116
4117
0
  if( m_pcEncCfg->m_MMVD > 2 )
4118
0
  {
4119
0
    if( CandCur % 4 == 0 )
4120
0
    {
4121
0
      if( ( bestCostOffset >= bestCostMerge ) && ( CandCur >= 4 ) )
4122
0
      {
4123
0
        if( mmvdMergeCand.val > MMVD_MAX_REFINE_NUM )
4124
0
        {
4125
0
          return 2;
4126
0
        }
4127
0
        else
4128
0
        {
4129
0
          mmvdMergeCand.val = MMVD_MAX_REFINE_NUM;
4130
0
          if( tempNum == mmvdMergeCand.val )
4131
0
          {
4132
0
            return 2;
4133
0
          }
4134
0
        }
4135
0
      }
4136
      //reset
4137
0
      bestCostOffset = MAX_DOUBLE;
4138
0
      bestCostMerge  = bestCostList;
4139
0
    }
4140
0
  }
4141
4142
0
  if( mmvdMergeCand.val == MMVD_MAX_REFINE_NUM )
4143
0
  {
4144
0
    bestDir = 0;
4145
0
  }
4146
0
  if( CandCur >= 4 )
4147
0
  {
4148
0
    if( CandCur % 4 != bestDir )
4149
0
    {
4150
0
      return 1;
4151
0
    }
4152
0
  }
4153
0
  return 0;
4154
0
}
4155
4156
4157
MergeItem::MergeItem()
4158
142k
{
4159
4160
142k
}
4161
MergeItem::~MergeItem()
4162
142k
{
4163
4164
142k
}
4165
4166
void MergeItem::create( ChromaFormat chromaFormat, const Area &area )
4167
142k
{
4168
142k
  if( m_pelStorage.bufs.empty() )
4169
142k
  {
4170
142k
    m_pelStorage.create( chromaFormat, area );
4171
142k
    m_mvStorage .resize( area.area() >> ( MIN_CU_LOG2 << 1 ) );
4172
142k
  }
4173
4174
142k
  init();
4175
142k
}
4176
4177
void MergeItem::init()
4178
142k
{
4179
  // reset data
4180
142k
  cost        = MAX_DOUBLE;
4181
142k
  mergeIdx    = 0;
4182
142k
  bcwIdx      = 0;
4183
142k
  interDir    = 0;
4184
142k
  useAltHpelIf  = false;
4185
142k
  affineType    = AFFINEMODEL_4PARAM;
4186
142k
  mergeItemType = MergeItemType::NUM;
4187
4188
142k
  noBdofRefine  = false;
4189
142k
  noResidual    = false;
4190
4191
142k
  lumaPredReady   = false;
4192
142k
  chromaPredReady = false;
4193
142k
}
4194
4195
void MergeItem::importMergeInfo(const MergeCtx& mergeCtx, int _mergeIdx, MergeItemType _mergeItemType, CodingUnit& pu)
4196
0
{
4197
0
  mergeIdx      = _mergeIdx;
4198
0
  mergeItemType = _mergeItemType;
4199
4200
0
  if( mergeItemType != MergeItemType::GPM && mergeItemType != MergeItemType::MMVD )
4201
0
  {
4202
0
    mvField[REF_PIC_LIST_0][0] = mergeCtx.mvFieldNeighbours [mergeIdx][REF_PIC_LIST_0];
4203
0
    mvField[REF_PIC_LIST_1][0] = mergeCtx.mvFieldNeighbours [mergeIdx][REF_PIC_LIST_1];
4204
0
    interDir                   = mergeCtx.interDirNeighbours[mergeIdx];
4205
0
    bcwIdx                     = mergeCtx.BcwIdx            [mergeIdx];
4206
0
    useAltHpelIf               = mergeCtx.useAltHpelIf      [mergeIdx];
4207
0
  }
4208
4209
0
  switch( _mergeItemType )
4210
0
  {
4211
0
  case MergeItemType::REGULAR:
4212
0
  case MergeItemType::CIIP:
4213
0
    break;
4214
4215
0
  case MergeItemType::MMVD:
4216
0
  {
4217
0
    MmvdIdx candIdx;
4218
4219
0
    candIdx.val                = mergeIdx;
4220
0
    mvField[L0][0]             . setMvField( pu.mv[L0][0], pu.refIdx[0] );
4221
0
    mvField[L1][0]             . setMvField( pu.mv[L1][0], pu.refIdx[1] );
4222
0
    interDir                   = pu.interDir;
4223
0
    bcwIdx                     = pu.BcwIdx;
4224
0
    useAltHpelIf               = mergeCtx.useAltHpelIf[candIdx.pos.baseIdx];
4225
4226
0
    break;
4227
0
  }
4228
4229
0
  case MergeItemType::GPM:
4230
0
    mvField[L0][0]             . setMvField( Mv( 0, 0 ), -1 );
4231
0
    mvField[L1][0]             . setMvField( Mv( 0, 0 ), -1 );
4232
0
    bcwIdx                     = BCW_DEFAULT;
4233
0
    useAltHpelIf               = false;
4234
4235
0
    break;
4236
4237
0
  case MergeItemType::IBC:
4238
0
  default:
4239
0
    THROW( "Wrong merge item type" );
4240
0
  }
4241
4242
0
  getMvBuf( pu ).copyFrom( pu.getMotionBuf() );
4243
0
}
4244
4245
void MergeItem::importMergeInfo( const AffineMergeCtx &mergeCtx, int _mergeIdx, MergeItemType _mergeItemType, CodingUnit& pu )
4246
0
{
4247
0
  mergeIdx      = _mergeIdx;
4248
0
  mergeItemType = _mergeItemType;
4249
4250
0
  affineType    = mergeCtx.affineType         [mergeIdx];
4251
0
  interDir      = mergeCtx.interDirNeighbours [mergeIdx];
4252
0
  bcwIdx        = mergeCtx.BcwIdx             [mergeIdx];
4253
0
  useAltHpelIf  = false;
4254
4255
0
  switch( _mergeItemType )
4256
0
  {
4257
0
  case MergeItemType::SBTMVP:
4258
    // the pu motion was already generated preparing for IFP check (unconditional)
4259
0
    mvField[L0][0] . setMvField( pu.mv[L0][0], pu.refIdx[L0] );
4260
0
    mvField[L1][0] . setMvField( pu.mv[L1][0], pu.refIdx[L1] );
4261
4262
0
    break;
4263
4264
0
  case MergeItemType::AFFINE:
4265
    // the pu motion was already generated preparing for IFP check (unconditional)
4266
0
    mvField[L0][0] . setMvField( pu.mv[L0][0], pu.refIdx[L0] );
4267
0
    mvField[L0][1] . setMvField( pu.mv[L0][1], pu.refIdx[L0] );
4268
0
    mvField[L0][2] . setMvField( pu.mv[L0][2], pu.refIdx[L0] );
4269
0
    mvField[L1][0] . setMvField( pu.mv[L1][0], pu.refIdx[L1] );
4270
0
    mvField[L1][1] . setMvField( pu.mv[L1][1], pu.refIdx[L1] );
4271
0
    mvField[L1][2] . setMvField( pu.mv[L1][2], pu.refIdx[L1] );
4272
4273
0
    break;
4274
4275
0
  default:
4276
0
    THROW( "Wrong merge item type" );
4277
0
  }
4278
4279
  // the MI buf was already generated preparing for IFP check (unconditional)
4280
0
  getMvBuf( pu ).copyFrom( pu.getMotionBuf() );
4281
0
}
4282
4283
bool MergeItem::exportMergeInfo( CodingUnit &pu, bool forceNoResidual ) const
4284
0
{
4285
0
  pu.mergeFlag        = true;
4286
0
  pu.mmvdMergeFlag    = false;
4287
0
  pu.interDir         = interDir;
4288
0
  pu.mergeIdx         = mergeIdx;
4289
0
  pu.mergeType        = MRG_TYPE_DEFAULT_N;
4290
0
  pu.mv[REF_PIC_LIST_0][0]  = mvField[REF_PIC_LIST_0][0].mv;
4291
0
  pu.mv[REF_PIC_LIST_1][0]  = mvField[REF_PIC_LIST_1][0].mv;
4292
0
  pu.refIdx[REF_PIC_LIST_0] = mvField[REF_PIC_LIST_0][0].refIdx;
4293
0
  pu.refIdx[REF_PIC_LIST_1] = mvField[REF_PIC_LIST_1][0].refIdx;
4294
0
  pu.mvd[REF_PIC_LIST_0][0] = Mv();
4295
0
  pu.mvd[REF_PIC_LIST_1][0] = Mv();
4296
0
  pu.mvpIdx[REF_PIC_LIST_0] = NOT_VALID;
4297
0
  pu.mvpIdx[REF_PIC_LIST_1] = NOT_VALID;
4298
0
  pu.mvpNum[REF_PIC_LIST_0] = NOT_VALID;
4299
0
  pu.mvpNum[REF_PIC_LIST_1] = NOT_VALID;
4300
0
  pu.BcwIdx         = ( interDir == 3 ) ? bcwIdx : BCW_DEFAULT;
4301
0
  pu.mcControl      = 0;
4302
0
  pu.mmvdSkip       = false;
4303
0
  pu.affine         = false;
4304
0
  pu.affineType     = AFFINEMODEL_4PARAM;
4305
0
  pu.geo            = false;
4306
0
  pu.mtsFlag        = false;
4307
0
  pu.ciip           = false;
4308
0
  pu.imv            = ( !pu.geo && useAltHpelIf ) ? IMV_HPEL : IMV_OFF;
4309
0
  pu.mvRefine       = false;
4310
4311
0
  const bool resetCiip2Regular = mergeItemType == MergeItemType::CIIP && forceNoResidual;
4312
0
  MergeItemType updatedType    = resetCiip2Regular ? MergeItemType::REGULAR : mergeItemType;
4313
4314
0
  switch( updatedType )
4315
0
  {
4316
0
  case MergeItemType::REGULAR:
4317
0
    CU::restrictBiPredMergeCandsOne( pu );
4318
0
    break;
4319
4320
0
  case MergeItemType::CIIP:
4321
0
    CHECK( forceNoResidual, "Cannot force no residuals for CIIP" );
4322
0
    pu.ciip           = true;
4323
0
    pu.intraDir[CH_L] = PLANAR_IDX;
4324
0
    pu.intraDir[CH_C] = DM_CHROMA_IDX;
4325
0
    break;
4326
4327
0
  case MergeItemType::MMVD:
4328
0
    pu.mmvdMergeFlag    = true;
4329
0
    pu.mmvdMergeIdx.val = mergeIdx;
4330
0
    if( forceNoResidual )
4331
0
    {
4332
0
      pu.mmvdSkip       = true;
4333
0
    }
4334
0
    CU::restrictBiPredMergeCandsOne( pu );
4335
0
    break;
4336
4337
0
  case MergeItemType::SBTMVP:
4338
0
    pu.affine    = true;
4339
0
    pu.mergeType = MRG_TYPE_SUBPU_ATMVP;
4340
0
    break;
4341
4342
0
  case MergeItemType::AFFINE:
4343
0
    pu.affine     = true;
4344
0
    pu.affineType = affineType;
4345
0
    pu.mv[L0][0]  = mvField[L0][0].mv;
4346
0
    pu.mv[L1][0]  = mvField[L1][0].mv;
4347
0
    pu.mv[L0][1]  = mvField[L0][1].mv;
4348
0
    pu.mv[L1][1]  = mvField[L1][1].mv;
4349
0
    pu.mv[L0][2]  = mvField[L0][2].mv;
4350
0
    pu.mv[L1][2]  = mvField[L1][2].mv;
4351
0
    pu.refIdx[L0] = mvField[L0][0].refIdx;
4352
0
    pu.refIdx[L1] = mvField[L1][0].refIdx;
4353
0
    break;
4354
4355
0
  case MergeItemType::GPM:
4356
0
    pu.mergeIdx = -1;
4357
0
    pu.geo      = true;
4358
0
    pu.BcwIdx   = BCW_DEFAULT;
4359
0
    updateGpmIdx( mergeIdx, pu.geoSplitDir, pu.geoMergeIdx );
4360
0
    pu.imv      = IMV_OFF;
4361
0
    break;
4362
4363
0
  case MergeItemType::IBC:
4364
0
  default:
4365
0
    THROW( "Wrong merge item type" );
4366
0
  }
4367
4368
0
  pu.getMotionBuf().copyFrom( getMvBuf( pu ) );
4369
4370
0
  return resetCiip2Regular;
4371
0
}
4372
4373
MergeItemList::MergeItemList()
4374
17.7k
{
4375
4376
17.7k
}
4377
4378
MergeItemList::~MergeItemList()
4379
17.7k
{
4380
17.7k
  for( MergeItem* p : m_list )
4381
0
  {
4382
0
    delete p;
4383
0
  }
4384
17.7k
  m_list.clear();
4385
4386
17.7k
  for( MergeItem *p : m_mergeItems )
4387
142k
  {
4388
142k
    delete p;
4389
142k
  }
4390
17.7k
  m_mergeItems.clear();
4391
17.7k
}
4392
4393
void MergeItemList::init( size_t maxSize, size_t maxExtSize, ChromaFormat chromaFormat, SizeType ctuWidth, SizeType ctuHeight )
4394
17.7k
{
4395
17.7k
  CHECK( !m_mergeItems.empty() || !m_list.empty(), "MergeItemList already initialized" );
4396
4397
17.7k
  m_list      . reserve( maxSize + 1 ); // to avoid reallocation when inserting a new item
4398
17.7k
  m_mergeItems. reserve( maxSize + 1 );
4399
17.7k
  m_maxSize   = maxSize;
4400
17.7k
  m_maxExtSize= maxExtSize;
4401
17.7k
  m_numExt    = 0;
4402
4403
159k
  for( int i = 0; i < maxSize + m_maxExtSize; i++ )
4404
142k
  {
4405
142k
    MergeItem *p = new MergeItem;
4406
142k
    p->create( chromaFormat, Area{ 0, 0, ctuWidth, ctuHeight } );
4407
142k
    m_mergeItems.push_back( p );
4408
142k
  }
4409
17.7k
}
4410
4411
MergeItem *MergeItemList::allocateNewMergeItem()
4412
0
{
4413
0
  m_numExt++;
4414
0
  CHECK( m_mergeItems.empty(), "Missing merge items!" );
4415
0
  CHECK( m_numExt > m_maxExtSize, "Taking out more external items than specified during list allocation!" );
4416
0
  MergeItem *p = m_mergeItems.back();
4417
0
  m_mergeItems.pop_back();
4418
0
  p->init();
4419
0
  return p;
4420
0
}
4421
4422
bool MergeItemList::insertMergeItemToList( MergeItem *p )
4423
0
{
4424
0
  CHECK( m_list.size() + m_mergeItems.size() + m_numExt != m_maxSize + m_maxExtSize, "Wrong number of items held" );
4425
4426
0
  m_numExt--;
4427
4428
0
  if( m_list.empty() )
4429
0
  {
4430
0
    m_list.push_back( p );
4431
0
  }
4432
0
  else if( m_list.size() == m_maxTrackingNum && p->cost >= m_list.back()->cost )
4433
0
  {
4434
0
    m_mergeItems.push_back( p );
4435
0
    return false;
4436
0
  }
4437
0
  else
4438
0
  {
4439
0
    if( m_list.size() == m_maxTrackingNum )
4440
0
    {
4441
0
      m_mergeItems.push_back( m_list.back() );
4442
0
      m_list      .pop_back();
4443
0
    }
4444
0
    auto it = std::find_if( m_list.begin(), m_list.end(), [&p]( const MergeItem *mi ) { return p->cost < mi->cost; } );
4445
0
    m_list.insert( it, p );
4446
0
  }
4447
4448
0
  return true;
4449
0
}
4450
4451
void MergeItemList::giveBackMergeItem( MergeItem *p )
4452
0
{
4453
0
  CHECK( m_list.size() + m_mergeItems.size() + m_numExt != m_maxSize + m_maxExtSize, "Wrong number of items held" );
4454
4455
0
  m_numExt--;
4456
4457
0
  m_mergeItems.push_back( p );
4458
0
}
4459
4460
MergeItem *MergeItemList::getMergeItemInList( size_t index )
4461
0
{
4462
0
  return index < m_maxTrackingNum ? m_list[index] : nullptr;
4463
0
}
4464
4465
void MergeItemList::resetList( size_t maxTrackingNum )
4466
0
{
4467
0
  CHECK( maxTrackingNum > m_maxSize, "Not enough items allocated to track " << maxTrackingNum << " items" );
4468
4469
0
  for( auto p : m_list )
4470
0
  {
4471
0
    m_mergeItems.push_back( p );
4472
0
  }
4473
0
  m_list.clear  ();
4474
4475
0
  m_maxTrackingNum = maxTrackingNum;
4476
0
}
4477
4478
void MergeItemList::shrinkList( size_t reduceTo )
4479
0
{
4480
0
  CHECK( reduceTo > m_maxSize, "Not enough items allocated to track " << reduceTo << " items" );
4481
4482
0
  while( m_list.size() > reduceTo )
4483
0
  {
4484
0
    m_mergeItems.push_back( m_list.back() );
4485
0
    m_list      .pop_back();
4486
0
  }
4487
0
}
4488
4489
} // namespace vvenc
4490
4491
//! \}