Coverage Report

Created: 2026-10-28 06:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/vvenc/source/Lib/EncoderLib/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
5.97k
  : m_CtxCache          ( nullptr )
237
5.97k
  , m_globalCtuQpVector ( nullptr )
238
5.97k
  , m_wppMutex          ( nullptr )
239
5.97k
  , m_CABACEstimator    ( nullptr )
240
5.97k
  , m_syncPicCtx        ( nullptr )
241
5.97k
  , m_boundPicId        ( 0 )
242
5.97k
{
243
5.97k
}
244
245
void EncCu::bindToPicture( const PicEncState& picState )
246
4.97k
{
247
4.97k
  if( m_boundPicId == picState.id )
248
2.80k
  {
249
2.80k
    return;
250
2.80k
  }
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
2.17k
  m_boundPicId = picState.id;
256
2.17k
  m_syncPicCtx = picState.syncPicCtx;
257
2.17k
  Slice& slice = *picState.pic->cs->slice;
258
2.17k
  setUpLambda( slice, picState.lambda, picState.qp, false, true );
259
2.17k
  initPic    ( picState.pic );
260
2.17k
  initSlice  ( &slice );
261
2.17k
}
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
13.2k
{
266
13.2k
  lambdas[COMP_Y] = lambda;
267
13.2k
  weights[COMP_Y] = 1.0;
268
39.7k
  for( uint32_t compIdx = 1; compIdx < MAX_NUM_COMP; compIdx++ )
269
26.4k
  {
270
26.4k
    const ComponentID compID = ComponentID( compIdx );
271
26.4k
    int chromaQPOffset       = slice.pps->chromaQpOffset[compID] + slice.sliceChromaQpDelta[ compID ];
272
26.4k
    int qpc = slice.sps->chromaQpMappingTable.getMappedChromaQpValue(compID, qp) + chromaQPOffset;
273
26.4k
    double tmpWeight         = pow( 2.0, ( qp - qpc ) / 3.0 );  // takes into account of the chroma qp mapping and chroma qp Offset
274
26.4k
    if( encCfg.m_DepQuantEnabled/* && !( m_pcEncCfg->getLFNST() ) */)
275
26.4k
    {
276
26.4k
      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
26.4k
    }
278
26.4k
    weights[compIdx] = tmpWeight;
279
26.4k
    lambdas[compIdx] = lambda / tmpWeight;
280
26.4k
  }
281
13.2k
}
282
283
void EncCu::initPic( Picture* pic )
284
2.17k
{
285
2.17k
  m_cInterSearch.setSearchRange( pic->cs->slice, *m_pcEncCfg );
286
287
2.17k
  m_wppMutex = (m_pcEncCfg->m_numThreads > 0 ) ? &pic->wppMutex : nullptr;
288
2.17k
}
289
290
void EncCu::initSlice( const Slice* slice )
291
2.17k
{
292
2.17k
  m_cTrQuant.setLambdas( slice->getLambdas() );
293
2.17k
  m_cRdCost.setLambda( slice->getLambdas()[0], slice->sps->bitDepths );
294
2.17k
}
295
296
void EncCu::setCtuEncRsrc( CABACWriter* cabacEstimator, CtxCache* ctxCache, ReuseUniMv* pReuseUniMv, BlkUniMvInfoBuffer* pBlkUniMvInfoBuffer, AffineProfList* pAffineProfList, IbcBvCand* pCachedBvs )
297
4.97k
{
298
4.97k
  m_CABACEstimator = cabacEstimator;
299
4.97k
  m_CtxCache       = ctxCache;
300
4.97k
  m_cIntraSearch.setCtuEncRsrc( cabacEstimator, ctxCache );
301
4.97k
  m_cInterSearch.setCtuEncRsrc( cabacEstimator, ctxCache, pReuseUniMv, pBlkUniMvInfoBuffer, pAffineProfList, pCachedBvs );
302
4.97k
}
303
304
void EncCu::setUpLambda (Slice& slice, const double dLambda, const int iQP, const bool setSliceLambda, const bool saveUnadjusted)
305
7.14k
{
306
  // store lambda
307
7.14k
  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
7.14k
  double dLambdas[MAX_NUM_COMP];
312
7.14k
  double weights [MAX_NUM_COMP];
313
7.14k
  deriveComponentLambdas( *m_pcEncCfg, slice, dLambda, iQP, dLambdas, weights );
314
21.4k
  for( uint32_t compIdx = 1; compIdx < MAX_NUM_COMP; compIdx++ )
315
14.2k
  {
316
14.2k
    m_cRdCost.setDistortionWeight( ComponentID( compIdx ), weights[compIdx] );
317
14.2k
  }
318
319
  // for RDOQ
320
7.14k
  m_cTrQuant.setLambdas( dLambdas );
321
322
  // for SAO, ALF
323
7.14k
  if (setSliceLambda)
324
0
  {
325
0
    slice.setLambdas( dLambdas );
326
0
  }
327
7.14k
  if( saveUnadjusted )
328
7.14k
  {
329
7.14k
    m_cRdCost.saveUnadjustedLambda();
330
7.14k
  }
331
7.14k
}
332
333
void EncCu::updateLambda(const Slice& slice, const double ctuLambda, const int ctuQP, const int newQP, const bool saveUnadjusted)
334
4.60k
{
335
4.60k
  const double  corrFactor = pow (2.0, double (newQP - ctuQP) / 3.0);
336
4.60k
  const double  newLambda  = ctuLambda * corrFactor;
337
  
338
4.60k
  double newLambdas[MAX_NUM_COMP];
339
4.60k
  double weights   [MAX_NUM_COMP];
340
4.60k
  deriveComponentLambdas( *m_pcEncCfg, slice, newLambda, newQP, newLambdas, weights );
341
13.8k
  for( uint32_t compIdx = 1; compIdx < MAX_NUM_COMP; compIdx++ )
342
9.20k
  {
343
9.20k
    m_cRdCost.setDistortionWeight( ComponentID( compIdx ), weights[compIdx] );
344
9.20k
  }
345
346
4.60k
  m_cTrQuant.setLambdas ( newLambdas);
347
4.60k
  m_cRdCost.setLambda   ( newLambda, slice.sps->bitDepths);
348
349
4.60k
  if (saveUnadjusted)
350
4.60k
  {
351
4.60k
    m_cRdCost.saveUnadjustedLambda(); // TODO hlm: check if this actually improves the overall quality
352
4.60k
  }
353
4.60k
}
354
355
void EncCu::init( const VVEncCfg& encCfg, const SPS& sps, std::vector<int>* const globalCtuQpVector, RateCtrl* pRateCtrl, TrQuant* otherTrQuant )
356
5.97k
{
357
5.97k
  DecCu::init( &m_cTrQuant, &m_cIntraSearch, &m_cInterSearch, encCfg.m_internChromaFormat );
358
5.97k
  m_cRdCost.create     ();
359
5.97k
  m_cRdCost.setCostMode( encCfg.m_costMode );
360
5.97k
  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
5.97k
  m_modeCtrl.init     ( encCfg, &m_cRdCost );
368
5.97k
  m_cIntraSearch.init ( encCfg, &m_cTrQuant, &m_cRdCost, &m_SortedPelUnitBufs, m_unitCache );
369
5.97k
  m_cInterSearch.init ( encCfg, &m_cTrQuant, &m_cRdCost, &m_modeCtrl, m_cIntraSearch.getSaveCSBuf() );
370
5.97k
  m_cTrQuant.init     ( otherTrQuant ? otherTrQuant->getQuant() : nullptr, encCfg.m_RDOQ, encCfg.m_useRDOQTS, false, true, encCfg.m_quantThresholdVal );
371
372
5.97k
  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
5.97k
  const int maxLog2TrDynamicRange[ MAX_NUM_CH ] = { sps.getMaxLog2TrDynamicRange(), sps.getMaxLog2TrDynamicRange() };
376
5.97k
  m_cTrQuant.getQuant()->setFlatScalingList( maxLog2TrDynamicRange, sps.bitDepths );
377
378
5.97k
  m_pcEncCfg       = &encCfg;
379
380
5.97k
  m_GeoCostList.init( encCfg.m_maxNumGeoCand );
381
382
5.97k
  unsigned      uiMaxSize    = encCfg.m_CTUSize;
383
5.97k
  ChromaFormat  chromaFormat = encCfg.m_internChromaFormat;
384
385
5.97k
  Area ctuArea = Area( 0, 0, uiMaxSize, uiMaxSize );
386
387
5.97k
  m_mergeItemList.init( encCfg.m_maxMergeRdCandNumTotal, m_pcEncCfg->m_Geo > 1 ? 3 : 1, chromaFormat, uiMaxSize, uiMaxSize );
388
389
77.6k
  for( int i = 0; i < maxCuDepth; i++ )
390
71.6k
  {
391
71.6k
    Area area = Area( 0, 0, uiMaxSize >> ( i >> 1 ), uiMaxSize >> ( ( i + 1 ) >> 1 ) );
392
393
71.6k
    if( area.width < (1 << MIN_CU_LOG2) || area.height < (1 << MIN_CU_LOG2) )
394
5.97k
    {
395
5.97k
      m_pTempCS[i] = m_pBestCS[i] = nullptr;
396
5.97k
      continue;
397
5.97k
    }
398
399
65.6k
    m_pTempCS[i] = new CodingStructure( m_unitCache, nullptr );
400
65.6k
    m_pBestCS[i] = new CodingStructure( m_unitCache, nullptr );
401
402
65.6k
    m_pTempCS[i]->createForSearch( chromaFormat, area );
403
65.6k
    m_pBestCS[i]->createForSearch( chromaFormat, area );
404
405
65.6k
    m_pOrgBuffer[i].create( chromaFormat, area );
406
65.6k
  }
407
408
5.97k
  m_pTempCS2 = new CodingStructure( m_unitCache, nullptr );
409
5.97k
  m_pBestCS2 = new CodingStructure( m_unitCache, nullptr );
410
411
5.97k
  m_pTempCS2->createForSearch( chromaFormat, ctuArea );
412
5.97k
  m_pBestCS2->createForSearch( chromaFormat, ctuArea );
413
414
5.97k
  m_cuChromaQpOffsetIdxPlus1 = 0;
415
5.97k
  m_tempQpDiff = 0;
416
5.97k
  m_globalCtuQpVector = globalCtuQpVector;
417
418
5.97k
  m_SortedPelUnitBufs.create( chromaFormat, uiMaxSize, uiMaxSize );
419
420
89.5k
  for( uint8_t i = 0; i < MAX_TMP_BUFS; i++)
421
83.6k
  {
422
83.6k
    m_aTmpStorageLCU[i].create(chromaFormat, Area(0, 0, uiMaxSize, uiMaxSize));
423
83.6k
  }
424
41.8k
  for (unsigned ui = 0; ui < MRG_MAX_NUM_CANDS; ui++)
425
35.8k
  {
426
35.8k
    m_acMergeTmpBuffer[ui].create(chromaFormat, Area(0, 0, uiMaxSize, uiMaxSize));
427
35.8k
  }
428
429
5.97k
  const unsigned maxDepth = 2 * MAX_CU_SIZE_IDX;
430
5.97k
  m_CtxBuffer.resize( maxDepth );
431
5.97k
  m_CurrCtx = 0;
432
5.97k
  if( encCfg.m_EDO )
433
5.97k
    m_dbBuffer.create( chromaFormat, Area( 0, 0, uiMaxSize, uiMaxSize ), 0, 8 );
434
435
5.97k
  m_MergeSimpleFlag = 0;
436
5.97k
  m_tileIdx = 0;
437
5.97k
}
438
439
440
void EncCu::destroy()
441
5.97k
{
442
77.6k
  for( int i = 0; i < maxCuDepth; i++ )
443
71.6k
  {
444
71.6k
    if( m_pTempCS[i] )
445
65.6k
    {
446
65.6k
      m_pTempCS[i]->destroy();
447
65.6k
      delete m_pTempCS[i]; m_pTempCS[i] = nullptr;
448
65.6k
    }
449
450
71.6k
    if( m_pBestCS[i] )
451
65.6k
    {
452
65.6k
      m_pBestCS[i]->destroy();
453
65.6k
      delete m_pBestCS[i]; m_pBestCS[i] = nullptr;
454
65.6k
    }
455
456
71.6k
    m_pOrgBuffer[i].destroy();
457
71.6k
  }
458
459
5.97k
  m_pTempCS2->destroy();
460
5.97k
  m_pBestCS2->destroy();
461
462
5.97k
  delete m_pTempCS2; m_pTempCS2 = nullptr;
463
5.97k
  delete m_pBestCS2; m_pBestCS2 = nullptr;
464
465
5.97k
  m_SortedPelUnitBufs.destroy();
466
467
89.5k
  for( uint8_t i = 0; i < MAX_TMP_BUFS; i++)
468
83.6k
  {
469
83.6k
    m_aTmpStorageLCU[i].destroy();
470
83.6k
  }
471
41.8k
  for (unsigned ui = 0; ui < MRG_MAX_NUM_CANDS; ui++)
472
35.8k
  {
473
35.8k
    m_acMergeTmpBuffer[ui].destroy();
474
35.8k
  }
475
476
477
5.97k
  m_dbBuffer.destroy();
478
5.97k
}
479
480
481
EncCu::~EncCu()
482
5.97k
{
483
5.97k
  destroy();
484
5.97k
}
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
4.97k
{
492
4.97k
  CodingStructure&     cs          = *pic->cs;
493
4.97k
  Slice*               slice       = cs.slice;
494
4.97k
  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
4.97k
  const int ctuRsAddr                 = ctuYPosInCtus * pcv.widthInCtus + ctuXPosInCtus;
506
507
4.97k
  const Position pos (ctuXPosInCtus * pcv.maxCUSize, ctuYPosInCtus * pcv.maxCUSize);
508
4.97k
  const UnitArea ctuArea( cs.area.chromaFormat, Area( pos.x, pos.y, pcv.maxCUSize, pcv.maxCUSize ) );
509
4.97k
  DTRACE_UPDATE( g_trace_ctx, std::make_pair( "ctu", ctuRsAddr ) );
510
511
4.97k
  const int tileXPosInCtus = cs.pps->tileColBd[cs.pps->ctuToTileCol[ctuXPosInCtus]];
512
4.97k
  const int tileYPosInCtus = cs.pps->tileRowBd[cs.pps->ctuToTileRow[ctuYPosInCtus]];
513
514
4.97k
  if( ( cs.slice->sliceType != VVENC_I_SLICE || cs.sps->IBC ) && ctuXPosInCtus == tileXPosInCtus )
515
2.69k
  {
516
2.69k
    const int tileRowId = cs.pps->getTileLineId( ctuXPosInCtus, ctuYPosInCtus );
517
2.69k
    cs.motionLutBuf[tileRowId].lut.resize( 0 );
518
2.69k
    cs.motionLutBuf[tileRowId].lutIbc.resize( 0 );
519
2.69k
  }
520
521
4.97k
  if( ( m_pcEncCfg->m_ensureWppBitEqual || m_pcEncCfg->m_entropyCodingSyncEnabled ) && ctuXPosInCtus == tileXPosInCtus )
522
2.69k
  {
523
2.69k
    m_CABACEstimator->initCtxModels( *slice );
524
525
2.69k
    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.69k
    prevQP[CH_L] = prevQP[CH_C] = slice->sliceQp; // hlm: call CU::predictQP() here!
531
2.69k
  }
532
2.28k
  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
4.97k
  xCompressCtu( cs, ctuArea, ctuRsAddr, prevQP );
539
540
4.97k
  m_CABACEstimator->resetBits();
541
4.97k
  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
4.97k
  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
4.97k
  DTRACE_AREA_CRC( g_trace_ctx, D_CRC, cs, ctuArea );
550
4.97k
}
551
552
// ====================================================================================================================
553
// Protected member functions
554
// ====================================================================================================================
555
556
void EncCu::xCompressCtu( CodingStructure& cs, const UnitArea& area, const unsigned ctuRsAddr, const int prevQP[] )
557
4.97k
{
558
4.97k
  m_tileIdx = cs.pps->getTileIdx( area.lumaPos() );
559
560
4.97k
  m_modeCtrl.initCTUEncoding( *cs.slice, m_tileIdx );
561
562
  // init the partitioning manager
563
4.97k
  Partitioner *partitioner = &m_partitioner;
564
4.97k
  partitioner->initCtu( area, CH_L, *cs.slice );
565
  
566
4.97k
  const Position& lumaPos = area.lumaPos();
567
4.97k
  const bool leftSameTile  = lumaPos.x == 0 || m_tileIdx == cs.pps->getTileIdx( lumaPos.offset(-1, 0) );
568
4.97k
  const bool aboveSameTile = lumaPos.y == 0 || m_tileIdx == cs.pps->getTileIdx( lumaPos.offset( 0,-1) );
569
4.97k
  m_EDO = (!m_pcEncCfg->m_tileParallelCtuEnc || (leftSameTile && aboveSameTile)) ? m_pcEncCfg->m_EDO : 0;
570
  
571
4.97k
  if( m_pcEncCfg->m_IBCMode )
572
4.97k
  {
573
4.97k
    m_cInterSearch.resetCtuRecordIBC();
574
4.97k
  }
575
576
  // init current context pointer
577
4.97k
  m_CurrCtx = m_CtxBuffer.data();
578
579
4.97k
  PelStorage* orgBuffer = &m_pOrgBuffer[0];
580
4.97k
  CodingStructure *tempCS =  m_pTempCS [0];
581
4.97k
  CodingStructure *bestCS =  m_pBestCS [0];
582
4.97k
  cs.initSubStructure( *tempCS, partitioner->chType, partitioner->currArea(), false, orgBuffer );
583
4.97k
  cs.initSubStructure( *bestCS, partitioner->chType, partitioner->currArea(), false, orgBuffer );
584
4.97k
  PROFILER_SCOPE_AND_STAGE_EXT( 1, _TPROF, P_COMPRESS_CU, tempCS, CH_L );
585
586
  // copy the relevant area
587
4.97k
  UnitArea clippedArea = clipArea( partitioner->currArea(), cs.area );
588
4.97k
  CPelUnitBuf org = cs.picture->getFilteredOrigBuffer().valid() ? cs.picture->getFiltOrigBuf( clippedArea ) : cs.picture->getOrigBuf( clippedArea );
589
4.97k
  tempCS->getOrgBuf( clippedArea ).copyFrom( org );
590
4.97k
  tempCS->currQP[CH_L] = bestCS->currQP[CH_L] =
591
4.97k
  tempCS->baseQP       = bestCS->baseQP       = cs.slice->sliceQp;
592
4.97k
  tempCS->prevQP[CH_L] = bestCS->prevQP[CH_L] = prevQP[CH_L];
593
594
4.97k
  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
4.97k
  CHECK( bestCS->cus.empty()                                   , "No possible encoding found" );
600
4.97k
  CHECK( bestCS->cus[0]->predMode == NUMBER_OF_PREDICTION_MODES, "No possible encoding found" );
601
4.97k
  CHECK( bestCS->cost             == MAX_DOUBLE                , "No possible encoding found" );
602
603
4.97k
  if ( m_wppMutex ) m_wppMutex->lock();
604
605
4.97k
  cs.useSubStructure( *bestCS, partitioner->chType, TREE_D, CS::getArea( *bestCS, area, partitioner->chType, partitioner->treeType ) );
606
607
4.97k
  if ( m_wppMutex ) m_wppMutex->unlock();
608
609
4.97k
  if( CS::isDualITree( cs ) && isChromaEnabled( cs.pcv->chrFormat ) )
610
4.97k
  {
611
4.97k
    m_CABACEstimator->getCtx() = m_CurrCtx->start;
612
613
4.97k
    partitioner->initCtu( area, CH_C, *cs.slice );
614
615
4.97k
    cs.initSubStructure( *tempCS, partitioner->chType, partitioner->currArea(), false, orgBuffer );
616
4.97k
    cs.initSubStructure( *bestCS, partitioner->chType, partitioner->currArea(), false, orgBuffer );
617
4.97k
    tempCS->currQP[CH_C] = bestCS->currQP[CH_C] =
618
4.97k
    tempCS->baseQP       = bestCS->baseQP       = cs.slice->sliceQp;
619
4.97k
    tempCS->prevQP[CH_C] = bestCS->prevQP[CH_C] = prevQP[CH_C];
620
621
4.97k
    xCompressCU( tempCS, bestCS, *partitioner );
622
    
623
    // Ensure that a coding was found
624
    // Selected mode's RD-cost must be not MAX_DOUBLE.
625
4.97k
    CHECK( bestCS->cus.empty()                                   , "No possible encoding found" );
626
4.97k
    CHECK( bestCS->cus[0]->predMode == NUMBER_OF_PREDICTION_MODES, "No possible encoding found" );
627
4.97k
    CHECK( bestCS->cost             == MAX_DOUBLE                , "No possible encoding found" );
628
629
4.97k
    if ( m_wppMutex ) m_wppMutex->lock();
630
631
4.97k
    cs.useSubStructure( *bestCS, partitioner->chType, TREE_D, CS::getArea( *bestCS, area, partitioner->chType, partitioner->treeType ) );
632
633
4.97k
    if ( m_wppMutex ) m_wppMutex->unlock();
634
4.97k
  }
635
636
  // reset context states and uninit context pointer
637
4.97k
  m_CABACEstimator->getCtx() = m_CurrCtx->start;
638
4.97k
  m_CurrCtx                  = 0;
639
4.97k
}
640
641
642
643
bool EncCu::xCheckBestMode( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode, const bool useEDO )
644
362k
{
645
362k
  bool bestCSUpdated = false;
646
647
362k
  if( !tempCS->cus.empty() )
648
219k
  {
649
219k
    if( tempCS->cus.size() == 1 )
650
166k
    {
651
166k
      const CodingUnit& cu = *tempCS->cus.front();
652
166k
      CHECK( cu.skip && !cu.mergeFlag, "Skip flag without a merge flag is not allowed!" );
653
166k
    }
654
655
219k
    DTRACE_BEST_MODE( tempCS, bestCS, m_cRdCost.getLambda(true), useEDO );
656
657
219k
    if( m_modeCtrl.useModeResult( encTestMode, tempCS, partitioner, useEDO ) )
658
198k
    {
659
198k
      std::swap( tempCS, bestCS );
660
      // store temp best CI for next CU coding
661
198k
      m_CurrCtx->best = m_CABACEstimator->getCtx();
662
198k
      bestCSUpdated = true;
663
198k
    }
664
219k
  }
665
666
  // reset context states
667
362k
  m_CABACEstimator->getCtx() = m_CurrCtx->start;
668
362k
  return bestCSUpdated;
669
670
362k
}
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
166k
{
748
166k
  const Area& lumaArea = tempCS->area.Y();
749
750
166k
  Slice&   slice      = *tempCS->slice;
751
166k
  const PPS &pps      = *tempCS->pps;
752
166k
  const SPS &sps      = *tempCS->sps;
753
166k
  const uint32_t uiLPelX  = tempCS->area.Y().lumaPos().x;
754
166k
  const uint32_t uiTPelY  = tempCS->area.Y().lumaPos().y;
755
166k
  const bool isBimEnabled = (m_pcEncCfg->hasBlockQpOffsets() && !bestCS->picture->m_picShared->m_ctuBimQpOffset.empty());
756
757
166k
  m_modeCtrl.initBlk( tempCS->area, slice.pic->poc );
758
166k
  m_CABACEstimator->determineNeighborCus( *tempCS, partitioner.currArea(), partitioner.chType, partitioner.treeType );
759
760
166k
  if ((m_pcEncCfg->m_usePerceptQPA || isBimEnabled || m_pcEncCfg->m_lumaLevelToDeltaQPEnabled == 1) && ( pps.useDQP || m_pcEncCfg->m_maxDeltaQP == 0 ) && isLuma (partitioner.chType) && partitioner.currQgEnable())
761
9.57k
  {
762
9.57k
    const PreCalcValues &pcv = *pps.pcv;
763
9.57k
    Picture* const pic = bestCS->picture;
764
9.57k
    const uint32_t ctuRsAddr = getCtuAddr (partitioner.currQgPos, pcv);
765
766
9.57k
    if (partitioner.currSubdiv == 0) // CTU-level QP adaptation
767
4.97k
    {
768
4.97k
      if (m_pcEncCfg->m_usePerceptQPA)
769
4.97k
      {
770
4.97k
        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
4.97k
        int clippedMaxDQP = 0;
776
777
4.97k
        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
4.97k
        else
805
4.97k
        {
806
4.97k
          tempCS->currQP[partitioner.chType] = tempCS->baseQP =
807
4.97k
          bestCS->currQP[partitioner.chType] = bestCS->baseQP = pic->ctuAdaptedQP[ctuRsAddr];
808
4.97k
        }
809
810
4.97k
        int deltaQP       = slice.sliceQp - tempCS->baseQP;
811
4.97k
        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
4.97k
        setUpLambda (slice, pic->ctuQpaLambda[ctuRsAddr], pic->ctuAdaptedQP[ctuRsAddr], false, true);
820
4.97k
      }
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
4.97k
    }
926
4.60k
    else if (m_pcEncCfg->m_usePerceptQPA && slice.isIntra()) // currSubdiv 2 - use sub-CTU QPA
927
4.60k
    {
928
4.60k
      CHECK ((partitioner.currArea().lwidth() >= pcv.maxCUSize) || (partitioner.currArea().lheight() >= pcv.maxCUSize), "sub-CTU delta-QP error");
929
4.60k
      tempCS->currQP[partitioner.chType] = tempCS->baseQP = BitAllocation::applyQPAdaptationSubCtu (&slice, m_pcEncCfg, lumaArea, m_pcRateCtrl->getMinNoiseLevels());
930
931
4.60k
      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
4.60k
      int backupBaseQP  = tempCS->baseQP;
937
4.60k
      int deltaQP       = slice.sliceQp - tempCS->baseQP;
938
4.60k
      int clippedMaxDQP = 0;
939
4.60k
      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
4.60k
      updateLambda( slice, pic->ctuQpaLambda[ctuRsAddr], pic->ctuAdaptedQP[ctuRsAddr], backupBaseQP, true );
945
4.60k
    }
946
9.57k
  }
947
948
166k
  if (partitioner.currQtDepth == 0)
949
9.95k
  {
950
9.95k
    m_MergeSimpleFlag = 0;
951
9.95k
  }
952
166k
  m_modeCtrl.initCULevel( partitioner, *tempCS, m_MergeSimpleFlag );
953
166k
  m_sbtCostSave[0] = m_sbtCostSave[1] = MAX_DOUBLE;
954
955
166k
  m_CurrCtx->start = m_CABACEstimator->getCtx();
956
957
166k
  m_cuChromaQpOffsetIdxPlus1 = 0;
958
959
166k
  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
166k
  DTRACE_UPDATE( g_trace_ctx, std::make_pair( "cux", uiLPelX ) );
969
166k
  DTRACE_UPDATE( g_trace_ctx, std::make_pair( "cuy", uiTPelY ) );
970
166k
  DTRACE_UPDATE( g_trace_ctx, std::make_pair( "cuw", tempCS->area.lwidth() ) );
971
166k
  DTRACE_UPDATE( g_trace_ctx, std::make_pair( "cuh", tempCS->area.lheight() ) );
972
166k
  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
166k
  if( tempCS->slice->checkLDC )
975
166k
  {
976
166k
    m_bestBcwCost[0] = m_bestBcwCost[1] = std::numeric_limits<double>::max();
977
166k
    m_bestBcwIdx[0] = m_bestBcwIdx[1] = -1;
978
166k
  }
979
980
166k
  m_cInterSearch.resetSavedAffineMotion();
981
166k
  {
982
166k
    const ComprCUCtx &cuECtx      = *m_modeCtrl.comprCUCtx;
983
166k
    const CodingStructure& cs     = *tempCS;
984
166k
    const PartSplit implicitSplit = partitioner.getImplicitSplit( cs );
985
166k
    const bool isBoundary         = implicitSplit != CU_DONT_SPLIT;
986
166k
    const bool lossless           = false;
987
166k
    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
166k
    if( ! isBoundary )
997
104k
    {
998
104k
      if (pps.useDQP && partitioner.isSepTree (*tempCS) && isChroma (partitioner.chType))
999
72.5k
      {
1000
72.5k
        const ChromaFormat chromaFm = tempCS->area.chromaFormat;
1001
72.5k
        const Position chromaCentral (tempCS->area.Cb().chromaPos().offset (tempCS->area.Cb().chromaSize().width >> 1, tempCS->area.Cb().chromaSize().height >> 1));
1002
72.5k
        const Position lumaRefPos (chromaCentral.x << getChannelTypeScaleX (CH_C, chromaFm), chromaCentral.y << getChannelTypeScaleY (CH_C, chromaFm));
1003
72.5k
        const CodingUnit* colLumaCu = bestCS->lumaCS->getCU (lumaRefPos, CH_L, TREE_D);
1004
        // update qp
1005
72.5k
        qp = colLumaCu->qp;
1006
72.5k
      }
1007
1008
104k
      m_cIntraSearch.reset();
1009
1010
104k
      bool isReuseCU = m_modeCtrl.isReusingCuValid( cs, partitioner, qp );
1011
1012
104k
      bool checkIbc = m_pcEncCfg->m_IBCMode && bestCS->picture->useIBC && (partitioner.chType == CH_L);
1013
104k
      if ((m_pcEncCfg->m_IBCFastMethod>3) && (cs.area.lwidth() * cs.area.lheight()) > (16 * 16))
1014
0
      {
1015
0
        checkIbc = false;
1016
0
      }
1017
104k
      if( isReuseCU )
1018
0
      {
1019
0
        xReuseCachedResult( tempCS, bestCS, partitioner );
1020
0
      }
1021
104k
      else
1022
104k
      {
1023
        // add first pass modes
1024
104k
        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
104k
        if (checkIbc && !partitioner.isConsInter())
1059
32.4k
        {
1060
32.4k
          EncTestMode encTestModeIBCMerge = { ETM_IBC_MERGE, ETO_STANDARD, qp, lossless };
1061
32.4k
          if ((m_pcEncCfg->m_IBCFastMethod < 4) && (partitioner.chType == CH_L) && m_modeCtrl.tryMode(encTestModeIBCMerge, cs, partitioner))
1062
32.4k
          {
1063
32.4k
            xCheckRDCostIBCModeMerge2Nx2N(tempCS, bestCS, partitioner, encTestModeIBCMerge);
1064
32.4k
          }
1065
1066
32.4k
          EncTestMode encTestModeIBC = { ETM_IBC, ETO_STANDARD, qp, lossless };
1067
32.4k
          if (m_modeCtrl.tryMode(encTestModeIBC, cs, partitioner))
1068
32.4k
          {
1069
32.4k
            xCheckRDCostIBCMode(tempCS, bestCS, partitioner, encTestModeIBC);
1070
32.4k
          }
1071
32.4k
        }
1072
104k
        if( m_EDO && bestCS->cost != MAX_DOUBLE )
1073
29.1k
        {
1074
29.1k
          xCalDebCost(*bestCS, partitioner);
1075
29.1k
        }
1076
1077
        // add intra modes
1078
104k
        EncTestMode encTestMode( {ETM_INTRA, ETO_STANDARD, qp, lossless} );
1079
104k
        if( !partitioner.isConsInter() && m_modeCtrl.tryMode( encTestMode, cs, partitioner ) )
1080
104k
        {
1081
104k
          xCheckRDCostIntra( tempCS, bestCS, partitioner, encTestMode );
1082
104k
        }
1083
104k
      } // reusing cu
1084
1085
104k
      m_modeCtrl.beforeSplit( partitioner );
1086
1087
104k
      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
104k
      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
104k
    } //boundary
1106
1107
166k
    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
166k
    EncTestMode lastTestMode;
1114
1115
166k
    if( cuECtx.qtBeforeBt )
1116
26.3k
    {
1117
26.3k
      EncTestMode encTestMode( { ETM_SPLIT_QT, ETO_STANDARD, qp, false } );
1118
26.3k
      if( m_modeCtrl.trySplit( encTestMode, cs, partitioner, lastTestMode ) )
1119
17.1k
      {
1120
17.1k
        lastTestMode = encTestMode;
1121
17.1k
        xCheckModeSplit( tempCS, bestCS, partitioner, encTestMode );
1122
17.1k
      }
1123
26.3k
    }
1124
1125
166k
    if( partitioner.canSplit( CU_HORZ_SPLIT, cs ) )
1126
88.2k
    {
1127
      // add split modes
1128
88.2k
      EncTestMode encTestMode( { ETM_SPLIT_BT_H, ETO_STANDARD, qp, false } );
1129
88.2k
      if( m_modeCtrl.trySplit( encTestMode, cs, partitioner, lastTestMode ) )
1130
88.2k
      {
1131
88.2k
        lastTestMode = encTestMode;
1132
88.2k
        xCheckModeSplit( tempCS, bestCS, partitioner, encTestMode );
1133
88.2k
      }
1134
88.2k
    }
1135
1136
166k
    if( partitioner.canSplit( CU_VERT_SPLIT, cs ) )
1137
83.7k
    {
1138
      // add split modes
1139
83.7k
      EncTestMode encTestMode( { ETM_SPLIT_BT_V, ETO_STANDARD, qp, false } );
1140
83.7k
      if( m_modeCtrl.trySplit( encTestMode, cs, partitioner, lastTestMode ) )
1141
83.7k
      {
1142
83.7k
        lastTestMode = encTestMode;
1143
83.7k
        xCheckModeSplit( tempCS, bestCS, partitioner, encTestMode );
1144
83.7k
      }
1145
83.7k
    }
1146
1147
166k
    if( partitioner.canSplit( CU_TRIH_SPLIT, cs ) )
1148
36.4k
    {
1149
      // add split modes
1150
36.4k
      EncTestMode encTestMode( { ETM_SPLIT_TT_H, ETO_STANDARD, qp, false } );
1151
36.4k
      if( m_modeCtrl.trySplit( encTestMode, cs, partitioner, lastTestMode ) )
1152
1.75k
      {
1153
1.75k
        lastTestMode = encTestMode;
1154
1.75k
        xCheckModeSplit( tempCS, bestCS, partitioner, encTestMode );
1155
1.75k
      }
1156
36.4k
    }
1157
1158
166k
    if( partitioner.canSplit( CU_TRIV_SPLIT, cs ) )
1159
28.8k
    {
1160
      // add split modes
1161
28.8k
      EncTestMode encTestMode( { ETM_SPLIT_TT_V, ETO_STANDARD, qp, false } );
1162
28.8k
      if( m_modeCtrl.trySplit( encTestMode, cs, partitioner, lastTestMode ) )
1163
1.27k
      {
1164
1.27k
        lastTestMode = encTestMode;
1165
1.27k
        xCheckModeSplit( tempCS, bestCS, partitioner, encTestMode );
1166
1.27k
      }
1167
28.8k
    }
1168
1169
166k
    if( !cuECtx.qtBeforeBt )
1170
140k
    {
1171
140k
      EncTestMode encTestMode( { ETM_SPLIT_QT, ETO_STANDARD, qp, false } );
1172
140k
      if( m_modeCtrl.trySplit( encTestMode, cs, partitioner, lastTestMode ) )
1173
35.8k
      {
1174
35.8k
        lastTestMode = encTestMode;
1175
35.8k
        xCheckModeSplit( tempCS, bestCS, partitioner, encTestMode );
1176
35.8k
      }
1177
140k
    }
1178
166k
  }
1179
1180
166k
  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
166k
  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
166k
  int numCUInThisNode = (int)bestCS->cus.size();
1194
166k
  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
166k
  else
1200
166k
  {
1201
166k
    bestCS->prevQP[partitioner.chType] = bestCS->cus.back()->qp;
1202
166k
  }
1203
166k
  if( ( !slice.isIntra() || slice.sps->IBC )
1204
166k
    && partitioner.chType == CH_L
1205
66.7k
    && 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
166k
  m_modeCtrl.finishCULevel( partitioner );
1219
166k
  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
166k
  CHECK( bestCS->cus.empty()                                   , "No possible encoding found" );
1227
166k
  CHECK( bestCS->cus[0]->predMode == NUMBER_OF_PREDICTION_MODES, "No possible encoding found" );
1228
166k
  CHECK( bestCS->cost             == MAX_DOUBLE                , "No possible encoding found" );
1229
166k
}
1230
1231
1232
void EncCu::xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode )
1233
228k
{
1234
228k
  const ModeType modeTypeParent  = partitioner.modeType;
1235
228k
  const TreeType treeTypeParent  = partitioner.treeType;
1236
228k
  const ChannelType chTypeParent = partitioner.chType;
1237
1238
228k
  int signalModeConsVal = CS::signalModeCons( *tempCS, partitioner.currArea(), getPartSplit(encTestMode), modeTypeParent);
1239
228k
  int numRoundRdo = signalModeConsVal == LDT_MODE_TYPE_SIGNAL ? 2 : 1;
1240
228k
  bool skipInterPass = false;
1241
456k
  for( int i = 0; i < numRoundRdo; i++ )
1242
228k
  {
1243
    //change cons modes
1244
228k
    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
228k
    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
228k
    else if( signalModeConsVal == LDT_MODE_TYPE_INHERIT )
1255
228k
    {
1256
228k
      CHECK( numRoundRdo != 1, "numRoundRdo shall be 1 - [LDT_MODE_TYPE_INHERIT]" );
1257
228k
      partitioner.modeType = modeTypeParent;
1258
228k
    }
1259
1260
    //for lite intra encoding fast algorithm, set the status to save inter coding info
1261
228k
    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
228k
    else if( modeTypeParent == MODE_TYPE_ALL && partitioner.modeType != MODE_TYPE_INTER )
1267
228k
    {
1268
228k
      m_cIntraSearch.setSaveCuCostInSCIPU( false );
1269
228k
      if( partitioner.modeType == MODE_TYPE_ALL )
1270
228k
      {
1271
228k
        m_cIntraSearch.setNumCuInSCIPU( 0 );
1272
228k
      }
1273
228k
    }
1274
1275
228k
    xCheckModeSplitInternal( tempCS, bestCS, partitioner, encTestMode, modeTypeParent, skipInterPass );
1276
    //recover cons modes
1277
228k
    partitioner.modeType = modeTypeParent;
1278
228k
    partitioner.treeType = treeTypeParent;
1279
228k
    partitioner.chType = chTypeParent;
1280
228k
    if( modeTypeParent == MODE_TYPE_ALL )
1281
228k
    {
1282
228k
      m_cIntraSearch.setSaveCuCostInSCIPU( false );
1283
228k
      if( numRoundRdo == 2 && partitioner.modeType == MODE_TYPE_INTRA )
1284
0
      {
1285
0
        m_cIntraSearch.initCuAreaCostInSCIPU();
1286
0
      }
1287
228k
    }
1288
228k
    if( skipInterPass )
1289
0
    {
1290
0
      break;
1291
0
    }
1292
228k
  }
1293
228k
}
1294
1295
void EncCu::xCheckModeSplitInternal(CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode, const ModeType modeTypeParent, bool& skipInterPass )
1296
228k
{
1297
228k
  const int qp                     = encTestMode.qp;
1298
228k
  const int oldPrevQp              = tempCS->prevQP[partitioner.chType];
1299
228k
  const auto oldMotionLut          = tempCS->motionLut;
1300
                                   
1301
228k
  const PartSplit split            = getPartSplit( encTestMode );
1302
228k
  const ModeType  modeTypeChild    = partitioner.modeType;
1303
1304
228k
  CHECK( !( split == CU_QUAD_SPLIT || split == CU_HORZ_SPLIT || split == CU_VERT_SPLIT
1305
228k
         || split == CU_TRIH_SPLIT || split == CU_TRIV_SPLIT ), "invalid split type" );
1306
1307
228k
  tempCS->initStructData( qp );
1308
1309
228k
  m_CABACEstimator->getCtx()       = m_CurrCtx->start;
1310
1311
228k
  const uint16_t split_ctx_size    = Ctx::SplitFlag.size() + Ctx::SplitQtFlag.size() + Ctx::SplitHvFlag.size() + Ctx::Split12Flag.size() + Ctx::ModeConsFlag.size();
1312
228k
  const TempCtx  ctxSplitFlags     ( m_CtxCache, SubCtx( CtxSet( Ctx::SplitFlag(), split_ctx_size ), m_CABACEstimator->getCtx() ) );
1313
1314
228k
  m_CABACEstimator->determineNeighborCus( *tempCS, partitioner.currArea(), partitioner.chType, partitioner.treeType );
1315
228k
  m_CABACEstimator->resetBits           ();
1316
228k
  m_CABACEstimator->split_cu_mode       ( split, *tempCS, partitioner );
1317
228k
  partitioner     . modeType            = modeTypeParent;
1318
228k
  m_CABACEstimator->mode_constraint     ( split, *tempCS, partitioner, modeTypeChild );
1319
228k
  partitioner     . modeType            = modeTypeChild;
1320
1321
228k
  const int64_t splitBits   = m_CABACEstimator->getEstFracBits();
1322
1323
228k
  const bool chromaNotSplit = modeTypeParent == MODE_TYPE_ALL && modeTypeChild == MODE_TYPE_INTRA;
1324
228k
  const bool isChromaTooBig = isChromaEnabled( tempCS->pps->pcv->chrFormat ) && tempCS->area.Y().maxDim() > tempCS->sps->getMaxTbSize();
1325
228k
  bool       skipSplitTest  = chromaNotSplit && isChromaTooBig;
1326
1327
228k
  if( !skipSplitTest )
1328
228k
  {
1329
228k
    double         a = -1, b = -1;
1330
228k
    const unsigned w       = partitioner.currArea().lwidth();
1331
228k
    const unsigned h       = partitioner.currArea().lheight();
1332
228k
    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
228k
    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
228k
    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
228k
    else
1360
228k
    {
1361
228k
      int numChild = 3;
1362
228k
      if( split == CU_VERT_SPLIT || split == CU_HORZ_SPLIT ) numChild--;
1363
55.9k
      else if( split == CU_QUAD_SPLIT ) numChild++;
1364
1365
228k
      int64_t approxBits = m_pcEncCfg->m_qtbttSpeedUp > 0 ? numChild << SCALE_BITS : 0;
1366
1367
228k
      const double factor     = ( tempCS->currQP[partitioner.chType] > 30                              ? 1.1  : 1.075 ) +
1368
228k
                                (   m_pcEncCfg->m_qtbttSpeedUp > 0                                     ? 0.01 : 0.0   ) +
1369
228k
                                ( ( m_pcEncCfg->m_qtbttSpeedUp > 0 && isChroma( partitioner.chType ) ) ? 0.2  : 0.0   );
1370
       
1371
228k
      const double baseCost   = bestCS->cost + bestCS->costDbOffset;
1372
228k
      const double predCost   = baseCost / factor + splitBits + approxBits;
1373
228k
      skipSplitTest           = predCost >= baseCost;
1374
228k
    }
1375
228k
  }
1376
1377
228k
  if( skipSplitTest )
1378
142k
  {
1379
142k
    m_CABACEstimator->getCtx() = SubCtx( CtxSet( Ctx::SplitFlag(), split_ctx_size ), ctxSplitFlags );
1380
142k
    xCheckBestMode( tempCS, bestCS, partitioner, encTestMode );
1381
142k
    return;
1382
142k
  }
1383
1384
85.6k
  if( partitioner.treeType == TREE_D )
1385
85.6k
  {
1386
85.6k
    if( chromaNotSplit )
1387
0
    {
1388
0
      CHECK( partitioner.chType != CH_L, "chType must be luma" );
1389
0
      partitioner.treeType = TREE_L;
1390
0
    }
1391
85.6k
    else
1392
85.6k
    {
1393
85.6k
      partitioner.treeType = TREE_D;
1394
85.6k
    }
1395
85.6k
  }
1396
1397
85.6k
  partitioner.splitCurrArea( split, *tempCS );
1398
85.6k
  bool qgEnableChildren = partitioner.currQgEnable(); // QG possible at children level
1399
1400
85.6k
  m_CurrCtx++;
1401
1402
85.6k
  AffineMVInfo tmpMVInfo;
1403
85.6k
  bool isAffMVInfoSaved = m_cInterSearch.m_AffineProfList->savePrevAffMVInfo( 0, tmpMVInfo );
1404
1405
85.6k
  BlkUniMvInfo tmpUniMvInfo;
1406
85.6k
  bool         isUniMvInfoSaved = false;
1407
85.6k
  if( !tempCS->slice->isIntra() )
1408
0
  {
1409
0
    m_cInterSearch.m_BlkUniMvInfoBuffer->savePrevUniMvInfo( tempCS->area.Y(), tmpUniMvInfo, isUniMvInfoSaved );
1410
0
  }
1411
1412
85.6k
  DeriveCtx deriveCtx = m_CABACEstimator->getDeriveCtx();
1413
1414
85.6k
  do
1415
220k
  {
1416
220k
    const auto &subCUArea  = partitioner.currArea();
1417
1418
220k
    if( tempCS->picture->Y().contains( subCUArea.lumaPos() ) )
1419
156k
    {
1420
156k
      PelStorage* orgBuffer =  &m_pOrgBuffer[partitioner.currDepth];
1421
156k
      CodingStructure *tempSubCS = m_pTempCS[partitioner.currDepth];
1422
156k
      CodingStructure *bestSubCS = m_pBestCS[partitioner.currDepth];
1423
1424
156k
      tempCS->initSubStructure( *tempSubCS, partitioner.chType, subCUArea, false, orgBuffer );
1425
156k
      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
156k
      orgBuffer->copyFrom( tempCS->getOrgBuf( subCUArea ) );
1429
1430
156k
      tempSubCS->bestParent = bestSubCS->bestParent = bestCS;
1431
1432
156k
      xCompressCU(tempSubCS, bestSubCS, partitioner );
1433
1434
156k
      tempSubCS->bestParent = bestSubCS->bestParent = nullptr;
1435
1436
156k
      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
156k
      tempCS->useSubStructure( *bestSubCS, partitioner.chType, TREE_D, CS::getArea( *tempCS, subCUArea, partitioner.chType, partitioner.treeType ), partitioner.hasNextPart() || chromaNotSplit );
1454
1455
156k
      if( partitioner.currQgEnable() )
1456
9.20k
      {
1457
9.20k
        tempCS->prevQP[partitioner.chType] = bestSubCS->prevQP[partitioner.chType];
1458
9.20k
      }
1459
156k
      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
156k
      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
156k
      tempSubCS->releaseIntermediateData();
1475
156k
      bestSubCS->releaseIntermediateData();
1476
156k
      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
156k
    }
1495
220k
  } while( partitioner.nextPart( *tempCS ) );
1496
1497
85.6k
  partitioner.exitCurrSplit();
1498
1499
85.6k
  m_CurrCtx--;
1500
1501
85.6k
  m_CABACEstimator->getDeriveCtx() = deriveCtx;
1502
1503
85.6k
  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
85.6k
  tempCS->fracBits += splitBits; // split bits
1596
85.6k
  tempCS->cost      = m_cRdCost.calcRdCost( tempCS->fracBits, tempCS->dist );
1597
85.6k
  partitioner.modeType = modeTypeParent;
1598
1599
  // Check Delta QP bits for splitted structure
1600
85.6k
  if( !qgEnableChildren ) // check at deepest QG level only
1601
82.2k
    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
85.6k
  if( bestCS->cost == MAX_DOUBLE )
1609
61.4k
  {
1610
61.4k
    bestCS->costDbOffset = 0;
1611
61.4k
  }
1612
1613
85.6k
  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
85.6k
  xCheckBestMode( tempCS, bestCS, partitioner, encTestMode, m_EDO );
1628
1629
85.6k
  if( isAffMVInfoSaved )
1630
0
  {
1631
0
    m_cInterSearch.m_AffineProfList->addAffMVInfo(tmpMVInfo);
1632
0
  }
1633
1634
85.6k
  if( !tempCS->slice->isIntra() && isUniMvInfoSaved )
1635
0
  {
1636
0
    m_cInterSearch.m_BlkUniMvInfoBuffer->addUniMvInfo(tmpUniMvInfo);
1637
0
  }
1638
1639
85.6k
  tempCS->motionLut = oldMotionLut;
1640
85.6k
  tempCS->releaseIntermediateData();
1641
85.6k
  tempCS->prevQP[partitioner.chType] = oldPrevQp;
1642
85.6k
}
1643
1644
1645
void EncCu::xCheckRDCostIntra( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode )
1646
104k
{
1647
104k
  PROFILER_SCOPE_AND_STAGE_EXT( 1, _TPROF, P_INTRA, tempCS, partitioner.chType );
1648
1649
104k
  tempCS->initStructData( encTestMode.qp, false ); // clear motion buffer
1650
1651
104k
  CodingUnit &cu      = tempCS->addCU( CS::getArea( *tempCS, tempCS->area, partitioner.chType, partitioner.treeType ), partitioner.chType );
1652
1653
104k
  partitioner.setCUData( cu );
1654
104k
  cu.slice            = tempCS->slice;
1655
104k
  cu.tileIdx          = m_tileIdx;
1656
104k
  cu.skip             = false;
1657
104k
  cu.mmvdSkip         = false;
1658
104k
  cu.predMode         = MODE_INTRA;
1659
104k
  cu.chromaQpAdj      = m_cuChromaQpOffsetIdxPlus1;
1660
104k
  cu.qp               = encTestMode.qp;
1661
104k
  cu.ispMode          = NOT_INTRA_SUBPARTITIONS;
1662
104k
  cu.initPuData();
1663
1664
104k
  m_cIntraSearch.m_ispTestedModes[0].init(0, 0, 1);
1665
104k
  if (m_pcEncCfg->m_FastIntraTools)
1666
104k
  {
1667
104k
    m_modeCtrl.comprCUCtx->intraWasTested = false;
1668
104k
    m_cIntraSearch.m_ispTestedModes[0].relatedCuIsValid = m_modeCtrl.comprCUCtx->relatedCuIsValid;
1669
104k
    if (!bestCS->cus.empty())
1670
29.1k
    {
1671
29.1k
      if ((bestCS->cus[0]->mergeFlag || bestCS->cus[0]->imv || bestCS->cus[0]->affine) && (!bestCS->cus[0]->ciip))
1672
29.1k
      {
1673
29.1k
        m_cIntraSearch.m_ispTestedModes[0].bestBefore[0] = -1;
1674
29.1k
      }
1675
29.1k
    }
1676
104k
    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
104k
  }
1694
1695
104k
  tempCS->interHad    = m_modeCtrl.comprCUCtx->interHad;
1696
104k
  double maxCostAllowedForChroma = MAX_DOUBLE;
1697
104k
  if( isLuma( partitioner.chType ) )
1698
32.4k
  {
1699
32.4k
    if (!tempCS->slice->isIntra() && bestCS)
1700
0
    {
1701
0
      m_cIntraSearch.estIntraPredLumaQT(cu, partitioner, bestCS->cost);
1702
0
    }
1703
32.4k
    else
1704
32.4k
    {
1705
32.4k
      m_cIntraSearch.estIntraPredLumaQT(cu, partitioner);
1706
32.4k
    }
1707
32.4k
    if (m_pcEncCfg->m_FastIntraTools)
1708
32.4k
    {
1709
32.4k
      if (m_cIntraSearch.m_ispTestedModes[0].intraWasTested)
1710
32.4k
      {
1711
32.4k
        m_modeCtrl.comprCUCtx->intraWasTested = m_cIntraSearch.m_ispTestedModes[0].intraWasTested;
1712
32.4k
      }
1713
32.4k
    }
1714
1715
32.4k
    if( !partitioner.isSepTree( *tempCS ) )
1716
0
    {
1717
0
      tempCS->lumaCost = m_cRdCost.calcRdCost( tempCS->fracBits, tempCS->dist );
1718
0
    }
1719
32.4k
    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
32.4k
  }
1726
1727
104k
  if( tempCS->area.chromaFormat != CHROMA_400 && ( partitioner.chType == CH_C || !CU::isSepTree(cu) ) )
1728
72.5k
  {
1729
72.5k
    bool useIntraSubPartitions = cu.ispMode != NOT_INTRA_SUBPARTITIONS;
1730
72.5k
    Partitioner subTuPartitioner = partitioner;
1731
72.5k
    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
72.5k
    m_cIntraSearch.estIntraPredChromaQT(
1736
72.5k
      cu, (!useIntraSubPartitions || (CU::isSepTree(cu) && !isLuma(CH_C))) ? partitioner : subTuPartitioner,
1737
72.5k
      maxCostAllowedForChroma);
1738
72.5k
    if ((m_pcEncCfg->m_ISP >= 3) && useIntraSubPartitions && !cu.ispMode)
1739
0
    {
1740
0
      return;
1741
0
    }
1742
72.5k
  }
1743
1744
104k
  cu.rootCbf = false;
1745
1746
419k
  for (uint32_t t = 0; t < getNumberValidTBlocks(*cu.cs->pcv); t++)
1747
314k
  {
1748
314k
    cu.rootCbf |= cu.firstTU->cbf[t] != 0;
1749
314k
  }
1750
1751
  // Get total bits for current mode: encode CU
1752
104k
  m_CABACEstimator->resetBits();
1753
1754
104k
  if ((!cu.cs->slice->isIntra() || cu.cs->slice->sps->IBC) && cu.Y().valid())
1755
32.4k
  {
1756
32.4k
    m_CABACEstimator->cu_skip_flag(cu);
1757
32.4k
  }
1758
104k
  m_CABACEstimator->pred_mode(cu);
1759
104k
  m_CABACEstimator->cu_pred_data(cu);
1760
1761
  // Encode Coefficients
1762
104k
  CUCtx cuCtx;
1763
104k
  cuCtx.isDQPCoded = true;
1764
104k
  cuCtx.isChromaQpAdjCoded = true;
1765
104k
  m_CABACEstimator->cu_residual(cu, partitioner, cuCtx);
1766
1767
104k
  tempCS->fracBits = m_CABACEstimator->getEstFracBits();
1768
104k
  tempCS->cost = m_cRdCost.calcRdCost(tempCS->fracBits, tempCS->dist);
1769
1770
104k
  xEncodeDontSplit(*tempCS, partitioner);
1771
1772
104k
  xCheckDQP(*tempCS, partitioner);
1773
1774
104k
  if( m_EDO )
1775
104k
  {
1776
104k
    xCalDebCost(*tempCS, partitioner);
1777
104k
  }
1778
1779
104k
  DTRACE_MODE_COST(*tempCS, m_cRdCost.getLambda(true));
1780
104k
  xCheckBestMode(tempCS, bestCS, partitioner, encTestMode, m_EDO);
1781
1782
104k
  STAT_COUNT_CU_MODES( partitioner.chType == CH_L, g_cuCounters1D[CU_MODES_TESTED][0][!tempCS->slice->isIntra() + tempCS->slice->depth] );
1783
104k
  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
104k
}
1785
1786
void EncCu::xCheckDQP( CodingStructure& cs, Partitioner& partitioner, bool bKeepCtx )
1787
216k
{
1788
216k
  if( !cs.pps->useDQP )
1789
0
  {
1790
0
    return;
1791
0
  }
1792
1793
216k
  if (partitioner.isSepTree(cs) && isChroma(partitioner.chType))
1794
121k
  {
1795
121k
    return;
1796
121k
  }
1797
1798
94.7k
  if( !partitioner.currQgEnable() ) // do not consider split or leaf/not leaf QG condition (checked by caller)
1799
85.0k
  {
1800
85.0k
    return;
1801
85.0k
  }
1802
1803
9.69k
  CodingUnit* cuFirst = cs.getCU( partitioner.chType, partitioner.treeType );
1804
1805
9.69k
  CHECK( bKeepCtx && cs.cus.size() <= 1 && partitioner.getImplicitSplit( cs ) == CU_DONT_SPLIT, "bKeepCtx should only be set in split case" );
1806
9.69k
  CHECK( !bKeepCtx && cs.cus.size() > 1, "bKeepCtx should never be set for non-split case" );
1807
9.69k
  CHECK( !cuFirst, "No CU available" );
1808
1809
9.69k
  bool hasResidual = false;
1810
9.69k
  for( const auto &cu : cs.cus )
1811
26.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
26.7k
    if( cu->rootCbf && !isChroma( cu->chType ))
1814
1.50k
    {
1815
1.50k
      hasResidual = true;
1816
1.50k
      break;
1817
1.50k
    }
1818
26.7k
  }
