Coverage Report

Created: 2026-05-30 06:10

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
20.7k
  : m_CtxCache          ( nullptr )
237
20.7k
  , m_globalCtuQpVector ( nullptr )
238
20.7k
  , m_wppMutex          ( nullptr )
239
20.7k
  , m_CABACEstimator    ( nullptr )
240
20.7k
{
241
20.7k
}
242
243
void EncCu::initPic( Picture* pic )
244
5.19k
{
245
5.19k
  const ReshapeData& reshapeData = pic->reshapeData;
246
5.19k
  m_cRdCost.setReshapeParams( reshapeData.getReshapeLumaLevelToWeightPLUT(), reshapeData.getChromaWeight() );
247
5.19k
  m_cInterSearch.setSearchRange( pic->cs->slice, *m_pcEncCfg );
248
249
5.19k
  m_wppMutex = (m_pcEncCfg->m_numThreads > 0 ) ? &pic->wppMutex : nullptr;
250
5.19k
}
251
252
void EncCu::initSlice( const Slice* slice )
253
5.19k
{
254
5.19k
  m_cTrQuant.setLambdas( slice->getLambdas() );
255
5.19k
  m_cRdCost.setLambda( slice->getLambdas()[0], slice->sps->bitDepths );
256
5.19k
}
257
258
void EncCu::setCtuEncRsrc( CABACWriter* cabacEstimator, CtxCache* ctxCache, ReuseUniMv* pReuseUniMv, BlkUniMvInfoBuffer* pBlkUniMvInfoBuffer, AffineProfList* pAffineProfList, IbcBvCand* pCachedBvs )
259
4.05k
{
260
4.05k
  m_CABACEstimator = cabacEstimator;
261
4.05k
  m_CtxCache       = ctxCache;
262
4.05k
  m_cIntraSearch.setCtuEncRsrc( cabacEstimator, ctxCache );
263
4.05k
  m_cInterSearch.setCtuEncRsrc( cabacEstimator, ctxCache, pReuseUniMv, pBlkUniMvInfoBuffer, pAffineProfList, pCachedBvs );
264
4.05k
}
265
266
void EncCu::setUpLambda (Slice& slice, const double dLambda, const int iQP, const bool setSliceLambda, const bool saveUnadjusted)
267
9.24k
{
268
  // store lambda
269
9.24k
  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
9.24k
  double dLambdas[MAX_NUM_COMP] = { dLambda };
274
27.7k
  for( uint32_t compIdx = 1; compIdx < MAX_NUM_COMP; compIdx++ )
275
18.4k
  {
276
18.4k
    const ComponentID compID = ComponentID( compIdx );
277
18.4k
    int chromaQPOffset       = slice.pps->chromaQpOffset[compID] + slice.sliceChromaQpDelta[ compID ];
278
18.4k
    int qpc = slice.sps->chromaQpMappingTable.getMappedChromaQpValue(compID, iQP) + chromaQPOffset;
279
18.4k
    double tmpWeight         = pow( 2.0, ( iQP - qpc ) / 3.0 );  // takes into account of the chroma qp mapping and chroma qp Offset
280
18.4k
    if( m_pcEncCfg->m_DepQuantEnabled/* && !( m_pcEncCfg->getLFNST() ) */)
281
18.4k
    {
282
18.4k
      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
18.4k
    }
284
18.4k
    m_cRdCost.setDistortionWeight( compID, tmpWeight );
285
18.4k
    dLambdas[compIdx] = dLambda / tmpWeight;
286
18.4k
  }
287
288
  // for RDOQ
289
9.24k
  m_cTrQuant.setLambdas( dLambdas );
290
291
  // for SAO, ALF
292
9.24k
  if (setSliceLambda)
293
5.19k
  {
294
5.19k
    slice.setLambdas( dLambdas );
295
5.19k
  }
296
9.24k
  if( saveUnadjusted )
297
9.24k
  {
298
9.24k
    m_cRdCost.saveUnadjustedLambda();
299
9.24k
  }
300
9.24k
}
301
302
void EncCu::updateLambda(const Slice& slice, const double ctuLambda, const int ctuQP, const int newQP, const bool saveUnadjusted)
303
3.70k
{
304
3.70k
  const double  corrFactor = pow (2.0, double (newQP - ctuQP) / 3.0);
305
3.70k
  const double  newLambda  = ctuLambda * corrFactor;
306
3.70k
  const double* oldLambdas = slice.getLambdas(); // assumes prior setUpLambda (slice, ctuLambda) call!
307
3.70k
  const double  newLambdas[MAX_NUM_COMP] = { oldLambdas[COMP_Y] * corrFactor, oldLambdas[COMP_Cb] * corrFactor, oldLambdas[COMP_Cr] * corrFactor };
308
309
3.70k
  m_cTrQuant.setLambdas ( newLambdas);
310
3.70k
  m_cRdCost.setLambda   ( newLambda, slice.sps->bitDepths);
311
312
3.70k
  if (saveUnadjusted)
313
3.70k
  {
314
3.70k
    m_cRdCost.saveUnadjustedLambda(); // TODO hlm: check if this actually improves the overall quality
315
3.70k
  }
316
3.70k
}
317
318
void EncCu::init( const VVEncCfg& encCfg, const SPS& sps, std::vector<int>* const globalCtuQpVector, Ctx* syncPicCtx, RateCtrl* pRateCtrl )
319
20.7k
{
320
20.7k
  DecCu::init( &m_cTrQuant, &m_cIntraSearch, &m_cInterSearch, encCfg.m_internChromaFormat );
321
20.7k
  m_cRdCost.create     ();
322
20.7k
  m_cRdCost.setCostMode( encCfg.m_costMode );
323
20.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
20.7k
  m_modeCtrl.init     ( encCfg, &m_cRdCost );
329
20.7k
  m_cIntraSearch.init ( encCfg, &m_cTrQuant, &m_cRdCost, &m_SortedPelUnitBufs, m_unitCache );
330
20.7k
  m_cInterSearch.init ( encCfg, &m_cTrQuant, &m_cRdCost, &m_modeCtrl, m_cIntraSearch.getSaveCSBuf() );
331
20.7k
  m_cTrQuant.init     ( nullptr, encCfg.m_RDOQ, encCfg.m_useRDOQTS, false, true, encCfg.m_quantThresholdVal );
332
333
20.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
20.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
20.7k
  const int maxLog2TrDynamicRange[ MAX_NUM_CH ] = { sps.getMaxLog2TrDynamicRange(), sps.getMaxLog2TrDynamicRange() };
338
20.7k
  m_cTrQuant.getQuant()->setFlatScalingList( maxLog2TrDynamicRange, sps.bitDepths );
339
340
20.7k
  m_pcEncCfg       = &encCfg;
341
342
20.7k
  m_GeoCostList.init( encCfg.m_maxNumGeoCand );
343
344
20.7k
  unsigned      uiMaxSize    = encCfg.m_CTUSize;
345
20.7k
  ChromaFormat  chromaFormat = encCfg.m_internChromaFormat;
346
347
20.7k
  Area ctuArea = Area( 0, 0, uiMaxSize, uiMaxSize );
348
349
20.7k
  m_mergeItemList.init( encCfg.m_maxMergeRdCandNumTotal, m_pcEncCfg->m_Geo > 1 ? 3 : 1, chromaFormat, uiMaxSize, uiMaxSize );
350
351
269k
  for( int i = 0; i < maxCuDepth; i++ )
352
249k
  {
353
249k
    Area area = Area( 0, 0, uiMaxSize >> ( i >> 1 ), uiMaxSize >> ( ( i + 1 ) >> 1 ) );
354
355
249k
    if( area.width < (1 << MIN_CU_LOG2) || area.height < (1 << MIN_CU_LOG2) )
356
20.7k
    {
357
20.7k
      m_pTempCS[i] = m_pBestCS[i] = nullptr;
358
20.7k
      continue;
359
20.7k
    }
360
361
228k
    m_pTempCS[i] = new CodingStructure( m_unitCache, nullptr );
362
228k
    m_pBestCS[i] = new CodingStructure( m_unitCache, nullptr );
363
364
228k
    m_pTempCS[i]->createForSearch( chromaFormat, area );
365
228k
    m_pBestCS[i]->createForSearch( chromaFormat, area );
366
367
228k
    m_pOrgBuffer[i].create( chromaFormat, area );
368
228k
    m_pRspBuffer[i].create( CHROMA_400, area );
369
228k
  }
370
371
20.7k
  m_pTempCS2 = new CodingStructure( m_unitCache, nullptr );
372
20.7k
  m_pBestCS2 = new CodingStructure( m_unitCache, nullptr );
373
374
20.7k
  m_pTempCS2->createForSearch( chromaFormat, ctuArea );
375
20.7k
  m_pBestCS2->createForSearch( chromaFormat, ctuArea );
376
377
20.7k
  m_cuChromaQpOffsetIdxPlus1 = 0;
378
20.7k
  m_tempQpDiff = 0;
379
20.7k
  m_globalCtuQpVector = globalCtuQpVector;
380
381
20.7k
  m_SortedPelUnitBufs.create( chromaFormat, uiMaxSize, uiMaxSize );
382
383
311k
  for( uint8_t i = 0; i < MAX_TMP_BUFS; i++)
384
290k
  {
385
290k
    m_aTmpStorageLCU[i].create(chromaFormat, Area(0, 0, uiMaxSize, uiMaxSize));
386
290k
  }
387
145k
  for (unsigned ui = 0; ui < MRG_MAX_NUM_CANDS; ui++)
388
124k
  {
389
124k
    m_acMergeTmpBuffer[ui].create(chromaFormat, Area(0, 0, uiMaxSize, uiMaxSize));
390
124k
  }
391
392
20.7k
  const unsigned maxDepth = 2 * MAX_CU_SIZE_IDX;
393
20.7k
  m_CtxBuffer.resize( maxDepth );
394
20.7k
  m_CurrCtx = 0;
395
20.7k
  if( encCfg.m_EDO )
396
20.7k
    m_dbBuffer.create( chromaFormat, Area( 0, 0, uiMaxSize, uiMaxSize ), 0, 8 );
397
398
20.7k
  m_MergeSimpleFlag = 0;
399
20.7k
  m_tileIdx = 0;
400
20.7k
}
401
402
403
void EncCu::destroy()
404
20.7k
{
405
269k
  for( int i = 0; i < maxCuDepth; i++ )
406
249k
  {
407
249k
    if( m_pTempCS[i] )
408
228k
    {
409
228k
      m_pTempCS[i]->destroy();
410
228k
      delete m_pTempCS[i]; m_pTempCS[i] = nullptr;
411
228k
    }
412
413
249k
    if( m_pBestCS[i] )
414
228k
    {
415
228k
      m_pBestCS[i]->destroy();
416
228k
      delete m_pBestCS[i]; m_pBestCS[i] = nullptr;
417
228k
    }
418
419
249k
    m_pOrgBuffer[i].destroy();
420
249k
    m_pRspBuffer[i].destroy();
421
249k
  }
422
423
20.7k
  m_pTempCS2->destroy();
424
20.7k
  m_pBestCS2->destroy();
425
426
20.7k
  delete m_pTempCS2; m_pTempCS2 = nullptr;
427
20.7k
  delete m_pBestCS2; m_pBestCS2 = nullptr;
428
429
20.7k
  m_SortedPelUnitBufs.destroy();
430
431
311k
  for( uint8_t i = 0; i < MAX_TMP_BUFS; i++)
432
290k
  {
433
290k
    m_aTmpStorageLCU[i].destroy();
434
290k
  }
435
145k
  for (unsigned ui = 0; ui < MRG_MAX_NUM_CANDS; ui++)
436
124k
  {
437
124k
    m_acMergeTmpBuffer[ui].destroy();
438
124k
  }
439
440
441
20.7k
  m_dbBuffer.destroy();
442
20.7k
}
443
444
445
EncCu::~EncCu()
446
20.7k
{
447
20.7k
  destroy();
448
20.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
4.05k
{
456
4.05k
  CodingStructure&     cs          = *pic->cs;
457
4.05k
  Slice*               slice       = cs.slice;
458
4.05k
  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
4.05k
  const int ctuRsAddr                 = ctuYPosInCtus * pcv.widthInCtus + ctuXPosInCtus;
470
471
4.05k
  const Position pos (ctuXPosInCtus * pcv.maxCUSize, ctuYPosInCtus * pcv.maxCUSize);
472
4.05k
  const UnitArea ctuArea( cs.area.chromaFormat, Area( pos.x, pos.y, pcv.maxCUSize, pcv.maxCUSize ) );
473
4.05k
  DTRACE_UPDATE( g_trace_ctx, std::make_pair( "ctu", ctuRsAddr ) );
474
475
4.05k
  const int tileXPosInCtus = cs.pps->tileColBd[cs.pps->ctuToTileCol[ctuXPosInCtus]];
476
4.05k
  const int tileYPosInCtus = cs.pps->tileRowBd[cs.pps->ctuToTileRow[ctuYPosInCtus]];
477
478
4.05k
  if( ( cs.slice->sliceType != VVENC_I_SLICE || cs.sps->IBC ) && ctuXPosInCtus == tileXPosInCtus )
479
2.26k
  {
480
2.26k
    const int tileRowId = cs.pps->getTileLineId( ctuXPosInCtus, ctuYPosInCtus );
481
2.26k
    cs.motionLutBuf[tileRowId].lut.resize( 0 );
482
2.26k
    cs.motionLutBuf[tileRowId].lutIbc.resize( 0 );
483
2.26k
  }
484
485
4.05k
  if( ( m_pcEncCfg->m_ensureWppBitEqual || m_pcEncCfg->m_entropyCodingSyncEnabled ) && ctuXPosInCtus == tileXPosInCtus )
486
2.26k
  {
487
2.26k
    m_CABACEstimator->initCtxModels( *slice );
488
489
2.26k
    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
2.26k
    prevQP[CH_L] = prevQP[CH_C] = slice->sliceQp; // hlm: call CU::predictQP() here!
495
2.26k
  }
496
1.78k
  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
4.05k
  xCompressCtu( cs, ctuArea, ctuRsAddr, prevQP );
503
504
4.05k
  m_CABACEstimator->resetBits();
505
4.05k
  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
4.05k
  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
4.05k
  DTRACE_AREA_CRC( g_trace_ctx, D_CRC, cs, ctuArea );
514
4.05k
}
515
516
// ====================================================================================================================
517
// Protected member functions
518
// ====================================================================================================================
519
520
void EncCu::xCompressCtu( CodingStructure& cs, const UnitArea& area, const unsigned ctuRsAddr, const int prevQP[] )
521
4.05k
{
522
4.05k
  m_tileIdx = cs.pps->getTileIdx( area.lumaPos() );
523
524
4.05k
  m_modeCtrl.initCTUEncoding( *cs.slice, m_tileIdx );
525
526
  // init the partitioning manager
527
4.05k
  Partitioner *partitioner = &m_partitioner;
528
4.05k
  partitioner->initCtu( area, CH_L, *cs.slice );
529
  
530
4.05k
  const Position& lumaPos = area.lumaPos();
531
4.05k
  const bool leftSameTile  = lumaPos.x == 0 || m_tileIdx == cs.pps->getTileIdx( lumaPos.offset(-1, 0) );
532
4.05k
  const bool aboveSameTile = lumaPos.y == 0 || m_tileIdx == cs.pps->getTileIdx( lumaPos.offset( 0,-1) );
533
4.05k
  m_EDO = (!m_pcEncCfg->m_tileParallelCtuEnc || (leftSameTile && aboveSameTile)) ? m_pcEncCfg->m_EDO : 0;
534
  
535
4.05k
  if( m_pcEncCfg->m_IBCMode )
536
4.05k
  {
537
4.05k
    m_cInterSearch.resetCtuRecordIBC();
538
4.05k
  }
539
540
  // init current context pointer
541
4.05k
  m_CurrCtx = m_CtxBuffer.data();
542
543
4.05k
  PelStorage* orgBuffer = &m_pOrgBuffer[0];
544
4.05k
  PelStorage* rspBuffer = &m_pRspBuffer[0];
545
4.05k
  CodingStructure *tempCS =  m_pTempCS [0];
546
4.05k
  CodingStructure *bestCS =  m_pBestCS [0];
547
4.05k
  cs.initSubStructure( *tempCS, partitioner->chType, partitioner->currArea(), false, orgBuffer, rspBuffer );
548
4.05k
  cs.initSubStructure( *bestCS, partitioner->chType, partitioner->currArea(), false, orgBuffer, rspBuffer );
549
4.05k
  PROFILER_SCOPE_AND_STAGE_EXT( 1, _TPROF, P_COMPRESS_CU, tempCS, CH_L );
550
551
  // copy the relevant area
552
4.05k
  UnitArea clippedArea = clipArea( partitioner->currArea(), cs.area );
553
4.05k
  CPelUnitBuf org = cs.picture->getFilteredOrigBuffer().valid() ? cs.picture->getRspOrigBuf( clippedArea ) : cs.picture->getOrigBuf( clippedArea );
554
4.05k
  tempCS->getOrgBuf( clippedArea ).copyFrom( org );
555
4.05k
  const ReshapeData& reshapeData = cs.picture->reshapeData;
556
4.05k
  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
4.05k
  tempCS->currQP[CH_L] = bestCS->currQP[CH_L] =
562
4.05k
  tempCS->baseQP       = bestCS->baseQP       = cs.slice->sliceQp;
563
4.05k
  tempCS->prevQP[CH_L] = bestCS->prevQP[CH_L] = prevQP[CH_L];
564
565
4.05k
  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
4.05k
  CHECK( bestCS->cus.empty()                                   , "No possible encoding found" );
571
4.05k
  CHECK( bestCS->cus[0]->predMode == NUMBER_OF_PREDICTION_MODES, "No possible encoding found" );
572
4.05k
  CHECK( bestCS->cost             == MAX_DOUBLE                , "No possible encoding found" );
573
574
4.05k
  if ( m_wppMutex ) m_wppMutex->lock();
575
576
4.05k
  cs.useSubStructure( *bestCS, partitioner->chType, TREE_D, CS::getArea( *bestCS, area, partitioner->chType, partitioner->treeType ) );
577
578
4.05k
  if ( m_wppMutex ) m_wppMutex->unlock();
579
580
4.05k
  if( CS::isDualITree( cs ) && isChromaEnabled( cs.pcv->chrFormat ) )
581
4.05k
  {
582
4.05k
    m_CABACEstimator->getCtx() = m_CurrCtx->start;
583
584
4.05k
    partitioner->initCtu( area, CH_C, *cs.slice );
585
586
4.05k
    cs.initSubStructure( *tempCS, partitioner->chType, partitioner->currArea(), false, orgBuffer, rspBuffer );
587
4.05k
    cs.initSubStructure( *bestCS, partitioner->chType, partitioner->currArea(), false, orgBuffer, rspBuffer );
588
4.05k
    tempCS->currQP[CH_C] = bestCS->currQP[CH_C] =
589
4.05k
    tempCS->baseQP       = bestCS->baseQP       = cs.slice->sliceQp;
590
4.05k
    tempCS->prevQP[CH_C] = bestCS->prevQP[CH_C] = prevQP[CH_C];
591
592
4.05k
    xCompressCU( tempCS, bestCS, *partitioner );
593
    
594
    // Ensure that a coding was found
595
    // Selected mode's RD-cost must be not MAX_DOUBLE.
596
4.05k
    CHECK( bestCS->cus.empty()                                   , "No possible encoding found" );
597
4.05k
    CHECK( bestCS->cus[0]->predMode == NUMBER_OF_PREDICTION_MODES, "No possible encoding found" );
598
4.05k
    CHECK( bestCS->cost             == MAX_DOUBLE                , "No possible encoding found" );
599
600
4.05k
    if ( m_wppMutex ) m_wppMutex->lock();
601
602
4.05k
    cs.useSubStructure( *bestCS, partitioner->chType, TREE_D, CS::getArea( *bestCS, area, partitioner->chType, partitioner->treeType ) );
603
604
4.05k
    if ( m_wppMutex ) m_wppMutex->unlock();
605
4.05k
  }
606
607
  // reset context states and uninit context pointer
608
4.05k
  m_CABACEstimator->getCtx() = m_CurrCtx->start;
609
4.05k
  m_CurrCtx                  = 0;
610
4.05k
}
611
612
613
614
bool EncCu::xCheckBestMode( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode, const bool useEDO )
615
303k
{
616
303k
  bool bestCSUpdated = false;
617
618
303k
  if( !tempCS->cus.empty() )
619
184k
  {
620
184k
    if( tempCS->cus.size() == 1 )
621
138k
    {
622
138k
      const CodingUnit& cu = *tempCS->cus.front();
623
138k
      CHECK( cu.skip && !cu.mergeFlag, "Skip flag without a merge flag is not allowed!" );
624
138k
    }
625
626
184k
    DTRACE_BEST_MODE( tempCS, bestCS, m_cRdCost.getLambda(true), useEDO );
627
628
184k
    if( m_modeCtrl.useModeResult( encTestMode, tempCS, partitioner, useEDO ) )
629
166k
    {
630
166k
      std::swap( tempCS, bestCS );
631
      // store temp best CI for next CU coding
632
166k
      m_CurrCtx->best = m_CABACEstimator->getCtx();
633
166k
      bestCSUpdated = true;
634
166k
    }
635
184k
  }
636
637
  // reset context states
638
303k
  m_CABACEstimator->getCtx() = m_CurrCtx->start;
639
303k
  return bestCSUpdated;
640
641
303k
}
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
139k
{
719
139k
  const Area& lumaArea = tempCS->area.Y();
720
721
139k
  Slice&   slice      = *tempCS->slice;
722
139k
  const PPS &pps      = *tempCS->pps;
723
139k
  const SPS &sps      = *tempCS->sps;
724
139k
  const uint32_t uiLPelX  = tempCS->area.Y().lumaPos().x;
725
139k
  const uint32_t uiTPelY  = tempCS->area.Y().lumaPos().y;
726
139k
  const bool isBimEnabled = (m_pcEncCfg->m_blockImportanceMapping && !bestCS->picture->m_picShared->m_ctuBimQpOffset.empty());
727
728
139k
  m_modeCtrl.initBlk( tempCS->area, slice.pic->poc );
729
139k
  m_CABACEstimator->determineNeighborCus( *tempCS, partitioner.currArea(), partitioner.chType, partitioner.treeType );
730
731
139k
  if ((m_pcEncCfg->m_usePerceptQPA || isBimEnabled) && pps.useDQP && isLuma (partitioner.chType) && partitioner.currQgEnable())
732
7.75k
  {
733
7.75k
    const PreCalcValues &pcv = *pps.pcv;
734
7.75k
    Picture* const pic = bestCS->picture;
735
7.75k
    const uint32_t ctuRsAddr = getCtuAddr (partitioner.currQgPos, pcv);
736
737
7.75k
    if (partitioner.currSubdiv == 0) // CTU-level QP adaptation
738
4.05k
    {
739
4.05k
      if (m_pcEncCfg->m_usePerceptQPA)
740
4.05k
      {
741
4.05k
        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
4.05k
        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
4.05k
        else
774
4.05k
        {
775
4.05k
          tempCS->currQP[partitioner.chType] = tempCS->baseQP =
776
4.05k
          bestCS->currQP[partitioner.chType] = bestCS->baseQP = pic->ctuAdaptedQP[ctuRsAddr];
777
4.05k
        }
778
779
4.05k
        setUpLambda (slice, pic->ctuQpaLambda[ctuRsAddr], pic->ctuAdaptedQP[ctuRsAddr], false, true);
780
4.05k
      }
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
4.05k
    }
801
3.70k
    else if (m_pcEncCfg->m_usePerceptQPA && slice.isIntra()) // currSubdiv 2 - use sub-CTU QPA
802
3.70k
    {
803
3.70k
      CHECK ((partitioner.currArea().lwidth() >= pcv.maxCUSize) || (partitioner.currArea().lheight() >= pcv.maxCUSize), "sub-CTU delta-QP error");
804
3.70k
      tempCS->currQP[partitioner.chType] = tempCS->baseQP = BitAllocation::applyQPAdaptationSubCtu (&slice, m_pcEncCfg, lumaArea, m_pcRateCtrl->getMinNoiseLevels());
805
806
3.70k
      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.70k
      updateLambda (slice, pic->ctuQpaLambda[ctuRsAddr], pic->ctuAdaptedQP[ctuRsAddr], tempCS->baseQP, true);
812
3.70k
    }
813
7.75k
  }
814
815
139k
  if (partitioner.currQtDepth == 0)
816
8.10k
  {
817
8.10k
    m_MergeSimpleFlag = 0;
818
8.10k
  }
819
139k
  m_modeCtrl.initCULevel( partitioner, *tempCS, m_MergeSimpleFlag );
820
139k
  m_sbtCostSave[0] = m_sbtCostSave[1] = MAX_DOUBLE;
821
822
139k
  m_CurrCtx->start = m_CABACEstimator->getCtx();
823
824
139k
  m_cuChromaQpOffsetIdxPlus1 = 0;
825
826
139k
  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
139k
  DTRACE_UPDATE( g_trace_ctx, std::make_pair( "cux", uiLPelX ) );
836
139k
  DTRACE_UPDATE( g_trace_ctx, std::make_pair( "cuy", uiTPelY ) );
837
139k
  DTRACE_UPDATE( g_trace_ctx, std::make_pair( "cuw", tempCS->area.lwidth() ) );
838
139k
  DTRACE_UPDATE( g_trace_ctx, std::make_pair( "cuh", tempCS->area.lheight() ) );
839
139k
  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
139k
  if( tempCS->slice->checkLDC )
842
139k
  {
843
139k
    m_bestBcwCost[0] = m_bestBcwCost[1] = std::numeric_limits<double>::max();
844
139k
    m_bestBcwIdx[0] = m_bestBcwIdx[1] = -1;
845
139k
  }
846
847
139k
  m_cInterSearch.resetSavedAffineMotion();
848
139k
  {
849
139k
    const ComprCUCtx &cuECtx      = *m_modeCtrl.comprCUCtx;
850
139k
    const CodingStructure& cs     = *tempCS;
851
139k
    const PartSplit implicitSplit = partitioner.getImplicitSplit( cs );
852
139k
    const bool isBoundary         = implicitSplit != CU_DONT_SPLIT;
853
139k
    const bool lossless           = false;
854
139k
    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
139k
    if( ! isBoundary )
864
88.1k
    {
865
88.1k
      if (pps.useDQP && partitioner.isSepTree (*tempCS) && isChroma (partitioner.chType))
866
60.9k
      {
867
60.9k
        const ChromaFormat chromaFm = tempCS->area.chromaFormat;
868
60.9k
        const Position chromaCentral (tempCS->area.Cb().chromaPos().offset (tempCS->area.Cb().chromaSize().width >> 1, tempCS->area.Cb().chromaSize().height >> 1));
869
60.9k
        const Position lumaRefPos (chromaCentral.x << getChannelTypeScaleX (CH_C, chromaFm), chromaCentral.y << getChannelTypeScaleY (CH_C, chromaFm));
870
60.9k
        const CodingUnit* colLumaCu = bestCS->lumaCS->getCU (lumaRefPos, CH_L, TREE_D);
871
        // update qp
872
60.9k
        qp = colLumaCu->qp;
873
60.9k
      }
874
875
88.1k
      m_cIntraSearch.reset();
876
877
88.1k
      bool isReuseCU = m_modeCtrl.isReusingCuValid( cs, partitioner, qp );
878
879
88.1k
      bool checkIbc = m_pcEncCfg->m_IBCMode && bestCS->picture->useIBC && (partitioner.chType == CH_L);
880
88.1k
      if ((m_pcEncCfg->m_IBCFastMethod>3) && (cs.area.lwidth() * cs.area.lheight()) > (16 * 16))
881
0
      {
882
0
        checkIbc = false;
883
0
      }
884
88.1k
      if( isReuseCU )
885
0
      {
886
0
        xReuseCachedResult( tempCS, bestCS, partitioner );
887
0
      }
888
88.1k
      else
889
88.1k
      {
890
        // add first pass modes
891
88.1k
        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
88.1k
        if (checkIbc && !partitioner.isConsInter())
926
27.1k
        {
927
27.1k
          EncTestMode encTestModeIBCMerge = { ETM_IBC_MERGE, ETO_STANDARD, qp, lossless };
928
27.1k
          if ((m_pcEncCfg->m_IBCFastMethod < 4) && (partitioner.chType == CH_L) && m_modeCtrl.tryMode(encTestModeIBCMerge, cs, partitioner))
929
27.1k
          {
930
27.1k
            xCheckRDCostIBCModeMerge2Nx2N(tempCS, bestCS, partitioner, encTestModeIBCMerge);
931
27.1k
          }
932
933
27.1k
          EncTestMode encTestModeIBC = { ETM_IBC, ETO_STANDARD, qp, lossless };
934
27.1k
          if (m_modeCtrl.tryMode(encTestModeIBC, cs, partitioner))
935
27.1k
          {
936
27.1k
            xCheckRDCostIBCMode(tempCS, bestCS, partitioner, encTestModeIBC);
937
27.1k
          }
938
27.1k
        }
939
88.1k
        if( m_EDO && bestCS->cost != MAX_DOUBLE )
940
24.3k
        {
941
24.3k
          xCalDebCost(*bestCS, partitioner);
942
24.3k
        }
943
944
        // add intra modes
945
88.1k
        EncTestMode encTestMode( {ETM_INTRA, ETO_STANDARD, qp, lossless} );
946
88.1k
        if( !partitioner.isConsInter() && m_modeCtrl.tryMode( encTestMode, cs, partitioner ) )
947
88.1k
        {
948
88.1k
          xCheckRDCostIntra( tempCS, bestCS, partitioner, encTestMode );
949
88.1k
        }
950
88.1k
      } // reusing cu
951
952
88.1k
      m_modeCtrl.beforeSplit( partitioner );
953
954
88.1k
      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
88.1k
      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
88.1k
    } //boundary
973
974
139k
    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
139k
    EncTestMode lastTestMode;
981
982
139k
    if( cuECtx.qtBeforeBt )
983
22.2k
    {
984
22.2k
      EncTestMode encTestMode( { ETM_SPLIT_QT, ETO_STANDARD, qp, false } );
985
22.2k
      if( m_modeCtrl.trySplit( encTestMode, cs, partitioner, lastTestMode ) )
986
14.4k
      {
987
14.4k
        lastTestMode = encTestMode;
988
14.4k
        xCheckModeSplit( tempCS, bestCS, partitioner, encTestMode );
989
14.4k
      }
990
22.2k
    }
991
992
139k
    if( partitioner.canSplit( CU_HORZ_SPLIT, cs ) )
993
74.2k
    {
994
      // add split modes
995
74.2k
      EncTestMode encTestMode( { ETM_SPLIT_BT_H, ETO_STANDARD, qp, false } );
996
74.2k
      if( m_modeCtrl.trySplit( encTestMode, cs, partitioner, lastTestMode ) )
997
74.2k
      {
998
74.2k
        lastTestMode = encTestMode;
999
74.2k
        xCheckModeSplit( tempCS, bestCS, partitioner, encTestMode );
1000
74.2k
      }
1001
74.2k
    }
1002
1003
139k
    if( partitioner.canSplit( CU_VERT_SPLIT, cs ) )
1004
70.2k
    {
1005
      // add split modes
1006
70.2k
      EncTestMode encTestMode( { ETM_SPLIT_BT_V, ETO_STANDARD, qp, false } );
1007
70.2k
      if( m_modeCtrl.trySplit( encTestMode, cs, partitioner, lastTestMode ) )
1008
70.2k
      {
1009
70.2k
        lastTestMode = encTestMode;
1010
70.2k
        xCheckModeSplit( tempCS, bestCS, partitioner, encTestMode );
1011
70.2k
      }
1012
70.2k
    }
1013
1014
139k
    if( partitioner.canSplit( CU_TRIH_SPLIT, cs ) )
1015
30.9k
    {
1016
      // add split modes
1017
30.9k
      EncTestMode encTestMode( { ETM_SPLIT_TT_H, ETO_STANDARD, qp, false } );
1018
30.9k
      if( m_modeCtrl.trySplit( encTestMode, cs, partitioner, lastTestMode ) )
1019
1.62k
      {
1020
1.62k
        lastTestMode = encTestMode;
1021
1.62k
        xCheckModeSplit( tempCS, bestCS, partitioner, encTestMode );
1022
1.62k
      }
1023
30.9k
    }
1024
1025
139k
    if( partitioner.canSplit( CU_TRIV_SPLIT, cs ) )
1026
24.4k
    {
1027
      // add split modes
1028
24.4k
      EncTestMode encTestMode( { ETM_SPLIT_TT_V, ETO_STANDARD, qp, false } );
1029
24.4k
      if( m_modeCtrl.trySplit( encTestMode, cs, partitioner, lastTestMode ) )
1030
1.20k
      {
1031
1.20k
        lastTestMode = encTestMode;
1032
1.20k
        xCheckModeSplit( tempCS, bestCS, partitioner, encTestMode );
1033
1.20k
      }
1034
24.4k
    }
1035
1036
139k
    if( !cuECtx.qtBeforeBt )
1037
117k
    {
1038
117k
      EncTestMode encTestMode( { ETM_SPLIT_QT, ETO_STANDARD, qp, false } );
1039
117k
      if( m_modeCtrl.trySplit( encTestMode, cs, partitioner, lastTestMode ) )
1040
29.2k
      {
1041
29.2k
        lastTestMode = encTestMode;
1042
29.2k
        xCheckModeSplit( tempCS, bestCS, partitioner, encTestMode );
1043
29.2k
      }
1044
117k
    }
1045
139k
  }
1046
1047
139k
  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
139k
  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
139k
  int numCUInThisNode = (int)bestCS->cus.size();
1061
139k
  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
139k
  else
1067
139k
  {
1068
139k
    bestCS->prevQP[partitioner.chType] = bestCS->cus.back()->qp;
1069
139k
  }
1070
139k
  if( ( !slice.isIntra() || slice.sps->IBC )
1071
139k
    && partitioner.chType == CH_L
1072
55.7k
    && 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
139k
  m_modeCtrl.finishCULevel( partitioner );
1086
139k
  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
139k
  CHECK( bestCS->cus.empty()                                   , "No possible encoding found" );
1094
139k
  CHECK( bestCS->cus[0]->predMode == NUMBER_OF_PREDICTION_MODES, "No possible encoding found" );
1095
139k
  CHECK( bestCS->cost             == MAX_DOUBLE                , "No possible encoding found" );
1096
139k
}
1097
1098
1099
void EncCu::xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode )
1100
191k
{
1101
191k
  const ModeType modeTypeParent  = partitioner.modeType;
1102
191k
  const TreeType treeTypeParent  = partitioner.treeType;
1103
191k
  const ChannelType chTypeParent = partitioner.chType;
1104
1105
191k
  int signalModeConsVal = CS::signalModeCons( *tempCS, partitioner.currArea(), getPartSplit(encTestMode), modeTypeParent);
1106
191k
  int numRoundRdo = signalModeConsVal == LDT_MODE_TYPE_SIGNAL ? 2 : 1;
1107
191k
  bool skipInterPass = false;
1108
382k
  for( int i = 0; i < numRoundRdo; i++ )
1109
191k
  {
1110
    //change cons modes
1111
191k
    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
191k
    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
191k
    else if( signalModeConsVal == LDT_MODE_TYPE_INHERIT )
1122
191k
    {
1123
191k
      CHECK( numRoundRdo != 1, "numRoundRdo shall be 1 - [LDT_MODE_TYPE_INHERIT]" );
1124
191k
      partitioner.modeType = modeTypeParent;
1125
191k
    }
1126
1127
    //for lite intra encoding fast algorithm, set the status to save inter coding info
1128
191k
    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
191k
    else if( modeTypeParent == MODE_TYPE_ALL && partitioner.modeType != MODE_TYPE_INTER )
1134
191k
    {
1135
191k
      m_cIntraSearch.setSaveCuCostInSCIPU( false );
1136
191k
      if( partitioner.modeType == MODE_TYPE_ALL )
1137
191k
      {
1138
191k
        m_cIntraSearch.setNumCuInSCIPU( 0 );
1139
191k
      }
1140
191k
    }
1141
1142
191k
    xCheckModeSplitInternal( tempCS, bestCS, partitioner, encTestMode, modeTypeParent, skipInterPass );
1143
    //recover cons modes
1144
191k
    partitioner.modeType = modeTypeParent;
1145
191k
    partitioner.treeType = treeTypeParent;
1146
191k
    partitioner.chType = chTypeParent;
1147
191k
    if( modeTypeParent == MODE_TYPE_ALL )
1148
191k
    {
1149
191k
      m_cIntraSearch.setSaveCuCostInSCIPU( false );
1150
191k
      if( numRoundRdo == 2 && partitioner.modeType == MODE_TYPE_INTRA )
1151
0
      {
1152
0
        m_cIntraSearch.initCuAreaCostInSCIPU();
1153
0
      }
1154
191k
    }
1155
191k
    if( skipInterPass )
1156
0
    {
1157
0
      break;
1158
0
    }
1159
191k
  }
1160
191k
}
1161
1162
void EncCu::xCheckModeSplitInternal(CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode, const ModeType modeTypeParent, bool& skipInterPass )
1163
191k
{
1164
191k
  const int qp                     = encTestMode.qp;
1165
191k
  const int oldPrevQp              = tempCS->prevQP[partitioner.chType];
1166
191k
  const auto oldMotionLut          = tempCS->motionLut;
1167
191k
  const ReshapeData& reshapeData   = tempCS->picture->reshapeData;
1168
                                   
1169
191k
  const PartSplit split            = getPartSplit( encTestMode );
1170
191k
  const ModeType  modeTypeChild    = partitioner.modeType;
1171
1172
191k
  CHECK( !( split == CU_QUAD_SPLIT || split == CU_HORZ_SPLIT || split == CU_VERT_SPLIT
1173
191k
         || split == CU_TRIH_SPLIT || split == CU_TRIV_SPLIT ), "invalid split type" );
1174
1175
191k
  tempCS->initStructData( qp );
1176
1177
191k
  m_CABACEstimator->getCtx()       = m_CurrCtx->start;
1178
1179
191k
  const uint16_t split_ctx_size    = Ctx::SplitFlag.size() + Ctx::SplitQtFlag.size() + Ctx::SplitHvFlag.size() + Ctx::Split12Flag.size() + Ctx::ModeConsFlag.size();
1180
191k
  const TempCtx  ctxSplitFlags     ( m_CtxCache, SubCtx( CtxSet( Ctx::SplitFlag(), split_ctx_size ), m_CABACEstimator->getCtx() ) );
1181
1182
191k
  m_CABACEstimator->determineNeighborCus( *tempCS, partitioner.currArea(), partitioner.chType, partitioner.treeType );
1183
191k
  m_CABACEstimator->resetBits           ();
1184
191k
  m_CABACEstimator->split_cu_mode       ( split, *tempCS, partitioner );
1185
191k
  partitioner     . modeType            = modeTypeParent;
1186
191k
  m_CABACEstimator->mode_constraint     ( split, *tempCS, partitioner, modeTypeChild );
1187
191k
  partitioner     . modeType            = modeTypeChild;
1188
1189
191k
  const int64_t splitBits   = m_CABACEstimator->getEstFracBits();
1190
1191
191k
  const bool chromaNotSplit = modeTypeParent == MODE_TYPE_ALL && modeTypeChild == MODE_TYPE_INTRA;
1192
191k
  const bool isChromaTooBig = isChromaEnabled( tempCS->pps->pcv->chrFormat ) && tempCS->area.Y().maxDim() > tempCS->sps->getMaxTbSize();
1193
191k
  bool       skipSplitTest  = chromaNotSplit && isChromaTooBig;
1194
1195
191k
  if( !skipSplitTest )
1196
191k
  {
1197
191k
    double         a = -1, b = -1;
1198
191k
    const unsigned w       = partitioner.currArea().lwidth();
1199
191k
    const unsigned h       = partitioner.currArea().lheight();
1200
191k
    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
191k
    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
191k
    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
191k
    else
1228
191k
    {
1229
191k
      int numChild = 3;
1230
191k
      if( split == CU_VERT_SPLIT || split == CU_HORZ_SPLIT ) numChild--;
1231
46.5k
      else if( split == CU_QUAD_SPLIT ) numChild++;
1232
1233
191k
      int64_t approxBits = m_pcEncCfg->m_qtbttSpeedUp > 0 ? numChild << SCALE_BITS : 0;
1234
1235
191k
      const double factor     = ( tempCS->currQP[partitioner.chType] > 30                              ? 1.1  : 1.075 ) +
1236
191k
                                (   m_pcEncCfg->m_qtbttSpeedUp > 0                                     ? 0.01 : 0.0   ) +
1237
191k
                                ( ( m_pcEncCfg->m_qtbttSpeedUp > 0 && isChroma( partitioner.chType ) ) ? 0.2  : 0.0   );
1238
       
1239
191k
      const double baseCost   = bestCS->cost + bestCS->costDbOffset;
1240
191k
      const double predCost   = baseCost / factor + splitBits + approxBits;
1241
191k
      skipSplitTest           = predCost >= baseCost;
1242
191k
    }
1243
191k
  }
1244
1245
191k
  if( skipSplitTest )
1246
119k
  {
1247
119k
    m_CABACEstimator->getCtx() = SubCtx( CtxSet( Ctx::SplitFlag(), split_ctx_size ), ctxSplitFlags );
1248
119k
    xCheckBestMode( tempCS, bestCS, partitioner, encTestMode );
1249
119k
    return;
1250
119k
  }
1251
1252
71.7k
  if( partitioner.treeType == TREE_D )
1253
71.7k
  {
1254
71.7k
    if( chromaNotSplit )
1255
0
    {
1256
0
      CHECK( partitioner.chType != CH_L, "chType must be luma" );
1257
0
      partitioner.treeType = TREE_L;
1258
0
    }
1259
71.7k
    else
1260
71.7k
    {
1261
71.7k
      partitioner.treeType = TREE_D;
1262
71.7k
    }
1263
71.7k
  }
1264
1265
71.7k
  partitioner.splitCurrArea( split, *tempCS );
1266
71.7k
  bool qgEnableChildren = partitioner.currQgEnable(); // QG possible at children level
1267
1268
71.7k
  m_CurrCtx++;
1269
1270
71.7k
  AffineMVInfo tmpMVInfo;
1271
71.7k
  bool isAffMVInfoSaved = m_cInterSearch.m_AffineProfList->savePrevAffMVInfo( 0, tmpMVInfo );
1272
1273
71.7k
  BlkUniMvInfo tmpUniMvInfo;
1274
71.7k
  bool         isUniMvInfoSaved = false;
1275
71.7k
  if( !tempCS->slice->isIntra() )
1276
0
  {
1277
0
    m_cInterSearch.m_BlkUniMvInfoBuffer->savePrevUniMvInfo( tempCS->area.Y(), tmpUniMvInfo, isUniMvInfoSaved );
1278
0
  }
1279
1280
71.7k
  DeriveCtx deriveCtx = m_CABACEstimator->getDeriveCtx();
1281
1282
71.7k
  do
1283
184k
  {
1284
184k
    const auto &subCUArea  = partitioner.currArea();
1285
1286
184k
    if( tempCS->picture->Y().contains( subCUArea.lumaPos() ) )
1287
131k
    {
1288
131k
      PelStorage* orgBuffer =  &m_pOrgBuffer[partitioner.currDepth];
1289
131k
      PelStorage* rspBuffer =  &m_pRspBuffer[partitioner.currDepth];
1290
131k
      CodingStructure *tempSubCS = m_pTempCS[partitioner.currDepth];
1291
131k
      CodingStructure *bestSubCS = m_pBestCS[partitioner.currDepth];
1292
1293
131k
      tempCS->initSubStructure( *tempSubCS, partitioner.chType, subCUArea, false, orgBuffer, rspBuffer );
1294
131k
      tempCS->initSubStructure( *bestSubCS, partitioner.chType, subCUArea, false, orgBuffer, rspBuffer );
1295
1296
      // copy org buffer, need to be done after initSubStructure because of reshaping!
1297
131k
      orgBuffer->copyFrom( tempCS->getOrgBuf( subCUArea ) );
1298
131k
      if( tempCS->slice->lmcsEnabled && reshapeData.getCTUFlag() )
1299
0
      {
1300
0
        rspBuffer->Y().copyFrom( tempCS->getRspOrgBuf( subCUArea.Y() ) );
1301
0
      }
1302
1303
131k
      tempSubCS->bestParent = bestSubCS->bestParent = bestCS;
1304
1305
131k
      xCompressCU(tempSubCS, bestSubCS, partitioner );
1306
1307
131k
      tempSubCS->bestParent = bestSubCS->bestParent = nullptr;
1308
1309
131k
      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
131k
      tempCS->useSubStructure( *bestSubCS, partitioner.chType, TREE_D, CS::getArea( *tempCS, subCUArea, partitioner.chType, partitioner.treeType ), partitioner.hasNextPart() || chromaNotSplit );
1327
1328
131k
      if( partitioner.currQgEnable() )
1329
7.40k
      {
1330
7.40k
        tempCS->prevQP[partitioner.chType] = bestSubCS->prevQP[partitioner.chType];
1331
7.40k
      }
1332
131k
      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
131k
      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
131k
      tempSubCS->releaseIntermediateData();
1348
131k
      bestSubCS->releaseIntermediateData();
1349
131k
      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
131k
    }
1368
184k
  } while( partitioner.nextPart( *tempCS ) );
1369
1370
71.7k
  partitioner.exitCurrSplit();
1371
1372
71.7k
  m_CurrCtx--;
1373
1374
71.7k
  m_CABACEstimator->getDeriveCtx() = deriveCtx;
1375
1376
71.7k
  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
71.7k
  tempCS->fracBits += splitBits; // split bits
1469
71.7k
  tempCS->cost      = m_cRdCost.calcRdCost( tempCS->fracBits, tempCS->dist );
1470
71.7k
  partitioner.modeType = modeTypeParent;
1471
1472
  // Check Delta QP bits for splitted structure
1473
71.7k
  if( !qgEnableChildren ) // check at deepest QG level only
1474
69.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
71.7k
  if( bestCS->cost == MAX_DOUBLE )
1482
51.1k
  {
1483
51.1k
    bestCS->costDbOffset = 0;
1484
51.1k
  }
1485
1486
71.7k
  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
71.7k
  xCheckBestMode( tempCS, bestCS, partitioner, encTestMode, m_EDO );
1501
1502
71.7k
  if( isAffMVInfoSaved )
1503
0
  {
1504
0
    m_cInterSearch.m_AffineProfList->addAffMVInfo(tmpMVInfo);
1505
0
  }
1506
1507
71.7k
  if( !tempCS->slice->isIntra() && isUniMvInfoSaved )
1508
0
  {
1509
0
    m_cInterSearch.m_BlkUniMvInfoBuffer->addUniMvInfo(tmpUniMvInfo);
1510
0
  }
1511
1512
71.7k
  tempCS->motionLut = oldMotionLut;
1513
71.7k
  tempCS->releaseIntermediateData();
1514
71.7k
  tempCS->prevQP[partitioner.chType] = oldPrevQp;
1515
71.7k
}
1516
1517
1518
void EncCu::xCheckRDCostIntra( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode )
1519
88.1k
{
1520
88.1k
  PROFILER_SCOPE_AND_STAGE_EXT( 1, _TPROF, P_INTRA, tempCS, partitioner.chType );
1521
1522
88.1k
  tempCS->initStructData( encTestMode.qp, false ); // clear motion buffer
1523
1524
88.1k
  CodingUnit &cu      = tempCS->addCU( CS::getArea( *tempCS, tempCS->area, partitioner.chType, partitioner.treeType ), partitioner.chType );
1525
1526
88.1k
  partitioner.setCUData( cu );
1527
88.1k
  cu.slice            = tempCS->slice;
1528
88.1k
  cu.tileIdx          = m_tileIdx;
1529
88.1k
  cu.skip             = false;
1530
88.1k
  cu.mmvdSkip         = false;
1531
88.1k
  cu.predMode         = MODE_INTRA;
1532
88.1k
  cu.chromaQpAdj      = m_cuChromaQpOffsetIdxPlus1;
1533
88.1k
  cu.qp               = encTestMode.qp;
1534
88.1k
  cu.ispMode          = NOT_INTRA_SUBPARTITIONS;
1535
88.1k
  cu.initPuData();
1536
1537
88.1k
  m_cIntraSearch.m_ispTestedModes[0].init(0, 0, 1);
1538
88.1k
  if (m_pcEncCfg->m_FastIntraTools)
1539
88.1k
  {
1540
88.1k
    m_modeCtrl.comprCUCtx->intraWasTested = false;
1541
88.1k
    m_cIntraSearch.m_ispTestedModes[0].relatedCuIsValid = m_modeCtrl.comprCUCtx->relatedCuIsValid;
1542
88.1k
    if (!bestCS->cus.empty())
1543
24.3k
    {
1544
24.3k
      if ((bestCS->cus[0]->mergeFlag || bestCS->cus[0]->imv || bestCS->cus[0]->affine) && (!bestCS->cus[0]->ciip))
1545
24.3k
      {
1546
24.3k
        m_cIntraSearch.m_ispTestedModes[0].bestBefore[0] = -1;
1547
24.3k
      }
1548
24.3k
    }
1549
88.1k
    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
88.1k
  }
1567
1568
88.1k
  tempCS->interHad    = m_modeCtrl.comprCUCtx->interHad;
1569
88.1k
  double maxCostAllowedForChroma = MAX_DOUBLE;
1570
88.1k
  if( isLuma( partitioner.chType ) )
1571
27.1k
  {
1572
27.1k
    if (!tempCS->slice->isIntra() && bestCS)
1573
0
    {
1574
0
      m_cIntraSearch.estIntraPredLumaQT(cu, partitioner, bestCS->cost);
1575
0
    }
1576
27.1k
    else
1577
27.1k
    {
1578
27.1k
      m_cIntraSearch.estIntraPredLumaQT(cu, partitioner);
1579
27.1k
    }
1580
27.1k
    if (m_pcEncCfg->m_FastIntraTools)
1581
27.1k
    {
1582
27.1k
      if (m_cIntraSearch.m_ispTestedModes[0].intraWasTested)
1583
27.1k
      {
1584
27.1k
        m_modeCtrl.comprCUCtx->intraWasTested = m_cIntraSearch.m_ispTestedModes[0].intraWasTested;
1585
27.1k
      }
1586
27.1k
    }
1587
1588
27.1k
    if( !partitioner.isSepTree( *tempCS ) )
1589
0
    {
1590
0
      tempCS->lumaCost = m_cRdCost.calcRdCost( tempCS->fracBits, tempCS->dist );
1591
0
    }
1592
27.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
27.1k
  }
1599
1600
88.1k
  if( tempCS->area.chromaFormat != CHROMA_400 && ( partitioner.chType == CH_C || !CU::isSepTree(cu) ) )
1601
60.9k
  {
1602
60.9k
    bool useIntraSubPartitions = cu.ispMode != NOT_INTRA_SUBPARTITIONS;
1603
60.9k
    Partitioner subTuPartitioner = partitioner;
1604
60.9k
    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
60.9k
    m_cIntraSearch.estIntraPredChromaQT(
1609
60.9k
      cu, (!useIntraSubPartitions || (CU::isSepTree(cu) && !isLuma(CH_C))) ? partitioner : subTuPartitioner,
1610
60.9k
      maxCostAllowedForChroma);
1611
60.9k
    if ((m_pcEncCfg->m_ISP >= 3) && useIntraSubPartitions && !cu.ispMode)
1612
0
    {
1613
0
      return;
1614
0
    }
1615
60.9k
  }
1616
1617
88.1k
  cu.rootCbf = false;
1618
1619
352k
  for (uint32_t t = 0; t < getNumberValidTBlocks(*cu.cs->pcv); t++)
1620
264k
  {
1621
264k
    cu.rootCbf |= cu.firstTU->cbf[t] != 0;
1622
264k
  }
1623
1624
  // Get total bits for current mode: encode CU
1625
88.1k
  m_CABACEstimator->resetBits();
1626
1627
88.1k
  if ((!cu.cs->slice->isIntra() || cu.cs->slice->sps->IBC) && cu.Y().valid())
1628
27.1k
  {
1629
27.1k
    m_CABACEstimator->cu_skip_flag(cu);
1630
27.1k
  }
1631
88.1k
  m_CABACEstimator->pred_mode(cu);
1632
88.1k
  m_CABACEstimator->cu_pred_data(cu);
1633
1634
  // Encode Coefficients
1635
88.1k
  CUCtx cuCtx;
1636
88.1k
  cuCtx.isDQPCoded = true;
1637
88.1k
  cuCtx.isChromaQpAdjCoded = true;
1638
88.1k
  m_CABACEstimator->cu_residual(cu, partitioner, cuCtx);
1639
1640
88.1k
  tempCS->fracBits = m_CABACEstimator->getEstFracBits();
1641
88.1k
  tempCS->cost = m_cRdCost.calcRdCost(tempCS->fracBits, tempCS->dist);
1642
1643
88.1k
  xEncodeDontSplit(*tempCS, partitioner);
1644
1645
88.1k
  xCheckDQP(*tempCS, partitioner);
1646
1647
88.1k
  if( m_EDO )
1648
88.1k
  {
1649
88.1k
    xCalDebCost(*tempCS, partitioner);
1650
88.1k
  }
1651
1652
88.1k
  DTRACE_MODE_COST(*tempCS, m_cRdCost.getLambda(true));
1653
88.1k
  xCheckBestMode(tempCS, bestCS, partitioner, encTestMode, m_EDO);
1654
1655
88.1k
  STAT_COUNT_CU_MODES( partitioner.chType == CH_L, g_cuCounters1D[CU_MODES_TESTED][0][!tempCS->slice->isIntra() + tempCS->slice->depth] );
1656
88.1k
  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
88.1k
}
1658
1659
void EncCu::xCheckDQP( CodingStructure& cs, Partitioner& partitioner, bool bKeepCtx )
1660
181k
{
1661
181k
  if( !cs.pps->useDQP )
1662
0
  {
1663
0
    return;
1664
0
  }
1665
1666
181k
  if (partitioner.isSepTree(cs) && isChroma(partitioner.chType))
1667
102k
  {
1668
102k
    return;
1669
102k
  }
1670
1671
79.2k
  if( !partitioner.currQgEnable() ) // do not consider split or leaf/not leaf QG condition (checked by caller)
1672
71.3k
  {
1673
71.3k
    return;
1674
71.3k
  }
1675
1676
7.83k
  CodingUnit* cuFirst = cs.getCU( partitioner.chType, partitioner.treeType );
1677
1678
7.83k
  CHECK( bKeepCtx && cs.cus.size() <= 1 && partitioner.getImplicitSplit( cs ) == CU_DONT_SPLIT, "bKeepCtx should only be set in split case" );
1679
7.83k
  CHECK( !bKeepCtx && cs.cus.size() > 1, "bKeepCtx should never be set for non-split case" );
1680
7.83k
  CHECK( !cuFirst, "No CU available" );
1681
1682
7.83k
  bool hasResidual = false;
1683
7.83k
  for( const auto &cu : cs.cus )
1684
21.9k
  {
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
21.9k
    if( cu->rootCbf && !isChroma( cu->chType ))
1687
1.30k
    {
1688
1.30k
      hasResidual = true;
1689
1.30k
      break;
1690
1.30k
    }
1691
21.9k
  }
1692
1693
7.83k
  int predQP = CU::predictQP( *cuFirst, cs.prevQP[partitioner.chType] );
1694
1695
7.83k
  if( hasResidual )
1696
1.30k
  {
1697
1.30k
    TempCtx ctxTemp( m_CtxCache );
1698
1.30k
    if( !bKeepCtx ) ctxTemp = SubCtx( Ctx::DeltaQP, m_CABACEstimator->getCtx() );
1699
1700
1.30k
    m_CABACEstimator->resetBits();
1701
1.30k
    m_CABACEstimator->cu_qp_delta( *cuFirst, predQP, cuFirst->qp );
1702
1703
1.30k
    cs.fracBits += m_CABACEstimator->getEstFracBits(); // dQP bits
1704
1.30k
    cs.cost      = m_cRdCost.calcRdCost(cs.fracBits, cs.dist);
1705
1706
1707
1.30k
    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.30k
    for( const auto &cu : cs.cus )
1711
1.31k
    {
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.31k
      if( cu->rootCbf && !isChroma( cu->chType ))
1714
1.30k
      {
1715
1.30k
        break;
1716
1.30k
      }
1717
8
      cu->qp = predQP;
1718
8
    }
1719
1.30k
  }
1720
6.52k
  else
1721
6.52k
  {
1722
    // No residuals: reset CU QP to predicted value
1723
6.52k
    for( const auto &cu : cs.cus )
1724
20.6k
    {
1725
20.6k
      cu->qp = predQP;
1726
20.6k
    }
1727
6.52k
  }
1728
7.83k
}
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
27.1k
{
2787
27.1k
  assert(partitioner.chType != CH_C); // chroma IBC is derived
2788
27.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
27.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
27.1k
  const SPS& sps = *tempCS->sps;
2802
2803
27.1k
  tempCS->initStructData(encTestMode.qp);
2804
27.1k
  MergeCtx mergeCtx;
2805
2806
27.1k
  {
2807
    // first get merge candidates
2808
27.1k
    CodingUnit cu(tempCS->area);
2809
27.1k
    cu.cs = tempCS;
2810
27.1k
    cu.predMode = MODE_IBC;
2811
27.1k
    cu.slice = tempCS->slice;
2812
27.1k
    cu.tileIdx = m_tileIdx;
2813
27.1k
    cu.initPuData();
2814
27.1k
    cu.cs = tempCS;
2815
27.1k
    cu.mmvdSkip = false;
2816
27.1k
    cu.mmvdMergeFlag = false;
2817
27.1k
    cu.geo = false;
2818
27.1k
    CU::getIBCMergeCandidates(cu, mergeCtx);
2819
27.1k
  }
2820
27.1k
  int candHasNoResidual[MRG_MAX_NUM_CANDS];
2821
190k
  for (unsigned int ui = 0; ui < mergeCtx.numValidMergeCand; ui++)
2822
162k
  {
2823
162k
    candHasNoResidual[ui] = 0;
2824
162k
  }
2825
2826
27.1k
  bool                                        bestIsSkip = false;
2827
27.1k
  unsigned                                    numMrgSATDCand = mergeCtx.numValidMergeCand;
2828
27.1k
  static_vector<unsigned, MRG_MAX_NUM_CANDS>  RdModeList(MRG_MAX_NUM_CANDS);
2829
190k
  for (unsigned i = 0; i < MRG_MAX_NUM_CANDS; i++)
2830
162k
  {
2831
162k
    RdModeList[i] = i;
2832
162k
  }
2833
2834
  //{
2835
27.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
27.1k
  {
2838
27.1k
    const double sqrtLambdaForFirstPass = m_cRdCost.getMotionLambda();
2839
2840
27.1k
    CodingUnit& cu = tempCS->addCU(CS::getArea(*tempCS, tempCS->area, partitioner.chType,partitioner.treeType), partitioner.chType);
2841
2842
27.1k
    partitioner.setCUData(cu);
2843
27.1k
    cu.slice = tempCS->slice;
2844
27.1k
    cu.tileIdx = m_tileIdx;
2845
27.1k
    cu.skip = false;
2846
27.1k
    cu.predMode = MODE_IBC;
2847
27.1k
    cu.chromaQpAdj = m_cuChromaQpOffsetIdxPlus1;
2848
27.1k
    cu.qp = encTestMode.qp;
2849
27.1k
    cu.mmvdSkip = false;
2850
27.1k
    cu.geo = false;
2851
27.1k
    DistParam distParam;
2852
27.1k
    cu.initPuData();
2853
27.1k
    cu.mmvdMergeFlag = false;
2854
27.1k
    Picture* refPic = cu.slice->pic;
2855
27.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
27.1k
    const CompArea& compArea = localUnitArea.block(COMP_Y);
2857
27.1k
    const CPelBuf refBuf = refPic->getRecoBuf(compArea);
2858
27.1k
    const Pel* piRefSrch = refBuf.buf;
2859
27.1k
    const ReshapeData& reshapeData = cu.cs->picture->reshapeData;
2860
27.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
27.1k
    else
2867
27.1k
    {
2868
27.1k
      distParam = m_cRdCost.setDistParam(tempCS->getOrgBuf(COMP_Y), refBuf, sps.bitDepths[CH_L], DF_HAD);
2869
27.1k
    }
2870
27.1k
    int refStride = refBuf.stride;
2871
2872
27.1k
    int numValidBv = mergeCtx.numValidMergeCand;
2873
190k
    for (unsigned int mergeCand = 0; mergeCand < mergeCtx.numValidMergeCand; mergeCand++)
2874
162k
    {
2875
162k
      mergeCtx.setMergeInfo(cu, mergeCand); // set bv info in merge mode
2876
162k
      const int cuPelX = cu.Y().x;
2877
162k
      const int cuPelY = cu.Y().y;
2878
162k
      int roiWidth     = cu.lwidth();
2879
162k
      int roiHeight    = cu.lheight();
2880
162k
      const int picWidth  = cu.cs->slice->pps->picWidthInLumaSamples;
2881
162k
      const int picHeight = cu.cs->slice->pps->picHeightInLumaSamples;
2882
162k
      const unsigned int lcuWidth = cu.cs->slice->sps->CTUSize;
2883
2884
162k
      Mv bv = cu.mv[0][0];
2885
162k
      bv.changePrecision( MV_PRECISION_INTERNAL, MV_PRECISION_INT);
2886
162k
      int xPred = bv.hor;
2887
162k
      int yPred = bv.ver;
2888
      
2889
162k
      if( !m_cInterSearch.searchBvIBC( cu, cuPelX, cuPelY, roiWidth, roiHeight, picWidth, picHeight, xPred, yPred, lcuWidth ) ) // not valid bv derived
2890
162k
      {
2891
162k
        numValidBv--;
2892
162k
        continue;
2893
162k
      }
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
27.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
27.1k
    else
2922
27.1k
    {
2923
27.1k
      tempCS->dist = 0;
2924
27.1k
      tempCS->fracBits = 0;
2925
27.1k
      tempCS->cost = MAX_DOUBLE;
2926
27.1k
      tempCS->costDbOffset = 0;
2927
27.1k
      tempCS->initStructData(encTestMode.qp);
2928
27.1k
      return;
2929
27.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
27.1k
{
3003
27.1k
  if (tempCS->area.lwidth() == 128 || tempCS->area.lheight() == 128)   // disable IBC mode larger than 64x64
3004
0
  {
3005
0
    return;
3006
0
  }
3007
27.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
27.1k
  tempCS->initStructData(encTestMode.qp);
3016
3017
27.1k
  CodingUnit& cu = tempCS->addCU(CS::getArea(*tempCS, tempCS->area, partitioner.chType, partitioner.treeType), partitioner.chType);
3018
3019
27.1k
  partitioner.setCUData(cu);
3020
27.1k
  cu.slice = tempCS->slice;
3021
27.1k
  cu.tileIdx = m_tileIdx;
3022
27.1k
  cu.skip = false;
3023
27.1k
  cu.predMode = MODE_IBC;
3024
27.1k
  cu.chromaQpAdj = m_cuChromaQpOffsetIdxPlus1;
3025
27.1k
  cu.qp = encTestMode.qp;
3026
27.1k
  cu.initPuData();
3027
27.1k
  cu.imv = IMV_OFF;
3028
27.1k
  cu.sbtInfo = 0;
3029
27.1k
  cu.mmvdSkip = false;
3030
27.1k
  cu.mmvdMergeFlag = false;
3031
3032
27.1k
  cu.intraDir[0] = DC_IDX; // set intra pred for ibc block
3033
27.1k
  cu.intraDir[1] = PLANAR_IDX; // set intra pred for ibc block
3034
3035
27.1k
  cu.interDir = 1; // use list 0 for IBC mode
3036
27.1k
  cu.refIdx[REF_PIC_LIST_0] = MAX_NUM_REF; // last idx in the list
3037
27.1k
  bool bValid = m_cInterSearch.predIBCSearch(cu, partitioner);
3038
3039
27.1k
  if (bValid)
3040
24.3k
  {
3041
24.3k
    CU::spanMotionInfo(cu);
3042
24.3k
    const bool chroma = !CU::isSepTree(cu);
3043
    //  MC
3044
24.3k
    cu.mcControl = chroma ? 0 : 2;
3045
24.3k
    m_cInterSearch.motionCompensationIBC(cu, tempCS->getPredBuf());
3046
3047
24.3k
    m_cInterSearch.encodeResAndCalcRdInterCU(*tempCS, partitioner, false);
3048
24.3k
    cu.mcControl = 0;
3049
3050
24.3k
    xEncodeDontSplit(*tempCS, partitioner);
3051
24.3k
    xCheckDQP(*tempCS, partitioner);
3052
24.3k
    xCheckBestMode(tempCS, bestCS, partitioner, encTestMode);
3053
24.3k
  } // bValid
3054
2.82k
  else
3055
2.82k
  {
3056
2.82k
    tempCS->dist = 0;
3057
2.82k
    tempCS->fracBits = 0;
3058
2.82k
    tempCS->cost = MAX_DOUBLE;
3059
2.82k
    tempCS->costDbOffset = 0;
3060
2.82k
  }
3061
27.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
112k
{
3451
112k
  PROFILER_SCOPE_AND_STAGE_EXT( 1, _TPROF, P_DEBLOCK_FILTER, &cs, partitioner.chType );
3452
112k
  if ( cs.slice->deblockingFilterDisable )
3453
0
  {
3454
0
    return;
3455
0
  }
3456
3457
112k
  const ChromaFormat format = cs.area.chromaFormat;
3458
112k
  CodingUnit*            cu = cs.getCU(partitioner.chType, partitioner.treeType);
3459
112k
  const Position    lumaPos = cu->Y().valid() ? cu->Y().pos() : recalcPosition( format, cu->chType, CH_L, cu->blocks[cu->chType].pos() );
3460
112k
  bool    topEdgeAvai = lumaPos.y > 0 && ((lumaPos.y % 4) == 0);
3461
112k
  bool   leftEdgeAvai = lumaPos.x > 0 && ((lumaPos.x % 4) == 0);
3462
3463
112k
  if( ! ( topEdgeAvai || leftEdgeAvai ))
3464
23.1k
  {
3465
23.1k
    return;
3466
23.1k
  }
3467
3468
89.2k
  ComponentID compStr = ( CU::isSepTree(*cu) && !isLuma( partitioner.chType ) ) ? COMP_Cb : COMP_Y;
3469
89.2k
  ComponentID compEnd = (( CU::isSepTree(*cu) && isLuma( partitioner.chType )) || cu->chromaFormat == VVENC_CHROMA_400 ) ? COMP_Y : COMP_Cr;
3470
89.2k
  const UnitArea currCsArea = clipArea( CS::getArea( cs, cs.area, partitioner.chType, partitioner.treeType ), *cs.picture );
3471
3472
89.2k
  PelStorage&  picDbBuf = m_dbBuffer; //th we could reduce the buffer size and do some relocate
3473
3474
  //deblock neighbour pixels
3475
89.2k
  const Size     lumaSize = cu->Y().valid() ? cu->Y().size() : recalcSize( format, cu->chType, CH_L, cu->blocks[cu->chType].size() );
3476
3477
89.2k
  int verOffset = lumaPos.y > 7 ? 8 : 4;
3478
89.2k
  int horOffset = lumaPos.x > 7 ? 8 : 4;
3479
3480
89.2k
  LoopFilter::calcFilterStrengths( *cu, true );
3481
3482
89.2k
  if( m_EDO == 2 && CS::isDualITree( cs ) && isLuma( partitioner.chType ) )
3483
49.6k
  {
3484
49.6k
    m_cLoopFilter.getMaxFilterLength( *cu, verOffset, horOffset );
3485
3486
49.6k
    if( 0== (verOffset + horOffset) )
3487
0
    {
3488
0
      return;
3489
0
    }
3490
3491
49.6k
    topEdgeAvai  &= verOffset != 0;
3492
49.6k
    leftEdgeAvai &= horOffset != 0;
3493
49.6k
  }
3494
3495
89.2k
  const UnitArea  areaTop  = UnitArea( format, Area( lumaPos.x,             lumaPos.y - verOffset, lumaSize.width, verOffset       ) );
3496
89.2k
  const UnitArea  areaLeft = UnitArea( format, Area( lumaPos.x - horOffset, lumaPos.y,             horOffset,      lumaSize.height ) );
3497
3498
218k
  for ( int compIdx = compStr; compIdx <= compEnd; compIdx++ )
3499
128k
  {
3500
128k
    ComponentID compId = (ComponentID)compIdx;
3501
3502
    //Copy current CU's reco to Deblock Pic Buffer
3503
128k
    const ReshapeData& reshapeData = cs.picture->reshapeData;
3504
128k
    const CompArea&  compArea = currCsArea.block( compId );
3505
128k
    CompArea         locArea  = compArea;
3506
128k
    locArea.x -= cu->blocks[compIdx].x;
3507
128k
    locArea.y -= cu->blocks[compIdx].y;
3508
128k
    PelBuf dbReco = picDbBuf.getBuf( locArea );
3509
128k
    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
128k
    else
3523
128k
    {
3524
128k
      PelBuf reco = cs.getRecoBuf( compId );
3525
128k
      dbReco.copyFrom( reco );
3526
128k
    }
3527
    //left neighbour
3528
128k
    if ( leftEdgeAvai )
3529
90.3k
    {
3530
90.3k
      const CompArea&  compArea = areaLeft.block(compId);
3531
90.3k
      CompArea         locArea = compArea;
3532
90.3k
      locArea.x -= cu->blocks[compIdx].x;
3533
90.3k
      locArea.y -= cu->blocks[compIdx].y;
3534
90.3k
      PelBuf dbReco = picDbBuf.getBuf( locArea );
3535
90.3k
      if (cs.slice->lmcsEnabled && isLuma(compId))
3536
0
      {
3537
0
        dbReco.rspSignal( cs.picture->getRecoBuf( compArea ), reshapeData.getInvLUT() );
3538
0
      }
3539
90.3k
      else
3540
90.3k
      {
3541
90.3k
        dbReco.copyFrom( cs.picture->getRecoBuf( compArea ) );
3542
90.3k
      }
3543
90.3k
    }
3544
    //top neighbour
3545
128k
    if ( topEdgeAvai )
3546
93.6k
    {
3547
93.6k
      const CompArea&  compArea = areaTop.block( compId );
3548
93.6k
      CompArea         locArea = compArea;
3549
93.6k
      locArea.x -= cu->blocks[compIdx].x;
3550
93.6k
      locArea.y -= cu->blocks[compIdx].y;
3551
93.6k
      PelBuf dbReco = picDbBuf.getBuf( locArea );
3552
93.6k
      if (cs.slice->lmcsEnabled && isLuma(compId))
3553
0
      {
3554
0
        dbReco.rspSignal( cs.picture->getRecoBuf( compArea ), reshapeData.getInvLUT() );
3555
0
      }
3556
93.6k
      else
3557
93.6k
      {
3558
93.6k
        dbReco.copyFrom( cs.picture->getRecoBuf( compArea ) );
3559
93.6k
      }
3560
93.6k
    }
3561
128k
  }
3562
3563
89.2k
  ChannelType dbChType = CU::isSepTree(*cu) ? partitioner.chType : MAX_NUM_CH;
3564
3565
89.2k
  CHECK( CU::isSepTree(*cu) && !cu->Y().valid() && partitioner.chType == CH_L, "xxx" );
3566
3567
89.2k
  if( cu->Y() .valid() ) m_cLoopFilter.setOrigin( CH_L, cu->lumaPos() );
3568
89.2k
  if( cu->chromaFormat != VVENC_CHROMA_400 && cu->Cb().valid() ) m_cLoopFilter.setOrigin( CH_C, cu->chromaPos() );
3569
3570
  //deblock
3571
89.2k
  if( leftEdgeAvai )
3572
65.9k
  {
3573
65.9k
    m_cLoopFilter.loopFilterCu( *cu, dbChType, EDGE_VER, m_dbBuffer );
3574
65.9k
  }
3575
3576
89.2k
  if( topEdgeAvai )
3577
67.4k
  {
3578
67.4k
    m_cLoopFilter.loopFilterCu( *cu, dbChType, EDGE_HOR, m_dbBuffer );
3579
67.4k
  }
3580
3581
  //calculate difference between DB_before_SSE and DB_after_SSE for neighbouring CUs
3582
89.2k
  Distortion distBeforeDb = 0, distAfterDb = 0, distCur = 0;
3583
218k
  for (int compIdx = compStr; compIdx <= compEnd; compIdx++)
3584
128k
  {
3585
128k
    ComponentID compId = (ComponentID)compIdx;
3586
128k
    {
3587
128k
      CompArea compArea = currCsArea.block( compId );
3588
128k
      CompArea         locArea  = compArea;
3589
128k
      locArea.x -= cu->blocks[compIdx].x;
3590
128k
      locArea.y -= cu->blocks[compIdx].y;
3591
128k
      CPelBuf reco      = picDbBuf.getBuf( locArea );
3592
128k
      CPelBuf org       = cs.getOrgBuf( compId );
3593
128k
      distCur += xGetDistortionDb( cs, org, reco, compArea, false );
3594
128k
    }
3595
3596
128k
    if ( leftEdgeAvai )
3597
90.3k
    {
3598
90.3k
      const CompArea&  compArea = areaLeft.block( compId );
3599
90.3k
      CompArea         locArea  = compArea;
3600
90.3k
      locArea.x -= cu->blocks[compIdx].x;
3601
90.3k
      locArea.y -= cu->blocks[compIdx].y;
3602
90.3k
      CPelBuf org    = cs.picture->getOrigBuf( compArea );
3603
90.3k
      if ( cs.picture->getFilteredOrigBuffer().valid() )
3604
0
      {
3605
0
        org = cs.picture->getRspOrigBuf( compArea );
3606
0
      }
3607
90.3k
      CPelBuf reco   = cs.picture->getRecoBuf( compArea );
3608
90.3k
      CPelBuf recoDb = picDbBuf.getBuf( locArea );
3609
90.3k
      distBeforeDb  += xGetDistortionDb( cs, org, reco,   compArea, true );
3610
90.3k
      distAfterDb   += xGetDistortionDb( cs, org, recoDb, compArea, false  );
3611
90.3k
    }
3612
3613
128k
    if ( topEdgeAvai )
3614
93.6k
    {
3615
93.6k
      const CompArea&  compArea = areaTop.block( compId );
3616
93.6k
      CompArea         locArea  = compArea;
3617
93.6k
      locArea.x -= cu->blocks[compIdx].x;
3618
93.6k
      locArea.y -= cu->blocks[compIdx].y;
3619
93.6k
      CPelBuf org    = cs.picture->getOrigBuf( compArea );
3620
93.6k
      if ( cs.picture->getFilteredOrigBuffer().valid() )
3621
0
      {
3622
0
        org = cs.picture->getRspOrigBuf( compArea );
3623
0
      }
3624
93.6k
      CPelBuf reco   = cs.picture->getRecoBuf( compArea );
3625
93.6k
      CPelBuf recoDb = picDbBuf.getBuf( locArea );
3626
93.6k
      distBeforeDb  += xGetDistortionDb( cs, org, reco,   compArea, true );
3627
93.6k
      distAfterDb   += xGetDistortionDb( cs, org, recoDb, compArea, false  );
3628
93.6k
    }
3629
128k
  }
3630
3631
  //updated cost
3632
89.2k
  int64_t distTmp = distCur - cs.dist + distAfterDb - distBeforeDb;
3633
89.2k
  cs.costDbOffset = distTmp < 0 ? -m_cRdCost.calcRdCost( 0, -distTmp ) : m_cRdCost.calcRdCost( 0, distTmp );
3634
89.2k
}
3635
3636
Distortion EncCu::xGetDistortionDb(CodingStructure &cs, CPelBuf& org, CPelBuf& reco, const CompArea& compArea, bool beforeDb)
3637
496k
{
3638
496k
  Distortion dist;
3639
496k
  const ReshapeData& reshapeData = cs.picture->reshapeData;
3640
496k
  const ComponentID compID = compArea.compID;
3641
496k
  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
496k
  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
496k
  dist = m_cRdCost.getDistPart(org, reco, cs.sps->bitDepths[toChannelType(compID)], compID, DF_SSE);
3687
496k
  return dist;
3688
496k
}
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
112k
{
4029
112k
  m_CABACEstimator->resetBits();
4030
4031
112k
  m_CABACEstimator->split_cu_mode( CU_DONT_SPLIT, cs, partitioner );
4032
112k
  if( partitioner.treeType == TREE_C )
4033
112k
    CHECK( m_CABACEstimator->getEstFracBits() != 0, "must be 0 bit" );
4034
4035
112k
  cs.fracBits += m_CABACEstimator->getEstFracBits(); // split bits
4036
112k
  cs.cost      = m_cRdCost.calcRdCost( cs.fracBits, cs.dist );
4037
112k
}
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
166k
{
4159
4160
166k
}
4161
MergeItem::~MergeItem()
4162
166k
{
4163
4164
166k
}
4165
4166
void MergeItem::create( ChromaFormat chromaFormat, const Area &area )
4167
166k
{
4168
166k
  if( m_pelStorage.bufs.empty() )
4169
166k
  {
4170
166k
    m_pelStorage.create( chromaFormat, area );
4171
166k
    m_mvStorage .resize( area.area() >> ( MIN_CU_LOG2 << 1 ) );
4172
166k
  }
4173
4174
166k
  init();
4175
166k
}
4176
4177
void MergeItem::init()
4178
166k
{
4179
  // reset data
4180
166k
  cost        = MAX_DOUBLE;
4181
166k
  mergeIdx    = 0;
4182
166k
  bcwIdx      = 0;
4183
166k
  interDir    = 0;
4184
166k
  useAltHpelIf  = false;
4185
166k
  affineType    = AFFINEMODEL_4PARAM;
4186
166k
  mergeItemType = MergeItemType::NUM;
4187
4188
166k
  noBdofRefine  = false;
4189
166k
  noResidual    = false;
4190
4191
166k
  lumaPredReady   = false;
4192
166k
  chromaPredReady = false;
4193
166k
}
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
20.7k
{
4375
4376
20.7k
}
4377
4378
MergeItemList::~MergeItemList()
4379
20.7k
{
4380
20.7k
  for( MergeItem* p : m_list )
4381
0
  {
4382
0
    delete p;
4383
0
  }
4384
20.7k
  m_list.clear();
4385
4386
20.7k
  for( MergeItem *p : m_mergeItems )
4387
166k
  {
4388
166k
    delete p;
4389
166k
  }
4390
20.7k
  m_mergeItems.clear();
4391
20.7k
}
4392
4393
void MergeItemList::init( size_t maxSize, size_t maxExtSize, ChromaFormat chromaFormat, SizeType ctuWidth, SizeType ctuHeight )
4394
20.7k
{
4395
20.7k
  CHECK( !m_mergeItems.empty() || !m_list.empty(), "MergeItemList already initialized" );
4396
4397
20.7k
  m_list      . reserve( maxSize + 1 ); // to avoid reallocation when inserting a new item
4398
20.7k
  m_mergeItems. reserve( maxSize + 1 );
4399
20.7k
  m_maxSize   = maxSize;
4400
20.7k
  m_maxExtSize= maxExtSize;
4401
20.7k
  m_numExt    = 0;
4402
4403
186k
  for( int i = 0; i < maxSize + m_maxExtSize; i++ )
4404
166k
  {
4405
166k
    MergeItem *p = new MergeItem;
4406
166k
    p->create( chromaFormat, Area{ 0, 0, ctuWidth, ctuHeight } );
4407
166k
    m_mergeItems.push_back( p );
4408
166k
  }
4409
20.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
//! \}