Coverage Report

Created: 2026-10-28 06:18

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