1819
1820
9.69k
  int predQP = CU::predictQP( *cuFirst, cs.prevQP[partitioner.chType] );
1821
1822
9.69k
  if( hasResidual )
1823
1.50k
  {
1824
1.50k
    TempCtx ctxTemp( m_CtxCache );
1825
1.50k
    if( !bKeepCtx ) ctxTemp = SubCtx( Ctx::DeltaQP, m_CABACEstimator->getCtx() );
1826
1827
1.50k
    m_CABACEstimator->resetBits();
1828
1.50k
    m_CABACEstimator->cu_qp_delta( *cuFirst, predQP, cuFirst->qp );
1829
1830
1.50k
    cs.fracBits += m_CABACEstimator->getEstFracBits(); // dQP bits
1831
1.50k
    cs.cost      = m_cRdCost.calcRdCost(cs.fracBits, cs.dist);
1832
1833
1834
1.50k
    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.50k
    for( const auto &cu : cs.cus )
1838
1.50k
    {
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.50k
      if( cu->rootCbf && !isChroma( cu->chType ))
1841
1.50k
      {
1842
1.50k
        break;
1843
1.50k
      }
1844
7
      cu->qp = predQP;
1845
7
    }
1846
1.50k
  }
1847
8.19k
  else
1848
8.19k
  {
1849
    // No residuals: reset CU QP to predicted value
1850
8.19k
    for( const auto &cu : cs.cus )
1851
25.2k
    {
1852
25.2k
      cu->qp = predQP;
1853
25.2k
    }
1854
8.19k
  }
