/src/vvenc/source/Lib/EncoderLib/SEIEncoder.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 | | #include "SEIEncoder.h" |
45 | | |
46 | | #include "vvenc/vvencCfg.h" |
47 | | #include "CommonLib/CommonDef.h" |
48 | | #include "CommonLib/SEI.h" |
49 | | #include "CommonLib/PicYuvMD5.h" |
50 | | #include "CommonLib/HRD.h" |
51 | | #include "CommonLib/Slice.h" |
52 | | #include "EncHRD.h" |
53 | | #include "GOPCfg.h" |
54 | | |
55 | | //! \ingroup EncoderLib |
56 | | //! \{ |
57 | | |
58 | | namespace vvenc { |
59 | | |
60 | | void SEIEncoder::init( const VVEncCfg& encCfg, const GOPCfg* gopCfg, EncHRD& encHRD) |
61 | 0 | { |
62 | 0 | m_pcEncCfg = &encCfg; |
63 | 0 | m_gopCfg = gopCfg; |
64 | 0 | m_pcEncHRD = &encHRD; |
65 | 0 | m_isInitialized = true; |
66 | 0 | ::memset(m_lastBPSEI, 0, sizeof(m_lastBPSEI)); |
67 | 0 | ::memset(m_totalCoded, 0, sizeof(m_totalCoded)); |
68 | 0 | } |
69 | | |
70 | | void SEIEncoder::initBufferingPeriodSEI( SEIBufferingPeriod& bpSei, bool noLeadingPictures) |
71 | 0 | { |
72 | 0 | CHECK(!(m_isInitialized), "bufferingPeriodSEI already initialized"); |
73 | |
|
74 | 0 | uint32_t uiInitialCpbRemovalDelay = (90000/2); // 0.5 sec |
75 | 0 | bpSei.bpNalCpbParamsPresent = true; |
76 | 0 | bpSei.bpVclCpbParamsPresent = true; |
77 | 0 | bpSei.bpMaxSubLayers = m_pcEncCfg->m_maxTLayer + 1; |
78 | 0 | bpSei.bpCpbCnt = 1; |
79 | 0 | for(int i=0; i < bpSei.bpMaxSubLayers; i++) |
80 | 0 | { |
81 | 0 | for(int j=0; j < bpSei.bpCpbCnt; j++) |
82 | 0 | { |
83 | 0 | bpSei.initialCpbRemovalDelay[j][i][0] = uiInitialCpbRemovalDelay; |
84 | 0 | bpSei.initialCpbRemovalDelay[j][i][1] = uiInitialCpbRemovalDelay; |
85 | 0 | bpSei.initialCpbRemovalOffset[j][i][0] = uiInitialCpbRemovalDelay; |
86 | 0 | bpSei.initialCpbRemovalOffset[j][i][1] = uiInitialCpbRemovalDelay; |
87 | 0 | } |
88 | 0 | } |
89 | | // We don't set concatenation_flag here. max_initial_removal_delay_for_concatenation depends on the usage scenario. |
90 | | // The parameters could be added to config file, but as long as the initialisation of generic buffering parameters is |
91 | | // not controllable, it does not seem to make sense to provide settings for these. |
92 | 0 | bpSei.concatenationFlag = false; |
93 | 0 | bpSei.maxInitialRemovalDelayForConcatenation = uiInitialCpbRemovalDelay; |
94 | 0 | bpSei.bpDecodingUnitHrdParamsPresent = false;//m_pcEncCfg->m_noPicPartitionFlag == false; |
95 | 0 | bpSei.decodingUnitCpbParamsInPicTimingSeiFlag = !m_pcEncCfg->m_decodingUnitInfoSEIEnabled; |
96 | 0 | bpSei.initialCpbRemovalDelayLength = 16; // assuming 0.5 sec, log2( 90,000 * 0.5 ) = 16-bit |
97 | | // Note: The following parameters require some knowledge about the GOP structure. |
98 | | // Using getIntraPeriod() should be avoided though, because it assumes certain GOP |
99 | | // properties, which are only valid in CTC. |
100 | | // Still copying this setting from HM for consistency, improvements welcome |
101 | 0 | bool isRandomAccess = m_pcEncCfg->m_picReordering; |
102 | 0 | if( isRandomAccess && m_pcEncCfg->m_IntraPeriod < 256) |
103 | 0 | { |
104 | 0 | bpSei.cpbRemovalDelayLength = // 6 // 32 = 2^5 (plus 1) |
105 | 0 | bpSei.dpbOutputDelayLength = ceilLog2( m_pcEncCfg->m_IntraPeriod)+1; // 6 // 32 + 3 = 2^6 |
106 | 0 | } |
107 | 0 | else |
108 | 0 | { |
109 | 0 | bpSei.cpbRemovalDelayLength = 9; // max. 2^10 |
110 | 0 | bpSei.dpbOutputDelayLength = 9; // max. 2^10 |
111 | 0 | } |
112 | 0 | bpSei.duCpbRemovalDelayIncrementLength = 7; // ceil( log2( tick_divisor_minus2 + 2 ) ) |
113 | 0 | bpSei.dpbOutputDelayDuLength = bpSei.dpbOutputDelayLength + bpSei.duCpbRemovalDelayIncrementLength; |
114 | | //for the concatenation, it can be set to one during splicing. |
115 | 0 | bpSei.concatenationFlag = 0; |
116 | | //since the temporal layer HRDParameters is not ready, we assumed it is fixed |
117 | 0 | bpSei.auCpbRemovalDelayDelta = 1; |
118 | 0 | CHECK( m_pcEncCfg->m_IntraPeriod % m_pcEncCfg->m_GOPSize != 0, "broken for aip" ); |
119 | 0 | bool bpDeltasGOPStructure = m_pcEncCfg->m_GOPSize == 8 || m_pcEncCfg->m_GOPSize == 16; //assume GOPs specified as in CTC |
120 | 0 | bpSei.cpbRemovalDelayDeltasPresent = bpDeltasGOPStructure; |
121 | 0 | if (bpSei.cpbRemovalDelayDeltasPresent) |
122 | 0 | { |
123 | 0 | switch (m_pcEncCfg->m_GOPSize) |
124 | 0 | { |
125 | 0 | case 8: |
126 | 0 | { |
127 | 0 | if (noLeadingPictures) |
128 | 0 | { |
129 | 0 | bpSei.numCpbRemovalDelayDeltas = 5; |
130 | 0 | bpSei.cpbRemovalDelayDelta[0] = 1; |
131 | 0 | bpSei.cpbRemovalDelayDelta[1] = 2; |
132 | 0 | bpSei.cpbRemovalDelayDelta[2] = 3; |
133 | 0 | bpSei.cpbRemovalDelayDelta[3] = 6; |
134 | 0 | bpSei.cpbRemovalDelayDelta[4] = 7; |
135 | 0 | } |
136 | 0 | else |
137 | 0 | { |
138 | 0 | bpSei.numCpbRemovalDelayDeltas = 3; |
139 | 0 | bpSei.cpbRemovalDelayDelta[0] = 1; |
140 | 0 | bpSei.cpbRemovalDelayDelta[1] = 2; |
141 | 0 | bpSei.cpbRemovalDelayDelta[2] = 3; |
142 | 0 | } |
143 | 0 | } |
144 | 0 | break; |
145 | 0 | case 16: |
146 | 0 | { |
147 | 0 | if (noLeadingPictures) |
148 | 0 | { |
149 | 0 | bpSei.numCpbRemovalDelayDeltas = 9; |
150 | 0 | bpSei.cpbRemovalDelayDelta[0] = 1; |
151 | 0 | bpSei.cpbRemovalDelayDelta[1] = 2; |
152 | 0 | bpSei.cpbRemovalDelayDelta[2] = 3; |
153 | 0 | bpSei.cpbRemovalDelayDelta[3] = 4; |
154 | 0 | bpSei.cpbRemovalDelayDelta[4] = 6; |
155 | 0 | bpSei.cpbRemovalDelayDelta[5] = 7; |
156 | 0 | bpSei.cpbRemovalDelayDelta[6] = 9; |
157 | 0 | bpSei.cpbRemovalDelayDelta[7] = 14; |
158 | 0 | bpSei.cpbRemovalDelayDelta[8] = 15; |
159 | 0 | } |
160 | 0 | else |
161 | 0 | { |
162 | 0 | bpSei.numCpbRemovalDelayDeltas = 5; |
163 | 0 | bpSei.cpbRemovalDelayDelta[0] = 1; |
164 | 0 | bpSei.cpbRemovalDelayDelta[1] = 2; |
165 | 0 | bpSei.cpbRemovalDelayDelta[2] = 3; |
166 | 0 | bpSei.cpbRemovalDelayDelta[3] = 6; |
167 | 0 | bpSei.cpbRemovalDelayDelta[4] = 7; |
168 | 0 | } |
169 | 0 | } |
170 | 0 | break; |
171 | 0 | default: |
172 | 0 | { |
173 | 0 | THROW("m_cpbRemovalDelayDelta not applicable for the GOP size"); |
174 | 0 | } |
175 | 0 | break; |
176 | 0 | } |
177 | 0 | } |
178 | 0 | bpSei.sublayerDpbOutputOffsetsPresent = true; |
179 | 0 | const std::vector<int>& numReorderPics = m_gopCfg->getNumReorderPics(); |
180 | 0 | for(int i = 0; i < bpSei.bpMaxSubLayers; i++) |
181 | 0 | { |
182 | 0 | bpSei.dpbOutputTidOffset[i] = numReorderPics[i] * (1<<(bpSei.bpMaxSubLayers-1-i)); |
183 | 0 | if(bpSei.dpbOutputTidOffset[i] >= numReorderPics[bpSei.bpMaxSubLayers-1]) |
184 | 0 | { |
185 | 0 | bpSei.dpbOutputTidOffset[i] -= numReorderPics[bpSei.bpMaxSubLayers-1]; |
186 | 0 | } |
187 | 0 | else |
188 | 0 | { |
189 | 0 | bpSei.dpbOutputTidOffset[i] = 0; |
190 | 0 | } |
191 | 0 | } |
192 | | // A commercial encoder should track the buffer state for all layers and sub-layers |
193 | | // to ensure CPB conformance. Such tracking is required for calculating alternative |
194 | | // CPB parameters. |
195 | | // Unfortunately VTM does not have such tracking. Thus we cannot encode alternative |
196 | | // CPB parameters here. |
197 | 0 | bpSei.altCpbParamsPresent = false; |
198 | 0 | bpSei.useAltCpbParamsFlag = false; |
199 | 0 | } |
200 | | |
201 | | //! calculate hashes for entire reconstructed picture |
202 | | void SEIEncoder::initDecodedPictureHashSEI( SEIDecodedPictureHash& dphSei, const CPelUnitBuf& pic, std::string &rHashString, const BitDepths &bitDepths) |
203 | 0 | { |
204 | 0 | CHECK(!(m_isInitialized), "Unspecified error"); |
205 | |
|
206 | 0 | dphSei.method = m_pcEncCfg->m_decodedPictureHashSEIType; |
207 | 0 | dphSei.singleCompFlag = m_pcEncCfg->m_internChromaFormat == 0; |
208 | |
|
209 | 0 | switch (m_pcEncCfg->m_decodedPictureHashSEIType) |
210 | 0 | { |
211 | 0 | case VVENC_HASHTYPE_MD5: |
212 | 0 | case VVENC_HASHTYPE_MD5_LOG: |
213 | 0 | { |
214 | 0 | uint32_t numChar=calcMD5(pic, dphSei.pictureHash, bitDepths); |
215 | 0 | rHashString = hashToString(dphSei.pictureHash, numChar); |
216 | 0 | } |
217 | 0 | break; |
218 | 0 | case VVENC_HASHTYPE_CRC: |
219 | 0 | case VVENC_HASHTYPE_CRC_LOG: |
220 | 0 | { |
221 | 0 | uint32_t numChar=calcCRC(pic, dphSei.pictureHash, bitDepths); |
222 | 0 | rHashString = hashToString(dphSei.pictureHash, numChar); |
223 | 0 | } |
224 | 0 | break; |
225 | 0 | case VVENC_HASHTYPE_CHECKSUM: |
226 | 0 | case VVENC_HASHTYPE_CHECKSUM_LOG: |
227 | 0 | default: |
228 | 0 | { |
229 | 0 | uint32_t numChar=calcChecksum(pic, dphSei.pictureHash, bitDepths); |
230 | 0 | rHashString = hashToString(dphSei.pictureHash, numChar); |
231 | 0 | } |
232 | 0 | break; |
233 | 0 | } |
234 | 0 | } |
235 | | |
236 | | void SEIEncoder::initPictureTimingSEI( SEIMessages& seiMessages, SEIMessages& nestedSeiMessages, SEIMessages& duInfoSeiMessages, const Slice *slice, const uint32_t numDU, const bool bpPresentInAU) |
237 | 0 | { |
238 | | // Picture timing depends on buffering period. When either of those is not disabled, |
239 | | // initialization would fail. Needs more cleanup after DU timing is integrated. |
240 | 0 | if (!(m_pcEncCfg->m_pictureTimingSEIEnabled && m_pcEncCfg->m_bufferingPeriodSEIEnabled)) |
241 | 0 | { |
242 | 0 | return; |
243 | 0 | } |
244 | | |
245 | 0 | const GeneralHrdParams *hrd = &slice->sps->generalHrdParams; |
246 | | |
247 | | // update decoding unit parameters |
248 | 0 | if ((m_pcEncCfg->m_pictureTimingSEIEnabled || m_pcEncCfg->m_bufferingPeriodSEIEnabled) && slice->nuhLayerId == slice->vps->layerId[0]) |
249 | 0 | { |
250 | 0 | int picSptDpbOutputDuDelay = 0; |
251 | 0 | SEIPictureTiming *ptSei = new SEIPictureTiming(); |
252 | 0 | const uint32_t maxNumSubLayers = slice->sps->maxTLayers; |
253 | | |
254 | | // DU parameters |
255 | 0 | if( hrd->generalDecodingUnitHrdParamsPresent ) |
256 | 0 | { |
257 | 0 | ptSei->numDecodingUnitsMinus1 = numDU - 1; |
258 | 0 | ptSei->duCommonCpbRemovalDelayFlag = false; |
259 | 0 | ptSei->numNalusInDuMinus1.resize( numDU ); |
260 | 0 | ptSei->duCpbRemovalDelayMinus1.resize( numDU * maxNumSubLayers ); |
261 | 0 | } |
262 | 0 | const uint32_t cpbRemovalDelayLegth = m_pcEncHRD->bufferingPeriodSEI.cpbRemovalDelayLength; |
263 | 0 | ptSei->auCpbRemovalDelay[maxNumSubLayers-1] = std::min<int>(std::max<int>(1, m_totalCoded[maxNumSubLayers-1] - m_lastBPSEI[maxNumSubLayers-1]), (1<<cpbRemovalDelayLegth)); // Syntax element signalled as minus, hence the . |
264 | 0 | CHECK( (m_totalCoded[maxNumSubLayers-1] - m_lastBPSEI[maxNumSubLayers-1]) > (1<<cpbRemovalDelayLegth), " cpbRemovalDelayLegth too small for m_auCpbRemovalDelay[pt_max_sub_layers_minus1] at picture timing SEI " ); |
265 | 0 | const uint32_t temporalId = slice->TLayer; |
266 | 0 | for( int i = temporalId ; i < maxNumSubLayers - 1 ; i ++ ) |
267 | 0 | { |
268 | 0 | CHECK( m_pcEncCfg->m_IntraPeriod % m_pcEncCfg->m_GOPSize != 0, "broken for aip" ); |
269 | 0 | int indexWithinGOP = (m_totalCoded[maxNumSubLayers - 1] - m_lastBPSEI[maxNumSubLayers - 1]) % m_pcEncCfg->m_GOPSize; |
270 | 0 | ptSei->ptSubLayerDelaysPresent[i] = true; |
271 | 0 | if( ((m_rapWithLeading == true) && (indexWithinGOP == 0)) || (m_totalCoded[maxNumSubLayers - 1] == 0) || bpPresentInAU || (slice->poc + m_pcEncCfg->m_GOPSize) > m_pcEncCfg->m_framesToBeEncoded ) |
272 | 0 | { |
273 | 0 | ptSei->cpbRemovalDelayDeltaEnabledFlag[i] = false; |
274 | 0 | } |
275 | 0 | else |
276 | 0 | { |
277 | 0 | ptSei->cpbRemovalDelayDeltaEnabledFlag[i] = m_pcEncHRD->bufferingPeriodSEI.cpbRemovalDelayDeltasPresent; |
278 | 0 | } |
279 | 0 | if( ptSei->cpbRemovalDelayDeltaEnabledFlag[i] ) |
280 | 0 | { |
281 | 0 | if( m_rapWithLeading == false ) |
282 | 0 | { |
283 | 0 | switch (m_pcEncCfg->m_GOPSize) |
284 | 0 | { |
285 | 0 | case 8: |
286 | 0 | { |
287 | 0 | if((indexWithinGOP == 1 && i == 2)) |
288 | 0 | { |
289 | 0 | ptSei->cpbRemovalDelayDeltaIdx[i] = 0; |
290 | 0 | } |
291 | 0 | else if((indexWithinGOP == 2 && i == 2) || (indexWithinGOP == 6 && i == 2)) |
292 | 0 | { |
293 | 0 | ptSei->cpbRemovalDelayDeltaIdx[i] = 1; |
294 | 0 | } |
295 | 0 | else if((indexWithinGOP == 1 && i == 1) || (indexWithinGOP == 3 && i == 2)) |
296 | 0 | { |
297 | 0 | ptSei->cpbRemovalDelayDeltaIdx[i] = 2; |
298 | 0 | } |
299 | 0 | else if(indexWithinGOP == 2 && i == 1) |
300 | 0 | { |
301 | 0 | ptSei->cpbRemovalDelayDeltaIdx[i] = 3; |
302 | 0 | } |
303 | 0 | else if(indexWithinGOP == 1 && i == 0) |
304 | 0 | { |
305 | 0 | ptSei->cpbRemovalDelayDeltaIdx[i] = 4; |
306 | 0 | } |
307 | 0 | else |
308 | 0 | { |
309 | 0 | THROW("m_cpbRemovalDelayDeltaIdx not applicable for the sub-layer and GOP size"); |
310 | 0 | } |
311 | 0 | } |
312 | 0 | break; |
313 | 0 | case 16: |
314 | 0 | { |
315 | 0 | if((indexWithinGOP == 1 && i == 3)) |
316 | 0 | { |
317 | 0 | ptSei->cpbRemovalDelayDeltaIdx[i] = 0; |
318 | 0 | } |
319 | 0 | else if((indexWithinGOP == 2 && i == 3) || (indexWithinGOP == 10 && i == 3) || (indexWithinGOP == 14 && i == 3)) |
320 | 0 | { |
321 | 0 | ptSei->cpbRemovalDelayDeltaIdx[i] = 1; |
322 | 0 | } |
323 | 0 | else if((indexWithinGOP == 1 && i == 2) || (indexWithinGOP == 3 && i == 3) || (indexWithinGOP == 7 && i == 3) || (indexWithinGOP == 11 && i == 3)) |
324 | 0 | { |
325 | 0 | ptSei->cpbRemovalDelayDeltaIdx[i] = 2; |
326 | 0 | } |
327 | 0 | else if(indexWithinGOP == 4 && i == 3) |
328 | 0 | { |
329 | 0 | ptSei->cpbRemovalDelayDeltaIdx[i] = 3; |
330 | 0 | } |
331 | 0 | else if((indexWithinGOP == 2 && i == 2) || (indexWithinGOP == 10 && i == 2)) |
332 | 0 | { |
333 | 0 | ptSei->cpbRemovalDelayDeltaIdx[i] = 4; |
334 | 0 | } |
335 | 0 | else if(indexWithinGOP == 1 && i == 1) |
336 | 0 | { |
337 | 0 | ptSei->cpbRemovalDelayDeltaIdx[i] = 5; |
338 | 0 | } |
339 | 0 | else if(indexWithinGOP == 3 && i == 2) |
340 | 0 | { |
341 | 0 | ptSei->cpbRemovalDelayDeltaIdx[i] = 6; |
342 | 0 | } |
343 | 0 | else if(indexWithinGOP == 2 && i == 1) |
344 | 0 | { |
345 | 0 | ptSei->cpbRemovalDelayDeltaIdx[i] = 7; |
346 | 0 | } |
347 | 0 | else if(indexWithinGOP == 1 && i == 0) |
348 | 0 | { |
349 | 0 | ptSei->cpbRemovalDelayDeltaIdx[i] = 8; |
350 | 0 | } |
351 | 0 | else |
352 | 0 | { |
353 | 0 | THROW("m_cpbRemovalDelayDeltaIdx not applicable for the sub-layer and GOP size"); |
354 | 0 | } |
355 | 0 | } |
356 | 0 | break; |
357 | 0 | default: |
358 | 0 | { |
359 | 0 | THROW("m_cpbRemovalDelayDeltaIdx not supported for the current GOP size"); |
360 | 0 | } |
361 | 0 | break; |
362 | 0 | } |
363 | 0 | } |
364 | 0 | else |
365 | 0 | { |
366 | 0 | switch (m_pcEncCfg->m_GOPSize) |
367 | 0 | { |
368 | 0 | case 8: |
369 | 0 | { |
370 | 0 | if((indexWithinGOP == 1 && i == 2) || (indexWithinGOP == 5 && i == 2)) |
371 | 0 | { |
372 | 0 | ptSei->cpbRemovalDelayDeltaIdx[i] = 0; |
373 | 0 | } |
374 | 0 | else if(indexWithinGOP == 2 && i == 2) |
375 | 0 | { |
376 | 0 | ptSei->cpbRemovalDelayDeltaIdx[i] = 1; |
377 | 0 | } |
378 | 0 | else if(indexWithinGOP == 1 && i == 1) |
379 | 0 | { |
380 | 0 | ptSei->cpbRemovalDelayDeltaIdx[i] = 2; |
381 | 0 | } |
382 | 0 | else |
383 | 0 | { |
384 | 0 | THROW("m_cpbRemovalDelayDeltaIdx not applicable for the sub-layer and GOP size"); |
385 | 0 | } |
386 | 0 | } |
387 | 0 | break; |
388 | 0 | case 16: |
389 | 0 | { |
390 | 0 | if((indexWithinGOP == 1 && i == 3) || (indexWithinGOP == 9 && i == 3) || (indexWithinGOP == 13 && i == 3)) |
391 | 0 | { |
392 | 0 | ptSei->cpbRemovalDelayDeltaIdx[i] = 0; |
393 | 0 | } |
394 | 0 | else if((indexWithinGOP == 2 && i == 3) || (indexWithinGOP == 6 && i == 3) || (indexWithinGOP == 10 && i == 3)) |
395 | 0 | { |
396 | 0 | ptSei->cpbRemovalDelayDeltaIdx[i] = 1; |
397 | 0 | } |
398 | 0 | else if((indexWithinGOP == 1 && i == 2) || (indexWithinGOP == 9 && i == 2) || (indexWithinGOP == 3 && i == 3)) |
399 | 0 | { |
400 | 0 | ptSei->cpbRemovalDelayDeltaIdx[i] = 2; |
401 | 0 | } |
402 | 0 | else if(indexWithinGOP == 2 && i == 2) |
403 | 0 | { |
404 | 0 | ptSei->cpbRemovalDelayDeltaIdx[i] = 3; |
405 | 0 | } |
406 | 0 | else if(indexWithinGOP == 1 && i == 1) |
407 | 0 | { |
408 | 0 | ptSei->cpbRemovalDelayDeltaIdx[i] = 4; |
409 | 0 | } |
410 | 0 | else |
411 | 0 | { |
412 | 0 | THROW("m_cpbRemovalDelayDeltaIdx not applicable for the sub-layer and GOP size"); |
413 | 0 | } |
414 | 0 | } |
415 | 0 | break; |
416 | 0 | default: |
417 | 0 | { |
418 | 0 | THROW("m_cpbRemovalDelayDeltaIdx not applicable for the sub-layer and GOP size"); |
419 | 0 | } |
420 | 0 | break; |
421 | 0 | } |
422 | 0 | } |
423 | 0 | } |
424 | 0 | else |
425 | 0 | { |
426 | 0 | int scaledDistToBuffPeriod = (m_totalCoded[i] - m_lastBPSEI[i]) * (1<<(maxNumSubLayers - 1 - i)); |
427 | 0 | ptSei->auCpbRemovalDelay[i] = std::min<int>(std::max<int>(1, scaledDistToBuffPeriod), (1<<cpbRemovalDelayLegth)); // Syntax element signalled as minus, hence the . |
428 | 0 | CHECK( scaledDistToBuffPeriod > (1<<cpbRemovalDelayLegth), " cpbRemovalDelayLegth too small for m_auCpbRemovalDelay[i] at picture timing SEI " ); |
429 | 0 | } |
430 | 0 | } |
431 | 0 | ptSei->picDpbOutputDelay = slice->sps->numReorderPics[slice->sps->maxTLayers-1] + slice->poc - m_totalCoded[maxNumSubLayers-1]; |
432 | | // if(m_pcEncCfg->m_efficientFieldIRAPEnabled && IRAPGOPid > 0 && IRAPGOPid < m_iGopSize) |
433 | | // { |
434 | | // // if pictures have been swapped there is likely one more picture delay on their tid. Very rough approximation |
435 | | // ptSei->picDpbOutputDelay ++; |
436 | | // } |
437 | 0 | int factor = hrd->tickDivisorMinus2 + 2; |
438 | 0 | ptSei->picDpbOutputDuDelay = factor * ptSei->picDpbOutputDelay; |
439 | 0 | if( m_pcEncCfg->m_decodingUnitInfoSEIEnabled ) |
440 | 0 | { |
441 | 0 | picSptDpbOutputDuDelay = factor * ptSei->picDpbOutputDelay; |
442 | 0 | } |
443 | 0 | if( bpPresentInAU ) |
444 | 0 | { |
445 | 0 | for( int i = temporalId ; i < maxNumSubLayers ; i ++ ) |
446 | 0 | { |
447 | 0 | m_lastBPSEI[i] = m_totalCoded[i]; |
448 | 0 | } |
449 | 0 | if( (slice->nalUnitType == VVENC_NAL_UNIT_CODED_SLICE_IDR_W_RADL)||(slice->nalUnitType == VVENC_NAL_UNIT_CODED_SLICE_CRA) ) |
450 | 0 | { |
451 | 0 | m_rapWithLeading = true; |
452 | 0 | } |
453 | 0 | } |
454 | | |
455 | |
|
456 | 0 | if( m_pcEncCfg->m_pictureTimingSEIEnabled ) |
457 | 0 | { |
458 | 0 | seiMessages.push_back( ptSei ); |
459 | | |
460 | | // if (m_pcEncCfg->m_scalableNestingSEIEnabled && !m_pcEncCfg->m_samePicTimingInAllOLS) |
461 | | // { |
462 | | // SEIPictureTiming *pictureTimingSEIcopy = new SEIPictureTiming(); |
463 | | // *pictureTimingSEIcopy = *pictureTimingSEI; |
464 | | // nestedSeiMessages.push_back(pictureTimingSEIcopy); |
465 | | // } |
466 | 0 | } |
467 | |
|
468 | 0 | if( m_pcEncCfg->m_decodingUnitInfoSEIEnabled && hrd->generalDecodingUnitHrdParamsPresent ) |
469 | 0 | { |
470 | 0 | for( int i = 0; i < ( ptSei->numDecodingUnitsMinus1 + 1 ); i ++ ) |
471 | 0 | { |
472 | 0 | SEIDecodingUnitInfo *duInfoSEI = new SEIDecodingUnitInfo(); |
473 | 0 | duInfoSEI->decodingUnitIdx = i; |
474 | 0 | for( int j = temporalId; j <= maxNumSubLayers; j++ ) |
475 | 0 | { |
476 | 0 | duInfoSEI->duSptCpbRemovalDelayIncrement[j] = ptSei->duCpbRemovalDelayMinus1[i*maxNumSubLayers+j] + 1; |
477 | 0 | } |
478 | 0 | duInfoSEI->dpbOutputDuDelayPresent = false; |
479 | 0 | duInfoSEI->picSptDpbOutputDuDelay = picSptDpbOutputDuDelay; |
480 | |
|
481 | 0 | duInfoSeiMessages.push_back(duInfoSEI); |
482 | 0 | } |
483 | 0 | } |
484 | |
|
485 | 0 | if( !m_pcEncCfg->m_pictureTimingSEIEnabled && ptSei ) |
486 | 0 | { |
487 | 0 | delete ptSei; |
488 | 0 | } |
489 | 0 | } |
490 | | |
491 | | // not sure if this is the final place |
492 | 0 | for( uint32_t i = slice->TLayer; i < slice->sps->maxTLayers; i ++ ) |
493 | 0 | { |
494 | 0 | m_totalCoded[i]++; |
495 | 0 | } |
496 | 0 | } |
497 | | |
498 | | void SEIEncoder::initSEIAlternativeTransferCharacteristics(SEIAlternativeTransferCharacteristics *seiAltTransCharacteristics) |
499 | 0 | { |
500 | 0 | CHECK(!(m_isInitialized), "Unspecified error"); |
501 | 0 | CHECK(!(seiAltTransCharacteristics!=NULL), "Unspecified error"); |
502 | | // Set SEI message parameters read from command line options |
503 | 0 | seiAltTransCharacteristics->preferredTransferCharacteristics = m_pcEncCfg->m_preferredTransferCharacteristics; |
504 | 0 | } |
505 | | |
506 | | void SEIEncoder::initSEIMasteringDisplayColourVolume(SEIMasteringDisplayColourVolume *seiMDCV) |
507 | 0 | { |
508 | 0 | CHECK(!(m_isInitialized), "Unspecified error"); |
509 | 0 | CHECK(!(seiMDCV != NULL), "Unspecified error"); |
510 | | |
511 | | // Set SEI message parameters read from command line options |
512 | 0 | seiMDCV->values.primaries[0][0] = m_pcEncCfg->m_masteringDisplay[0]; |
513 | 0 | seiMDCV->values.primaries[0][1] = m_pcEncCfg->m_masteringDisplay[1]; |
514 | |
|
515 | 0 | seiMDCV->values.primaries[1][0] = m_pcEncCfg->m_masteringDisplay[2]; |
516 | 0 | seiMDCV->values.primaries[1][1] = m_pcEncCfg->m_masteringDisplay[3]; |
517 | |
|
518 | 0 | seiMDCV->values.primaries[2][0] = m_pcEncCfg->m_masteringDisplay[4]; |
519 | 0 | seiMDCV->values.primaries[2][1] = m_pcEncCfg->m_masteringDisplay[5]; |
520 | |
|
521 | 0 | seiMDCV->values.whitePoint[0] = m_pcEncCfg->m_masteringDisplay[6]; |
522 | 0 | seiMDCV->values.whitePoint[1] = m_pcEncCfg->m_masteringDisplay[7]; |
523 | |
|
524 | 0 | seiMDCV->values.maxLuminance = m_pcEncCfg->m_masteringDisplay[8]; |
525 | 0 | seiMDCV->values.minLuminance = m_pcEncCfg->m_masteringDisplay[9]; |
526 | 0 | } |
527 | | |
528 | | void SEIEncoder::initSEIContentLightLevel(SEIContentLightLevelInfo *seiCLL) |
529 | 0 | { |
530 | 0 | CHECK(!(m_isInitialized), "Unspecified error"); |
531 | 0 | CHECK(!(seiCLL != NULL), "Unspecified error"); |
532 | | |
533 | | // Set SEI message parameters read from command line options |
534 | 0 | seiCLL->maxContentLightLevel = m_pcEncCfg->m_contentLightLevel[0]; |
535 | 0 | seiCLL->maxPicAverageLightLevel = m_pcEncCfg->m_contentLightLevel[1]; |
536 | 0 | } |
537 | | |
538 | | void SEIEncoder::initSeiFgc(SeiFgc* seiFilmGrain) |
539 | 0 | { |
540 | 0 | CHECK(!(m_isInitialized), "Unspecified error"); |
541 | 0 | CHECK(!(seiFilmGrain != nullptr), "Unspecified error"); |
542 | | // Set SEI message parameters read from command line options |
543 | 0 | seiFilmGrain->fgcCancelFlag = m_pcEncCfg->m_fg.m_fgcSEICancelFlag; |
544 | 0 | seiFilmGrain->fgcPersistenceFlag = m_pcEncCfg->m_fg.m_fgcSEIPersistenceFlag; |
545 | 0 | seiFilmGrain->filmGrainModelId = m_pcEncCfg->m_fg.m_fgcSEIModelID; |
546 | 0 | seiFilmGrain->separateColourDescriptionPresent = m_pcEncCfg->m_fg.m_fgcSEISepColourDescPresentFlag; |
547 | 0 | seiFilmGrain->blendingModeId = m_pcEncCfg->m_fg.m_fgcSEIBlendingModeID; |
548 | 0 | seiFilmGrain->log2ScaleFactor = m_pcEncCfg->m_fg.m_fgcSEILog2ScaleFactor; |
549 | 0 | for (int i = 0; i < MAX_NUM_COMP; i++) |
550 | 0 | { |
551 | 0 | seiFilmGrain->compModel[i].presentFlag = m_pcEncCfg->m_fg.m_fgcSEICompModelPresent[i]; |
552 | 0 | if (seiFilmGrain->compModel[i].presentFlag) |
553 | 0 | { |
554 | 0 | seiFilmGrain->compModel[i].numModelValues = 1 + m_pcEncCfg->m_fg.m_fgcSEINumModelValuesMinus1[i]; |
555 | 0 | seiFilmGrain->compModel[i].numIntensityIntervals = 1 + m_pcEncCfg->m_fg.m_fgcSEINumIntensityIntervalMinus1[i]; |
556 | 0 | seiFilmGrain->compModel[i].intensityValues.resize(seiFilmGrain->compModel[i].numIntensityIntervals); |
557 | 0 | for (int j = 0; j < seiFilmGrain->compModel[i].numIntensityIntervals; j++) |
558 | 0 | { |
559 | 0 | seiFilmGrain->compModel[i].intensityValues[j].intensityIntervalLowerBound = m_pcEncCfg->m_fg.m_fgcSEIIntensityIntervalLowerBound[i][j]; |
560 | 0 | seiFilmGrain->compModel[i].intensityValues[j].intensityIntervalUpperBound = m_pcEncCfg->m_fg.m_fgcSEIIntensityIntervalUpperBound[i][j]; |
561 | 0 | seiFilmGrain->compModel[i].intensityValues[j].compModelValue.resize(seiFilmGrain->compModel[i].numModelValues); |
562 | 0 | for (int k = 0; k < seiFilmGrain->compModel[i].numModelValues; k++) |
563 | 0 | { |
564 | 0 | seiFilmGrain->compModel[i].intensityValues[j].compModelValue[k] = m_pcEncCfg->m_fg.m_fgcSEICompModelValue[i][j][k]; |
565 | 0 | } |
566 | 0 | } |
567 | 0 | } |
568 | 0 | } |
569 | 0 | } |
570 | | |
571 | | } // namespace vvenc |
572 | | |
573 | | //! \} |
574 | | |