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