/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 | 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 | CHECK( vps && !vps->getIndependentLayerFlag( nalu.m_nuhLayerId ), "Decoding of dependent layers not implemented. Dependent layer POC derivation was here." ); |
459 | | |
460 | | // update independent slice index |
461 | 0 | m_apcSlicePilot->setIndependentSliceIdx( m_uiSliceSegmentIdx ); |
462 | |
|
463 | 0 | DTRACE_UPDATE( g_trace_ctx, std::make_pair( "poc", m_apcSlicePilot->getPOC() ) ); |
464 | | |
465 | |
|
466 | 0 | if( m_bFirstSliceInPicture ) |
467 | 0 | { |
468 | 0 | const auto pictureType = m_apcSlicePilot->getNalUnitType(); |
469 | |
|
470 | 0 | if( !pps->getMixedNaluTypesInPicFlag() |
471 | 0 | && ( pictureType == NAL_UNIT_CODED_SLICE_IDR_W_RADL |
472 | 0 | || pictureType == NAL_UNIT_CODED_SLICE_IDR_N_LP |
473 | 0 | || pictureType == NAL_UNIT_CODED_SLICE_CRA |
474 | 0 | || pictureType == NAL_UNIT_CODED_SLICE_GDR ) ) |
475 | 0 | { |
476 | 0 | m_pocCRA [nalu.m_nuhLayerId] = m_apcSlicePilot->getPOC(); |
477 | 0 | m_associatedIRAPType[nalu.m_nuhLayerId] = pictureType; |
478 | 0 | } |
479 | 0 | } |
480 | |
|
481 | 0 | xUpdatePreviousTid0POC( m_apcSlicePilot ); |
482 | |
|
483 | 0 | m_apcSlicePilot->setAssociatedIRAPPOC ( m_pocCRA [nalu.m_nuhLayerId] ); |
484 | 0 | m_apcSlicePilot->setAssociatedIRAPType( m_associatedIRAPType[nalu.m_nuhLayerId] ); |
485 | |
|
486 | 0 | if( m_apcSlicePilot->getRapPicFlag() || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR ) |
487 | 0 | { |
488 | | // Derive NoOutputBeforeRecoveryFlag |
489 | 0 | if( !pps->getMixedNaluTypesInPicFlag() ) |
490 | 0 | { |
491 | 0 | if( m_bFirstSliceInSequence[nalu.m_nuhLayerId] ) |
492 | 0 | { |
493 | 0 | m_picHeader->setNoOutputBeforeRecoveryFlag( true ); |
494 | 0 | } |
495 | 0 | else if( m_apcSlicePilot->getIdrPicFlag() ) |
496 | 0 | { |
497 | 0 | m_picHeader->setNoOutputBeforeRecoveryFlag( true ); |
498 | 0 | } |
499 | 0 | else if( m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA ) |
500 | 0 | { |
501 | 0 | m_picHeader->setNoOutputBeforeRecoveryFlag( m_picHeader->getHandleCraAsCvsStartFlag() ); |
502 | 0 | } |
503 | 0 | else if( m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR ) |
504 | 0 | { |
505 | 0 | m_picHeader->setNoOutputBeforeRecoveryFlag( m_picHeader->getHandleGdrAsCvsStartFlag() ); |
506 | 0 | } |
507 | 0 | } |
508 | 0 | else |
509 | 0 | { |
510 | 0 | m_picHeader->setNoOutputBeforeRecoveryFlag( false ); |
511 | 0 | } |
512 | |
|
513 | 0 | if( m_apcSlicePilot->isCRAorGDR() ) |
514 | 0 | { |
515 | 0 | m_lastNoOutputBeforeRecoveryFlag[nalu.m_nuhLayerId] = m_picHeader->getNoOutputBeforeRecoveryFlag(); |
516 | 0 | } |
517 | | |
518 | | // the inference for NoOutputOfPriorPicsFlag |
519 | 0 | if( m_apcSlicePilot->getNoOutputOfPriorPicsFlag() ) |
520 | 0 | { |
521 | 0 | m_lastPOCNoOutputPriorPics = m_apcSlicePilot->getPOC(); |
522 | 0 | m_isNoOutputPriorPics = true; |
523 | 0 | } |
524 | 0 | else |
525 | 0 | { |
526 | 0 | m_isNoOutputPriorPics = false; |
527 | 0 | } |
528 | 0 | } |
529 | |
|
530 | 0 | #if !DISABLE_CHECK_NO_OUTPUT_PRIOR_PICS_FLAG |
531 | 0 | if( m_bFirstSliceInPicture && m_apcSlicePilot->getPOC() != m_prevPOC |
532 | 0 | && ( m_apcSlicePilot->getRapPicFlag() || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR ) |
533 | 0 | && m_picHeader->getNoOutputBeforeRecoveryFlag() |
534 | 0 | && getNoOutputPriorPicsFlag() ) |
535 | 0 | { |
536 | 0 | checkNoOutputPriorPics(); |
537 | 0 | setNoOutputPriorPicsFlag( false ); |
538 | 0 | } |
539 | 0 | #endif |
540 | | |
541 | | |
542 | | //For inference of PicOutputFlag |
543 | 0 | if( !pps->getMixedNaluTypesInPicFlag() && ( m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_RASL ) ) |
544 | 0 | { |
545 | 0 | if( m_lastNoOutputBeforeRecoveryFlag[nalu.m_nuhLayerId] ) |
546 | 0 | { |
547 | 0 | m_picHeader->setPicOutputFlag( false ); |
548 | 0 | } |
549 | 0 | } |
550 | |
|
551 | 0 | if( sps->getVPSId() > 0 ) |
552 | 0 | { |
553 | 0 | const VPS *vps = m_parameterSetManager.getVPS( sps->getVPSId() ); |
554 | 0 | CHECK( vps == 0, "No VPS present" ); |
555 | 0 | if( ( vps->getOlsModeIdc() == 0 |
556 | 0 | && vps->getGeneralLayerIdx( nalu.m_nuhLayerId ) < ( vps->getMaxLayers() - 1 ) |
557 | 0 | && vps->getOlsOutputLayerFlag( vps->m_iTargetLayer, vps->getMaxLayers() - 1 ) == 1 ) |
558 | 0 | || ( vps->getOlsModeIdc() == 2 |
559 | 0 | && vps->getOlsOutputLayerFlag( vps->m_iTargetLayer, vps->getGeneralLayerIdx( nalu.m_nuhLayerId ) ) == 0 ) ) |
560 | 0 | { |
561 | 0 | m_picHeader->setPicOutputFlag( false ); |
562 | 0 | } |
563 | 0 | } |
564 | | |
565 | | //Reset POC MSB when CRA or GDR has NoOutputBeforeRecoveryFlag equal to 1 |
566 | 0 | if( !pps->getMixedNaluTypesInPicFlag() && m_apcSlicePilot->isCRAorGDR() && m_lastNoOutputBeforeRecoveryFlag[nalu.m_nuhLayerId] ) |
567 | 0 | { |
568 | 0 | int iMaxPOClsb = 1 << sps->getBitsForPOC(); |
569 | 0 | m_apcSlicePilot->setPOC( m_apcSlicePilot->getPOC() & ( iMaxPOClsb - 1 ) ); |
570 | 0 | xUpdatePreviousTid0POC ( m_apcSlicePilot ); |
571 | 0 | m_lastPOCNoOutputPriorPics = m_apcSlicePilot->getPOC(); |
572 | 0 | } |
573 | | |
574 | | // Skip pictures due to random access |
575 | 0 | if( isRandomAccessSkipPicture() ) |
576 | 0 | { |
577 | 0 | m_prevSliceSkipped = true; |
578 | 0 | m_skippedPOC = m_apcSlicePilot->getPOC(); |
579 | 0 | msg( VERBOSE, "POC %i: RASL not decodable\n", m_skippedPOC ); |
580 | 0 | return false; |
581 | 0 | } |
582 | | |
583 | | // clear previous slice skipped flag |
584 | 0 | m_prevSliceSkipped = false; |
585 | | |
586 | | //we should only get a different poc for a new picture (with CTU address==0) |
587 | 0 | if( m_apcSlicePilot->getPOC() != m_prevPOC |
588 | 0 | && !m_bFirstSliceInSequence[nalu.m_nuhLayerId] |
589 | 0 | && m_apcSlicePilot->getFirstCtuRsAddrInSlice() != 0 ) |
590 | 0 | { |
591 | 0 | msg( WARNING, "Warning, the first slice of a picture might have been lost!\n"); |
592 | 0 | } |
593 | |
|
594 | 0 | m_prevLayerID = nalu.m_nuhLayerId; |
595 | | |
596 | | //detect lost reference picture and insert copy of earlier frame. |
597 | 0 | if( m_apcSlicePilot->getSliceType() != I_SLICE ) |
598 | 0 | { |
599 | 0 | for( const auto rplIdx: { REF_PIC_LIST_0, REF_PIC_LIST_1 } ) |
600 | 0 | { |
601 | 0 | const auto* rpl = m_apcSlicePilot->getRPL( rplIdx ); |
602 | |
|
603 | 0 | int missingPoc = MAX_INT; |
604 | 0 | int missingRefPicIndex = 0; |
605 | 0 | while( !m_apcSlicePilot->checkThatAllRefPicsAreAvailable( m_dpbReferencePics, |
606 | 0 | rpl, |
607 | 0 | m_apcSlicePilot->getNumRefIdx( rplIdx ), |
608 | 0 | &missingPoc, |
609 | 0 | &missingRefPicIndex ) ) |
610 | 0 | { |
611 | 0 | if( !pps->getMixedNaluTypesInPicFlag() |
612 | 0 | && ( ( m_apcSlicePilot->isIDR() && ( sps->getIDRRefParamListPresent() || pps->getRplInfoInPhFlag() ) ) |
613 | 0 | || ( m_apcSlicePilot->isCRAorGDR() && m_picHeader->getNoOutputBeforeRecoveryFlag() ) ) ) |
614 | 0 | { |
615 | 0 | if( !rpl->isInterLayerRefPic( missingRefPicIndex ) ) |
616 | 0 | { |
617 | 0 | prepareUnavailablePicture( false, |
618 | 0 | pps, |
619 | 0 | missingPoc, |
620 | 0 | m_apcSlicePilot->getNalUnitLayerId(), |
621 | 0 | rpl->isRefPicLongterm( missingRefPicIndex ), |
622 | 0 | m_apcSlicePilot->getTLayer() ); |
623 | 0 | } |
624 | 0 | } |
625 | 0 | else |
626 | 0 | { |
627 | 0 | prepareUnavailablePicture( true, |
628 | 0 | pps, |
629 | 0 | missingPoc, |
630 | 0 | m_apcSlicePilot->getNalUnitLayerId(), |
631 | 0 | rpl->isRefPicLongterm( missingRefPicIndex ), |
632 | 0 | m_apcSlicePilot->getTLayer() ); |
633 | 0 | } |
634 | 0 | } |
635 | 0 | } |
636 | 0 | } |
637 | 0 | xActivateParameterSets( nalu.m_nuhLayerId ); |
638 | | |
639 | | // WARNING: don't use m_apcSlicePilot after this point, because it has been reallocated |
640 | |
|
641 | 0 | Slice* slice = m_pcParsePic->slices[m_uiSliceSegmentIdx]; |
642 | |
|
643 | 0 | m_pcParsePic->neededForOutput = m_picHeader->getPicOutputFlag(); |
644 | 0 | if( m_pcParsePic->lastSliceOfPicPresent() ) |
645 | 0 | { |
646 | | #if 0 |
647 | | // TODO for VPS support: |
648 | | if( sps->getVPSId() > 0 && NOT IN OUTPUT LAYER SET ) |
649 | | { |
650 | | m_pcParsePic->neededForOutput = false; |
651 | | } |
652 | | else |
653 | | #endif |
654 | 0 | { |
655 | 0 | if( !m_gdrRecovered[nalu.m_nuhLayerId] && slice->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR && m_gdrRecoveryPointPocVal[nalu.m_nuhLayerId] == INIT_POC ) |
656 | 0 | { |
657 | 0 | m_gdrRecoveryPointPocVal[nalu.m_nuhLayerId] = m_pcParsePic->poc + m_picHeader->getRecoveryPocCnt(); |
658 | 0 | } |
659 | |
|
660 | 0 | if( !m_gdrRecovered[nalu.m_nuhLayerId] |
661 | 0 | && ( m_gdrRecoveryPointPocVal[nalu.m_nuhLayerId] == m_pcParsePic->poc || m_picHeader->getRecoveryPocCnt() == 0 ) ) |
662 | 0 | { |
663 | 0 | m_gdrRecovered [nalu.m_nuhLayerId] = true; |
664 | 0 | m_gdrRecoveryPointPocVal[nalu.m_nuhLayerId] = INIT_POC; |
665 | 0 | } |
666 | |
|
667 | 0 | const bool is_recovering_picture = slice->getAssociatedIRAPType() == NAL_UNIT_CODED_SLICE_GDR && m_pcParsePic->poc < m_gdrRecoveryPointPocVal[nalu.m_nuhLayerId]; |
668 | 0 | if( slice->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR && m_gdrRecovered[nalu.m_nuhLayerId] ) |
669 | 0 | { |
670 | 0 | m_pcParsePic->neededForOutput = true; |
671 | 0 | } |
672 | 0 | else if( slice->getNalUnitType() == NAL_UNIT_CODED_SLICE_RASL && m_lastNoOutputBeforeRecoveryFlag[nalu.m_nuhLayerId] ) |
673 | 0 | { |
674 | 0 | m_pcParsePic->neededForOutput = false; |
675 | 0 | } |
676 | 0 | else if( ( slice->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR && m_picHeader->getNoOutputBeforeRecoveryFlag() ) |
677 | 0 | || ( is_recovering_picture && ( !m_gdrRecovered[nalu.m_nuhLayerId] || m_lastNoOutputBeforeRecoveryFlag[nalu.m_nuhLayerId] ) ) ) |
678 | 0 | { |
679 | 0 | m_pcParsePic->neededForOutput = false; |
680 | 0 | } |
681 | 0 | } |
682 | 0 | } |
683 | |
|
684 | 0 | return true; |
685 | 0 | } |
686 | | |
687 | | bool DecLibParser::xDecodeSliceMain( InputNALUnit& nalu ) |
688 | 0 | { |
689 | 0 | ITT_TASKSTART( itt_domain_oth, itt_handle_start ); |
690 | | // actual decoding starts here |
691 | 0 | Slice* pcSlice = m_pcParsePic->slices[m_uiSliceSegmentIdx]; |
692 | 0 | m_pcParsePic->poc = pcSlice->getPOC(); |
693 | 0 | m_pcParsePic->tempLayer = pcSlice->getTLayer(); |
694 | 0 | m_pcParsePic->dpbReferenceMark = pcSlice->getPicHeader()->getNonReferencePictureFlag() ? Picture::unreferenced : Picture::ShortTerm; |
695 | 0 | m_pcParsePic->stillReferenced = !!m_pcParsePic->dpbReferenceMark; |
696 | 0 | m_pcParsePic->isReferencePic = !!m_pcParsePic->dpbReferenceMark; |
697 | 0 | m_pcParsePic->eNalUnitType = nalu.m_nalUnitType; |
698 | 0 | m_pcParsePic->cts = nalu.m_cts; |
699 | 0 | m_pcParsePic->dts = nalu.m_dts; |
700 | 0 | m_pcParsePic->rap = nalu.m_rap; |
701 | 0 | m_pcParsePic->userData = nalu.m_userData; |
702 | 0 | m_pcParsePic->bits += nalu.m_bits + m_nonVCLbits; |
703 | 0 | m_pcParsePic->layerId = nalu.m_nuhLayerId; |
704 | 0 | m_pcParsePic->subLayerNonReferencePictureDueToSTSA = false; |
705 | |
|
706 | 0 | m_nonVCLbits = 0; |
707 | |
|
708 | 0 | CHECK( m_pcParsePic->tempLayer != nalu.m_temporalId, |
709 | 0 | "Currently parsed pic should have the same temporal layer as the NAL unit" ); |
710 | |
|
711 | 0 | if( pcSlice->getSPS()->getProfileTierLevel()->getConstraintInfo()->getNoApsConstraintFlag() ) |
712 | 0 | { |
713 | 0 | bool flag = pcSlice->getSPS()->getUseCCALF() || pcSlice->getPicHeader()->getNumAlfAps() || pcSlice->getPicHeader()->getAlfEnabledFlag( COMPONENT_Cb ) || pcSlice->getPicHeader()->getAlfEnabledFlag( COMPONENT_Cr ); |
714 | 0 | CHECK( flag, "When no_aps_constraint_flag is equal to 1, the values of " |
715 | 0 | "ph_num_alf_aps_ids_luma, sh_num_alf_aps_ids_luma, ph_alf_cb_flag, " |
716 | 0 | "ph_alf_cr_flag, sh_alf_cb_flag, sh_alf_cr_flag, " |
717 | 0 | "and sps_ccalf_enabled_flag shall all be equal to 0" ) |
718 | 0 | } |
719 | | |
720 | 0 | if( pcSlice->getNalUnitLayerId() != pcSlice->getSPS()->getLayerId() ) |
721 | 0 | { |
722 | 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" ); |
723 | 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" ); |
724 | 0 | for (int i = 0; i < pcSlice->getVPS()->getNumOutputLayerSets(); i++ ) |
725 | 0 | { |
726 | 0 | bool isCurrLayerInOls = false; |
727 | 0 | bool isRefLayerInOls = false; |
728 | 0 | int j = pcSlice->getVPS()->getNumLayersInOls(i) - 1; |
729 | 0 | for (; j >= 0; j--) |
730 | 0 | { |
731 | 0 | if( pcSlice->getVPS()->getLayerIdInOls(i, j) == pcSlice->getNalUnitLayerId() ) |
732 | 0 | { |
733 | 0 | isCurrLayerInOls = true; |
734 | 0 | } |
735 | 0 | if( pcSlice->getVPS()->getLayerIdInOls(i, j) == pcSlice->getSPS()->getLayerId() ) |
736 | 0 | { |
737 | 0 | isRefLayerInOls = true; |
738 | 0 | } |
739 | 0 | } |
740 | 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" ); |
741 | 0 | } |
742 | 0 | } |
743 | 0 | if( pcSlice->getNalUnitLayerId() != pcSlice->getPPS()->getLayerId() ) |
744 | 0 | { |
745 | 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" ); |
746 | 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" ); |
747 | 0 | for (int i = 0; i < pcSlice->getVPS()->getNumOutputLayerSets(); i++ ) |
748 | 0 | { |
749 | 0 | bool isCurrLayerInOls = false; |
750 | 0 | bool isRefLayerInOls = false; |
751 | 0 | int j = pcSlice->getVPS()->getNumLayersInOls(i) - 1; |
752 | 0 | for (; j >= 0; j--) |
753 | 0 | { |
754 | 0 | if( pcSlice->getVPS()->getLayerIdInOls(i, j) == pcSlice->getNalUnitLayerId() ) |
755 | 0 | { |
756 | 0 | isCurrLayerInOls = true; |
757 | 0 | } |
758 | 0 | if( pcSlice->getVPS()->getLayerIdInOls(i, j) == pcSlice->getPPS()->getLayerId() ) |
759 | 0 | { |
760 | 0 | isRefLayerInOls = true; |
761 | 0 | } |
762 | 0 | } |
763 | 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" ); |
764 | 0 | } |
765 | 0 | } |
766 | | |
767 | 0 | if( m_bFirstSliceInPicture ) |
768 | 0 | { |
769 | 0 | m_pcParsePic->setDecodingOrderNumber( m_decodingOrderCounter ); |
770 | 0 | m_decodingOrderCounter++; |
771 | |
|
772 | 0 | pcSlice->getPic()->subPictures.clear(); |
773 | 0 | pcSlice->getPic()->sliceSubpicIdx.clear(); |
774 | |
|
775 | 0 | for( int subPicIdx = 0; subPicIdx < pcSlice->getSPS()->getNumSubPics(); subPicIdx++ ) |
776 | 0 | { |
777 | 0 | pcSlice->getPic()->subPictures.push_back( pcSlice->getPPS()->getSubPic( subPicIdx ) ); |
778 | 0 | } |
779 | 0 | } |
780 | |
|
781 | 0 | pcSlice->getPic()->sliceSubpicIdx.push_back(pcSlice->getPPS()->getSubPicIdxFromSubPicId(pcSlice->getSliceSubPicId())); |
782 | | |
783 | | // When decoding the slice header, the stored start and end addresses were actually RS addresses, not TS addresses. |
784 | | // Now, having set up the maps, convert them to the correct form. |
785 | | |
786 | | // Sanity check: verify that there are no duplicate POCs in the DPB before constructing the ref picture lists |
787 | 0 | m_tmpSeenPocs.clear(); |
788 | 0 | m_tmpSeenPocs.reserve( m_dpbReferencePics.size() ); |
789 | 0 | for( auto& p: m_dpbReferencePics ) |
790 | 0 | { |
791 | 0 | CHECK( m_tmpSeenPocs.count( p->poc ) != 0, "duplicate POC in DPB" ); |
792 | 0 | if( p->dpbReferenceMark ) // we only care about reference pictures in the DPB |
793 | 0 | { |
794 | 0 | m_tmpSeenPocs.insert( p->poc ); |
795 | 0 | } |
796 | 0 | } |
797 | | |
798 | | #if !DISABLE_CONFROMANCE_CHECK |
799 | | pcSlice->checkCRA( m_pocCRA[nalu.m_nuhLayerId], m_associatedIRAPType[nalu.m_nuhLayerId], m_picListManager.getPicListRange( m_pcParsePic ) ); |
800 | | #endif |
801 | 0 | pcSlice->constructRefPicLists( m_dpbReferencePics ); |
802 | | #if !DISABLE_CONFROMANCE_CHECK |
803 | | pcSlice->checkRPL(pcSlice->getRPL0(), pcSlice->getRPL1(), m_associatedIRAPDecodingOrderNumber, m_picListManager.getPicListRange( m_pcParsePic ) ); |
804 | | pcSlice->checkSTSA( m_picListManager.getPicListRange( pcParsePic ) ); |
805 | | #endif |
806 | |
|
807 | | #if TBC |
808 | | pcSlice->setPrevGDRSubpicPOC(m_prevGDRSubpicPOC[nalu.m_nuhLayerId][currSubPicIdx]); |
809 | | pcSlice->setPrevIRAPSubpicPOC(m_prevIRAPSubpicPOC[nalu.m_nuhLayerId][currSubPicIdx]); |
810 | | pcSlice->setPrevIRAPSubpicType(m_prevIRAPSubpicType[nalu.m_nuhLayerId][currSubPicIdx]); |
811 | | pcSlice->checkSubpicTypeConstraints(m_cListPic, pcSlice->getRPL0(), pcSlice->getRPL1(), m_prevIRAPSubpicDecOrderNo[nalu.m_nuhLayerId][currSubPicIdx]); |
812 | | #endif |
813 | |
|
814 | 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 ) |
815 | 0 | { |
816 | 0 | CU::checkConformanceILRP(pcSlice); |
817 | 0 | } |
818 | |
|
819 | 0 | pcSlice->scaleRefPicList( m_pcParsePic->cs->picHeader.get() ); |
820 | | |
821 | |
|
822 | 0 | if (!pcSlice->isIntra()) |
823 | 0 | { |
824 | 0 | const int iCurrPOC = pcSlice->getPOC(); |
825 | |
|
826 | 0 | bool bLowDelay = true; |
827 | 0 | for( int iRefIdx = 0; iRefIdx < pcSlice->getNumRefIdx( REF_PIC_LIST_0 ) && bLowDelay; iRefIdx++ ) |
828 | 0 | { |
829 | 0 | if( pcSlice->getRefPOC( REF_PIC_LIST_0, iRefIdx ) > iCurrPOC ) |
830 | 0 | { |
831 | 0 | bLowDelay = false; |
832 | 0 | } |
833 | 0 | } |
834 | 0 | if( pcSlice->isInterB() ) |
835 | 0 | { |
836 | 0 | for( int iRefIdx = 0; iRefIdx < pcSlice->getNumRefIdx( REF_PIC_LIST_1 ) && bLowDelay; iRefIdx++ ) |
837 | 0 | { |
838 | 0 | if( pcSlice->getRefPOC( REF_PIC_LIST_1, iRefIdx ) > iCurrPOC ) |
839 | 0 | { |
840 | 0 | bLowDelay = false; |
841 | 0 | } |
842 | 0 | } |
843 | 0 | } |
844 | |
|
845 | 0 | pcSlice->setCheckLDC( bLowDelay ); |
846 | 0 | } |
847 | |
|
848 | 0 | if( pcSlice->getSPS()->getUseSMVD() && !pcSlice->getCheckLDC() && !pcSlice->getPicHeader()->getMvdL1ZeroFlag() ) |
849 | 0 | { |
850 | 0 | int currPOC = pcSlice->getPOC(); |
851 | |
|
852 | 0 | int forwardPOC = currPOC; |
853 | 0 | int backwardPOC = currPOC; |
854 | 0 | int ref = 0; |
855 | 0 | int refIdx0 = -1; |
856 | 0 | int refIdx1 = -1; |
857 | | |
858 | | // search nearest forward POC in List 0 |
859 | 0 | for ( ref = 0; ref < pcSlice->getNumRefIdx( REF_PIC_LIST_0 ); ref++ ) |
860 | 0 | { |
861 | 0 | int poc = pcSlice->getRefPOC( REF_PIC_LIST_0, ref ); |
862 | 0 | const bool isRefLongTerm = pcSlice->getIsUsedAsLongTerm( REF_PIC_LIST_0, ref ); |
863 | 0 | if( poc < currPOC && ( poc > forwardPOC || refIdx0 == -1 ) && !isRefLongTerm ) |
864 | 0 | { |
865 | 0 | forwardPOC = poc; |
866 | 0 | refIdx0 = ref; |
867 | 0 | } |
868 | 0 | } |
869 | | |
870 | | // search nearest backward POC in List 1 |
871 | 0 | for ( ref = 0; ref < pcSlice->getNumRefIdx( REF_PIC_LIST_1 ); ref++ ) |
872 | 0 | { |
873 | 0 | int poc = pcSlice->getRefPOC( REF_PIC_LIST_1, ref ); |
874 | 0 | const bool isRefLongTerm = pcSlice->getIsUsedAsLongTerm( REF_PIC_LIST_1, ref ); |
875 | 0 | if( poc > currPOC && ( poc < backwardPOC || refIdx1 == -1 ) && !isRefLongTerm ) |
876 | 0 | { |
877 | 0 | backwardPOC = poc; |
878 | 0 | refIdx1 = ref; |
879 | 0 | } |
880 | 0 | } |
881 | |
|
882 | 0 | if ( !(forwardPOC < currPOC && backwardPOC > currPOC) ) |
883 | 0 | { |
884 | 0 | forwardPOC = currPOC; |
885 | 0 | backwardPOC = currPOC; |
886 | 0 | refIdx0 = -1; |
887 | 0 | refIdx1 = -1; |
888 | | |
889 | | // search nearest backward POC in List 0 |
890 | 0 | for ( ref = 0; ref < pcSlice->getNumRefIdx( REF_PIC_LIST_0 ); ref++ ) |
891 | 0 | { |
892 | 0 | int poc = pcSlice->getRefPOC( REF_PIC_LIST_0, ref ); |
893 | 0 | const bool isRefLongTerm = pcSlice->getIsUsedAsLongTerm( REF_PIC_LIST_0, ref ); |
894 | 0 | if( poc > currPOC && ( poc < backwardPOC || refIdx0 == -1 ) && !isRefLongTerm ) |
895 | 0 | { |
896 | 0 | backwardPOC = poc; |
897 | 0 | refIdx0 = ref; |
898 | 0 | } |
899 | 0 | } |
900 | | |
901 | | // search nearest forward POC in List 1 |
902 | 0 | for ( ref = 0; ref < pcSlice->getNumRefIdx( REF_PIC_LIST_1 ); ref++ ) |
903 | 0 | { |
904 | 0 | int poc = pcSlice->getRefPOC( REF_PIC_LIST_1, ref ); |
905 | 0 | const bool isRefLongTerm = pcSlice->getIsUsedAsLongTerm( REF_PIC_LIST_1, ref ); |
906 | 0 | if( poc < currPOC && ( poc > forwardPOC || refIdx1 == -1 ) && !isRefLongTerm ) |
907 | 0 | { |
908 | 0 | forwardPOC = poc; |
909 | 0 | refIdx1 = ref; |
910 | 0 | } |
911 | 0 | } |
912 | 0 | } |
913 | |
|
914 | 0 | if ( forwardPOC < currPOC && backwardPOC > currPOC ) |
915 | 0 | { |
916 | 0 | pcSlice->setBiDirPred( true, refIdx0, refIdx1 ); |
917 | 0 | } |
918 | 0 | else |
919 | 0 | { |
920 | 0 | pcSlice->setBiDirPred( false, -1, -1 ); |
921 | 0 | } |
922 | 0 | } |
923 | 0 | else |
924 | 0 | { |
925 | 0 | pcSlice->setBiDirPred( false, -1, -1 ); |
926 | 0 | } |
927 | | |
928 | | //--------------- |
929 | 0 | xCheckMixedNalUnit( pcSlice, nalu ); |
930 | |
|
931 | 0 | if( m_bFirstSliceInPicture ) |
932 | 0 | { |
933 | 0 | #if RECO_WHILE_PARSE |
934 | 0 | for( int ctu = 0; ctu < pcSlice->getPPS()->pcv->sizeInCtus; ctu++ ) |
935 | 0 | { |
936 | 0 | m_pcParsePic->ctuParsedBarrier[ctu].lock(); |
937 | 0 | } |
938 | |
|
939 | 0 | #endif |
940 | 0 | m_parseFrameList.push_back( m_pcParsePic ); |
941 | 0 | } |
942 | |
|
943 | 0 | ITT_TASKEND( itt_domain_oth, itt_handle_start ); |
944 | |
|
945 | 0 | static const auto parseTask = []( int threadId, void* param ) |
946 | 0 | { |
947 | 0 | Slice* slice = static_cast<Slice*>( param ); |
948 | 0 | auto& decLib = slice->parseTaskParams.decLibParser; |
949 | 0 | auto& bitstream = slice->parseTaskParams.bitstream; |
950 | 0 | auto* pic = slice->getPic(); |
951 | |
|
952 | 0 | try |
953 | 0 | { |
954 | 0 | pic->startProcessingTimer(); |
955 | | |
956 | | // Decode a picture |
957 | 0 | ITT_TASKSTART( itt_domain_prs, itt_handle_parse ); |
958 | 0 | decLib->m_cSliceDecoder.parseSlice( slice, &bitstream, threadId ); |
959 | 0 | ITT_TASKEND( itt_domain_prs, itt_handle_parse ); |
960 | |
|
961 | 0 | pic->stopProcessingTimer(); |
962 | |
|
963 | 0 | bitstream.clearFifo(); |
964 | 0 | bitstream.clearEmulationPreventionByteLocation(); |
965 | 0 | } |
966 | 0 | catch( ... ) |
967 | 0 | { |
968 | 0 | pic->error = true; |
969 | 0 | pic->parseDone.setException( std::current_exception() ); |
970 | 0 | #if RECO_WHILE_PARSE |
971 | 0 | for( auto& b: pic->ctuParsedBarrier ) |
972 | 0 | { |
973 | 0 | b.setException( std::current_exception() ); |
974 | 0 | } |
975 | 0 | #endif |
976 | 0 | std::rethrow_exception( std::current_exception() ); |
977 | 0 | } |
978 | 0 | return true; |
979 | 0 | }; |
980 | |
|
981 | 0 | pcSlice->parseTaskParams.init( this, std::move( nalu.getBitstream() ) ); |
982 | 0 | pcSlice->parseDone.lock(); |
983 | |
|
984 | 0 | auto expected = Picture::init; |
985 | 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 |
986 | |
|
987 | 0 | if( m_threadPool && m_threadPool->numThreads() > 0 ) |
988 | 0 | { |
989 | 0 | if( m_uiSliceSegmentIdx > 0 ) |
990 | 0 | { |
991 | 0 | m_threadPool->addBarrierTask( TP_TASK_NAME_ARG( "POC:" + std::to_string( m_pcParsePic->poc ) + " parseTask" ) |
992 | 0 | parseTask, pcSlice, &m_pcParsePic->m_divTasksCounter, &pcSlice->parseDone, |
993 | 0 | CBarrierVec{ &m_pcParsePic->slices[m_uiSliceSegmentIdx - 1]->parseDone } ); |
994 | 0 | } |
995 | 0 | else |
996 | 0 | { |
997 | 0 | m_threadPool->addBarrierTask( TP_TASK_NAME_ARG( "POC:" + std::to_string( m_pcParsePic->poc ) + " parseTask" ) |
998 | 0 | parseTask, pcSlice, &m_pcParsePic->m_divTasksCounter, &pcSlice->parseDone ); |
999 | 0 | } |
1000 | 0 | } |
1001 | 0 | else |
1002 | 0 | { |
1003 | 0 | parseTask( 0, pcSlice ); |
1004 | 0 | pcSlice->parseDone.unlock(); |
1005 | 0 | if( m_pcParsePic->slices.size() != 1 && !m_pcParsePic->parseDone.isBlocked() && m_numDecThreads == 0 ) |
1006 | 0 | { |
1007 | 0 | while( !m_threadPool->processTasksOnMainThread() ); |
1008 | 0 | } |
1009 | 0 | } |
1010 | |
|
1011 | 0 | if( pcSlice->getFirstCtuRsAddrInSlice() == 0 && !m_bFirstSliceInPicture ) |
1012 | 0 | { |
1013 | 0 | if( m_prevPOC >= m_pocRandomAccess ) |
1014 | 0 | { |
1015 | 0 | DTRACE_UPDATE( g_trace_ctx, std::make_pair( "final", 0 ) ); |
1016 | 0 | } |
1017 | 0 | } |
1018 | 0 | else |
1019 | 0 | { |
1020 | 0 | DTRACE_UPDATE( g_trace_ctx, std::make_pair( "final", 1 ) ); |
1021 | 0 | } |
1022 | 0 | m_prevPOC = pcSlice->getPOC(); |
1023 | |
|
1024 | 0 | m_bFirstSliceInSequence[nalu.m_nuhLayerId] = false; |
1025 | 0 | m_bFirstSliceInBitstream = false; |
1026 | | |
1027 | |
|
1028 | 0 | const unsigned lastCtuInSlice = pcSlice->getCtuAddrInSlice( pcSlice->getNumCtuInSlice() - 1 ); |
1029 | 0 | if( lastCtuInSlice == pcSlice->getPPS()->pcv->sizeInCtus - 1 ) |
1030 | 0 | { |
1031 | 0 | return true; |
1032 | 0 | } |
1033 | | |
1034 | 0 | return false; |
1035 | 0 | } |
1036 | | |
1037 | | void DecLibParser::xActivateParameterSets( const int layerId ) |
1038 | 0 | { |
1039 | 0 | ParameterSetManager::ActivePSs paramSets; |
1040 | |
|
1041 | 0 | if( m_bFirstSliceInPicture ) |
1042 | 0 | { |
1043 | 0 | paramSets = m_parameterSetManager.xActivateParameterSets( m_bFirstSliceInPicture, m_apcSlicePilot, m_picHeader.get() ); |
1044 | 0 | const SPS* sps = paramSets.sps; |
1045 | 0 | const PPS* pps = paramSets.pps; |
1046 | 0 | const APS** alfApss = paramSets.alfAPSs->data(); |
1047 | 0 | const APS* lmcsAPS = paramSets.lmcsAps; |
1048 | 0 | const APS* scalingListAPS = paramSets.scalingListAps; |
1049 | |
|
1050 | 0 | xParsePrefixSEImessages(); |
1051 | |
|
1052 | 0 | CHECK( sps->getBitDepth() > 12, "High bit depth support must be enabled at compile-time in order to decode this bitstream\n" ); |
1053 | |
|
1054 | 0 | applyReferencePictureListBasedMarking( m_apcSlicePilot, layerId, *pps ); |
1055 | | |
1056 | | // Get a new picture buffer |
1057 | 0 | m_pcParsePic = m_picListManager.getNewPicBuffer( *sps, *pps, m_apcSlicePilot->getTLayer(), layerId, m_parameterSetManager.getVPS( sps->getVPSId() ) ); |
1058 | 0 | CHECK( std::find( m_dpbReferencePics.cbegin(), m_dpbReferencePics.cend(), m_pcParsePic ) != m_dpbReferencePics.cend(), "reused picture shouldn't be in decoded picture buffer" ); |
1059 | 0 | m_dpbReferencePics.push_back( m_pcParsePic ); |
1060 | | // assign these fields already, because they are needed by PicListManager::getPicListRange() and Slice::applyReferencePictureSet() |
1061 | 0 | m_pcParsePic->poc = m_apcSlicePilot->getPOC(); |
1062 | 0 | m_pcParsePic->eNalUnitType = m_apcSlicePilot->getNalUnitType(); |
1063 | 0 | m_pcParsePic->finalInit( &m_cuChunkCache, &m_tuChunkCache, sps, pps, m_picHeader, alfApss, lmcsAPS, scalingListAPS ); |
1064 | |
|
1065 | | #if !DISABLE_CONFROMANCE_CHECK |
1066 | | m_apcSlicePilot->checkLeadingPictureRestrictions( m_dpbReferencePics ); |
1067 | | #endif |
1068 | |
|
1069 | 0 | m_pcParsePic->dpbReferenceMark = m_apcSlicePilot->getPicHeader()->getNonReferencePictureFlag() ? Picture::unreferenced : Picture::ShortTerm; |
1070 | 0 | m_pcParsePic->stillReferenced = !!m_pcParsePic->dpbReferenceMark; |
1071 | 0 | m_pcParsePic->isReferencePic = !!m_pcParsePic->dpbReferenceMark; |
1072 | | |
1073 | | // Set Field/Frame coding mode |
1074 | 0 | bool isField = false; |
1075 | 0 | bool isTopField = false; |
1076 | 0 | if(!m_seiMessageList.empty()) |
1077 | 0 | { |
1078 | | // Check if any new Frame Field Info SEI has arrived |
1079 | 0 | seiMessages frameFieldSEIs = SEI_internal::getSeisByType( m_seiMessageList, VVDEC_FRAME_FIELD_INFO ); |
1080 | 0 | if(!frameFieldSEIs.empty()) |
1081 | 0 | { |
1082 | 0 | const vvdecSEIFrameFieldInfo* ff = (vvdecSEIFrameFieldInfo*) frameFieldSEIs.front()->payload; |
1083 | 0 | isField = ff->fieldPicFlag; |
1084 | 0 | isTopField = isField && (!ff->bottomFieldFlag); |
1085 | 0 | } |
1086 | 0 | } |
1087 | 0 | m_pcParsePic->fieldPic = isField; |
1088 | 0 | m_pcParsePic->topField = isTopField; |
1089 | | |
1090 | | // transfer any SEI messages that have been received to the picture |
1091 | 0 | m_pcParsePic->seiMessageList = m_seiMessageList; |
1092 | 0 | m_seiMessageList.clear(); |
1093 | |
|
1094 | 0 | m_apcSlicePilot->setPicHeader( m_picHeader.get() ); |
1095 | 0 | } |
1096 | 0 | else |
1097 | 0 | { |
1098 | 0 | paramSets = m_parameterSetManager.xActivateParameterSets( m_bFirstSliceInPicture, m_apcSlicePilot, m_picHeader.get() ); |
1099 | 0 | m_apcSlicePilot->setAlfApss( paramSets.alfAPSs->data() ); |
1100 | |
|
1101 | 0 | for( int i = 0; i < ALF_CTB_MAX_NUM_APS; ++i ) |
1102 | 0 | { |
1103 | 0 | m_pcParsePic->cs->alfApss[i] = paramSets.alfAPSs->data()[i] ? paramSets.alfAPSs->data()[i]->getSharedPtr() : nullptr; |
1104 | 0 | } |
1105 | 0 | } |
1106 | | |
1107 | | // make the slice-pilot a real slice, and set up the slice-pilot for the next slice |
1108 | 0 | Slice* pSlice = m_pcParsePic->allocateNewSlice( &m_apcSlicePilot ); |
1109 | 0 | CHECK_FATAL( m_pcParsePic->slices.size() != ( m_uiSliceSegmentIdx + 1 ), "Invalid number of slices" ); |
1110 | |
|
1111 | 0 | const VPS* vps = pSlice->getVPS_nothrow(); |
1112 | 0 | const SPS* sps = pSlice->getSPS(); |
1113 | 0 | const PPS* pps = pSlice->getPPS(); |
1114 | |
|
1115 | 0 | if( !m_bFirstSliceInPicture ) |
1116 | 0 | { |
1117 | 0 | const APS* lmcsAPS = pSlice->getPicHeader()->getLmcsAPS().get(); |
1118 | | |
1119 | | // check that the current active PPS has not changed... |
1120 | 0 | CHECK( sps->getChangedFlag(), "Error - a new SPS has been decoded while processing a picture" ); |
1121 | 0 | CHECK( pps->getChangedFlag(), "Error - a new PPS has been decoded while processing a picture" ); |
1122 | 0 | for( int i = 0; i < ALF_CTB_MAX_NUM_APS; i++ ) |
1123 | 0 | { |
1124 | 0 | const APS* aps = m_parameterSetManager.getAPS_nothrow( i, ALF_APS ); |
1125 | 0 | CHECK( aps && aps->getChangedFlag(), "Error - a new APS has been decoded while processing a picture" ); |
1126 | 0 | } |
1127 | 0 | CHECK( lmcsAPS && lmcsAPS->getChangedFlag(), "Error - a new LMCS APS has been decoded while processing a picture" ); |
1128 | |
|
1129 | 0 | xParsePrefixSEImessages(); |
1130 | | |
1131 | | // Check if any new SEI has arrived |
1132 | 0 | if( !m_seiMessageList.empty() ) |
1133 | 0 | { |
1134 | | // Currently only decoding Unit SEI message occurring between VCL NALUs copied |
1135 | 0 | seiMessages& picSEI = m_pcParsePic->seiMessageList; |
1136 | 0 | seiMessages decodingUnitInfos = SEI_internal::extractSeisByType( m_seiMessageList, VVDEC_DECODING_UNIT_INFO ); |
1137 | 0 | picSEI.insert( picSEI.end(), decodingUnitInfos.begin(), decodingUnitInfos.end() ); |
1138 | 0 | SEI_internal::deleteSEIs ( m_seiMessageList ); |
1139 | 0 | } |
1140 | 0 | } |
1141 | | |
1142 | 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 " ); |
1143 | 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." ); |
1144 | 0 | CHECK( !sps->getUseWPBiPred() && pps->getWPBiPred(), |
1145 | 0 | "When sps_weighted_bipred_flag is equal to 0, the value of pps_weighted_bipred_flag shall be equal to 0." ); |
1146 | |
|
1147 | 0 | CHECK( !sps->getResChangeInClvsEnabledFlag() && pps->getPicWidthInLumaSamples() != sps->getMaxPicWidthInLumaSamples(), |
1148 | 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." ); |
1149 | 0 | CHECK( !sps->getResChangeInClvsEnabledFlag() && pps->getPicHeightInLumaSamples() != sps->getMaxPicHeightInLumaSamples(), |
1150 | 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." ); |
1151 | 0 | CHECK( sps->getResChangeInClvsEnabledFlag() && sps->getSubPicInfoPresentFlag() != 0, |
1152 | 0 | "When res_change_in_clvs_allowed_flag is equal to 1, the value of subpic_info_present_flag shall be equal to 0." ); |
1153 | 0 | CHECK( sps->getResChangeInClvsEnabledFlag() && sps->getVirtualBoundariesEnabledFlag(), |
1154 | 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" ); |
1155 | 0 | if( vps && vps->m_numOutputLayersInOls[vps->m_iTargetLayer] > 1 ) |
1156 | 0 | { |
1157 | 0 | CHECK( sps->getMaxPicWidthInLumaSamples() > vps->getOlsDpbPicSize( vps->m_iTargetLayer ).width, |
1158 | 0 | "pic_width_max_in_luma_samples shall be less than or equal to the value of ols_dpb_pic_width[ i ]" ); |
1159 | 0 | CHECK( sps->getMaxPicHeightInLumaSamples() > vps->getOlsDpbPicSize( vps->m_iTargetLayer ).height, |
1160 | 0 | "pic_height_max_in_luma_samples shall be less than or equal to the value of ols_dpb_pic_height[ i ]" ); |
1161 | 0 | } |
1162 | | |
1163 | 0 | CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getOneTilePerPicConstraintFlag() && pps->getNumTiles() != 1, |
1164 | 0 | "When one_tile_per_pic_constraint_flag is equal to 1, each picture shall contain only one tile" ); |
1165 | 0 | CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getOneSlicePerPicConstraintFlag() && pps->getRectSliceFlag() && pps->getNumSlicesInPic() != 1, |
1166 | 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" ); |
1167 | 0 | CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getNoRprConstraintFlag() && sps->getRprEnabledFlag(), |
1168 | 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" ); |
1169 | 0 | CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getNoResChangeInClvsConstraintFlag() && sps->getResChangeInClvsEnabledFlag(), |
1170 | 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" ); |
1171 | 0 | CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getNoIdrRplConstraintFlag() && sps->getIDRRefParamListPresent(), |
1172 | 0 | "When gci_no_idr_rpl_constraint_flag equal to 1 , the value of sps_idr_rpl_present_flag shall be equal to 0" ); |
1173 | 0 | CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getNoMixedNaluTypesInPicConstraintFlag() && pps->getMixedNaluTypesInPicFlag(), |
1174 | 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" ); |
1175 | 0 | CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getNoRectSliceConstraintFlag() && pps->getRectSliceFlag(), |
1176 | 0 | "When gci_no_rectangular_slice_constraint_flag equal to 1, the value of pps_rect_slice_flag shall be equal to 0" ); |
1177 | 0 | CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getOneSlicePerSubpicConstraintFlag() && !pps->getSingleSlicePerSubPicFlag(), |
1178 | 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" ); |
1179 | 0 | CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getNoSubpicInfoConstraintFlag() && sps->getSubPicInfoPresentFlag(), |
1180 | 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" ); |
1181 | |
|
1182 | 0 | if( sps->getProfileTierLevel()->getConstraintInfo()->getNoMttConstraintFlag() ) |
1183 | 0 | { |
1184 | 0 | CHECK( sps->getMaxMTTHierarchyDepth() || sps->getMaxMTTHierarchyDepthI() || sps->getMaxMTTHierarchyDepthIChroma(), |
1185 | 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" |
1186 | 0 | " and sps_max_mtt_hierarchy_depth_intra_slice_chroma shall be equal to 0" ); |
1187 | 0 | } |
1188 | 0 | if( sps->getProfileTierLevel()->getConstraintInfo()->getNoWeightedPredictionConstraintFlag() ) |
1189 | 0 | { |
1190 | 0 | CHECK( sps->getUseWP() || sps->getUseWPBiPred(), |
1191 | 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" ); |
1192 | 0 | } |
1193 | | |
1194 | 0 | CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getNoChromaQpOffsetConstraintFlag() && pps->getCuChromaQpOffsetEnabledFlag(), |
1195 | 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" ); |
1196 | |
|
1197 | 0 | CHECK( sps->getCTUSize() > ( 1 << sps->getProfileTierLevel()->getConstraintInfo()->getMaxLog2CtuSizeConstraintIdc() ), |
1198 | 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" ); |
1199 | 0 | CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getNoLumaTransformSize64ConstraintFlag() && sps->getLog2MaxTbSize() != 5, |
1200 | 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" ); |
1201 | | |
1202 | | // TODO: fix MT static maps |
1203 | 0 | static std::unordered_map<int, int> m_layerChromaFormat; |
1204 | 0 | static std::unordered_map<int, int> m_layerBitDepth; |
1205 | |
|
1206 | 0 | if( vps && vps->getMaxLayers() > 1 ) |
1207 | 0 | { |
1208 | 0 | int curLayerIdx = vps->getGeneralLayerIdx(layerId); |
1209 | 0 | int curLayerChromaFormat = sps->getChromaFormatIdc(); |
1210 | 0 | int curLayerBitDepth = sps->getBitDepth(); |
1211 | |
|
1212 | 0 | if( pSlice->isClvssPu() && m_bFirstSliceInPicture ) |
1213 | 0 | { |
1214 | 0 | m_layerChromaFormat[curLayerIdx] = curLayerChromaFormat; |
1215 | 0 | m_layerBitDepth [curLayerIdx] = curLayerBitDepth; |
1216 | 0 | } |
1217 | 0 | else |
1218 | 0 | { |
1219 | 0 | CHECK( m_layerChromaFormat[curLayerIdx] != curLayerChromaFormat, "Different chroma format in the same layer." ); |
1220 | 0 | CHECK( m_layerBitDepth [curLayerIdx] != curLayerBitDepth, "Different bit-depth in the same layer." ); |
1221 | 0 | } |
1222 | | |
1223 | 0 | for( int i = 0; i < curLayerIdx; i++ ) |
1224 | 0 | { |
1225 | 0 | if( vps->getDirectRefLayerFlag( curLayerIdx, i ) ) |
1226 | 0 | { |
1227 | 0 | int refLayerChromaFormat = m_layerChromaFormat[i]; |
1228 | 0 | CHECK( curLayerChromaFormat != refLayerChromaFormat, "The chroma formats of the current layer and the reference layer are different" ); |
1229 | 0 | int refLayerBitDepth = m_layerBitDepth[i]; |
1230 | 0 | CHECK( curLayerBitDepth != refLayerBitDepth, "The bit-depth of the current layer and the reference layer are different" ); |
1231 | 0 | } |
1232 | 0 | } |
1233 | 0 | } |
1234 | | |
1235 | 0 | const int minCuSize = 1 << sps->getLog2MinCodingBlockSize(); |
1236 | 0 | CHECK( ( pps->getPicWidthInLumaSamples() % ( std::max( 8, minCuSize) ) ) != 0, "Coded frame width must be a multiple of Max(8, the minimum unit size)" ); |
1237 | 0 | CHECK( ( pps->getPicHeightInLumaSamples() % ( std::max( 8, minCuSize) ) ) != 0, "Coded frame height must be a multiple of Max(8, the minimum unit size)" ); |
1238 | |
|
1239 | 0 | if( sps->getCTUSize() + 2 * ( 1 << sps->getLog2MinCodingBlockSize() ) > pps->getPicWidthInLumaSamples() ) |
1240 | 0 | { |
1241 | 0 | CHECK( pps->getUseWrapAround(), |
1242 | 0 | "Wraparound shall be disabled when the value of ( CtbSizeY / MinCbSizeY + 1) is greater than or equal to" |
1243 | 0 | " ( pic_width_in_luma_samples / MinCbSizeY - 1 )" ); |
1244 | 0 | } |
1245 | | |
1246 | 0 | if( pSlice->getPicHeader()->getGdrOrIrapPicFlag() && !pSlice->getPicHeader()->getGdrPicFlag() |
1247 | 0 | && ( !vps || vps->getIndependentLayerFlag( vps->getGeneralLayerIdx( layerId ) ) ) ) |
1248 | 0 | { |
1249 | 0 | CHECK( pSlice->getPicHeader()->getPicInterSliceAllowedFlag(), |
1250 | 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 ] ] " |
1251 | 0 | "is equal to 1, ph_inter_slice_allowed_flag shall be equal to 0" ); |
1252 | 0 | } |
1253 | | |
1254 | 0 | if( sps->getVPSId() && vps && vps->m_numLayersInOls[vps->m_iTargetLayer] == 1 ) |
1255 | 0 | { |
1256 | 0 | CHECK( !sps->getPtlDpbHrdParamsPresentFlag(), |
1257 | 0 | "When sps_video_parameter_set_id is greater than 0 and there is an OLS that contains only one layer" |
1258 | 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" ); |
1259 | 0 | } |
1260 | | |
1261 | 0 | ProfileLevelTierFeatures ptlFeature; |
1262 | 0 | ptlFeature.extractPTLInformation(*sps); |
1263 | |
|
1264 | 0 | const LevelTierFeatures* ltFeature = ptlFeature.getLevelTierFeatures(); |
1265 | 0 | const ProfileFeatures* pFeature = ptlFeature.getProfileFeatures(); |
1266 | |
|
1267 | 0 | CHECK( ltFeature && pps->getNumTileColumns() > ltFeature->maxTileCols, "Num tile columns signaled in PPS exceed level limits" ); |
1268 | 0 | CHECK( ltFeature && pps->getNumTiles() > ltFeature->maxTilesPerAu, "Num tiles signaled in PPS exceed level limits" ); |
1269 | 0 | CHECK( pFeature && sps->getBitDepth() > pFeature->maxBitDepth, "Bit depth exceed profile limit" ); |
1270 | 0 | CHECK( pFeature && sps->getChromaFormatIdc() > pFeature->maxChromaFormat, "Chroma format exceed profile limit" ); |
1271 | 0 | } |
1272 | | |
1273 | | void DecLibParser::prepareUnavailablePicture( bool isLost, const PPS* pps, int iUnavailablePoc, const int layerId, const bool longTermFlag, const int temporalId ) |
1274 | 0 | { |
1275 | 0 | if( isLost ) |
1276 | 0 | { |
1277 | 0 | CHECK( !( m_errHandlingFlags & ERR_HANDLING_TRY_CONTINUE ), "missing reference picture poc: " << iUnavailablePoc ); |
1278 | |
|
1279 | 0 | if( !m_picListManager.getBackPic() ) |
1280 | 0 | { |
1281 | 0 | THROW_RECOVERABLE( "no pictures yet." ); |
1282 | 0 | return; |
1283 | 0 | } |
1284 | 0 | msg( WARNING, "inserting lost poc : %d\n", iUnavailablePoc ); |
1285 | 0 | } |
1286 | 0 | else |
1287 | 0 | { |
1288 | 0 | msg( INFO, "inserting unavailable poc : %d\n", iUnavailablePoc ); |
1289 | 0 | } |
1290 | 0 | Picture* cFillPic = m_picListManager.getNewPicBuffer( *m_parameterSetManager.getFirstSPS(), *m_parameterSetManager.getFirstPPS(), 0, layerId, m_parameterSetManager.getVPS( m_parameterSetManager.getFirstSPS()->getVPSId() ) ); |
1291 | 0 | CHECK( std::find( m_dpbReferencePics.cbegin(), m_dpbReferencePics.cend(), cFillPic ) != m_dpbReferencePics.cend(), "reused picture shouldn't be in decoded picture buffer" ); |
1292 | 0 | m_dpbReferencePics.push_back( cFillPic ); |
1293 | 0 | const APS* nullAlfApss[ALF_CTB_MAX_NUM_APS] = { nullptr, }; |
1294 | 0 | cFillPic->finalInit( &m_cuChunkCache, &m_tuChunkCache, m_parameterSetManager.getFirstSPS(), m_parameterSetManager.getFirstPPS(), m_picHeader, nullAlfApss, nullptr, nullptr, false ); |
1295 | 0 | cFillPic->cs->initStructData(); |
1296 | |
|
1297 | 0 | CHECK_FATAL( !cFillPic->slices.empty(), "fill pic should not contain slices, already." ); |
1298 | 0 | cFillPic->allocateNewSlice(); |
1299 | 0 | cFillPic->slices[0]->initSlice(); |
1300 | 0 | cFillPic->slices[0]->setPOC( iUnavailablePoc ); |
1301 | 0 | cFillPic->slices[0]->setTLayer( temporalId ); |
1302 | 0 | cFillPic->slices[0]->setNalUnitLayerId( layerId ); |
1303 | | |
1304 | | // picture header is not derived for generated reference picture |
1305 | 0 | cFillPic->slices[0]->setPicHeader( nullptr ); |
1306 | 0 | cFillPic->slices[0]->setPPS( pps ); |
1307 | |
|
1308 | 0 | cFillPic->dpbReferenceMark = longTermFlag ? Picture::LongTerm : Picture::ShortTerm; |
1309 | 0 | cFillPic->stillReferenced = true; |
1310 | 0 | cFillPic->isReferencePic = true; |
1311 | 0 | cFillPic->poc = iUnavailablePoc; |
1312 | 0 | cFillPic->neededForOutput = false; |
1313 | 0 | cFillPic->tempLayer = temporalId; |
1314 | 0 | cFillPic->nonReferencePictureFlag = false; |
1315 | 0 | cFillPic->wasLost = isLost; |
1316 | |
|
1317 | 0 | if( cFillPic->slices[0]->getTLayer() == 0 && |
1318 | 0 | cFillPic->slices[0]->getNalUnitType() != NAL_UNIT_CODED_SLICE_RASL && |
1319 | 0 | cFillPic->slices[0]->getNalUnitType() != NAL_UNIT_CODED_SLICE_RADL ) |
1320 | 0 | { |
1321 | 0 | m_prevTid0POC = cFillPic->slices[0]->getPOC(); |
1322 | 0 | } |
1323 | |
|
1324 | 0 | cFillPic->subPictures.clear(); |
1325 | 0 | cFillPic->sliceSubpicIdx.clear(); |
1326 | |
|
1327 | 0 | for( int subPicIdx = 0; subPicIdx < pps->getNumSubPics(); subPicIdx++ ) |
1328 | 0 | { |
1329 | 0 | cFillPic->subPictures.push_back( pps->getSubPic( subPicIdx ) ); |
1330 | 0 | } |
1331 | |
|
1332 | 0 | cFillPic->parseDone.unlock(); |
1333 | |
|
1334 | | #if 0 |
1335 | | // NOT YET IMPLEMENTED |
1336 | | if( isLost && ( m_errHandlingFlags & ERR_HANDLING_COPY_CLOSEST ) ) |
1337 | | { |
1338 | | // this will be filled in later, when closer pictures might have been reconstructed. |
1339 | | |
1340 | | cFillPic->progress = Picture::parsed; |
1341 | | m_parseFrameList.push_back( cFillPic ); |
1342 | | return; |
1343 | | } |
1344 | | #endif |
1345 | |
|
1346 | 0 | cFillPic->fillGrey( m_parameterSetManager.getFirstSPS() ); |
1347 | |
|
1348 | 0 | if( m_pocRandomAccess == MAX_INT ) |
1349 | 0 | { |
1350 | 0 | m_pocRandomAccess = iUnavailablePoc; |
1351 | 0 | } |
1352 | 0 | } |
1353 | | |
1354 | | #if 0 |
1355 | | // NOT YET IMPLEMENTED |
1356 | | void DecLibParser::fillMissingPicBuf( Picture* pcPic, bool copyClosest ) |
1357 | | { |
1358 | | if( copyClosest ) |
1359 | | { |
1360 | | CHECK_FATAL( pcPic->progress != Picture::parsed, "filled in picture should have been marked as parsed" ); |
1361 | | CHECK_FATAL( pcPic->parseDone.isBlocked(), "parsed barrier should be unlocked" ); |
1362 | | |
1363 | | auto closestPic = m_picListManager.findClosestPic( pcPic->poc ); |
1364 | | if( closestPic ) |
1365 | | { |
1366 | | CHECK_FATAL( closestPic->progress < Picture::reconstructed, "closest Picture is not yet reconstructed" ) |
1367 | | // the next not-lost picture in the parseFrameList should be the one, that referenced this picture |
1368 | | auto referencedBy = std::find_if( m_parseFrameList.begin(), m_parseFrameList.end(), []( Picture* p ) { return !p->wasLost && !p->error; } ); |
1369 | | msg( INFO, "copying picture %d to %d (%d)\n", closestPic->getPOC(), pcPic->poc, ( referencedBy != m_parseFrameList.end() ) ? ( *referencedBy )->poc : -1 ); |
1370 | | |
1371 | | pcPic->getRecoBuf().copyFrom( closestPic->getRecoBuf() ); |
1372 | | |
1373 | | pcPic->slices[0]->copySliceInfo( closestPic->slices[0] ); |
1374 | | pcPic->slices[0]->setPOC( pcPic->poc ); |
1375 | | } |
1376 | | |
1377 | | // currently we don't output filled-in reference pictures |
1378 | | // pcPic->neededForOutput = true; |
1379 | | } |
1380 | | else |
1381 | | { |
1382 | | pcPic->fillGrey( pcPic->cs->sps.get() ); |
1383 | | } |
1384 | | |
1385 | | pcPic->progress = Picture::reconstructed; |
1386 | | pcPic->reconDone.unlock(); |
1387 | | } |
1388 | | #endif |
1389 | | |
1390 | | |
1391 | | // Function for applying picture marking based on the Reference Picture List |
1392 | | void DecLibParser::applyReferencePictureListBasedMarking( Slice* currSlice, const int layerId, const PPS& pps ) |
1393 | 0 | { |
1394 | | // checkLeadingPictureRestrictions(rcListPic, pps); |
1395 | | |
1396 | | // mark long-term reference pictures in List0 |
1397 | 0 | for( const auto l: { REF_PIC_LIST_0, REF_PIC_LIST_1 } ) |
1398 | 0 | { |
1399 | 0 | const ReferencePictureList* rpl = currSlice->getRPL( l ); |
1400 | |
|
1401 | 0 | for( int i = 0; i < rpl->getNumRefEntries(); i++ ) |
1402 | 0 | { |
1403 | 0 | if( !rpl->isRefPicLongterm( i ) || rpl->isInterLayerRefPic( i ) ) |
1404 | 0 | { |
1405 | 0 | continue; |
1406 | 0 | } |
1407 | | |
1408 | 0 | Picture* availableST = nullptr; |
1409 | 0 | for( Picture* pic: m_dpbReferencePics ) |
1410 | 0 | { |
1411 | 0 | if( !pic->dpbReferenceMark ) |
1412 | 0 | { |
1413 | 0 | continue; |
1414 | 0 | } |
1415 | | |
1416 | 0 | const int bitsForPoc = pic->cs->sps->getBitsForPOC(); |
1417 | 0 | const int curPoc = pic->getPOC(); |
1418 | 0 | const int ltRefPoc = rpl->calcLTRefPOC( currSlice->getPOC(), bitsForPoc, i ); |
1419 | 0 | if( pic->dpbReferenceMark == Picture::LongTerm && isLTPocEqual( curPoc, ltRefPoc, bitsForPoc, rpl->getDeltaPocMSBPresentFlag( i ) ) ) |
1420 | 0 | { |
1421 | 0 | break; |
1422 | 0 | } |
1423 | | |
1424 | | // if there was no such long-term check the short terms |
1425 | 0 | if( pic->dpbReferenceMark == Picture::ShortTerm && isLTPocEqual( curPoc, ltRefPoc, bitsForPoc, rpl->getDeltaPocMSBPresentFlag( i ) ) ) |
1426 | 0 | { |
1427 | 0 | availableST = pic; |
1428 | | // but don't break here, because we might still find a LT |
1429 | 0 | } |
1430 | 0 | } |
1431 | | |
1432 | | // the found picture was not yet marked as long term, so we mark it here |
1433 | 0 | if ( availableST ) |
1434 | 0 | { |
1435 | 0 | availableST->dpbReferenceMark = Picture::LongTerm; |
1436 | 0 | } |
1437 | 0 | } |
1438 | 0 | } |
1439 | |
|
1440 | 0 | if( currSlice->isIDR() && !pps.getMixedNaluTypesInPicFlag() ) |
1441 | 0 | { |
1442 | 0 | for( Picture* pic: m_dpbReferencePics ) |
1443 | 0 | { |
1444 | 0 | pic->dpbReferenceMark = Picture::unreferenced; |
1445 | 0 | } |
1446 | | |
1447 | | // ignore neededForOutput flag here, because we only care about reference pictures in the DPB |
1448 | 0 | m_dpbReferencePics.remove_if( []( Picture* pic ) { return !pic->dpbReferenceMark; } ); |
1449 | 0 | return; |
1450 | 0 | } |
1451 | | |
1452 | | // loop through all pictures in the reference picture buffer |
1453 | 0 | for( Picture* pic: m_dpbReferencePics ) |
1454 | 0 | { |
1455 | 0 | if( !pic->dpbReferenceMark ) |
1456 | 0 | { |
1457 | 0 | continue; |
1458 | 0 | } |
1459 | | |
1460 | 0 | bool isReference = false; |
1461 | |
|
1462 | 0 | for( const auto l: { REF_PIC_LIST_0, REF_PIC_LIST_1 } ) |
1463 | 0 | { |
1464 | 0 | if( currSlice->getRPL( l )->findInRefPicList( pic, currSlice->getPOC(), layerId ) ) |
1465 | 0 | { |
1466 | 0 | isReference = true; |
1467 | 0 | break; |
1468 | 0 | } |
1469 | 0 | } |
1470 | | |
1471 | | // mark the picture as "unused for reference" if it is not in |
1472 | | // the Reference Picture List |
1473 | 0 | if( !isReference && pic->poc != currSlice->getPOC() && pic->layerId == layerId ) |
1474 | 0 | { |
1475 | 0 | pic->dpbReferenceMark = Picture::unreferenced; |
1476 | 0 | } |
1477 | | |
1478 | | // // sanity checks |
1479 | | // if( pic->referenced ) |
1480 | | // { |
1481 | | // // check that pictures of higher temporal layers are not used |
1482 | | // CHECK_FATAL( pic->usedByCurr && pic->temporalId > this->getTLayer(), "Invalid state" ); |
1483 | | // } |
1484 | 0 | } |
1485 | | |
1486 | | // ignore neededForOutput flag here, because we only care about reference pictures in the DPB |
1487 | 0 | m_dpbReferencePics.remove_if( []( Picture* pic ) { return !pic->dpbReferenceMark; } ); |
1488 | 0 | } |
1489 | | |
1490 | | void DecLibParser::xParsePrefixSEImessages() |
1491 | 0 | { |
1492 | 0 | while( !m_prefixSEINALUs.empty() ) |
1493 | 0 | { |
1494 | 0 | InputNALUnit& nalu = m_prefixSEINALUs.front(); |
1495 | 0 | const SPS *sps = m_parameterSetManager.getActiveSPS(); |
1496 | 0 | const VPS *vps = m_parameterSetManager.getVPS(sps->getVPSId()); |
1497 | 0 | m_seiReader.parseSEImessage( &(nalu.getBitstream()), m_seiMessageList, nalu.m_nalUnitType, nalu.m_nuhLayerId, nalu.m_temporalId, vps, sps, m_HRD, m_pDecodedSEIOutputStream ); |
1498 | 0 | m_prefixSEINALUs.pop_front(); |
1499 | 0 | } |
1500 | 0 | } |
1501 | | |
1502 | | void DecLibParser::xParsePrefixSEIsForUnknownVCLNal() |
1503 | 0 | { |
1504 | 0 | while (!m_prefixSEINALUs.empty()) |
1505 | 0 | { |
1506 | | // do nothing? |
1507 | 0 | msg( VERBOSE, "Discarding Prefix SEI associated with unknown VCL NAL unit.\n"); |
1508 | 0 | m_prefixSEINALUs.pop_front(); |
1509 | 0 | } |
1510 | | // TODO: discard following suffix SEIs as well? |
1511 | 0 | } |
1512 | | |
1513 | | void DecLibParser::xDecodePicHeader( InputNALUnit& nalu ) |
1514 | 0 | { |
1515 | 0 | m_HLSReader.setBitstream( &nalu.getBitstream() ); |
1516 | 0 | m_picHeader = std::make_shared<PicHeader>(); |
1517 | 0 | m_HLSReader.parsePictureHeader( m_picHeader.get(), &m_parameterSetManager, true ); |
1518 | 0 | } |
1519 | | |
1520 | | void DecLibParser::xDecodeVPS( InputNALUnit& nalu ) |
1521 | 0 | { |
1522 | | // We don't parse the VPS, because the needed bounds checks in parseVPS() are not yet implemented, and we don't process it anyways |
1523 | | #if 0 |
1524 | | std::unique_ptr<VPS> vps( new VPS() ); |
1525 | | m_HLSReader.setBitstream( &nalu.getBitstream() ); |
1526 | | m_HLSReader.parseVPS( vps.get() ); |
1527 | | m_parameterSetManager.storeVPS( vps.release(), nalu.getBitstream().getFifo() ); |
1528 | | #endif |
1529 | 0 | } |
1530 | | |
1531 | | void DecLibParser::xDecodeDCI( InputNALUnit& nalu ) |
1532 | 0 | { |
1533 | 0 | m_HLSReader.setBitstream(&nalu.getBitstream()); |
1534 | |
|
1535 | 0 | CHECK(nalu.m_temporalId, "The value of TemporalId of DCI NAL units shall be equal to 0"); |
1536 | 0 | if( !m_dci ) |
1537 | 0 | { |
1538 | 0 | m_dci = new DCI; |
1539 | 0 | m_HLSReader.parseDCI( m_dci ); |
1540 | 0 | } |
1541 | 0 | else |
1542 | 0 | { |
1543 | 0 | DCI dupDCI; |
1544 | 0 | m_HLSReader.parseDCI( &dupDCI ); |
1545 | 0 | CHECK( !m_dci->IsIndenticalDCI( dupDCI ), "Two signaled DCIs are different"); |
1546 | 0 | } |
1547 | 0 | } |
1548 | | |
1549 | | void DecLibParser::xDecodeSPS( InputNALUnit& nalu ) |
1550 | 0 | { |
1551 | 0 | std::unique_ptr<SPS> sps( new SPS() ); |
1552 | 0 | m_HLSReader.setBitstream( &nalu.getBitstream() ); |
1553 | 0 | m_HLSReader.parseSPS( sps.get(), &m_parameterSetManager ); |
1554 | 0 | sps->setLayerId( nalu.m_nuhLayerId ); |
1555 | 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 |
1556 | 0 | m_parameterSetManager.storeSPS( sps.release(), nalu.getBitstream().getFifo() ); |
1557 | 0 | } |
1558 | | |
1559 | | void DecLibParser::xDecodePPS( InputNALUnit& nalu ) |
1560 | 0 | { |
1561 | 0 | std::unique_ptr<PPS> pps( new PPS() ); |
1562 | 0 | m_HLSReader.setBitstream( &nalu.getBitstream() ); |
1563 | 0 | m_HLSReader.parsePPS( pps.get(), &m_parameterSetManager ); |
1564 | 0 | pps->setLayerId( nalu.m_nuhLayerId ); |
1565 | 0 | m_parameterSetManager.storePPS( pps.release(), nalu.getBitstream().getFifo() ); |
1566 | 0 | } |
1567 | | |
1568 | | void DecLibParser::xDecodeAPS( InputNALUnit& nalu ) |
1569 | 0 | { |
1570 | 0 | std::unique_ptr<APS> aps( new APS() ); |
1571 | 0 | m_HLSReader.setBitstream( &nalu.getBitstream() ); |
1572 | 0 | if( !m_HLSReader.parseAPS( aps.get() ) ) |
1573 | 0 | { // ignore unsupported APS types |
1574 | 0 | return; |
1575 | 0 | } |
1576 | 0 | aps->setTemporalId( nalu.m_temporalId ); |
1577 | 0 | aps->setLayerId( nalu.m_nuhLayerId ); |
1578 | 0 | aps->setHasPrefixNalUnitType( nalu.m_nalUnitType == NAL_UNIT_PREFIX_APS ); |
1579 | 0 | m_parameterSetManager.storeAPS( aps.release(), nalu.getBitstream().getFifo() ); |
1580 | 0 | } |
1581 | | |
1582 | | void DecLibParser::xUpdatePreviousTid0POC(Slice * pSlice) |
1583 | 0 | { |
1584 | 0 | if( pSlice->getTLayer() == 0 && pSlice->getNalUnitType() != NAL_UNIT_CODED_SLICE_RASL && pSlice->getNalUnitType() != NAL_UNIT_CODED_SLICE_RADL |
1585 | 0 | && !pSlice->getPicHeader()->getNonReferencePictureFlag() ) |
1586 | 0 | { |
1587 | 0 | m_prevTid0POC = pSlice->getPOC(); |
1588 | 0 | } |
1589 | 0 | } |
1590 | | |
1591 | | |
1592 | | void DecLibParser::checkNoOutputPriorPics() |
1593 | 0 | { |
1594 | 0 | if( !m_isNoOutputPriorPics ) |
1595 | 0 | { |
1596 | 0 | return; |
1597 | 0 | } |
1598 | | |
1599 | 0 | for( auto& pcPicTmp: m_dpbReferencePics ) |
1600 | 0 | { |
1601 | 0 | if( pcPicTmp->progress >= Picture::reconstructed && pcPicTmp->getPOC() < m_lastPOCNoOutputPriorPics ) |
1602 | 0 | { |
1603 | 0 | pcPicTmp->neededForOutput = false; |
1604 | 0 | } |
1605 | 0 | } |
1606 | 0 | } |
1607 | | |
1608 | | /** 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. |
1609 | | * All pictures prior to the random access point indicated by the counter iSkipFrame are skipped. |
1610 | | * It also checks the type of Nal unit type at the random access point. |
1611 | | * 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. |
1612 | | * If the random access point is IDR all pictures after the random access point are decoded. |
1613 | | * If the random access point is none of the above, a warning is issues, and decoding of pictures with POC |
1614 | | * equal to or greater than the random access point POC is attempted. For non IDR/CRA/BLA random |
1615 | | * access point there is no guarantee that the decoder will not crash. |
1616 | | */ |
1617 | | bool DecLibParser::isRandomAccessSkipPicture() |
1618 | 0 | { |
1619 | 0 | if( m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP ) |
1620 | 0 | { |
1621 | 0 | m_pocRandomAccess = -MAX_INT; // no need to skip the reordered pictures in IDR, they are decodable. |
1622 | 0 | } |
1623 | 0 | else if( m_pocRandomAccess == MAX_INT ) // start of random access point, m_pocRandomAccess has not been set yet. |
1624 | 0 | { |
1625 | 0 | #if GDR_ADJ |
1626 | 0 | if( m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR ) |
1627 | | #else |
1628 | | if( m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA ) |
1629 | | #endif |
1630 | 0 | { |
1631 | | // set the POC random access since we need to skip the reordered pictures in the case of CRA/CRANT/BLA/BLANT. |
1632 | 0 | m_pocRandomAccess = m_apcSlicePilot->getPOC(); |
1633 | 0 | } |
1634 | 0 | else |
1635 | 0 | { |
1636 | 0 | if( !m_warningMessageSkipPicture ) |
1637 | 0 | { |
1638 | 0 | msg( WARNING, "Warning: this is not a valid random access point and the data is discarded until the first CRA picture\n" ); |
1639 | 0 | m_warningMessageSkipPicture = true; |
1640 | 0 | } |
1641 | 0 | return true; |
1642 | 0 | } |
1643 | 0 | } |
1644 | | // skip the reordered pictures, if necessary |
1645 | 0 | else if( m_apcSlicePilot->getPOC() < m_pocRandomAccess && ( m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_RASL ) ) |
1646 | 0 | { |
1647 | 0 | return true; |
1648 | 0 | } |
1649 | | // if we reach here, then the picture is not skipped. |
1650 | 0 | return false; |
1651 | 0 | } |
1652 | | |
1653 | | void DecLibParser::xCheckMixedNalUnit( Slice* pcSlice, const InputNALUnit& nalu ) |
1654 | 0 | { |
1655 | 0 | if( pcSlice->getPPS()->getMixedNaluTypesInPicFlag() ) |
1656 | 0 | { |
1657 | 0 | CHECK(pcSlice->getPPS()->getNumSlicesInPic() < 2, "mixed nal unit type picture, but with less than 2 slices"); |
1658 | |
|
1659 | 0 | CHECK( pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR, "picture with mixed NAL unit type cannot have GDR slice"); |
1660 | | |
1661 | | //Check that if current slice is IRAP type, the other type of NAL can only be TRAIL_NUT |
1662 | 0 | if( pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL |
1663 | 0 | || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP |
1664 | 0 | || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA ) |
1665 | 0 | { |
1666 | 0 | for( int i = 0; i < m_uiSliceSegmentIdx; i++ ) |
1667 | 0 | { |
1668 | 0 | Slice* preSlice = m_pcParsePic->slices[i]; |
1669 | 0 | CHECK( pcSlice->getNalUnitType() != preSlice->getNalUnitType() |
1670 | 0 | && preSlice->getNalUnitType() != NAL_UNIT_CODED_SLICE_TRAIL, |
1671 | 0 | "In a mixed NAL unt type picture, an IRAP slice can be mixed with Trail slice(s) only" ); |
1672 | 0 | } |
1673 | 0 | } |
1674 | | |
1675 | | // if this is the last slice of the picture, check whether that there are at least two different NAL unit types in the picture |
1676 | 0 | if( pcSlice->getPPS()->getNumSlicesInPic() == (m_uiSliceSegmentIdx + 1) ) |
1677 | 0 | { |
1678 | 0 | bool hasDiffTypes = false; |
1679 | 0 | for( int i = 1; !hasDiffTypes && i <= m_uiSliceSegmentIdx; i++ ) |
1680 | 0 | { |
1681 | 0 | Slice* slice1 = m_pcParsePic->slices[i-1]; |
1682 | 0 | Slice* slice2 = m_pcParsePic->slices[i]; |
1683 | 0 | if( slice1->getNalUnitType() != slice2->getNalUnitType()) |
1684 | 0 | { |
1685 | 0 | hasDiffTypes = true; |
1686 | 0 | } |
1687 | 0 | } |
1688 | 0 | CHECK( !hasDiffTypes, "VCL NAL units of the picture shall have two or more different nal_unit_type values"); |
1689 | 0 | } |
1690 | 0 | } |
1691 | 0 | else // all slices shall have the same nal unit type |
1692 | 0 | { |
1693 | 0 | bool sameNalUnitType = true; |
1694 | 0 | for( int i = 0; i < m_uiSliceSegmentIdx; i++ ) |
1695 | 0 | { |
1696 | 0 | Slice* PreSlice = m_pcParsePic->slices[i]; |
1697 | 0 | if( PreSlice->getNalUnitType() != pcSlice->getNalUnitType() ) |
1698 | 0 | { |
1699 | 0 | sameNalUnitType = false; |
1700 | 0 | } |
1701 | 0 | } |
1702 | 0 | CHECK( !sameNalUnitType, "mixed_nalu_types_in_pic_flag is zero, but have different nal unit types" ); |
1703 | 0 | } |
1704 | 0 | } |
1705 | | |
1706 | | void DecLibParser::waitForPicsToFinishParsing( const std::vector<Picture*>& refPics ) |
1707 | 0 | { |
1708 | 0 | for( Picture* pic: refPics ) |
1709 | 0 | { |
1710 | 0 | if( m_threadPool->numThreads() == 0 ) |
1711 | 0 | { |
1712 | 0 | m_threadPool->processTasksOnMainThread(); |
1713 | 0 | } |
1714 | 0 | try |
1715 | 0 | { |
1716 | 0 | pic->parseDone.wait(); |
1717 | 0 | } |
1718 | 0 | catch( ... ) |
1719 | 0 | { |
1720 | 0 | pic->waitForAllTasks(); |
1721 | 0 | } |
1722 | 0 | } |
1723 | 0 | } |
1724 | | |
1725 | | } // namespace vvdec |