/work/vvdec/source/Lib/DecoderLib/DecLibParser.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) 2018-2026, Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. & The VVdeC 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 | | #include "DecLib.h" |
44 | | #include "DecLibParser.h" |
45 | | #include "NALread.h" |
46 | | |
47 | | #include "CommonLib/dtrace_next.h" |
48 | | |
49 | | #include "UnitTools.h" |
50 | | #include "Utilities/ThreadPool.h" |
51 | | |
52 | | #include <unordered_map> |
53 | | #include <utility> |
54 | | |
55 | | namespace vvdec |
56 | | { |
57 | | template<class TArr, class TElem = decltype( std::declval<TArr>()[0] )> |
58 | | void fill_array( TArr& array, const TElem& val ) |
59 | 1.91k | { |
60 | 1.91k | std::fill( std::begin( array ), std::end( array ), val ); |
61 | 1.91k | } void vvdec::fill_array<vvdec::NalUnitType [64], vvdec::NalUnitType>(vvdec::NalUnitType (&) [64], vvdec::NalUnitType const&) Line | Count | Source | 59 | 478 | { | 60 | 478 | std::fill( std::begin( array ), std::end( array ), val ); | 61 | 478 | } |
void vvdec::fill_array<int [64], int>(int (&) [64], int const&) Line | Count | Source | 59 | 956 | { | 60 | 956 | std::fill( std::begin( array ), std::end( array ), val ); | 61 | 956 | } |
void vvdec::fill_array<bool [64], bool>(bool (&) [64], bool const&) Line | Count | Source | 59 | 478 | { | 60 | 478 | std::fill( std::begin( array ), std::end( array ), val ); | 61 | 478 | } |
|
62 | | |
63 | | #ifdef TRACE_ENABLE_ITT |
64 | | extern __itt_domain* itt_domain_prs; |
65 | | extern __itt_domain* itt_domain_oth; |
66 | | |
67 | | extern __itt_string_handle* itt_handle_parse; |
68 | | extern __itt_string_handle* itt_handle_start; |
69 | | |
70 | | #define ITT_TASKSTART( d, t ) __itt_task_begin( ( d ), __itt_null, __itt_null, ( t ) ) |
71 | | #define ITT_TASKEND( d, t ) __itt_task_end ( ( d ) ) |
72 | | #else |
73 | | #define ITT_TASKSTART( d, t ) |
74 | | #define ITT_TASKEND( d, t ) |
75 | | #endif |
76 | | |
77 | | static const int INIT_POC = -MAX_INT; |
78 | | |
79 | | DecLibParser::~DecLibParser() |
80 | 956 | { |
81 | 956 | m_prefixSEINALUs.clear(); |
82 | | |
83 | 956 | destroy(); |
84 | 956 | } |
85 | | |
86 | | void DecLibParser::create( ThreadPool* tp, int parserFrameDelay, int numReconInst, int numDecThreads, ErrHandlingFlags errHandlingFlags ) |
87 | 478 | { |
88 | 478 | m_threadPool = tp; |
89 | 478 | m_parseFrameDelay = parserFrameDelay; |
90 | 478 | m_numDecThreads = numDecThreads; |
91 | 478 | m_maxPicReconSkip = numReconInst - 1; |
92 | 478 | m_errHandlingFlags = errHandlingFlags; |
93 | | |
94 | 478 | m_apcSlicePilot = new Slice; |
95 | 478 | m_uiSliceSegmentIdx = 0; |
96 | | |
97 | 478 | fill_array( m_associatedIRAPType, NAL_UNIT_INVALID ); |
98 | 478 | fill_array( m_pocCRA, INIT_POC ); |
99 | 478 | fill_array( m_gdrRecoveryPointPocVal, INIT_POC ); |
100 | 478 | fill_array( m_gdrRecovered, false ); |
101 | | |
102 | 478 | m_cSliceDecoder.setContextStateVec( numDecThreads ); |
103 | 478 | } |
104 | | |
105 | | void DecLibParser::destroy() |
106 | 1.43k | { |
107 | 1.43k | SEI_internal::deleteSEIs( m_seiMessageList ); |
108 | | |
109 | 1.43k | m_threadPool = nullptr; |
110 | | |
111 | 1.43k | delete m_apcSlicePilot; |
112 | 1.43k | m_apcSlicePilot = nullptr; |
113 | | |
114 | 1.43k | m_picHeader.reset(); |
115 | | |
116 | 1.43k | m_cSliceDecoder.destroy(); |
117 | | |
118 | 1.43k | if( m_dci ) |
119 | 44 | { |
120 | 44 | delete m_dci; |
121 | 44 | m_dci = NULL; |
122 | 44 | } |
123 | 1.43k | } |
124 | | |
125 | | bool DecLibParser::parse( InputNALUnit& nalu ) |
126 | 1.05k | { |
127 | 1.05k | if( !nalu.isVcl() ) |
128 | 966 | { |
129 | 966 | if( nalu.m_nalUnitType == NAL_UNIT_SUFFIX_APS || nalu.m_nalUnitType == NAL_UNIT_SUFFIX_SEI ) |
130 | 64 | { |
131 | 64 | if( m_pcParsePic ) |
132 | 0 | { |
133 | 0 | m_pcParsePic->bits += nalu.m_bits; |
134 | 0 | } |
135 | 64 | } |
136 | 902 | else |
137 | 902 | { |
138 | 902 | m_nonVCLbits += nalu.m_bits; |
139 | 902 | } |
140 | 966 | } |
141 | | |
142 | 1.05k | GCC_EXTRA_WARNING_switch_enum; |
143 | 1.05k | switch( nalu.m_nalUnitType ) |
144 | 1.05k | { |
145 | 7 | case NAL_UNIT_CODED_SLICE_TRAIL: |
146 | 8 | case NAL_UNIT_CODED_SLICE_STSA: |
147 | 9 | case NAL_UNIT_CODED_SLICE_RADL: |
148 | 10 | case NAL_UNIT_CODED_SLICE_RASL: |
149 | 11 | case NAL_UNIT_CODED_SLICE_IDR_W_RADL: |
150 | 12 | case NAL_UNIT_CODED_SLICE_IDR_N_LP: |
151 | 13 | case NAL_UNIT_CODED_SLICE_CRA: |
152 | 14 | case NAL_UNIT_CODED_SLICE_GDR: |
153 | 14 | try |
154 | 14 | { |
155 | 14 | if( !xDecodeSliceHead( nalu ) ) |
156 | 0 | { |
157 | 0 | return false; |
158 | 0 | } |
159 | 14 | if( !xDecodeSliceMain( nalu ) || m_parseFrameList.size() <= m_parseFrameDelay ) |
160 | 0 | { |
161 | 0 | return false; |
162 | 0 | } |
163 | 14 | return true; |
164 | 14 | } |
165 | 14 | catch( ... ) |
166 | 14 | { |
167 | 14 | if( m_pcParsePic ) |
168 | 0 | { |
169 | 0 | m_pcParsePic->error = true; |
170 | 0 | m_pcParsePic->exceptionThrownOut = true; |
171 | 0 | if( m_pcParsePic->parseDone.hasException() ) // this happens only in the single-threaded case. |
172 | 0 | { // multithreaded mode should see exceptions from the parse tasks later |
173 | 0 | m_pcParsePic->parseDone.clearException(); |
174 | 0 | } |
175 | 0 | } |
176 | | |
177 | 14 | std::rethrow_exception( std::current_exception() ); |
178 | 14 | } |
179 | | |
180 | 2 | case NAL_UNIT_OPI: |
181 | | // NOT IMPLEMENTED |
182 | 2 | return false; |
183 | | |
184 | 45 | case NAL_UNIT_DCI: |
185 | 45 | xDecodeDCI( nalu ); |
186 | 45 | return false; |
187 | | |
188 | 12 | case NAL_UNIT_VPS: |
189 | 12 | xDecodeVPS( nalu ); |
190 | | // m_vps->m_iTargetLayer = iTargetOlsIdx; |
191 | 12 | return false; |
192 | | |
193 | 241 | case NAL_UNIT_SPS: |
194 | 241 | xDecodeSPS( nalu ); |
195 | 241 | return false; |
196 | | |
197 | 2 | case NAL_UNIT_PPS: |
198 | 2 | xDecodePPS( nalu ); |
199 | 2 | return false; |
200 | | |
201 | 66 | case NAL_UNIT_PREFIX_APS: |
202 | 129 | case NAL_UNIT_SUFFIX_APS: |
203 | 129 | xDecodeAPS( nalu ); |
204 | 129 | return false; |
205 | | |
206 | 3 | case NAL_UNIT_PH: |
207 | 3 | xDecodePicHeader( nalu ); |
208 | 3 | return false; |
209 | | |
210 | 2 | case NAL_UNIT_ACCESS_UNIT_DELIMITER: |
211 | 2 | { |
212 | 2 | AUDReader audReader; |
213 | 2 | uint32_t picType; |
214 | 2 | audReader.parseAccessUnitDelimiter( &( nalu.getBitstream() ), picType ); |
215 | 2 | msg( VERBOSE, "Found NAL_UNIT_ACCESS_UNIT_DELIMITER\n" ); |
216 | 2 | return false; |
217 | 66 | } |
218 | | |
219 | 476 | case NAL_UNIT_EOS: |
220 | 485 | case NAL_UNIT_EOB: // the end of the bitstream also ends the current CVS |
221 | 485 | failIncompleteParsePic(); // the current picture will never be completed |
222 | 31.5k | for( int layer = 0; layer < MAX_VPS_LAYERS; ++layer ) |
223 | 31.0k | { |
224 | | // EOS ends only its own layer, while EOB ends all of them (its nuh_layer_id is unconstrained) |
225 | 31.0k | if( nalu.m_nalUnitType == NAL_UNIT_EOS && layer != nalu.m_nuhLayerId ) |
226 | 29.9k | { |
227 | 29.9k | continue; |
228 | 29.9k | } |
229 | 1.05k | m_associatedIRAPType[layer] = NAL_UNIT_INVALID; |
230 | 1.05k | m_pocCRA[layer] = INIT_POC; |
231 | 1.05k | m_gdrRecoveryPointPocVal[layer] = INIT_POC; |
232 | 1.05k | m_gdrRecovered[layer] = false; |
233 | 1.05k | m_bFirstSliceInSequence[layer] = true; |
234 | 1.05k | } |
235 | 485 | m_pocRandomAccess = MAX_INT; |
236 | 485 | m_prevPOC = MAX_INT; |
237 | 485 | m_prevSliceSkipped = false; |
238 | 485 | m_skippedPOC = 0; |
239 | 485 | m_bFirstSliceInPicture = true; |
240 | 485 | m_picListManager.restart(); |
241 | 485 | return false; |
242 | | |
243 | 2 | case NAL_UNIT_PREFIX_SEI: |
244 | | // Buffer up prefix SEI messages until SPS of associated VCL is known. |
245 | 2 | m_prefixSEINALUs.emplace_back( std::move( nalu ) ); |
246 | 2 | return false; |
247 | | |
248 | 1 | case NAL_UNIT_SUFFIX_SEI: |
249 | 1 | if( m_pcParsePic /*&& !m_pcParsePic->wasLost*/ ) |
250 | 0 | { |
251 | 0 | const SPS* sps = m_parameterSetManager.getActiveSPS(); |
252 | 0 | const VPS* vps = m_parameterSetManager.getVPS( sps->getVPSId() ); |
253 | 0 | m_seiReader.parseSEImessage( &( nalu.getBitstream() ), m_pcParsePic->seiMessageList, nalu.m_nalUnitType, nalu.m_nuhLayerId, nalu.m_temporalId, vps, sps, m_HRD, m_pDecodedSEIOutputStream ); |
254 | |
|
255 | 0 | if( m_parseFrameDelay == 0 && !m_pcParsePic->error ) // if m_parseFrameDelay > 0, it has to be done in finishPicture() |
256 | 0 | { |
257 | | // if parallel parsing is disabled, wait for the picture to finish |
258 | 0 | if( m_threadPool->numThreads() == 0 ) |
259 | 0 | { |
260 | 0 | m_threadPool->processTasksOnMainThread(); |
261 | 0 | } |
262 | 0 | else |
263 | 0 | { |
264 | 0 | m_pcParsePic->reconDone.wait(); |
265 | 0 | } |
266 | 0 | m_decLib.checkPictureHashSEI( m_pcParsePic ); |
267 | 0 | } |
268 | 0 | } |
269 | 1 | else |
270 | 1 | { |
271 | 1 | msg( NOTICE, "Received suffix SEI but no picture currently active.\n" ); |
272 | 1 | } |
273 | 1 | return false; |
274 | | |
275 | 5 | case NAL_UNIT_FD: |
276 | 5 | return false; |
277 | | |
278 | 10 | case NAL_UNIT_RESERVED_VCL_4: |
279 | 12 | case NAL_UNIT_RESERVED_VCL_5: |
280 | 70 | case NAL_UNIT_RESERVED_VCL_6: |
281 | 71 | case NAL_UNIT_RESERVED_IRAP_VCL_11: |
282 | 71 | msg( NOTICE, "Found reserved VCL NAL unit.\n" ); |
283 | 71 | xParsePrefixSEIsForUnknownVCLNal(); |
284 | 71 | return false; |
285 | 2 | case NAL_UNIT_RESERVED_NVCL_26: |
286 | 3 | case NAL_UNIT_RESERVED_NVCL_27: |
287 | 3 | msg( NOTICE, "Found reserved NAL unit.\n" ); |
288 | 3 | return false; |
289 | 1 | case NAL_UNIT_UNSPECIFIED_28: |
290 | 2 | case NAL_UNIT_UNSPECIFIED_29: |
291 | 3 | case NAL_UNIT_UNSPECIFIED_30: |
292 | 34 | case NAL_UNIT_UNSPECIFIED_31: |
293 | 34 | msg( NOTICE, "Found unspecified NAL unit.\n" ); |
294 | 34 | return false; |
295 | 0 | case NAL_UNIT_INVALID: |
296 | 0 | default: |
297 | 0 | THROW_RECOVERABLE( "Invalid NAL unit type" ); |
298 | 0 | break; |
299 | 1.05k | } |
300 | 0 | GCC_WARNING_RESET; |
301 | |
|
302 | 0 | return false; |
303 | 1.05k | } |
304 | | |
305 | | void DecLibParser::failIncompleteParsePic() |
306 | 957 | { |
307 | 957 | if( !m_pcParsePic || m_pcParsePic->lastSliceOfPicPresent() ) |
308 | 957 | { |
309 | 957 | return; |
310 | 957 | } |
311 | | |
312 | | // reconstruction can already be waiting for CTUs, that will never be parsed, so the picture needs to be failed explicitly |
313 | 0 | m_pcParsePic->setParseError( std::make_exception_ptr( RecoverableException( "the slices of the picture don't cover all CTUs" ) ) ); |
314 | 0 | m_pcParsePic = nullptr; |
315 | 0 | } |
316 | | |
317 | | Picture* DecLibParser::getNextDecodablePicture() |
318 | 472 | { |
319 | 472 | if( m_parseFrameList.empty() ) |
320 | 472 | { |
321 | 472 | return nullptr; |
322 | 472 | } |
323 | | |
324 | 0 | if( m_threadPool->numThreads() == 0 || m_parseFrameDelay == 0 ) |
325 | 0 | { |
326 | | // adhere to strict decoding order if running singlethreaded |
327 | 0 | Picture * pic = m_parseFrameList.front(); |
328 | 0 | m_parseFrameList.pop_front(); |
329 | 0 | return pic; |
330 | 0 | } |
331 | | |
332 | 0 | if( m_parseFrameList.front()->skippedDecCount >= MAX_OUT_OF_ORDER_PICS || m_parseFrameList.front()->error ) |
333 | 0 | { |
334 | 0 | Picture* pic = m_parseFrameList.front(); |
335 | 0 | m_parseFrameList.pop_front(); |
336 | 0 | return pic; |
337 | 0 | } |
338 | | |
339 | | // try to find next picture, that is parsed and has all reference pictures decoded |
340 | 0 | for( auto picIt = m_parseFrameList.begin(); picIt != m_parseFrameList.end(); ++picIt ) |
341 | 0 | { |
342 | 0 | Picture* pic = *picIt; |
343 | |
|
344 | 0 | if( pic->parseDone.getState() != Barrier::unlocked ) // this doesn't throw if the barrier has an exception set |
345 | 0 | continue; |
346 | | |
347 | 0 | if( pic->wasLost || pic->error ) |
348 | 0 | continue; |
349 | | |
350 | 0 | bool allRefPicsDone = true; |
351 | 0 | for( const Slice* slice: pic->slices ) |
352 | 0 | { |
353 | 0 | if( slice->isIntra() ) |
354 | 0 | { |
355 | 0 | continue; |
356 | 0 | } |
357 | 0 | for( int iDir = REF_PIC_LIST_0; iDir < NUM_REF_PIC_LIST_01 && allRefPicsDone; ++iDir ) |
358 | 0 | { |
359 | 0 | for( int iRefIdx = 0; iRefIdx < slice->getNumRefIdx( (RefPicList) iDir ) && allRefPicsDone; iRefIdx++ ) |
360 | 0 | { |
361 | 0 | const Picture* refPic = slice->getRefPic( (RefPicList) iDir, iRefIdx ); |
362 | 0 | if( refPic->progress < Picture::reconstructed ) |
363 | 0 | { |
364 | 0 | allRefPicsDone = false; |
365 | 0 | break; |
366 | 0 | } |
367 | 0 | } |
368 | 0 | } |
369 | 0 | } |
370 | |
|
371 | 0 | if( allRefPicsDone ) |
372 | 0 | { |
373 | | // increase skip count for all previous pictures |
374 | 0 | for( auto& skipped: PicListRange{ m_parseFrameList.begin(), picIt } ) |
375 | 0 | { |
376 | 0 | skipped->skippedDecCount++; |
377 | 0 | } |
378 | |
|
379 | 0 | m_parseFrameList.erase( picIt ); |
380 | 0 | return pic; |
381 | 0 | } |
382 | | |
383 | | // if( pic->getTLayer() < m_parseFrameList.front()->getTLayer() ) |
384 | | // { |
385 | | // break; |
386 | | // } |
387 | 0 | } |
388 | | |
389 | | // if no picture has all reference-pictures decoded, use next pic in (regular) decoding order. |
390 | 0 | Picture * pic = m_parseFrameList.front(); |
391 | 0 | m_parseFrameList.pop_front(); |
392 | 0 | return pic; |
393 | 0 | } |
394 | | |
395 | | bool DecLibParser::xDecodeSliceHead( InputNALUnit& nalu ) |
396 | 14 | { |
397 | | // all slices for the previous picture have been parsed |
398 | 14 | if( m_pcParsePic && m_pcParsePic->lastSliceOfPicPresent() ) |
399 | 0 | { |
400 | 0 | m_pcParsePic = nullptr; |
401 | 0 | } |
402 | | |
403 | 14 | m_apcSlicePilot->initSlice(); // the slice pilot is an object to prepare for a new slice |
404 | | // it is not associated with picture, sps or pps structures. |
405 | | |
406 | 14 | m_apcSlicePilot->setNalUnitType ( nalu.m_nalUnitType ); |
407 | 14 | m_apcSlicePilot->setNalUnitLayerId( nalu.m_nuhLayerId ); |
408 | 14 | m_apcSlicePilot->setTLayer ( nalu.m_temporalId ); |
409 | | |
410 | 14 | m_HLSReader.setBitstream( &nalu.getBitstream() ); |
411 | | |
412 | 14 | m_bFirstSliceInPicture = true; // set for now, will be set correctly in parseSliceHeader |
413 | 14 | m_HLSReader.parseSliceHeader( m_apcSlicePilot, m_picHeader, &m_parameterSetManager, m_prevTid0POC, m_bFirstSliceInPicture ); |
414 | | |
415 | 14 | CHECK( m_bFirstSliceInPicture != ( m_apcSlicePilot->getCtuAddrInSlice( 0 ) == 0 ), "first slice in picture should start at CTU-addr 0" ); |
416 | | |
417 | 14 | if( m_bFirstSliceInPicture ) |
418 | 0 | { |
419 | 0 | failIncompleteParsePic(); // a new picture starts, but the previous one was never completed |
420 | |
|
421 | 0 | m_uiSliceSegmentIdx = 0; |
422 | 0 | m_apcSlicePilot->setPicHeader ( m_picHeader.get() ); |
423 | 0 | } |
424 | 14 | else // if it turns out, this was not the first slice in the picture, we need to parse the header again |
425 | 14 | { |
426 | 14 | m_uiSliceSegmentIdx++; |
427 | 14 | CHECK( !m_pcParsePic, "m_pcParsePic should be initialized, when this is not the first slice in the picture" ); |
428 | | // a PH NAL unit or a PH in the slice header always starts a new picture (7.4.2.4.4) |
429 | 14 | CHECK( m_picHeader != m_pcParsePic->cs->picHeader, "a new picture header was received, but the slice is not the first slice of a picture" ); |
430 | 14 | CHECK( m_pcParsePic->slices.size() <= m_uiSliceSegmentIdx - 1 || m_pcParsePic->slices[m_uiSliceSegmentIdx - 1] == nullptr, "can't access previous slice" ); |
431 | 14 | CHECK( !m_pcParsePic->getMixedNaluTypesInPicFlag() && nalu.m_nalUnitType != m_pcParsePic->slices[m_uiSliceSegmentIdx - 1]->getNalUnitType(), |
432 | 14 | "The value of NAL unit type shall be the same for all coded slice NAL units of a picture if pps_mixed_nalu_types_in_pic_flag is not set" ); |
433 | | |
434 | 14 | m_apcSlicePilot->copySliceInfo( m_pcParsePic->slices[m_uiSliceSegmentIdx - 1] ); |
435 | | |
436 | 14 | m_apcSlicePilot->setNalUnitType ( nalu.m_nalUnitType ); |
437 | 14 | m_apcSlicePilot->setNalUnitLayerId( nalu.m_nuhLayerId ); |
438 | 14 | m_apcSlicePilot->setTLayer ( nalu.m_temporalId ); |
439 | | |
440 | 14 | nalu.getBitstream().resetToStart(); |
441 | 14 | nalu.readNalUnitHeader(); |
442 | 14 | m_HLSReader.setBitstream ( &nalu.getBitstream() ); |
443 | | |
444 | 14 | m_HLSReader.parseSliceHeader( m_apcSlicePilot, m_picHeader, &m_parameterSetManager, m_prevTid0POC, m_bFirstSliceInPicture ); |
445 | 14 | } |
446 | | |
447 | 14 | const PPS* pps = static_cast<const ParameterSetManager&>( m_parameterSetManager ).getPPS( m_apcSlicePilot->getPicHeader()->getPPSId() ); |
448 | 14 | CHECK( pps == 0, "No PPS present" ); |
449 | 14 | const SPS* sps = static_cast<const ParameterSetManager&>( m_parameterSetManager ).getSPS( pps->getSPSId() ); |
450 | 14 | CHECK( sps == 0, "No SPS present" ); |
451 | 14 | const VPS* vps = static_cast<const ParameterSetManager&>( m_parameterSetManager ).getVPS( sps->getVPSId() ); |
452 | 14 | CHECK( sps->getVPSId() > 0 && vps == 0, "Invalid VPS" ); |
453 | 14 | if( sps->getVPSId() == 0 && m_prevLayerID != MAX_INT ) |
454 | 0 | { |
455 | 0 | CHECK( m_prevLayerID != nalu.m_nuhLayerId, "All VCL NAL unit in the CVS shall have the same value of nuh_layer_id " |
456 | 0 | "when sps_video_parameter_set_id is equal to 0" ); |
457 | 0 | } |
458 | | |
459 | 14 | CHECK( vps && !vps->getIndependentLayerFlag( nalu.m_nuhLayerId ), "Decoding of dependent layers not implemented. Dependent layer POC derivation was here." ); |
460 | | |
461 | 14 | if( !m_bFirstSliceInPicture ) |
462 | 0 | { |
463 | | // the slices of a picture shall be in increasing order of their addresses and shall not overlap |
464 | 0 | const Slice* prevSlice = m_pcParsePic->slices[m_uiSliceSegmentIdx - 1]; |
465 | 0 | if( pps->getRectSliceFlag() ) |
466 | 0 | { |
467 | | // the rect slice map is a partition of the picture (verified in PPS::checkSliceMap()), so distinct indices suffice |
468 | 0 | CHECK( m_apcSlicePilot->getSliceID() <= prevSlice->getSliceID(), "slices shall be in increasing order of their slice indices" ); |
469 | 0 | } |
470 | 0 | else |
471 | 0 | { |
472 | | // a raster-scan slice covers the tiles [sh_slice_address, sh_slice_address + numTilesInSlice) |
473 | 0 | const uint32_t prevSliceLastTileIdx = pps->getTileIdx( prevSlice->getCtuAddrInSlice( prevSlice->getNumCtuInSlice() - 1 ) ); |
474 | 0 | CHECK( m_apcSlicePilot->getSliceID() <= prevSliceLastTileIdx, "slices shall be in increasing order of sh_slice_address and shall not overlap" ); |
475 | 0 | } |
476 | 0 | } |
477 | | |
478 | | // update independent slice index |
479 | 14 | m_apcSlicePilot->setIndependentSliceIdx( m_uiSliceSegmentIdx ); |
480 | | |
481 | 14 | DTRACE_UPDATE( g_trace_ctx, std::make_pair( "poc", m_apcSlicePilot->getPOC() ) ); |
482 | | |
483 | | |
484 | 14 | if( m_bFirstSliceInPicture ) |
485 | 0 | { |
486 | 0 | const auto pictureType = m_apcSlicePilot->getNalUnitType(); |
487 | |
|
488 | 0 | if( !pps->getMixedNaluTypesInPicFlag() |
489 | 0 | && ( pictureType == NAL_UNIT_CODED_SLICE_IDR_W_RADL |
490 | 0 | || pictureType == NAL_UNIT_CODED_SLICE_IDR_N_LP |
491 | 0 | || pictureType == NAL_UNIT_CODED_SLICE_CRA |
492 | 0 | || pictureType == NAL_UNIT_CODED_SLICE_GDR ) ) |
493 | 0 | { |
494 | 0 | m_pocCRA [nalu.m_nuhLayerId] = m_apcSlicePilot->getPOC(); |
495 | 0 | m_associatedIRAPType[nalu.m_nuhLayerId] = pictureType; |
496 | 0 | } |
497 | 0 | } |
498 | | |
499 | 14 | xUpdatePreviousTid0POC( m_apcSlicePilot ); |
500 | | |
501 | 14 | m_apcSlicePilot->setAssociatedIRAPPOC ( m_pocCRA [nalu.m_nuhLayerId] ); |
502 | 14 | m_apcSlicePilot->setAssociatedIRAPType( m_associatedIRAPType[nalu.m_nuhLayerId] ); |
503 | | |
504 | 14 | if( m_apcSlicePilot->getRapPicFlag() || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR ) |
505 | 0 | { |
506 | | // Derive NoOutputBeforeRecoveryFlag |
507 | 0 | if( !pps->getMixedNaluTypesInPicFlag() ) |
508 | 0 | { |
509 | 0 | if( m_bFirstSliceInSequence[nalu.m_nuhLayerId] ) |
510 | 0 | { |
511 | 0 | m_picHeader->setNoOutputBeforeRecoveryFlag( true ); |
512 | 0 | } |
513 | 0 | else if( m_apcSlicePilot->getIdrPicFlag() ) |
514 | 0 | { |
515 | 0 | m_picHeader->setNoOutputBeforeRecoveryFlag( true ); |
516 | 0 | } |
517 | 0 | else if( m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA ) |
518 | 0 | { |
519 | 0 | m_picHeader->setNoOutputBeforeRecoveryFlag( m_picHeader->getHandleCraAsCvsStartFlag() ); |
520 | 0 | } |
521 | 0 | else if( m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR ) |
522 | 0 | { |
523 | 0 | m_picHeader->setNoOutputBeforeRecoveryFlag( m_picHeader->getHandleGdrAsCvsStartFlag() ); |
524 | 0 | } |
525 | 0 | } |
526 | 0 | else |
527 | 0 | { |
528 | 0 | m_picHeader->setNoOutputBeforeRecoveryFlag( false ); |
529 | 0 | } |
530 | |
|
531 | 0 | if( m_apcSlicePilot->isCRAorGDR() ) |
532 | 0 | { |
533 | 0 | m_lastNoOutputBeforeRecoveryFlag[nalu.m_nuhLayerId] = m_picHeader->getNoOutputBeforeRecoveryFlag(); |
534 | 0 | } |
535 | | |
536 | | // the inference for NoOutputOfPriorPicsFlag |
537 | 0 | if( m_apcSlicePilot->getNoOutputOfPriorPicsFlag() ) |
538 | 0 | { |
539 | 0 | m_lastPOCNoOutputPriorPics = m_apcSlicePilot->getPOC(); |
540 | 0 | m_isNoOutputPriorPics = true; |
541 | 0 | } |
542 | 0 | else |
543 | 0 | { |
544 | 0 | m_isNoOutputPriorPics = false; |
545 | 0 | } |
546 | 0 | } |
547 | | |
548 | 14 | #if !DISABLE_CHECK_NO_OUTPUT_PRIOR_PICS_FLAG |
549 | 14 | if( m_bFirstSliceInPicture && m_apcSlicePilot->getPOC() != m_prevPOC |
550 | 0 | && ( m_apcSlicePilot->getRapPicFlag() || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR ) |
551 | 0 | && m_picHeader->getNoOutputBeforeRecoveryFlag() |
552 | 0 | && getNoOutputPriorPicsFlag() ) |
553 | 0 | { |
554 | 0 | checkNoOutputPriorPics(); |
555 | 0 | setNoOutputPriorPicsFlag( false ); |
556 | 0 | } |
557 | 14 | #endif |
558 | | |
559 | | |
560 | | //For inference of PicOutputFlag |
561 | 14 | if( !pps->getMixedNaluTypesInPicFlag() && ( m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_RASL ) ) |
562 | 0 | { |
563 | 0 | if( m_lastNoOutputBeforeRecoveryFlag[nalu.m_nuhLayerId] ) |
564 | 0 | { |
565 | 0 | m_picHeader->setPicOutputFlag( false ); |
566 | 0 | } |
567 | 0 | } |
568 | | |
569 | 14 | if( sps->getVPSId() > 0 ) |
570 | 0 | { |
571 | 0 | const VPS *vps = m_parameterSetManager.getVPS( sps->getVPSId() ); |
572 | 0 | CHECK( vps == 0, "No VPS present" ); |
573 | 0 | if( ( vps->getOlsModeIdc() == 0 |
574 | 0 | && vps->getGeneralLayerIdx( nalu.m_nuhLayerId ) < ( vps->getMaxLayers() - 1 ) |
575 | 0 | && vps->getOlsOutputLayerFlag( vps->m_iTargetLayer, vps->getMaxLayers() - 1 ) == 1 ) |
576 | 0 | || ( vps->getOlsModeIdc() == 2 |
577 | 0 | && vps->getOlsOutputLayerFlag( vps->m_iTargetLayer, vps->getGeneralLayerIdx( nalu.m_nuhLayerId ) ) == 0 ) ) |
578 | 0 | { |
579 | 0 | m_picHeader->setPicOutputFlag( false ); |
580 | 0 | } |
581 | 0 | } |
582 | | |
583 | | //Reset POC MSB when CRA or GDR has NoOutputBeforeRecoveryFlag equal to 1 |
584 | 14 | if( !pps->getMixedNaluTypesInPicFlag() && m_apcSlicePilot->isCRAorGDR() && m_lastNoOutputBeforeRecoveryFlag[nalu.m_nuhLayerId] ) |
585 | 0 | { |
586 | 0 | int iMaxPOClsb = 1 << sps->getBitsForPOC(); |
587 | 0 | m_apcSlicePilot->setPOC( m_apcSlicePilot->getPOC() & ( iMaxPOClsb - 1 ) ); |
588 | 0 | xUpdatePreviousTid0POC ( m_apcSlicePilot ); |
589 | 0 | m_lastPOCNoOutputPriorPics = m_apcSlicePilot->getPOC(); |
590 | 0 | } |
591 | | |
592 | | // Skip pictures due to random access |
593 | 14 | if( isRandomAccessSkipPicture() ) |
594 | 0 | { |
595 | 0 | m_prevSliceSkipped = true; |
596 | 0 | m_skippedPOC = m_apcSlicePilot->getPOC(); |
597 | 0 | msg( VERBOSE, "POC %i: RASL not decodable\n", m_skippedPOC ); |
598 | | // prefix SEIs belong to the skipped picture's PU |
599 | 0 | m_prefixSEINALUs.clear(); |
600 | 0 | return false; |
601 | 0 | } |
602 | | |
603 | | // clear previous slice skipped flag |
604 | 14 | m_prevSliceSkipped = false; |
605 | | |
606 | | //we should only get a different poc for a new picture (with CTU address==0) |
607 | 14 | if( m_apcSlicePilot->getPOC() != m_prevPOC |
608 | 0 | && !m_bFirstSliceInSequence[nalu.m_nuhLayerId] |
609 | 0 | && m_apcSlicePilot->getFirstCtuRsAddrInSlice() != 0 ) |
610 | 0 | { |
611 | 0 | msg( WARNING, "Warning, the first slice of a picture might have been lost!\n"); |
612 | 0 | } |
613 | | |
614 | 14 | m_prevLayerID = nalu.m_nuhLayerId; |
615 | | |
616 | | // reference picture marking (8.3.3) precedes the generation of unavailable reference pictures (8.3.4) |
617 | 14 | if( m_bFirstSliceInPicture ) |
618 | 0 | { |
619 | 0 | applyReferencePictureListBasedMarking( m_apcSlicePilot, nalu.m_nuhLayerId ); |
620 | 0 | } |
621 | | |
622 | | //detect lost reference picture and insert copy of earlier frame. |
623 | 14 | if( m_apcSlicePilot->getSliceType() != I_SLICE ) |
624 | 0 | { |
625 | 0 | for( const auto rplIdx: { REF_PIC_LIST_0, REF_PIC_LIST_1 } ) |
626 | 0 | { |
627 | 0 | const auto* rpl = m_apcSlicePilot->getRPL( rplIdx ); |
628 | |
|
629 | 0 | int missingPoc = MAX_INT; |
630 | 0 | int missingRefPicIndex = 0; |
631 | 0 | int prevMissingIndex = -1; |
632 | 0 | while( !m_apcSlicePilot->checkThatAllRefPicsAreAvailable( m_dpbReferencePics, |
633 | 0 | rpl, |
634 | 0 | m_apcSlicePilot->getNumRefIdx( rplIdx ), |
635 | 0 | sps->getBitsForPOC(), |
636 | 0 | &missingPoc, |
637 | 0 | &missingRefPicIndex ) ) |
638 | 0 | { |
639 | | // a generated picture that doesn't satisfy its entry would otherwise allocate pictures forever |
640 | 0 | CHECK( missingRefPicIndex == prevMissingIndex, "unable to generate missing reference picture poc: " << missingPoc ); |
641 | 0 | prevMissingIndex = missingRefPicIndex; |
642 | 0 | if( !pps->getMixedNaluTypesInPicFlag() |
643 | 0 | && ( ( m_apcSlicePilot->isIDR() && ( sps->getIDRRefParamListPresent() || pps->getRplInfoInPhFlag() ) ) |
644 | 0 | || ( m_apcSlicePilot->isCRAorGDR() && m_picHeader->getNoOutputBeforeRecoveryFlag() ) ) ) |
645 | 0 | { |
646 | 0 | if( !rpl->isInterLayerRefPic( missingRefPicIndex ) ) |
647 | 0 | { |
648 | 0 | prepareUnavailablePicture( false, |
649 | 0 | pps, |
650 | 0 | missingPoc, |
651 | 0 | m_apcSlicePilot->getNalUnitLayerId(), |
652 | 0 | rpl->isRefPicLongterm( missingRefPicIndex ), |
653 | 0 | m_apcSlicePilot->getTLayer() ); |
654 | 0 | } |
655 | 0 | } |
656 | 0 | else |
657 | 0 | { |
658 | 0 | prepareUnavailablePicture( true, |
659 | 0 | pps, |
660 | 0 | missingPoc, |
661 | 0 | m_apcSlicePilot->getNalUnitLayerId(), |
662 | 0 | rpl->isRefPicLongterm( missingRefPicIndex ), |
663 | 0 | m_apcSlicePilot->getTLayer() ); |
664 | 0 | } |
665 | 0 | } |
666 | 0 | } |
667 | 0 | } |
668 | 14 | xActivateParameterSets( nalu.m_nuhLayerId ); |
669 | | |
670 | | // WARNING: don't use m_apcSlicePilot after this point, because it has been reallocated |
671 | | |
672 | 14 | Slice* slice = m_pcParsePic->slices[m_uiSliceSegmentIdx]; |
673 | | |
674 | 14 | m_pcParsePic->neededForOutput = m_picHeader->getPicOutputFlag(); |
675 | 14 | if( m_pcParsePic->lastSliceOfPicPresent() ) |
676 | 0 | { |
677 | | #if 0 |
678 | | // TODO for VPS support: |
679 | | if( sps->getVPSId() > 0 && NOT IN OUTPUT LAYER SET ) |
680 | | { |
681 | | m_pcParsePic->neededForOutput = false; |
682 | | } |
683 | | else |
684 | | #endif |
685 | 0 | { |
686 | 0 | if( !m_gdrRecovered[nalu.m_nuhLayerId] && slice->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR && m_gdrRecoveryPointPocVal[nalu.m_nuhLayerId] == INIT_POC ) |
687 | 0 | { |
688 | 0 | m_gdrRecoveryPointPocVal[nalu.m_nuhLayerId] = m_pcParsePic->poc + m_picHeader->getRecoveryPocCnt(); |
689 | 0 | } |
690 | |
|
691 | 0 | if( !m_gdrRecovered[nalu.m_nuhLayerId] |
692 | 0 | && ( m_gdrRecoveryPointPocVal[nalu.m_nuhLayerId] == m_pcParsePic->poc || m_picHeader->getRecoveryPocCnt() == 0 ) ) |
693 | 0 | { |
694 | 0 | m_gdrRecovered [nalu.m_nuhLayerId] = true; |
695 | 0 | m_gdrRecoveryPointPocVal[nalu.m_nuhLayerId] = INIT_POC; |
696 | 0 | } |
697 | |
|
698 | 0 | const bool is_recovering_picture = slice->getAssociatedIRAPType() == NAL_UNIT_CODED_SLICE_GDR && m_pcParsePic->poc < m_gdrRecoveryPointPocVal[nalu.m_nuhLayerId]; |
699 | 0 | if( slice->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR && m_gdrRecovered[nalu.m_nuhLayerId] ) |
700 | 0 | { |
701 | 0 | m_pcParsePic->neededForOutput = true; |
702 | 0 | } |
703 | 0 | else if( slice->getNalUnitType() == NAL_UNIT_CODED_SLICE_RASL && m_lastNoOutputBeforeRecoveryFlag[nalu.m_nuhLayerId] ) |
704 | 0 | { |
705 | 0 | m_pcParsePic->neededForOutput = false; |
706 | 0 | } |
707 | 0 | else if( ( slice->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR && m_picHeader->getNoOutputBeforeRecoveryFlag() ) |
708 | 0 | || ( is_recovering_picture && ( !m_gdrRecovered[nalu.m_nuhLayerId] || m_lastNoOutputBeforeRecoveryFlag[nalu.m_nuhLayerId] ) ) ) |
709 | 0 | { |
710 | 0 | m_pcParsePic->neededForOutput = false; |
711 | 0 | } |
712 | 0 | } |
713 | | |
714 | | // the picture header belongs to exactly one picture, so don't let the next one silently reuse it |
715 | 0 | m_picHeader.reset(); |
716 | 0 | } |
717 | | |
718 | 14 | return true; |
719 | 14 | } |
720 | | |
721 | | bool DecLibParser::xDecodeSliceMain( InputNALUnit& nalu ) |
722 | 0 | { |
723 | 0 | ITT_TASKSTART( itt_domain_oth, itt_handle_start ); |
724 | | // actual decoding starts here |
725 | 0 | Slice* pcSlice = m_pcParsePic->slices[m_uiSliceSegmentIdx]; |
726 | 0 | m_pcParsePic->poc = pcSlice->getPOC(); |
727 | 0 | m_pcParsePic->tempLayer = pcSlice->getTLayer(); |
728 | 0 | m_pcParsePic->dpbReferenceMark = pcSlice->getPicHeader()->getNonReferencePictureFlag() ? Picture::unreferenced : Picture::ShortTerm; |
729 | 0 | m_pcParsePic->stillReferenced = !!m_pcParsePic->dpbReferenceMark; |
730 | 0 | m_pcParsePic->isReferencePic = !!m_pcParsePic->dpbReferenceMark; |
731 | 0 | m_pcParsePic->eNalUnitType = nalu.m_nalUnitType; |
732 | 0 | m_pcParsePic->cts = nalu.m_cts; |
733 | 0 | m_pcParsePic->dts = nalu.m_dts; |
734 | 0 | m_pcParsePic->rap = nalu.m_rap; |
735 | 0 | m_pcParsePic->userData = nalu.m_userData; |
736 | 0 | m_pcParsePic->bits += nalu.m_bits + m_nonVCLbits; |
737 | 0 | m_pcParsePic->layerId = nalu.m_nuhLayerId; |
738 | 0 | m_pcParsePic->subLayerNonReferencePictureDueToSTSA = false; |
739 | |
|
740 | 0 | m_nonVCLbits = 0; |
741 | |
|
742 | 0 | if( !( m_errHandlingFlags & ERR_HANDLING_TRY_CONTINUE ) ) |
743 | 0 | { |
744 | 0 | CHECK( m_uiSliceSegmentIdx > 0 && pcSlice->getTLayer() != m_pcParsePic->slices[0]->getTLayer(), |
745 | 0 | "All VCL NAL units of a picture shall have the same TemporalId" ); |
746 | 0 | } |
747 | | |
748 | 0 | if( pcSlice->getSPS()->getProfileTierLevel()->getConstraintInfo()->getNoApsConstraintFlag() ) |
749 | 0 | { |
750 | 0 | bool flag = pcSlice->getSPS()->getUseCCALF() || pcSlice->getPicHeader()->getNumAlfAps() || pcSlice->getPicHeader()->getAlfEnabledFlag( COMPONENT_Cb ) || pcSlice->getPicHeader()->getAlfEnabledFlag( COMPONENT_Cr ); |
751 | 0 | CHECK( flag, "When no_aps_constraint_flag is equal to 1, the values of " |
752 | 0 | "ph_num_alf_aps_ids_luma, sh_num_alf_aps_ids_luma, ph_alf_cb_flag, " |
753 | 0 | "ph_alf_cr_flag, sh_alf_cb_flag, sh_alf_cr_flag, " |
754 | 0 | "and sps_ccalf_enabled_flag shall all be equal to 0" ) |
755 | 0 | } |
756 | | |
757 | 0 | if( pcSlice->getNalUnitLayerId() != pcSlice->getSPS()->getLayerId() ) |
758 | 0 | { |
759 | 0 | CHECK( pcSlice->getSPS()->getLayerId() > pcSlice->getNalUnitLayerId(), "Layer Id of SPS cannot be greater than layer Id of VCL NAL unit the refer to it" ); |
760 | 0 | CHECK( pcSlice->getSPS()->getVPSId() == 0, "VPSId of the referred SPS cannot be 0 when layer Id of SPS and layer Id of current slice are different" ); |
761 | 0 | for (int i = 0; i < pcSlice->getVPS()->getNumOutputLayerSets(); i++ ) |
762 | 0 | { |
763 | 0 | bool isCurrLayerInOls = false; |
764 | 0 | bool isRefLayerInOls = false; |
765 | 0 | int j = pcSlice->getVPS()->getNumLayersInOls(i) - 1; |
766 | 0 | for (; j >= 0; j--) |
767 | 0 | { |
768 | 0 | if( pcSlice->getVPS()->getLayerIdInOls(i, j) == pcSlice->getNalUnitLayerId() ) |
769 | 0 | { |
770 | 0 | isCurrLayerInOls = true; |
771 | 0 | } |
772 | 0 | if( pcSlice->getVPS()->getLayerIdInOls(i, j) == pcSlice->getSPS()->getLayerId() ) |
773 | 0 | { |
774 | 0 | isRefLayerInOls = true; |
775 | 0 | } |
776 | 0 | } |
777 | 0 | CHECK( isCurrLayerInOls && !isRefLayerInOls, "When VCL NAl unit in layer A refers to SPS in layer B, all OLS that contains layer A shall also contains layer B" ); |
778 | 0 | } |
779 | 0 | } |
780 | 0 | if( pcSlice->getNalUnitLayerId() != pcSlice->getPPS()->getLayerId() ) |
781 | 0 | { |
782 | 0 | CHECK( pcSlice->getPPS()->getLayerId() > pcSlice->getNalUnitLayerId(), "Layer Id of PPS cannot be greater than layer Id of VCL NAL unit the refer to it" ); |
783 | 0 | CHECK( pcSlice->getSPS()->getVPSId() == 0, "VPSId of the referred SPS cannot be 0 when layer Id of PPS and layer Id of current slice are different" ); |
784 | 0 | for (int i = 0; i < pcSlice->getVPS()->getNumOutputLayerSets(); i++ ) |
785 | 0 | { |
786 | 0 | bool isCurrLayerInOls = false; |
787 | 0 | bool isRefLayerInOls = false; |
788 | 0 | int j = pcSlice->getVPS()->getNumLayersInOls(i) - 1; |
789 | 0 | for (; j >= 0; j--) |
790 | 0 | { |
791 | 0 | if( pcSlice->getVPS()->getLayerIdInOls(i, j) == pcSlice->getNalUnitLayerId() ) |
792 | 0 | { |
793 | 0 | isCurrLayerInOls = true; |
794 | 0 | } |
795 | 0 | if( pcSlice->getVPS()->getLayerIdInOls(i, j) == pcSlice->getPPS()->getLayerId() ) |
796 | 0 | { |
797 | 0 | isRefLayerInOls = true; |
798 | 0 | } |
799 | 0 | } |
800 | 0 | CHECK( isCurrLayerInOls && !isRefLayerInOls, "When VCL NAl unit in layer A refers to PPS in layer B, all OLS that contains layer A shall also contains layer B" ); |
801 | 0 | } |
802 | 0 | } |
803 | | |
804 | 0 | if( m_bFirstSliceInPicture ) |
805 | 0 | { |
806 | 0 | m_pcParsePic->setDecodingOrderNumber( m_decodingOrderCounter ); |
807 | 0 | m_decodingOrderCounter++; |
808 | |
|
809 | 0 | pcSlice->getPic()->subPictures.clear(); |
810 | 0 | pcSlice->getPic()->sliceSubpicIdx.clear(); |
811 | |
|
812 | 0 | for( int subPicIdx = 0; subPicIdx < pcSlice->getSPS()->getNumSubPics(); subPicIdx++ ) |
813 | 0 | { |
814 | 0 | pcSlice->getPic()->subPictures.push_back( pcSlice->getPPS()->getSubPic( subPicIdx ) ); |
815 | 0 | } |
816 | 0 | } |
817 | |
|
818 | 0 | pcSlice->getPic()->sliceSubpicIdx.push_back(pcSlice->getPPS()->getSubPicIdxFromSubPicId(pcSlice->getSliceSubPicId())); |
819 | | |
820 | | // When decoding the slice header, the stored start and end addresses were actually RS addresses, not TS addresses. |
821 | | // Now, having set up the maps, convert them to the correct form. |
822 | | |
823 | | // Sanity check: verify that there are no duplicate POCs in the DPB before constructing the ref picture lists |
824 | 0 | m_tmpSeenPocs.clear(); |
825 | 0 | m_tmpSeenPocs.reserve( m_dpbReferencePics.size() ); |
826 | 0 | for( auto& p: m_dpbReferencePics ) |
827 | 0 | { |
828 | 0 | CHECK( m_tmpSeenPocs.count( p->poc ) != 0, "duplicate POC in DPB" ); |
829 | 0 | if( p->dpbReferenceMark ) // we only care about reference pictures in the DPB |
830 | 0 | { |
831 | 0 | m_tmpSeenPocs.insert( p->poc ); |
832 | 0 | } |
833 | 0 | } |
834 | | |
835 | | #if !DISABLE_CONFROMANCE_CHECK |
836 | | pcSlice->checkCRA( m_pocCRA[nalu.m_nuhLayerId], m_associatedIRAPType[nalu.m_nuhLayerId], m_picListManager.getPicListRange( m_pcParsePic ) ); |
837 | | #endif |
838 | 0 | pcSlice->constructRefPicLists( m_dpbReferencePics ); |
839 | | #if !DISABLE_CONFROMANCE_CHECK |
840 | | pcSlice->checkRPL(pcSlice->getRPL0(), pcSlice->getRPL1(), m_associatedIRAPDecodingOrderNumber, m_picListManager.getPicListRange( m_pcParsePic ) ); |
841 | | pcSlice->checkSTSA( m_picListManager.getPicListRange( pcParsePic ) ); |
842 | | #endif |
843 | |
|
844 | | #if TBC |
845 | | pcSlice->setPrevGDRSubpicPOC(m_prevGDRSubpicPOC[nalu.m_nuhLayerId][currSubPicIdx]); |
846 | | pcSlice->setPrevIRAPSubpicPOC(m_prevIRAPSubpicPOC[nalu.m_nuhLayerId][currSubPicIdx]); |
847 | | pcSlice->setPrevIRAPSubpicType(m_prevIRAPSubpicType[nalu.m_nuhLayerId][currSubPicIdx]); |
848 | | pcSlice->checkSubpicTypeConstraints(m_cListPic, pcSlice->getRPL0(), pcSlice->getRPL1(), m_prevIRAPSubpicDecOrderNo[nalu.m_nuhLayerId][currSubPicIdx]); |
849 | | #endif |
850 | |
|
851 | 0 | if( m_pcParsePic->cs->vps && !m_pcParsePic->cs->vps->getIndependentLayerFlag( m_pcParsePic->cs->vps->getGeneralLayerIdx( nalu.m_nuhLayerId ) ) && m_pcParsePic->cs->pps->getNumSubPics() > 1 ) |
852 | 0 | { |
853 | 0 | CU::checkConformanceILRP(pcSlice); |
854 | 0 | } |
855 | |
|
856 | 0 | pcSlice->scaleRefPicList(); |
857 | | |
858 | |
|
859 | 0 | if (!pcSlice->isIntra()) |
860 | 0 | { |
861 | 0 | const int iCurrPOC = pcSlice->getPOC(); |
862 | |
|
863 | 0 | bool bLowDelay = true; |
864 | 0 | for( int iRefIdx = 0; iRefIdx < pcSlice->getNumRefIdx( REF_PIC_LIST_0 ) && bLowDelay; iRefIdx++ ) |
865 | 0 | { |
866 | 0 | if( pcSlice->getRefPOC( REF_PIC_LIST_0, iRefIdx ) > iCurrPOC ) |
867 | 0 | { |
868 | 0 | bLowDelay = false; |
869 | 0 | } |
870 | 0 | } |
871 | 0 | if( pcSlice->isInterB() ) |
872 | 0 | { |
873 | 0 | for( int iRefIdx = 0; iRefIdx < pcSlice->getNumRefIdx( REF_PIC_LIST_1 ) && bLowDelay; iRefIdx++ ) |
874 | 0 | { |
875 | 0 | if( pcSlice->getRefPOC( REF_PIC_LIST_1, iRefIdx ) > iCurrPOC ) |
876 | 0 | { |
877 | 0 | bLowDelay = false; |
878 | 0 | } |
879 | 0 | } |
880 | 0 | } |
881 | |
|
882 | 0 | pcSlice->setCheckLDC( bLowDelay ); |
883 | 0 | } |
884 | |
|
885 | 0 | if( pcSlice->getSPS()->getUseSMVD() && !pcSlice->getCheckLDC() && !pcSlice->getPicHeader()->getMvdL1ZeroFlag() ) |
886 | 0 | { |
887 | 0 | int currPOC = pcSlice->getPOC(); |
888 | |
|
889 | 0 | int forwardPOC = currPOC; |
890 | 0 | int backwardPOC = currPOC; |
891 | 0 | int ref = 0; |
892 | 0 | int refIdx0 = -1; |
893 | 0 | int refIdx1 = -1; |
894 | | |
895 | | // search nearest forward POC in List 0 |
896 | 0 | for ( ref = 0; ref < pcSlice->getNumRefIdx( REF_PIC_LIST_0 ); ref++ ) |
897 | 0 | { |
898 | 0 | int poc = pcSlice->getRefPOC( REF_PIC_LIST_0, ref ); |
899 | 0 | const bool isRefLongTerm = pcSlice->getIsUsedAsLongTerm( REF_PIC_LIST_0, ref ); |
900 | 0 | if( poc < currPOC && ( poc > forwardPOC || refIdx0 == -1 ) && !isRefLongTerm ) |
901 | 0 | { |
902 | 0 | forwardPOC = poc; |
903 | 0 | refIdx0 = ref; |
904 | 0 | } |
905 | 0 | } |
906 | | |
907 | | // search nearest backward POC in List 1 |
908 | 0 | for ( ref = 0; ref < pcSlice->getNumRefIdx( REF_PIC_LIST_1 ); ref++ ) |
909 | 0 | { |
910 | 0 | int poc = pcSlice->getRefPOC( REF_PIC_LIST_1, ref ); |
911 | 0 | const bool isRefLongTerm = pcSlice->getIsUsedAsLongTerm( REF_PIC_LIST_1, ref ); |
912 | 0 | if( poc > currPOC && ( poc < backwardPOC || refIdx1 == -1 ) && !isRefLongTerm ) |
913 | 0 | { |
914 | 0 | backwardPOC = poc; |
915 | 0 | refIdx1 = ref; |
916 | 0 | } |
917 | 0 | } |
918 | |
|
919 | 0 | if ( !(forwardPOC < currPOC && backwardPOC > currPOC) ) |
920 | 0 | { |
921 | 0 | forwardPOC = currPOC; |
922 | 0 | backwardPOC = currPOC; |
923 | 0 | refIdx0 = -1; |
924 | 0 | refIdx1 = -1; |
925 | | |
926 | | // search nearest backward POC in List 0 |
927 | 0 | for ( ref = 0; ref < pcSlice->getNumRefIdx( REF_PIC_LIST_0 ); ref++ ) |
928 | 0 | { |
929 | 0 | int poc = pcSlice->getRefPOC( REF_PIC_LIST_0, ref ); |
930 | 0 | const bool isRefLongTerm = pcSlice->getIsUsedAsLongTerm( REF_PIC_LIST_0, ref ); |
931 | 0 | if( poc > currPOC && ( poc < backwardPOC || refIdx0 == -1 ) && !isRefLongTerm ) |
932 | 0 | { |
933 | 0 | backwardPOC = poc; |
934 | 0 | refIdx0 = ref; |
935 | 0 | } |
936 | 0 | } |
937 | | |
938 | | // search nearest forward POC in List 1 |
939 | 0 | for ( ref = 0; ref < pcSlice->getNumRefIdx( REF_PIC_LIST_1 ); ref++ ) |
940 | 0 | { |
941 | 0 | int poc = pcSlice->getRefPOC( REF_PIC_LIST_1, ref ); |
942 | 0 | const bool isRefLongTerm = pcSlice->getIsUsedAsLongTerm( REF_PIC_LIST_1, ref ); |
943 | 0 | if( poc < currPOC && ( poc > forwardPOC || refIdx1 == -1 ) && !isRefLongTerm ) |
944 | 0 | { |
945 | 0 | forwardPOC = poc; |
946 | 0 | refIdx1 = ref; |
947 | 0 | } |
948 | 0 | } |
949 | 0 | } |
950 | |
|
951 | 0 | if ( forwardPOC < currPOC && backwardPOC > currPOC ) |
952 | 0 | { |
953 | 0 | pcSlice->setBiDirPred( true, refIdx0, refIdx1 ); |
954 | 0 | } |
955 | 0 | else |
956 | 0 | { |
957 | 0 | pcSlice->setBiDirPred( false, -1, -1 ); |
958 | 0 | } |
959 | 0 | } |
960 | 0 | else |
961 | 0 | { |
962 | 0 | pcSlice->setBiDirPred( false, -1, -1 ); |
963 | 0 | } |
964 | | |
965 | | //--------------- |
966 | 0 | xCheckMixedNalUnit( pcSlice, nalu ); |
967 | |
|
968 | 0 | if( m_bFirstSliceInPicture ) |
969 | 0 | { |
970 | 0 | #if RECO_WHILE_PARSE |
971 | 0 | for( int ctu = 0; ctu < pcSlice->getPPS()->pcv->sizeInCtus; ctu++ ) |
972 | 0 | { |
973 | 0 | m_pcParsePic->ctuParsedBarrier[ctu].lock(); |
974 | 0 | } |
975 | |
|
976 | 0 | #endif |
977 | 0 | m_parseFrameList.push_back( m_pcParsePic ); |
978 | 0 | } |
979 | |
|
980 | 0 | ITT_TASKEND( itt_domain_oth, itt_handle_start ); |
981 | |
|
982 | 0 | static const auto parseTask = []( int threadId, void* param ) |
983 | 0 | { |
984 | 0 | Slice* slice = static_cast<Slice*>( param ); |
985 | 0 | auto& decLib = slice->parseTaskParams.decLibParser; |
986 | 0 | auto& bitstream = slice->parseTaskParams.bitstream; |
987 | 0 | auto* pic = slice->getPic(); |
988 | |
|
989 | 0 | try |
990 | 0 | { |
991 | 0 | pic->startProcessingTimer(); |
992 | | |
993 | | // Decode a picture |
994 | 0 | ITT_TASKSTART( itt_domain_prs, itt_handle_parse ); |
995 | 0 | decLib->m_cSliceDecoder.parseSlice( slice, &bitstream, threadId ); |
996 | 0 | ITT_TASKEND( itt_domain_prs, itt_handle_parse ); |
997 | |
|
998 | 0 | pic->stopProcessingTimer(); |
999 | |
|
1000 | 0 | bitstream.clearFifo(); |
1001 | 0 | bitstream.clearEmulationPreventionByteLocation(); |
1002 | 0 | } |
1003 | 0 | catch( ... ) |
1004 | 0 | { |
1005 | 0 | pic->setParseError( std::current_exception() ); |
1006 | 0 | std::rethrow_exception( std::current_exception() ); |
1007 | 0 | } |
1008 | 0 | return true; |
1009 | 0 | }; |
1010 | |
|
1011 | 0 | pcSlice->parseTaskParams.init( this, std::move( nalu.getBitstream() ) ); |
1012 | 0 | pcSlice->parseDone.lock(); |
1013 | |
|
1014 | 0 | auto expected = Picture::init; |
1015 | 0 | m_pcParsePic->progress.compare_exchange_strong( expected, Picture::parsing ); // if RECO_WHILE_PARSE reconstruction can already have started, so we make sure to not overwrite that state |
1016 | |
|
1017 | 0 | if( m_threadPool && m_threadPool->numThreads() > 0 ) |
1018 | 0 | { |
1019 | 0 | if( m_uiSliceSegmentIdx > 0 ) |
1020 | 0 | { |
1021 | 0 | m_threadPool->addBarrierTask( TP_TASK_NAME_ARG( "POC:" + std::to_string( m_pcParsePic->poc ) + " parseTask" ) |
1022 | 0 | parseTask, pcSlice, &m_pcParsePic->m_divTasksCounter, &pcSlice->parseDone, |
1023 | 0 | CBarrierVec{ &m_pcParsePic->slices[m_uiSliceSegmentIdx - 1]->parseDone } ); |
1024 | 0 | } |
1025 | 0 | else |
1026 | 0 | { |
1027 | 0 | m_threadPool->addBarrierTask( TP_TASK_NAME_ARG( "POC:" + std::to_string( m_pcParsePic->poc ) + " parseTask" ) |
1028 | 0 | parseTask, pcSlice, &m_pcParsePic->m_divTasksCounter, &pcSlice->parseDone ); |
1029 | 0 | } |
1030 | 0 | } |
1031 | 0 | else |
1032 | 0 | { |
1033 | 0 | parseTask( 0, pcSlice ); |
1034 | 0 | pcSlice->parseDone.unlock(); |
1035 | 0 | } |
1036 | |
|
1037 | 0 | if( pcSlice->getFirstCtuRsAddrInSlice() == 0 && !m_bFirstSliceInPicture ) |
1038 | 0 | { |
1039 | 0 | if( m_prevPOC >= m_pocRandomAccess ) |
1040 | 0 | { |
1041 | 0 | DTRACE_UPDATE( g_trace_ctx, std::make_pair( "final", 0 ) ); |
1042 | 0 | } |
1043 | 0 | } |
1044 | 0 | else |
1045 | 0 | { |
1046 | 0 | DTRACE_UPDATE( g_trace_ctx, std::make_pair( "final", 1 ) ); |
1047 | 0 | } |
1048 | 0 | m_prevPOC = pcSlice->getPOC(); |
1049 | |
|
1050 | 0 | m_bFirstSliceInSequence[nalu.m_nuhLayerId] = false; |
1051 | 0 | m_bFirstSliceInBitstream = false; |
1052 | | |
1053 | |
|
1054 | 0 | const unsigned lastCtuInSlice = pcSlice->getCtuAddrInSlice( pcSlice->getNumCtuInSlice() - 1 ); |
1055 | 0 | if( lastCtuInSlice == pcSlice->getPPS()->pcv->sizeInCtus - 1 ) |
1056 | 0 | { |
1057 | 0 | return true; |
1058 | 0 | } |
1059 | | |
1060 | 0 | return false; |
1061 | 0 | } |
1062 | | |
1063 | | void DecLibParser::xActivateParameterSets( const int layerId ) |
1064 | 0 | { |
1065 | 0 | ParameterSetManager::ActivePSs paramSets; |
1066 | |
|
1067 | 0 | if( m_bFirstSliceInPicture ) |
1068 | 0 | { |
1069 | 0 | paramSets = m_parameterSetManager.xActivateParameterSets( m_bFirstSliceInPicture, m_apcSlicePilot, m_picHeader.get(), |
1070 | 0 | !( m_errHandlingFlags & ERR_HANDLING_TRY_CONTINUE ) ); |
1071 | 0 | const SPS* sps = paramSets.sps; |
1072 | 0 | const PPS* pps = paramSets.pps; |
1073 | 0 | const APS** alfApss = paramSets.alfAPSs->data(); |
1074 | 0 | const APS* lmcsAPS = paramSets.lmcsAps; |
1075 | 0 | const APS* scalingListAPS = paramSets.scalingListAps; |
1076 | |
|
1077 | 0 | xParsePrefixSEImessages(); |
1078 | | |
1079 | | // Get a new picture buffer |
1080 | 0 | m_pcParsePic = m_picListManager.getNewPicBuffer( *sps, *pps, m_apcSlicePilot->getTLayer(), layerId, m_parameterSetManager.getVPS( sps->getVPSId() ) ); |
1081 | 0 | CHECK( std::find( m_dpbReferencePics.cbegin(), m_dpbReferencePics.cend(), m_pcParsePic ) != m_dpbReferencePics.cend(), "reused picture shouldn't be in decoded picture buffer" ); |
1082 | 0 | m_dpbReferencePics.push_back( m_pcParsePic ); |
1083 | | // assign these fields already, because they are needed by PicListManager::getPicListRange() and Slice::applyReferencePictureSet() |
1084 | 0 | m_pcParsePic->poc = m_apcSlicePilot->getPOC(); |
1085 | 0 | m_pcParsePic->eNalUnitType = m_apcSlicePilot->getNalUnitType(); |
1086 | 0 | m_pcParsePic->finalInit( &m_cuChunkCache, &m_tuChunkCache, &m_cuMapCache, &m_chromaCuMapCache, sps, pps, m_picHeader, alfApss, lmcsAPS, scalingListAPS ); |
1087 | |
|
1088 | | #if !DISABLE_CONFROMANCE_CHECK |
1089 | | m_apcSlicePilot->checkLeadingPictureRestrictions( m_dpbReferencePics ); |
1090 | | #endif |
1091 | |
|
1092 | 0 | m_pcParsePic->dpbReferenceMark = m_apcSlicePilot->getPicHeader()->getNonReferencePictureFlag() ? Picture::unreferenced : Picture::ShortTerm; |
1093 | 0 | m_pcParsePic->stillReferenced = !!m_pcParsePic->dpbReferenceMark; |
1094 | 0 | m_pcParsePic->isReferencePic = !!m_pcParsePic->dpbReferenceMark; |
1095 | | |
1096 | | // Set Field/Frame coding mode |
1097 | 0 | bool isField = false; |
1098 | 0 | bool isTopField = false; |
1099 | 0 | if(!m_seiMessageList.empty()) |
1100 | 0 | { |
1101 | | // Check if any new Frame Field Info SEI has arrived |
1102 | 0 | seiMessages frameFieldSEIs = SEI_internal::getSeisByType( m_seiMessageList, VVDEC_FRAME_FIELD_INFO ); |
1103 | 0 | if(!frameFieldSEIs.empty()) |
1104 | 0 | { |
1105 | 0 | const vvdecSEIFrameFieldInfo* ff = (vvdecSEIFrameFieldInfo*) frameFieldSEIs.front()->payload; |
1106 | 0 | isField = ff->fieldPicFlag; |
1107 | 0 | isTopField = isField && (!ff->bottomFieldFlag); |
1108 | 0 | } |
1109 | 0 | } |
1110 | 0 | m_pcParsePic->fieldPic = isField; |
1111 | 0 | m_pcParsePic->topField = isTopField; |
1112 | | |
1113 | | // transfer any SEI messages that have been received to the picture |
1114 | 0 | m_pcParsePic->seiMessageList = m_seiMessageList; |
1115 | 0 | m_seiMessageList.clear(); |
1116 | |
|
1117 | 0 | m_apcSlicePilot->setPicHeader( m_picHeader.get() ); |
1118 | 0 | } |
1119 | 0 | else |
1120 | 0 | { |
1121 | 0 | paramSets = m_parameterSetManager.xActivateParameterSets( m_bFirstSliceInPicture, m_apcSlicePilot, m_picHeader.get() ); |
1122 | 0 | m_apcSlicePilot->setAlfApss( paramSets.alfAPSs->data() ); |
1123 | |
|
1124 | 0 | for( int i = 0; i < ALF_CTB_MAX_NUM_APS; ++i ) |
1125 | 0 | { |
1126 | 0 | m_pcParsePic->cs->alfApss[i] = paramSets.alfAPSs->data()[i] ? paramSets.alfAPSs->data()[i]->getSharedPtr() : nullptr; |
1127 | 0 | } |
1128 | 0 | } |
1129 | | |
1130 | | // make the slice-pilot a real slice, and set up the slice-pilot for the next slice |
1131 | 0 | Slice* pSlice = m_pcParsePic->allocateNewSlice( &m_apcSlicePilot ); |
1132 | 0 | CHECK_FATAL( m_pcParsePic->slices.size() != ( m_uiSliceSegmentIdx + 1 ), "Invalid number of slices" ); |
1133 | |
|
1134 | 0 | const VPS* vps = pSlice->getVPS_nothrow(); |
1135 | 0 | const SPS* sps = pSlice->getSPS(); |
1136 | 0 | const PPS* pps = pSlice->getPPS(); |
1137 | |
|
1138 | 0 | if( !m_bFirstSliceInPicture ) |
1139 | 0 | { |
1140 | | // check that the current active PPS has not changed... |
1141 | 0 | CHECK( sps->getChangedFlag(), "Error - a new SPS has been decoded while processing a picture" ); |
1142 | 0 | CHECK( pps->getChangedFlag(), "Error - a new PPS has been decoded while processing a picture" ); |
1143 | 0 | CHECK( m_parameterSetManager.getAPSChangedFlag(), "Error - a new APS has been decoded while processing a picture" ); |
1144 | |
|
1145 | 0 | xParsePrefixSEImessages(); |
1146 | | |
1147 | | // Check if any new SEI has arrived |
1148 | 0 | if( !m_seiMessageList.empty() ) |
1149 | 0 | { |
1150 | | // Currently only decoding Unit SEI message occurring between VCL NALUs copied |
1151 | 0 | seiMessages& picSEI = m_pcParsePic->seiMessageList; |
1152 | 0 | seiMessages decodingUnitInfos = SEI_internal::extractSeisByType( m_seiMessageList, VVDEC_DECODING_UNIT_INFO ); |
1153 | 0 | picSEI.insert( picSEI.end(), decodingUnitInfos.begin(), decodingUnitInfos.end() ); |
1154 | 0 | SEI_internal::deleteSEIs ( m_seiMessageList ); |
1155 | 0 | } |
1156 | 0 | } |
1157 | | |
1158 | 0 | CHECK( !sps->getGDREnabledFlag() && m_picHeader->getGdrPicFlag(), "When gdr_enabled_flag is equal to 0, the value of gdr_pic_flag shall be equal to 0 " ); |
1159 | 0 | CHECK( !sps->getUseWP() && pps->getUseWP(), "When sps_weighted_pred_flag is equal to 0, the value of pps_weighted_pred_flag shall be equal to 0." ); |
1160 | 0 | CHECK( !sps->getUseWPBiPred() && pps->getWPBiPred(), |
1161 | 0 | "When sps_weighted_bipred_flag is equal to 0, the value of pps_weighted_bipred_flag shall be equal to 0." ); |
1162 | |
|
1163 | 0 | CHECK( !sps->getResChangeInClvsEnabledFlag() && pps->getPicWidthInLumaSamples() != sps->getMaxPicWidthInLumaSamples(), |
1164 | 0 | "When res_change_in_clvs_allowed_flag equal to 0, the value of pic_width_in_luma_samples shall be equal to pic_width_max_in_luma_samples." ); |
1165 | 0 | CHECK( !sps->getResChangeInClvsEnabledFlag() && pps->getPicHeightInLumaSamples() != sps->getMaxPicHeightInLumaSamples(), |
1166 | 0 | "When res_change_in_clvs_allowed_flag equal to 0, the value of pic_height_in_luma_samples shall be equal to pic_height_max_in_luma_samples." ); |
1167 | 0 | CHECK( sps->getResChangeInClvsEnabledFlag() && sps->getSubPicInfoPresentFlag() != 0, |
1168 | 0 | "When res_change_in_clvs_allowed_flag is equal to 1, the value of subpic_info_present_flag shall be equal to 0." ); |
1169 | 0 | CHECK( sps->getResChangeInClvsEnabledFlag() && sps->getVirtualBoundariesEnabledFlag(), |
1170 | 0 | "when the value of res_change_in_clvs_allowed_flag is equal to 1, the value of sps_virtual_boundaries_present_flag shall be equal to 0" ); |
1171 | 0 | if( vps && vps->m_numOutputLayersInOls[vps->m_iTargetLayer] > 1 ) |
1172 | 0 | { |
1173 | 0 | CHECK( sps->getMaxPicWidthInLumaSamples() > vps->getOlsDpbPicSize( vps->m_iTargetLayer ).width, |
1174 | 0 | "pic_width_max_in_luma_samples shall be less than or equal to the value of ols_dpb_pic_width[ i ]" ); |
1175 | 0 | CHECK( sps->getMaxPicHeightInLumaSamples() > vps->getOlsDpbPicSize( vps->m_iTargetLayer ).height, |
1176 | 0 | "pic_height_max_in_luma_samples shall be less than or equal to the value of ols_dpb_pic_height[ i ]" ); |
1177 | 0 | } |
1178 | | |
1179 | 0 | CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getOneTilePerPicConstraintFlag() && pps->getNumTiles() != 1, |
1180 | 0 | "When one_tile_per_pic_constraint_flag is equal to 1, each picture shall contain only one tile" ); |
1181 | 0 | CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getOneSlicePerPicConstraintFlag() && pps->getRectSliceFlag() && pps->getNumSlicesInPic() != 1, |
1182 | 0 | "When one_slice_per_pic_constraint_flag is equal to 1 and if pps_rect_slice_flag is equal to 1, the value of num_slices_in_pic_minus1 shall be equal to 0" ); |
1183 | 0 | CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getNoRprConstraintFlag() && sps->getRprEnabledFlag(), |
1184 | 0 | "When gci_no_ref_pic_resampling_constraint_flag is equal to 1, the value of sps_ref_pic_resampling_enabled_flag shall be equal to 0" ); |
1185 | 0 | CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getNoResChangeInClvsConstraintFlag() && sps->getResChangeInClvsEnabledFlag(), |
1186 | 0 | "When gci_no_res_change_in_clvs_constraint_flag is equal to 1, the value of sps_res_change_in_clvs_allowed_flag shall be equal to 0" ); |
1187 | 0 | CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getNoIdrRplConstraintFlag() && sps->getIDRRefParamListPresent(), |
1188 | 0 | "When gci_no_idr_rpl_constraint_flag equal to 1 , the value of sps_idr_rpl_present_flag shall be equal to 0" ); |
1189 | 0 | CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getNoMixedNaluTypesInPicConstraintFlag() && pps->getMixedNaluTypesInPicFlag(), |
1190 | 0 | "When gci_no_mixed_nalu_types_in_pic_constraint_flag equal to 1, the value of pps_mixed_nalu_types_in_pic_flag shall be equal to 0" ); |
1191 | 0 | CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getNoRectSliceConstraintFlag() && pps->getRectSliceFlag(), |
1192 | 0 | "When gci_no_rectangular_slice_constraint_flag equal to 1, the value of pps_rect_slice_flag shall be equal to 0" ); |
1193 | 0 | CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getOneSlicePerSubpicConstraintFlag() && !pps->getSingleSlicePerSubPicFlag(), |
1194 | 0 | "When gci_one_slice_per_subpic_constraint_flag equal to 1, the value of pps_single_slice_per_subpic_flag shall be equal to 1" ); |
1195 | 0 | CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getNoSubpicInfoConstraintFlag() && sps->getSubPicInfoPresentFlag(), |
1196 | 0 | "When gci_no_subpic_info_constraint_flag is equal to 1, the value of sps_subpic_info_present_flag shall be equal to 0" ); |
1197 | |
|
1198 | 0 | if( sps->getProfileTierLevel()->getConstraintInfo()->getNoMttConstraintFlag() ) |
1199 | 0 | { |
1200 | 0 | CHECK( sps->getMaxMTTHierarchyDepth() || sps->getMaxMTTHierarchyDepthI() || sps->getMaxMTTHierarchyDepthIChroma(), |
1201 | 0 | "When gci_no_mtt_constraint_flag is equal to 1, the values of sps_max_mtt_hierarchy_depth_intra_slice_luma, sps_max_mtt_hierarchy_depth_inter_slice" |
1202 | 0 | " and sps_max_mtt_hierarchy_depth_intra_slice_chroma shall be equal to 0" ); |
1203 | 0 | } |
1204 | 0 | if( sps->getProfileTierLevel()->getConstraintInfo()->getNoWeightedPredictionConstraintFlag() ) |
1205 | 0 | { |
1206 | 0 | CHECK( sps->getUseWP() || sps->getUseWPBiPred(), |
1207 | 0 | "When gci_no_weighted_prediction_constraint_flag is equal to 1, the values of sps_weighted_pred_flag and sps_weighted_bipred_flag shall be equal to 0" ); |
1208 | 0 | } |
1209 | | |
1210 | 0 | CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getNoChromaQpOffsetConstraintFlag() && pps->getCuChromaQpOffsetEnabledFlag(), |
1211 | 0 | "When gci_no_ChromaQpOffset_constraint_flag is equal to 1, the values of pps_cu_chroma_qp_offset_list_enabled_flag shall be equal to 0" ); |
1212 | |
|
1213 | 0 | CHECK( sps->getCTUSize() > ( 1 << sps->getProfileTierLevel()->getConstraintInfo()->getMaxLog2CtuSizeConstraintIdc() ), |
1214 | 0 | "The CTU size specified by sps_log2_ctu_size_minus5 shall not exceed the constraint specified by gci_three_minus_max_log2_ctu_size_constraint_idc" ); |
1215 | 0 | CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getNoLumaTransformSize64ConstraintFlag() && sps->getLog2MaxTbSize() != 5, |
1216 | 0 | "When gci_no_luma_transform_size_64_constraint_flag is equal to 1, the value of sps_max_luma_transform_size_64_flag shall be equal to 0" ); |
1217 | |
|
1218 | | #if 0 |
1219 | | if( vps && vps->getMaxLayers() > 1 ) |
1220 | | { |
1221 | | // TODO: fix MT static maps |
1222 | | static std::unordered_map<int, int> m_layerChromaFormat; |
1223 | | static std::unordered_map<int, int> m_layerBitDepth; |
1224 | | |
1225 | | int curLayerIdx = vps->getGeneralLayerIdx(layerId); |
1226 | | int curLayerChromaFormat = sps->getChromaFormatIdc(); |
1227 | | int curLayerBitDepth = sps->getBitDepth(); |
1228 | | |
1229 | | if( pSlice->isClvssPu() && m_bFirstSliceInPicture ) |
1230 | | { |
1231 | | m_layerChromaFormat[curLayerIdx] = curLayerChromaFormat; |
1232 | | m_layerBitDepth [curLayerIdx] = curLayerBitDepth; |
1233 | | } |
1234 | | else |
1235 | | { |
1236 | | CHECK( m_layerChromaFormat[curLayerIdx] != curLayerChromaFormat, "Different chroma format in the same layer." ); |
1237 | | CHECK( m_layerBitDepth [curLayerIdx] != curLayerBitDepth, "Different bit-depth in the same layer." ); |
1238 | | } |
1239 | | |
1240 | | for( int i = 0; i < curLayerIdx; i++ ) |
1241 | | { |
1242 | | if( vps->getDirectRefLayerFlag( curLayerIdx, i ) ) |
1243 | | { |
1244 | | int refLayerChromaFormat = m_layerChromaFormat[i]; |
1245 | | CHECK( curLayerChromaFormat != refLayerChromaFormat, "The chroma formats of the current layer and the reference layer are different" ); |
1246 | | int refLayerBitDepth = m_layerBitDepth[i]; |
1247 | | CHECK( curLayerBitDepth != refLayerBitDepth, "The bit-depth of the current layer and the reference layer are different" ); |
1248 | | } |
1249 | | } |
1250 | | } |
1251 | | #endif |
1252 | |
|
1253 | 0 | const int minCuSize = 1 << sps->getLog2MinCodingBlockSize(); |
1254 | 0 | CHECK( ( pps->getPicWidthInLumaSamples() % ( std::max( 8, minCuSize) ) ) != 0, "Coded frame width must be a multiple of Max(8, the minimum unit size)" ); |
1255 | 0 | CHECK( ( pps->getPicHeightInLumaSamples() % ( std::max( 8, minCuSize) ) ) != 0, "Coded frame height must be a multiple of Max(8, the minimum unit size)" ); |
1256 | |
|
1257 | 0 | if( sps->getCTUSize() + 2 * ( 1 << sps->getLog2MinCodingBlockSize() ) > pps->getPicWidthInLumaSamples() ) |
1258 | 0 | { |
1259 | 0 | CHECK( pps->getUseWrapAround(), |
1260 | 0 | "Wraparound shall be disabled when the value of ( CtbSizeY / MinCbSizeY + 1) is greater than or equal to" |
1261 | 0 | " ( pic_width_in_luma_samples / MinCbSizeY - 1 )" ); |
1262 | 0 | } |
1263 | | |
1264 | 0 | if( pSlice->getPicHeader()->getGdrOrIrapPicFlag() && !pSlice->getPicHeader()->getGdrPicFlag() |
1265 | 0 | && ( !vps || vps->getIndependentLayerFlag( vps->getGeneralLayerIdx( layerId ) ) ) ) |
1266 | 0 | { |
1267 | 0 | CHECK( pSlice->getPicHeader()->getPicInterSliceAllowedFlag(), |
1268 | 0 | "When gdr_or_irap_pic_flag is equal to 1 and gdr_pic_flag is equal to 0 and vps_independent_layer_flag[ GeneralLayerIdx[ nuh_layer_id ] ] " |
1269 | 0 | "is equal to 1, ph_inter_slice_allowed_flag shall be equal to 0" ); |
1270 | 0 | } |
1271 | | |
1272 | 0 | if( sps->getVPSId() && vps && vps->m_numLayersInOls[vps->m_iTargetLayer] == 1 ) |
1273 | 0 | { |
1274 | 0 | CHECK( !sps->getPtlDpbHrdParamsPresentFlag(), |
1275 | 0 | "When sps_video_parameter_set_id is greater than 0 and there is an OLS that contains only one layer" |
1276 | 0 | " with nuh_layer_id equal to the nuh_layer_id of the SPS, the value of sps_ptl_dpb_hrd_params_present_flag shall be equal to 1" ); |
1277 | 0 | } |
1278 | | |
1279 | 0 | ProfileLevelTierFeatures ptlFeature; |
1280 | 0 | ptlFeature.extractPTLInformation(*sps); |
1281 | |
|
1282 | 0 | const LevelTierFeatures* ltFeature = ptlFeature.getLevelTierFeatures(); |
1283 | 0 | const ProfileFeatures* pFeature = ptlFeature.getProfileFeatures(); |
1284 | |
|
1285 | 0 | CHECK( ltFeature && pps->getNumTileColumns() > ltFeature->maxTileCols, "Num tile columns signaled in PPS exceed level limits" ); |
1286 | 0 | CHECK( ltFeature && pps->getNumTiles() > ltFeature->maxTilesPerAu, "Num tiles signaled in PPS exceed level limits" ); |
1287 | 0 | CHECK( pFeature && sps->getBitDepth() > pFeature->maxBitDepth, "Bit depth exceed profile limit" ); |
1288 | 0 | CHECK( pFeature && sps->getChromaFormatIdc() > pFeature->maxChromaFormat, "Chroma format exceed profile limit" ); |
1289 | 0 | } |
1290 | | |
1291 | | void DecLibParser::prepareUnavailablePicture( bool isLost, const PPS* pps, int iUnavailablePoc, const int layerId, const bool longTermFlag, const int temporalId ) |
1292 | 0 | { |
1293 | 0 | if( isLost ) |
1294 | 0 | { |
1295 | 0 | CHECK( !( m_errHandlingFlags & ERR_HANDLING_TRY_CONTINUE ), "missing reference picture poc: " << iUnavailablePoc ); |
1296 | |
|
1297 | 0 | if( !m_picListManager.getBackPic() ) |
1298 | 0 | { |
1299 | 0 | THROW_RECOVERABLE( "no pictures yet." ); |
1300 | 0 | return; |
1301 | 0 | } |
1302 | 0 | msg( WARNING, "inserting lost poc : %d\n", iUnavailablePoc ); |
1303 | 0 | } |
1304 | 0 | else |
1305 | 0 | { |
1306 | 0 | msg( INFO, "inserting unavailable poc : %d\n", iUnavailablePoc ); |
1307 | 0 | } |
1308 | | // use the parameter sets of the referencing picture, so the generated reference has a compatible buffer layout |
1309 | 0 | const SPS* sps = static_cast<const ParameterSetManager&>( m_parameterSetManager ).getSPS( pps->getSPSId() ); |
1310 | 0 | CHECK( !sps, "no SPS for unavailable reference picture" ); |
1311 | 0 | Picture* cFillPic = m_picListManager.getNewPicBuffer( *sps, *pps, 0, layerId, m_parameterSetManager.getVPS( sps->getVPSId() ) ); |
1312 | 0 | CHECK( std::find( m_dpbReferencePics.cbegin(), m_dpbReferencePics.cend(), cFillPic ) != m_dpbReferencePics.cend(), "reused picture shouldn't be in decoded picture buffer" ); |
1313 | 0 | m_dpbReferencePics.push_back( cFillPic ); |
1314 | 0 | const APS* nullAlfApss[ALF_CTB_MAX_NUM_APS] = { nullptr, }; |
1315 | 0 | cFillPic->finalInit( &m_cuChunkCache, &m_tuChunkCache, &m_cuMapCache, &m_chromaCuMapCache, sps, pps, m_picHeader, nullAlfApss, nullptr, nullptr, false ); |
1316 | |
|
1317 | 0 | CHECK_FATAL( !cFillPic->slices.empty(), "fill pic should not contain slices, already." ); |
1318 | 0 | cFillPic->allocateNewSlice(); |
1319 | 0 | cFillPic->slices[0]->initSlice(); |
1320 | 0 | cFillPic->slices[0]->setPOC( iUnavailablePoc ); |
1321 | 0 | cFillPic->slices[0]->setTLayer( temporalId ); |
1322 | 0 | cFillPic->slices[0]->setNalUnitLayerId( layerId ); |
1323 | | |
1324 | | // picture header is not derived for generated reference picture |
1325 | 0 | cFillPic->slices[0]->setPicHeader( nullptr ); |
1326 | 0 | cFillPic->slices[0]->setPPS( pps->getSharedPtr() ); |
1327 | |
|
1328 | 0 | cFillPic->dpbReferenceMark = longTermFlag ? Picture::LongTerm : Picture::ShortTerm; |
1329 | 0 | cFillPic->stillReferenced = true; |
1330 | 0 | cFillPic->isReferencePic = true; |
1331 | 0 | cFillPic->poc = iUnavailablePoc; |
1332 | 0 | cFillPic->neededForOutput = false; |
1333 | 0 | cFillPic->tempLayer = temporalId; |
1334 | 0 | cFillPic->nonReferencePictureFlag = false; |
1335 | 0 | cFillPic->wasLost = isLost; |
1336 | | |
1337 | | // a generated unavailable picture (8.3.4) precedes the current IRAP/GDR picture, so it can't be prevTid0Pic (8.3.1) |
1338 | 0 | if( isLost && cFillPic->slices[0]->getTLayer() == 0 && |
1339 | 0 | cFillPic->slices[0]->getNalUnitType() != NAL_UNIT_CODED_SLICE_RASL && |
1340 | 0 | cFillPic->slices[0]->getNalUnitType() != NAL_UNIT_CODED_SLICE_RADL ) |
1341 | 0 | { |
1342 | 0 | m_prevTid0POC = cFillPic->slices[0]->getPOC(); |
1343 | 0 | } |
1344 | |
|
1345 | 0 | cFillPic->subPictures.clear(); |
1346 | 0 | cFillPic->sliceSubpicIdx.clear(); |
1347 | |
|
1348 | 0 | for( int subPicIdx = 0; subPicIdx < pps->getNumSubPics(); subPicIdx++ ) |
1349 | 0 | { |
1350 | 0 | cFillPic->subPictures.push_back( pps->getSubPic( subPicIdx ) ); |
1351 | 0 | } |
1352 | |
|
1353 | 0 | cFillPic->parseDone.unlock(); |
1354 | |
|
1355 | | #if 0 |
1356 | | // NOT YET IMPLEMENTED |
1357 | | if( isLost && ( m_errHandlingFlags & ERR_HANDLING_COPY_CLOSEST ) ) |
1358 | | { |
1359 | | // this will be filled in later, when closer pictures might have been reconstructed. |
1360 | | |
1361 | | cFillPic->progress = Picture::parsed; |
1362 | | m_parseFrameList.push_back( cFillPic ); |
1363 | | return; |
1364 | | } |
1365 | | #endif |
1366 | |
|
1367 | 0 | cFillPic->fillGrey( sps ); |
1368 | |
|
1369 | 0 | if( m_pocRandomAccess == MAX_INT ) |
1370 | 0 | { |
1371 | 0 | m_pocRandomAccess = iUnavailablePoc; |
1372 | 0 | } |
1373 | 0 | } |
1374 | | |
1375 | | #if 0 |
1376 | | // NOT YET IMPLEMENTED |
1377 | | void DecLibParser::fillMissingPicBuf( Picture* pcPic, bool copyClosest ) |
1378 | | { |
1379 | | if( copyClosest ) |
1380 | | { |
1381 | | CHECK_FATAL( pcPic->progress != Picture::parsed, "filled in picture should have been marked as parsed" ); |
1382 | | CHECK_FATAL( pcPic->parseDone.isBlocked(), "parsed barrier should be unlocked" ); |
1383 | | |
1384 | | auto closestPic = m_picListManager.findClosestPic( pcPic->poc ); |
1385 | | if( closestPic ) |
1386 | | { |
1387 | | CHECK_FATAL( closestPic->progress < Picture::reconstructed, "closest Picture is not yet reconstructed" ) |
1388 | | // the next not-lost picture in the parseFrameList should be the one, that referenced this picture |
1389 | | auto referencedBy = std::find_if( m_parseFrameList.begin(), m_parseFrameList.end(), []( Picture* p ) { return !p->wasLost && !p->error; } ); |
1390 | | msg( INFO, "copying picture %d to %d (%d)\n", closestPic->getPOC(), pcPic->poc, ( referencedBy != m_parseFrameList.end() ) ? ( *referencedBy )->poc : -1 ); |
1391 | | |
1392 | | pcPic->getRecoBuf().copyFrom( closestPic->getRecoBuf() ); |
1393 | | |
1394 | | pcPic->slices[0]->copySliceInfo( closestPic->slices[0] ); |
1395 | | pcPic->slices[0]->setPOC( pcPic->poc ); |
1396 | | } |
1397 | | |
1398 | | // currently we don't output filled-in reference pictures |
1399 | | // pcPic->neededForOutput = true; |
1400 | | } |
1401 | | else |
1402 | | { |
1403 | | pcPic->fillGrey( pcPic->cs->sps.get() ); |
1404 | | } |
1405 | | |
1406 | | pcPic->progress = Picture::reconstructed; |
1407 | | pcPic->reconDone.unlock(); |
1408 | | } |
1409 | | #endif |
1410 | | |
1411 | | void DecLibParser::markAllRefPicsUnused( const int layerId ) |
1412 | 0 | { |
1413 | 0 | for( Picture* pic: m_dpbReferencePics ) |
1414 | 0 | { |
1415 | 0 | if( pic->layerId == layerId ) |
1416 | 0 | { |
1417 | 0 | pic->dpbReferenceMark = Picture::unreferenced; |
1418 | 0 | } |
1419 | 0 | } |
1420 | 0 | m_dpbReferencePics.remove_if( []( Picture* pic ) { return !pic->dpbReferenceMark; } ); |
1421 | 0 | } |
1422 | | |
1423 | | // Function for applying picture marking based on the Reference Picture List |
1424 | | void DecLibParser::applyReferencePictureListBasedMarking( Slice* currSlice, const int layerId ) |
1425 | 0 | { |
1426 | | // checkLeadingPictureRestrictions(rcListPic, pps); |
1427 | | |
1428 | | // CLVSS picture |
1429 | 0 | if( ( currSlice->isIDR() || currSlice->isCRAorGDR() ) && currSlice->getPicHeader()->getNoOutputBeforeRecoveryFlag() ) |
1430 | 0 | { |
1431 | 0 | markAllRefPicsUnused( layerId ); |
1432 | 0 | return; |
1433 | 0 | } |
1434 | | |
1435 | | // mark long-term reference pictures in List0 |
1436 | 0 | for( const auto l: { REF_PIC_LIST_0, REF_PIC_LIST_1 } ) |
1437 | 0 | { |
1438 | 0 | const ReferencePictureList* rpl = currSlice->getRPL( l ); |
1439 | |
|
1440 | 0 | for( int i = 0; i < rpl->getNumRefEntries(); i++ ) |
1441 | 0 | { |
1442 | 0 | if( !rpl->isRefPicLongterm( i ) || rpl->isInterLayerRefPic( i ) ) |
1443 | 0 | { |
1444 | 0 | continue; |
1445 | 0 | } |
1446 | | |
1447 | 0 | Picture* availableST = nullptr; |
1448 | 0 | for( Picture* pic: m_dpbReferencePics ) |
1449 | 0 | { |
1450 | 0 | if( !pic->dpbReferenceMark ) |
1451 | 0 | { |
1452 | 0 | continue; |
1453 | 0 | } |
1454 | | |
1455 | 0 | const int bitsForPoc = pic->cs->sps->getBitsForPOC(); |
1456 | 0 | const int curPoc = pic->getPOC(); |
1457 | 0 | const int ltRefPoc = rpl->calcLTRefPOC( currSlice->getPOC(), bitsForPoc, i ); |
1458 | 0 | if( pic->dpbReferenceMark == Picture::LongTerm && isLTPocEqual( curPoc, ltRefPoc, bitsForPoc, rpl->getDeltaPocMSBPresentFlag( i ) ) ) |
1459 | 0 | { |
1460 | 0 | break; |
1461 | 0 | } |
1462 | | |
1463 | | // if there was no such long-term check the short terms |
1464 | 0 | if( pic->dpbReferenceMark == Picture::ShortTerm && isLTPocEqual( curPoc, ltRefPoc, bitsForPoc, rpl->getDeltaPocMSBPresentFlag( i ) ) ) |
1465 | 0 | { |
1466 | 0 | availableST = pic; |
1467 | | // but don't break here, because we might still find a LT |
1468 | 0 | } |
1469 | 0 | } |
1470 | | |
1471 | | // the found picture was not yet marked as long term, so we mark it here |
1472 | 0 | if ( availableST ) |
1473 | 0 | { |
1474 | 0 | availableST->dpbReferenceMark = Picture::LongTerm; |
1475 | 0 | } |
1476 | 0 | } |
1477 | 0 | } |
1478 | | |
1479 | | // loop through all pictures in the reference picture buffer |
1480 | 0 | for( Picture* pic: m_dpbReferencePics ) |
1481 | 0 | { |
1482 | 0 | if( !pic->dpbReferenceMark ) |
1483 | 0 | { |
1484 | 0 | continue; |
1485 | 0 | } |
1486 | | |
1487 | 0 | bool isReference = false; |
1488 | |
|
1489 | 0 | for( const auto l: { REF_PIC_LIST_0, REF_PIC_LIST_1 } ) |
1490 | 0 | { |
1491 | 0 | if( currSlice->getRPL( l )->findInRefPicList( pic, currSlice->getPOC(), layerId ) ) |
1492 | 0 | { |
1493 | 0 | isReference = true; |
1494 | 0 | break; |
1495 | 0 | } |
1496 | 0 | } |
1497 | | |
1498 | | // mark the picture as "unused for reference" if it is not in |
1499 | | // the Reference Picture List |
1500 | 0 | if( !isReference && pic->poc != currSlice->getPOC() && pic->layerId == layerId ) |
1501 | 0 | { |
1502 | 0 | pic->dpbReferenceMark = Picture::unreferenced; |
1503 | 0 | } |
1504 | | |
1505 | | // // sanity checks |
1506 | | // if( pic->referenced ) |
1507 | | // { |
1508 | | // // check that pictures of higher temporal layers are not used |
1509 | | // CHECK_FATAL( pic->usedByCurr && pic->temporalId > this->getTLayer(), "Invalid state" ); |
1510 | | // } |
1511 | 0 | } |
1512 | | |
1513 | | // ignore neededForOutput flag here, because we only care about reference pictures in the DPB |
1514 | 0 | m_dpbReferencePics.remove_if( []( Picture* pic ) { return !pic->dpbReferenceMark; } ); |
1515 | 0 | } |
1516 | | |
1517 | | void DecLibParser::xParsePrefixSEImessages() |
1518 | 0 | { |
1519 | 0 | while( !m_prefixSEINALUs.empty() ) |
1520 | 0 | { |
1521 | 0 | InputNALUnit& nalu = m_prefixSEINALUs.front(); |
1522 | 0 | const SPS *sps = m_parameterSetManager.getActiveSPS(); |
1523 | 0 | const VPS *vps = m_parameterSetManager.getVPS(sps->getVPSId()); |
1524 | 0 | m_seiReader.parseSEImessage( &(nalu.getBitstream()), m_seiMessageList, nalu.m_nalUnitType, nalu.m_nuhLayerId, nalu.m_temporalId, vps, sps, m_HRD, m_pDecodedSEIOutputStream ); |
1525 | 0 | m_prefixSEINALUs.pop_front(); |
1526 | 0 | } |
1527 | 0 | } |
1528 | | |
1529 | | void DecLibParser::xParsePrefixSEIsForUnknownVCLNal() |
1530 | 71 | { |
1531 | 71 | while (!m_prefixSEINALUs.empty()) |
1532 | 0 | { |
1533 | | // do nothing? |
1534 | 0 | msg( VERBOSE, "Discarding Prefix SEI associated with unknown VCL NAL unit.\n"); |
1535 | 0 | m_prefixSEINALUs.pop_front(); |
1536 | 0 | } |
1537 | | // TODO: discard following suffix SEIs as well? |
1538 | 71 | } |
1539 | | |
1540 | | void DecLibParser::xDecodePicHeader( InputNALUnit& nalu ) |
1541 | 3 | { |
1542 | 3 | m_HLSReader.setBitstream( &nalu.getBitstream() ); |
1543 | 3 | m_picHeader = std::make_shared<PicHeader>(); |
1544 | 3 | m_HLSReader.parsePictureHeader( m_picHeader.get(), &m_parameterSetManager, true ); |
1545 | 3 | } |
1546 | | |
1547 | | void DecLibParser::xDecodeVPS( InputNALUnit& nalu ) |
1548 | 12 | { |
1549 | | // We don't parse the VPS, because the needed bounds checks in parseVPS() are not yet implemented, and we don't process it anyways |
1550 | | #if 0 |
1551 | | std::unique_ptr<VPS> vps( new VPS() ); |
1552 | | m_HLSReader.setBitstream( &nalu.getBitstream() ); |
1553 | | m_HLSReader.parseVPS( vps.get() ); |
1554 | | m_parameterSetManager.storeVPS( vps.release(), nalu.getBitstream().getFifo() ); |
1555 | | #endif |
1556 | 12 | } |
1557 | | |
1558 | | void DecLibParser::xDecodeDCI( InputNALUnit& nalu ) |
1559 | 45 | { |
1560 | 45 | m_HLSReader.setBitstream(&nalu.getBitstream()); |
1561 | | |
1562 | 45 | CHECK(nalu.m_temporalId, "The value of TemporalId of DCI NAL units shall be equal to 0"); |
1563 | 44 | if( !m_dci ) |
1564 | 44 | { |
1565 | 44 | m_dci = new DCI; |
1566 | 44 | m_HLSReader.parseDCI( m_dci ); |
1567 | 44 | } |
1568 | 0 | else |
1569 | 0 | { |
1570 | 0 | DCI dupDCI; |
1571 | 0 | m_HLSReader.parseDCI( &dupDCI ); |
1572 | 0 | CHECK( !m_dci->IsIndenticalDCI( dupDCI ), "Two signaled DCIs are different"); |
1573 | 0 | } |
1574 | 44 | } |
1575 | | |
1576 | | void DecLibParser::xDecodeSPS( InputNALUnit& nalu ) |
1577 | 241 | { |
1578 | 241 | std::unique_ptr<SPS> sps( new SPS() ); |
1579 | 241 | m_HLSReader.setBitstream( &nalu.getBitstream() ); |
1580 | 241 | m_HLSReader.parseSPS( sps.get(), &m_parameterSetManager ); |
1581 | 241 | sps->setLayerId( nalu.m_nuhLayerId ); |
1582 | 241 | DTRACE( g_trace_ctx, D_QP_PER_CTU, "CTU Size: %dx%d", sps->getMaxCUWidth(), sps->getMaxCUHeight() ); // don't move after storeSPS, because SPS could have been deleted |
1583 | 241 | m_parameterSetManager.storeSPS( sps.release(), nalu.getBitstream().getFifo() ); |
1584 | 241 | } |
1585 | | |
1586 | | void DecLibParser::xDecodePPS( InputNALUnit& nalu ) |
1587 | 2 | { |
1588 | 2 | std::unique_ptr<PPS> pps( new PPS() ); |
1589 | 2 | m_HLSReader.setBitstream( &nalu.getBitstream() ); |
1590 | 2 | m_HLSReader.parsePPS( pps.get(), &m_parameterSetManager ); |
1591 | 2 | pps->setLayerId( nalu.m_nuhLayerId ); |
1592 | 2 | m_parameterSetManager.storePPS( pps.release(), nalu.getBitstream().getFifo() ); |
1593 | 2 | } |
1594 | | |
1595 | | void DecLibParser::xDecodeAPS( InputNALUnit& nalu ) |
1596 | 129 | { |
1597 | 129 | std::unique_ptr<APS> aps( new APS() ); |
1598 | 129 | m_HLSReader.setBitstream( &nalu.getBitstream() ); |
1599 | 129 | if( !m_HLSReader.parseAPS( aps.get() ) ) |
1600 | 1 | { // ignore unsupported APS types |
1601 | 1 | return; |
1602 | 1 | } |
1603 | 128 | aps->setTemporalId( nalu.m_temporalId ); |
1604 | 128 | aps->setLayerId( nalu.m_nuhLayerId ); |
1605 | 128 | aps->setHasPrefixNalUnitType( nalu.m_nalUnitType == NAL_UNIT_PREFIX_APS ); |
1606 | 128 | m_parameterSetManager.storeAPS( aps.release(), nalu.getBitstream().getFifo() ); |
1607 | 128 | } |
1608 | | |
1609 | | void DecLibParser::xUpdatePreviousTid0POC(Slice * pSlice) |
1610 | 0 | { |
1611 | 0 | if( pSlice->getTLayer() == 0 && pSlice->getNalUnitType() != NAL_UNIT_CODED_SLICE_RASL && pSlice->getNalUnitType() != NAL_UNIT_CODED_SLICE_RADL |
1612 | 0 | && !pSlice->getPicHeader()->getNonReferencePictureFlag() ) |
1613 | 0 | { |
1614 | 0 | m_prevTid0POC = pSlice->getPOC(); |
1615 | 0 | } |
1616 | 0 | } |
1617 | | |
1618 | | |
1619 | | void DecLibParser::checkNoOutputPriorPics() |
1620 | 0 | { |
1621 | 0 | if( !m_isNoOutputPriorPics ) |
1622 | 0 | { |
1623 | 0 | return; |
1624 | 0 | } |
1625 | | |
1626 | 0 | for( auto& pcPicTmp: m_dpbReferencePics ) |
1627 | 0 | { |
1628 | 0 | if( pcPicTmp->progress >= Picture::reconstructed && pcPicTmp->getPOC() < m_lastPOCNoOutputPriorPics ) |
1629 | 0 | { |
1630 | 0 | pcPicTmp->neededForOutput = false; |
1631 | 0 | } |
1632 | 0 | } |
1633 | 0 | } |
1634 | | |
1635 | | /** Function for checking if picture should be skipped because of random access. This function checks the skipping of pictures in the case of -s option random access. |
1636 | | * All pictures prior to the random access point indicated by the counter iSkipFrame are skipped. |
1637 | | * It also checks the type of Nal unit type at the random access point. |
1638 | | * If the random access point is CRA/CRANT/BLA/BLANT, TFD pictures with POC less than the POC of the random access point are skipped. |
1639 | | * If the random access point is IDR all pictures after the random access point are decoded. |
1640 | | * If the random access point is none of the above, a warning is issues, and decoding of pictures with POC |
1641 | | * equal to or greater than the random access point POC is attempted. For non IDR/CRA/BLA random |
1642 | | * access point there is no guarantee that the decoder will not crash. |
1643 | | */ |
1644 | | bool DecLibParser::isRandomAccessSkipPicture() |
1645 | 0 | { |
1646 | 0 | if( m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP ) |
1647 | 0 | { |
1648 | 0 | m_pocRandomAccess = -MAX_INT; // no need to skip the reordered pictures in IDR, they are decodable. |
1649 | 0 | } |
1650 | 0 | else if( m_pocRandomAccess == MAX_INT ) // start of random access point, m_pocRandomAccess has not been set yet. |
1651 | 0 | { |
1652 | 0 | #if GDR_ADJ |
1653 | 0 | if( m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR ) |
1654 | | #else |
1655 | | if( m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA ) |
1656 | | #endif |
1657 | 0 | { |
1658 | | // set the POC random access since we need to skip the reordered pictures in the case of CRA/CRANT/BLA/BLANT. |
1659 | 0 | m_pocRandomAccess = m_apcSlicePilot->getPOC(); |
1660 | 0 | } |
1661 | 0 | else |
1662 | 0 | { |
1663 | 0 | if( !m_warningMessageSkipPicture ) |
1664 | 0 | { |
1665 | 0 | msg( WARNING, "Warning: this is not a valid random access point and the data is discarded until the first CRA picture\n" ); |
1666 | 0 | m_warningMessageSkipPicture = true; |
1667 | 0 | } |
1668 | 0 | return true; |
1669 | 0 | } |
1670 | 0 | } |
1671 | | // skip the reordered pictures, if necessary |
1672 | 0 | else if( m_apcSlicePilot->getPOC() < m_pocRandomAccess && ( m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_RASL ) ) |
1673 | 0 | { |
1674 | 0 | return true; |
1675 | 0 | } |
1676 | | // if we reach here, then the picture is not skipped. |
1677 | 0 | return false; |
1678 | 0 | } |
1679 | | |
1680 | | void DecLibParser::xCheckMixedNalUnit( Slice* pcSlice, const InputNALUnit& nalu ) |
1681 | 0 | { |
1682 | 0 | if( pcSlice->getPPS()->getMixedNaluTypesInPicFlag() ) |
1683 | 0 | { |
1684 | 0 | CHECK(pcSlice->getPPS()->getNumSlicesInPic() < 2, "mixed nal unit type picture, but with less than 2 slices"); |
1685 | |
|
1686 | 0 | CHECK( pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR, "picture with mixed NAL unit type cannot have GDR slice"); |
1687 | | |
1688 | | //Check that if current slice is IRAP type, the other type of NAL can only be TRAIL_NUT |
1689 | 0 | if( pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL |
1690 | 0 | || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP |
1691 | 0 | || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA ) |
1692 | 0 | { |
1693 | 0 | for( int i = 0; i < m_uiSliceSegmentIdx; i++ ) |
1694 | 0 | { |
1695 | 0 | Slice* preSlice = m_pcParsePic->slices[i]; |
1696 | 0 | CHECK( pcSlice->getNalUnitType() != preSlice->getNalUnitType() |
1697 | 0 | && preSlice->getNalUnitType() != NAL_UNIT_CODED_SLICE_TRAIL, |
1698 | 0 | "In a mixed NAL unt type picture, an IRAP slice can be mixed with Trail slice(s) only" ); |
1699 | 0 | } |
1700 | 0 | } |
1701 | | |
1702 | | // if this is the last slice of the picture, check whether that there are at least two different NAL unit types in the picture |
1703 | 0 | if( pcSlice->getPPS()->getNumSlicesInPic() == (m_uiSliceSegmentIdx + 1) ) |
1704 | 0 | { |
1705 | 0 | bool hasDiffTypes = false; |
1706 | 0 | for( int i = 1; !hasDiffTypes && i <= m_uiSliceSegmentIdx; i++ ) |
1707 | 0 | { |
1708 | 0 | Slice* slice1 = m_pcParsePic->slices[i-1]; |
1709 | 0 | Slice* slice2 = m_pcParsePic->slices[i]; |
1710 | 0 | if( slice1->getNalUnitType() != slice2->getNalUnitType()) |
1711 | 0 | { |
1712 | 0 | hasDiffTypes = true; |
1713 | 0 | } |
1714 | 0 | } |
1715 | 0 | CHECK( !hasDiffTypes, "VCL NAL units of the picture shall have two or more different nal_unit_type values"); |
1716 | 0 | } |
1717 | 0 | } |
1718 | 0 | else // all slices shall have the same nal unit type |
1719 | 0 | { |
1720 | 0 | bool sameNalUnitType = true; |
1721 | 0 | for( int i = 0; i < m_uiSliceSegmentIdx; i++ ) |
1722 | 0 | { |
1723 | 0 | Slice* PreSlice = m_pcParsePic->slices[i]; |
1724 | 0 | if( PreSlice->getNalUnitType() != pcSlice->getNalUnitType() ) |
1725 | 0 | { |
1726 | 0 | sameNalUnitType = false; |
1727 | 0 | } |
1728 | 0 | } |
1729 | 0 | CHECK( !sameNalUnitType, "mixed_nalu_types_in_pic_flag is zero, but have different nal unit types" ); |
1730 | 0 | } |
1731 | 0 | } |
1732 | | |
1733 | | } // namespace vvdec |