Coverage Report

Created: 2026-10-17 06:56

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