Coverage Report

Created: 2026-04-01 07:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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