Coverage Report

Created: 2026-09-01 06:57

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