Coverage Report

Created: 2026-06-16 07:20

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