1855
9.69k
}
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->hasBlockQpOffsets() && !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
32.4k
{
2893
32.4k
  assert(partitioner.chType != CH_C); // chroma IBC is derived
2894
32.4k
  if (tempCS->area.lwidth() == 128 || tempCS->area.lheight() == 128) // disable IBC mode larger than 64x64
2895
0
  {
2896
0
    return;
2897
0
  }
2898
2899
32.4k
  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
32.4k
  const SPS& sps = *tempCS->sps;
2908
2909
32.4k
  tempCS->initStructData(encTestMode.qp);
2910
32.4k
  MergeCtx mergeCtx;
2911
2912
32.4k
  {
2913
    // first get merge candidates
2914
32.4k
    CodingUnit cu(tempCS->area);
2915
32.4k
    cu.cs = tempCS;
2916
32.4k
    cu.predMode = MODE_IBC;
2917
32.4k
    cu.slice = tempCS->slice;
2918
32.4k
    cu.tileIdx = m_tileIdx;
2919
32.4k
    cu.initPuData();
2920
32.4k
    cu.cs = tempCS;
2921
32.4k
    cu.mmvdSkip = false;
2922
32.4k
    cu.mmvdMergeFlag = false;
2923
32.4k
    cu.geo = false;
2924
32.4k
    CU::getIBCMergeCandidates(cu, mergeCtx);
2925
32.4k
  }
2926
32.4k
  int candHasNoResidual[MRG_MAX_NUM_CANDS];
2927
226k
  for (unsigned int ui = 0; ui < mergeCtx.numValidMergeCand; ui++)
2928
194k
  {
2929
194k
    candHasNoResidual[ui] = 0;
2930
194k
  }
2931
2932
32.4k
  bool                                        bestIsSkip = false;
2933
32.4k
  unsigned                                    numMrgSATDCand = mergeCtx.numValidMergeCand;
2934
32.4k
  static_vector<unsigned, MRG_MAX_NUM_CANDS>  RdModeList(MRG_MAX_NUM_CANDS);
2935
226k
  for (unsigned i = 0; i < MRG_MAX_NUM_CANDS; i++)
2936
194k
  {
2937
194k
    RdModeList[i] = i;
2938
194k
  }
2939
2940
  //{
2941
32.4k
  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
32.4k
  {
2944
32.4k
    const double sqrtLambdaForFirstPass = m_cRdCost.getMotionLambda();
2945
2946
32.4k
    CodingUnit& cu = tempCS->addCU(CS::getArea(*tempCS, tempCS->area, partitioner.chType,partitioner.treeType), partitioner.chType);
2947
2948
32.4k
    partitioner.setCUData(cu);
2949
32.4k
    cu.slice = tempCS->slice;
2950
32.4k
    cu.tileIdx = m_tileIdx;
2951
32.4k
    cu.skip = false;
2952
32.4k
    cu.predMode = MODE_IBC;
2953
32.4k
    cu.chromaQpAdj = m_cuChromaQpOffsetIdxPlus1;
2954
32.4k
    cu.qp = encTestMode.qp;
2955
32.4k
    cu.mmvdSkip = false;
2956
32.4k
    cu.geo = false;
2957
32.4k
    DistParam distParam;
2958
32.4k
    cu.initPuData();
2959
32.4k
    cu.mmvdMergeFlag = false;
2960
32.4k
    Picture* refPic = cu.slice->pic;
2961
32.4k
    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
32.4k
    const CompArea& compArea = localUnitArea.block(COMP_Y);
2963
32.4k
    const CPelBuf refBuf = refPic->getRecoBuf(compArea);
2964
32.4k
    const Pel* piRefSrch = refBuf.buf;
2965
2966
32.4k
      distParam = m_cRdCost.setDistParam(tempCS->getOrgBuf(COMP_Y), refBuf, sps.bitDepths[CH_L], DF_HAD);
2967
32.4k
    int refStride = refBuf.stride;
2968
2969
32.4k
    int numValidBv = mergeCtx.numValidMergeCand;
2970
226k
    for (unsigned int mergeCand = 0; mergeCand < mergeCtx.numValidMergeCand; mergeCand++)
2971
194k
    {
2972
194k
      mergeCtx.setMergeInfo(cu, mergeCand); // set bv info in merge mode
2973
194k
      const int cuPelX = cu.Y().x;
2974
194k
      const int cuPelY = cu.Y().y;
2975
194k
      int roiWidth     = cu.lwidth();
2976
194k
      int roiHeight    = cu.lheight();
2977
194k
      const int picWidth  = cu.cs->slice->pps->picWidthInLumaSamples;
2978
194k
      const int picHeight = cu.cs->slice->pps->picHeightInLumaSamples;
2979
194k
      const unsigned int lcuWidth = cu.cs->slice->sps->CTUSize;
2980
2981
194k
      Mv bv = cu.mv[0][0];
2982
194k
      bv.changePrecision( MV_PRECISION_INTERNAL, MV_PRECISION_INT);
2983
194k
      int xPred = bv.hor;
2984
194k
      int yPred = bv.ver;
2985
      
2986
194k
      if( !m_cInterSearch.searchBvIBC( cu, cuPelX, cuPelY, roiWidth, roiHeight, picWidth, picHeight, xPred, yPred, lcuWidth ) ) // not valid bv derived
2987
194k
      {
2988
194k
        numValidBv--;
2989
194k
        continue;
2990
194k
      }
2991
0
      CU::spanMotionInfo(cu);
2992
0
      distParam.cur.buf = piRefSrch + refStride * yPred + xPred;
2993
2994
0
      Distortion sad = distParam.distFunc(distParam);
2995
0
      unsigned int bitsCand = mergeCand + 1;
2996
0
      if (mergeCand == tempCS->sps->maxNumIBCMergeCand - 1)
2997
0
      {
2998
0
        bitsCand--;
2999
0
      }
3000
0
      double cost = (double)sad + (double)bitsCand * sqrtLambdaForFirstPass;
3001
3002
0
      updateCandList( mergeCand, cost, RdModeList, candCostList, numMrgSATDCand );
3003
0
    }
3004
3005
    // Try to limit number of candidates using SATD-costs
3006
32.4k
    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
32.4k
    else
3019
32.4k
    {
3020
32.4k
      tempCS->dist = 0;
3021
32.4k
      tempCS->fracBits = 0;
3022
32.4k
      tempCS->cost = MAX_DOUBLE;
3023
32.4k
      tempCS->costDbOffset = 0;
3024
32.4k
      tempCS->initStructData(encTestMode.qp);
3025
32.4k
      return;
3026
32.4k
    }
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
32.4k
{
3100
32.4k
  if (tempCS->area.lwidth() == 128 || tempCS->area.lheight() == 128)   // disable IBC mode larger than 64x64
3101
0
  {
3102
0
    return;
3103
0
  }
3104
32.4k
  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
32.4k
  tempCS->initStructData(encTestMode.qp);
3113
3114
32.4k
  CodingUnit& cu = tempCS->addCU(CS::getArea(*tempCS, tempCS->area, partitioner.chType, partitioner.treeType), partitioner.chType);
3115
3116
32.4k
  partitioner.setCUData(cu);
3117
32.4k
  cu.slice = tempCS->slice;
3118
32.4k
  cu.tileIdx = m_tileIdx;
3119
32.4k
  cu.skip = false;
3120
32.4k
  cu.predMode = MODE_IBC;
3121
32.4k
  cu.chromaQpAdj = m_cuChromaQpOffsetIdxPlus1;
3122
32.4k
  cu.qp = encTestMode.qp;
3123
32.4k
  cu.initPuData();
3124
32.4k
  cu.imv = IMV_OFF;
3125
32.4k
  cu.sbtInfo = 0;
3126
32.4k
  cu.mmvdSkip = false;
3127
32.4k
  cu.mmvdMergeFlag = false;
3128
3129
32.4k
  cu.intraDir[0] = DC_IDX; // set intra pred for ibc block
3130
32.4k
  cu.intraDir[1] = PLANAR_IDX; // set intra pred for ibc block
3131
3132
32.4k
  cu.interDir = 1; // use list 0 for IBC mode
3133
32.4k
  cu.refIdx[REF_PIC_LIST_0] = MAX_NUM_REF; // last idx in the list
3134
32.4k
  bool bValid = m_cInterSearch.predIBCSearch(cu, partitioner);
3135
3136
32.4k
  if (bValid)
3137
29.1k
  {
3138
29.1k
    CU::spanMotionInfo(cu);
3139
29.1k
    const bool chroma = !CU::isSepTree(cu);
3140
    //  MC
3141
29.1k
    cu.mcControl = chroma ? 0 : 2;
3142
29.1k
    m_cInterSearch.motionCompensationIBC(cu, tempCS->getPredBuf());
3143
3144
29.1k
    m_cInterSearch.encodeResAndCalcRdInterCU(*tempCS, partitioner, false);
3145
29.1k
    cu.mcControl = 0;
3146
3147
29.1k
    xEncodeDontSplit(*tempCS, partitioner);
3148
29.1k
    xCheckDQP(*tempCS, partitioner);
3149
29.1k
    xCheckBestMode(tempCS, bestCS, partitioner, encTestMode);
3150
29.1k
  } // bValid
3151
3.29k
  else
3152
3.29k
  {
3153
3.29k
    tempCS->dist = 0;
3154
3.29k
    tempCS->fracBits = 0;
3155
3.29k
    tempCS->cost = MAX_DOUBLE;
3156
3.29k
    tempCS->costDbOffset = 0;
3157
3.29k
  }
3158
32.4k
}
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
134k
{
3548
134k
  PROFILER_SCOPE_AND_STAGE_EXT( 1, _TPROF, P_DEBLOCK_FILTER, &cs, partitioner.chType );
3549
134k
  if ( cs.slice->deblockingFilterDisable )
3550
0
  {
3551
0
    return;
3552
0
  }
3553
3554
134k
  const ChromaFormat format = cs.area.chromaFormat;
3555
134k
  CodingUnit*            cu = cs.getCU(partitioner.chType, partitioner.treeType);
3556
134k
  const Position    lumaPos = cu->Y().valid() ? cu->Y().pos() : recalcPosition( format, cu->chType, CH_L, cu->blocks[cu->chType].pos() );
3557
134k
  bool    topEdgeAvai = lumaPos.y > 0 && ((lumaPos.y % 4) == 0);
3558
134k
  bool   leftEdgeAvai = lumaPos.x > 0 && ((lumaPos.x % 4) == 0);
3559
3560
134k
  if( ! ( topEdgeAvai || leftEdgeAvai ))
3561
27.1k
  {
3562
27.1k
    return;
3563
27.1k
  }
3564
3565
106k
  ComponentID compStr = ( CU::isSepTree(*cu) && !isLuma( partitioner.chType ) ) ? COMP_Cb : COMP_Y;
3566
106k
  ComponentID compEnd = (( CU::isSepTree(*cu) && isLuma( partitioner.chType )) || cu->chromaFormat == VVENC_CHROMA_400 ) ? COMP_Y : COMP_Cr;
3567
106k
  const UnitArea currCsArea = clipArea( CS::getArea( cs, cs.area, partitioner.chType, partitioner.treeType ), *cs.picture );
3568
3569
106k
  PelStorage&  picDbBuf = m_dbBuffer; //th we could reduce the buffer size and do some relocate
3570
3571
  //deblock neighbour pixels
3572
106k
  const Size     lumaSize = cu->Y().valid() ? cu->Y().size() : recalcSize( format, cu->chType, CH_L, cu->blocks[cu->chType].size() );
3573
3574
106k
  int verOffset = lumaPos.y > 7 ? 8 : 4;
3575
106k
  int horOffset = lumaPos.x > 7 ? 8 : 4;
3576
3577
106k
  LoopFilter::calcFilterStrengths( *cu, true );
3578
3579
106k
  if( m_EDO == 2 && CS::isDualITree( cs ) && isLuma( partitioner.chType ) )
3580
59.4k
  {
3581
59.4k
    m_cLoopFilter.getMaxFilterLength( *cu, verOffset, horOffset );
3582
3583
59.4k
    if( 0== (verOffset + horOffset) )
3584
0
    {
3585
0
      return;
3586
0
    }
3587
3588
59.4k
    topEdgeAvai  &= verOffset != 0;
3589
59.4k
    leftEdgeAvai &= horOffset != 0;
3590
59.4k
  }
3591
3592
106k
  const UnitArea  areaTop  = UnitArea( format, Area( lumaPos.x,             lumaPos.y - verOffset, lumaSize.width, verOffset       ) );
3593
106k
  const UnitArea  areaLeft = UnitArea( format, Area( lumaPos.x - horOffset, lumaPos.y,             horOffset,      lumaSize.height ) );
3594
3595
261k
  for ( int compIdx = compStr; compIdx <= compEnd; compIdx++ )
3596
154k
  {
3597
154k
    ComponentID compId = (ComponentID)compIdx;
3598
3599
    //Copy current CU's reco to Deblock Pic Buffer
3600
154k
    const CompArea&  compArea = currCsArea.block( compId );
3601
154k
    CompArea         locArea  = compArea;
3602
154k
    locArea.x -= cu->blocks[compIdx].x;
3603
154k
    locArea.y -= cu->blocks[compIdx].y;
3604
154k
    PelBuf dbReco = picDbBuf.getBuf( locArea );
3605
154k
      PelBuf reco = cs.getRecoBuf( compId );
3606
154k
      dbReco.copyFrom( reco );
3607
    //left neighbour
3608
154k
    if ( leftEdgeAvai )
3609
108k
    {
3610
108k
      const CompArea&  compArea = areaLeft.block(compId);
3611
108k
      CompArea         locArea = compArea;
3612
108k
      locArea.x -= cu->blocks[compIdx].x;
3613
108k
      locArea.y -= cu->blocks[compIdx].y;
3614
108k
      PelBuf dbReco = picDbBuf.getBuf( locArea );
3615
108k
        dbReco.copyFrom( cs.picture->getRecoBuf( compArea ) );
3616
108k
      }
3617
    //top neighbour
3618
154k
    if ( topEdgeAvai )
3619
112k
    {
3620
112k
      const CompArea&  compArea = areaTop.block( compId );
3621
112k
      CompArea         locArea = compArea;
3622
112k
      locArea.x -= cu->blocks[compIdx].x;
3623
112k
      locArea.y -= cu->blocks[compIdx].y;
3624
112k
      PelBuf dbReco = picDbBuf.getBuf( locArea );
3625
112k
        dbReco.copyFrom( cs.picture->getRecoBuf( compArea ) );
3626
112k
      }
3627
154k
    }
3628
3629
18.4E
  ChannelType dbChType = CU::isSepTree(*cu) ? partitioner.chType : MAX_NUM_CH;
3630
3631
106k
  CHECK( CU::isSepTree(*cu) && !cu->Y().valid() && partitioner.chType == CH_L, "xxx" );
3632
3633
106k
  if( cu->Y() .valid() ) m_cLoopFilter.setOrigin( CH_L, cu->lumaPos() );
3634
106k
  if( cu->chromaFormat != VVENC_CHROMA_400 && cu->Cb().valid() ) m_cLoopFilter.setOrigin( CH_C, cu->chromaPos() );
3635
3636
  //deblock
3637
106k
  if( leftEdgeAvai )
3638
79.4k
  {
3639
79.4k
    m_cLoopFilter.loopFilterCu( *cu, dbChType, EDGE_VER, m_dbBuffer );
3640
79.4k
  }
3641
3642
106k
  if( topEdgeAvai )
3643
81.1k
  {
3644
81.1k
    m_cLoopFilter.loopFilterCu( *cu, dbChType, EDGE_HOR, m_dbBuffer );
3645
81.1k
  }
3646
3647
  //calculate difference between DB_before_SSE and DB_after_SSE for neighbouring CUs
3648
106k
  Distortion distBeforeDb = 0, distAfterDb = 0, distCur = 0;
3649
261k
  for (int compIdx = compStr; compIdx <= compEnd; compIdx++)
3650
154k
  {
3651
154k
    ComponentID compId = (ComponentID)compIdx;
3652
154k
    {
3653
154k
      CompArea compArea = currCsArea.block( compId );
3654
154k
      CompArea         locArea  = compArea;
3655
154k
      locArea.x -= cu->blocks[compIdx].x;
3656
154k
      locArea.y -= cu->blocks[compIdx].y;
3657
154k
      CPelBuf reco      = picDbBuf.getBuf( locArea );
3658
154k
      CPelBuf org       = cs.getOrgBuf( compId );
3659
154k
      distCur += xGetDistortionDb( cs, org, reco, compArea, false );
3660
154k
    }
3661
3662
154k
    if ( leftEdgeAvai )
3663
108k
    {
3664
108k
      const CompArea&  compArea = areaLeft.block( compId );
3665
108k
      CompArea         locArea  = compArea;
3666
108k
      locArea.x -= cu->blocks[compIdx].x;
3667
108k
      locArea.y -= cu->blocks[compIdx].y;
3668
108k
      CPelBuf org    = cs.picture->getOrigBuf( compArea );
3669
108k
      if ( cs.picture->getFilteredOrigBuffer().valid() )
3670
0
      {
3671
0
        org = cs.picture->getFiltOrigBuf( compArea );
3672
0
      }
3673
108k
      CPelBuf reco   = cs.picture->getRecoBuf( compArea );
3674
108k
      CPelBuf recoDb = picDbBuf.getBuf( locArea );
3675
108k
      distBeforeDb  += xGetDistortionDb( cs, org, reco,   compArea, true );
3676
108k
      distAfterDb   += xGetDistortionDb( cs, org, recoDb, compArea, false  );
3677
108k
    }
3678
3679
154k
    if ( topEdgeAvai )
3680
112k
    {
3681
112k
      const CompArea&  compArea = areaTop.block( compId );
3682
112k
      CompArea         locArea  = compArea;
3683
112k
      locArea.x -= cu->blocks[compIdx].x;
3684
112k
      locArea.y -= cu->blocks[compIdx].y;
3685
112k
      CPelBuf org    = cs.picture->getOrigBuf( compArea );
3686
112k
      if ( cs.picture->getFilteredOrigBuffer().valid() )
3687
0
      {
3688
0
        org = cs.picture->getFiltOrigBuf( compArea );
3689
0
      }
3690
112k
      CPelBuf reco   = cs.picture->getRecoBuf( compArea );
3691
112k
      CPelBuf recoDb = picDbBuf.getBuf( locArea );
3692
112k
      distBeforeDb  += xGetDistortionDb( cs, org, reco,   compArea, true );
3693
112k
      distAfterDb   += xGetDistortionDb( cs, org, recoDb, compArea, false  );
3694
112k
    }
3695
154k
  }
3696
3697
  //updated cost
3698
106k
  int64_t distTmp = distCur - cs.dist + distAfterDb - distBeforeDb;
3699
106k
  cs.costDbOffset = distTmp < 0 ? -m_cRdCost.calcRdCost( 0, -distTmp ) : m_cRdCost.calcRdCost( 0, distTmp );
3700
106k
}
3701
3702
Distortion EncCu::xGetDistortionDb(CodingStructure &cs, CPelBuf& org, CPelBuf& reco, const CompArea& compArea, bool beforeDb)
3703
597k
{
3704
597k
  Distortion dist;
3705
597k
  const ComponentID compID = compArea.compID;
3706
3707
597k
  dist = m_cRdCost.getDistPart(org, reco, cs.sps->bitDepths[toChannelType(compID)], compID, DF_SSE);
3708
597k
  return dist;
3709
597k
}
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
134k
{
4050
134k
  m_CABACEstimator->resetBits();
4051
4052
134k
  m_CABACEstimator->split_cu_mode( CU_DONT_SPLIT, cs, partitioner );
4053
134k
  if( partitioner.treeType == TREE_C )
4054
134k
    CHECK( m_CABACEstimator->getEstFracBits() != 0, "must be 0 bit" );
4055
4056
134k
  cs.fracBits += m_CABACEstimator->getEstFracBits(); // split bits
4057
134k
  cs.cost      = m_cRdCost.calcRdCost( cs.fracBits, cs.dist );
4058
134k
}
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
47.7k
{
4198
4199
47.7k
}
4200
MergeItem::~MergeItem()
4201
47.7k
{
4202
4203
47.7k
}
4204
4205
void MergeItem::create( ChromaFormat chromaFormat, const Area &area )
4206
47.7k
{
4207
47.7k
  if( m_pelStorage.bufs.empty() )
4208
47.7k
  {
4209
47.7k
    m_pelStorage.create( chromaFormat, area );
4210
47.7k
    m_mvStorage .resize( area.area() >> ( MIN_CU_LOG2 << 1 ) );
4211
47.7k
  }
4212
4213
47.7k
  init();
4214
47.7k
}
4215
4216
void MergeItem::init()
4217
47.7k
{
4218
  // reset data
4219
47.7k
  cost        = MAX_DOUBLE;
4220
47.7k
  mergeIdx    = 0;
4221
47.7k
  bcwIdx      = 0;
4222
47.7k
  interDir    = 0;
4223
47.7k
  useAltHpelIf  = false;
4224
47.7k
  affineType    = AFFINEMODEL_4PARAM;
4225
47.7k
  mergeItemType = MergeItemType::NUM;
4226
4227
47.7k
  noBdofRefine  = false;
4228
47.7k
  noResidual    = false;
4229
4230
47.7k
  lumaPredReady   = false;
4231
47.7k
  chromaPredReady = false;
4232
47.7k
}
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
5.97k
{
4426
4427
5.97k
}
4428
4429
MergeItemList::~MergeItemList()
4430
5.97k
{
4431
5.97k
  for( MergeItem* p : m_list )
4432
0
  {
4433
0
    delete p;
4434
0
  }
4435
5.97k
  m_list.clear();
4436
4437
5.97k
  for( MergeItem *p : m_mergeItems )
4438
47.7k
  {
4439
47.7k
    delete p;
4440
47.7k
  }
4441
5.97k
  m_mergeItems.clear();
4442
5.97k
}
4443
4444
void MergeItemList::init( size_t maxSize, size_t maxExtSize, ChromaFormat chromaFormat, SizeType ctuWidth, SizeType ctuHeight )
4445
5.97k
{
4446
5.97k
  CHECK( !m_mergeItems.empty() || !m_list.empty(), "MergeItemList already initialized" );
4447
4448
5.97k
  m_list      . reserve( maxSize + 1 ); // to avoid reallocation when inserting a new item
4449
5.97k
  m_mergeItems. reserve( maxSize + 1 );
4450
5.97k
  m_maxSize   = maxSize;
4451
5.97k
  m_maxExtSize= maxExtSize;
4452
5.97k
  m_numExt    = 0;
4453
4454
53.7k
  for( int i = 0; i < maxSize + m_maxExtSize; i++ )
4455
47.7k
  {
4456
47.7k
    MergeItem *p = new MergeItem;
4457
47.7k
    p->create( chromaFormat, Area{ 0, 0, ctuWidth, ctuHeight } );
4458
47.7k
    m_mergeItems.push_back( p );
4459
47.7k
  }
4460
5.97k
}
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
//! \}