Coverage Report

Created: 2026-07-25 07:06

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
        else
258
0
        {
259
0
          m_pcParsePic->reconDone.wait();
260
0
        }
261
0
        m_decLib.checkPictureHashSEI( m_pcParsePic );
262
0
      }
263
0
    }
264
1
    else
265
1
    {
266
1
      msg( NOTICE, "Received suffix SEI but no picture currently active.\n" );
267
1
    }
268
1
    return false;
269
270
1
  case NAL_UNIT_FD:
271
1
    return false;
272
273
0
  case NAL_UNIT_RESERVED_VCL_4:
274
2
  case NAL_UNIT_RESERVED_VCL_5:
275
5
  case NAL_UNIT_RESERVED_VCL_6:
276
5
  case NAL_UNIT_RESERVED_IRAP_VCL_11:
277
5
    msg( NOTICE, "Found reserved VCL NAL unit.\n" );
278
5
    xParsePrefixSEIsForUnknownVCLNal();
279
5
    return false;
280
1
  case NAL_UNIT_RESERVED_NVCL_26:
281
2
  case NAL_UNIT_RESERVED_NVCL_27:
282
2
    msg( NOTICE, "Found reserved NAL unit.\n" );
283
2
    return false;
284
2
  case NAL_UNIT_UNSPECIFIED_28:
285
3
  case NAL_UNIT_UNSPECIFIED_29:
286
3
  case NAL_UNIT_UNSPECIFIED_30:
287
5
  case NAL_UNIT_UNSPECIFIED_31:
288
5
    msg( NOTICE, "Found unspecified NAL unit.\n" );
289
5
    return false;
290
0
  case NAL_UNIT_INVALID:
291
0
  default:
292
0
    THROW_RECOVERABLE( "Invalid NAL unit type" );
293
0
    break;
294
3.50k
  }
295
0
  GCC_WARNING_RESET;
296
297
0
  return false;
298
3.50k
}
299
300
Picture* DecLibParser::getNextDecodablePicture()
301
1.62k
{
302
1.62k
  if( m_parseFrameList.empty() )
303
916
  {
304
916
    return nullptr;
305
916
  }
306
307
713
  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
713
  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
1.42k
  for( auto picIt = m_parseFrameList.begin(); picIt != m_parseFrameList.end(); ++picIt )
324
713
  {
325
713
    Picture* pic = *picIt;
326
327
713
    if( pic->parseDone.getState() != Barrier::unlocked )   // this doesn't throw if the barrier has an exception set
328
713
      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
713
  Picture * pic = m_parseFrameList.front();
374
713
  m_parseFrameList.pop_front();
375
713
  return pic;
376
713
}
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
752
{
403
  // all slices for the previous picture have been parsed
404
752
  if( m_pcParsePic && m_pcParsePic->lastSliceOfPicPresent() )
405
7
  {
406
7
    m_pcParsePic = nullptr;
407
7
  }
408
409
752
  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
752
  m_apcSlicePilot->setNalUnitType   ( nalu.m_nalUnitType );
413
752
  m_apcSlicePilot->setNalUnitLayerId( nalu.m_nuhLayerId  );
414
752
  m_apcSlicePilot->setTLayer        ( nalu.m_temporalId  );
415
416
752
  m_HLSReader.setBitstream( &nalu.getBitstream() );
417
418
752
  m_bFirstSliceInPicture = true;  // set for now, will be set correctly in parseSliceHeader
419
752
  m_HLSReader.parseSliceHeader( m_apcSlicePilot, m_picHeader, &m_parameterSetManager, m_prevTid0POC, m_bFirstSliceInPicture );
420
421
752
  CHECK( m_bFirstSliceInPicture != ( m_apcSlicePilot->getCtuAddrInSlice( 0 ) == 0 ), "first slice in picture should start at CTU-addr 0" );
422
423
752
  if( m_bFirstSliceInPicture )
424
714
  {
425
714
    m_uiSliceSegmentIdx = 0;
426
714
    m_apcSlicePilot->setPicHeader   ( m_picHeader.get() );
427
714
  }
428
38
  else // if it turns out, this was not the first slice in the picture, we need to parse the header again
429
38
  {
430
38
    m_uiSliceSegmentIdx++;
431
38
    CHECK( !m_pcParsePic, "m_pcParsePic should be initialized, when this is not the first slice in the picture" );
432
38
    CHECK( m_pcParsePic->slices.size() <= m_uiSliceSegmentIdx - 1 || m_pcParsePic->slices[m_uiSliceSegmentIdx - 1] == nullptr, "can't access previous slice" );
433
38
    CHECK( !m_pcParsePic->getMixedNaluTypesInPicFlag() && nalu.m_nalUnitType != m_pcParsePic->slices[m_uiSliceSegmentIdx - 1]->getNalUnitType(),
434
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" );
435
436
38
    m_apcSlicePilot->copySliceInfo( m_pcParsePic->slices[m_uiSliceSegmentIdx - 1] );
437
438
38
    m_apcSlicePilot->setNalUnitType   ( nalu.m_nalUnitType );
439
38
    m_apcSlicePilot->setNalUnitLayerId( nalu.m_nuhLayerId );
440
38
    m_apcSlicePilot->setTLayer        ( nalu.m_temporalId );
441
442
38
    nalu.getBitstream().resetToStart();
443
38
    nalu.readNalUnitHeader();
444
38
    m_HLSReader.setBitstream        ( &nalu.getBitstream() );
445
446
38
    m_HLSReader.parseSliceHeader( m_apcSlicePilot, m_picHeader, &m_parameterSetManager, m_prevTid0POC, m_bFirstSliceInPicture );
447
38
  }
448
449
752
  const PPS* pps = static_cast<const ParameterSetManager&>( m_parameterSetManager ).getPPS( m_apcSlicePilot->getPicHeader()->getPPSId() );
450
752
  CHECK( pps == 0, "No PPS present" );
451
752
  const SPS* sps = static_cast<const ParameterSetManager&>( m_parameterSetManager ).getSPS( pps->getSPSId() );
452
752
  CHECK( sps == 0, "No SPS present" );
453
752
  const VPS* vps = static_cast<const ParameterSetManager&>( m_parameterSetManager ).getVPS( sps->getVPSId() );
454
752
  CHECK( sps->getVPSId() > 0 && vps == 0, "Invalid VPS" );
455
752
  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
752
  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
752
  m_apcSlicePilot->setIndependentSliceIdx( m_uiSliceSegmentIdx );
465
466
752
  DTRACE_UPDATE( g_trace_ctx, std::make_pair( "poc", m_apcSlicePilot->getPOC() ) );
467
468
469
752
  if( m_bFirstSliceInPicture )
470
714
  {
471
714
    const auto pictureType = m_apcSlicePilot->getNalUnitType();
472
473
714
    if( !pps->getMixedNaluTypesInPicFlag()
474
714
        && ( 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
714
    {
479
714
      m_pocCRA            [nalu.m_nuhLayerId] = m_apcSlicePilot->getPOC();
480
714
      m_associatedIRAPType[nalu.m_nuhLayerId] = pictureType;
481
714
    }
482
714
  }
483
484
752
  xUpdatePreviousTid0POC( m_apcSlicePilot );
485
486
752
  m_apcSlicePilot->setAssociatedIRAPPOC ( m_pocCRA            [nalu.m_nuhLayerId] );
487
752
  m_apcSlicePilot->setAssociatedIRAPType( m_associatedIRAPType[nalu.m_nuhLayerId] );
488
489
752
  if( m_apcSlicePilot->getRapPicFlag() || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR )
490
714
  {
491
    // Derive NoOutputBeforeRecoveryFlag
492
714
    if( !pps->getMixedNaluTypesInPicFlag() )
493
714
    {
494
714
      if( m_bFirstSliceInSequence[nalu.m_nuhLayerId] )
495
714
      {
496
714
        m_picHeader->setNoOutputBeforeRecoveryFlag( true );
497
714
      }
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
714
    }
511
0
    else
512
0
    {
513
0
      m_picHeader->setNoOutputBeforeRecoveryFlag( false );
514
0
    }
515
516
714
    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
714
    if( m_apcSlicePilot->getNoOutputOfPriorPicsFlag() )
523
0
    {
524
0
      m_lastPOCNoOutputPriorPics = m_apcSlicePilot->getPOC();
525
0
      m_isNoOutputPriorPics      = true;
526
0
    }
527
714
    else
528
714
    {
529
714
      m_isNoOutputPriorPics = false;
530
714
    }
531
714
  }
532
533
752
#if !DISABLE_CHECK_NO_OUTPUT_PRIOR_PICS_FLAG
534
752
  if( m_bFirstSliceInPicture && m_apcSlicePilot->getPOC() != m_prevPOC
535
714
      && ( m_apcSlicePilot->getRapPicFlag() || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR )
536
714
      && m_picHeader->getNoOutputBeforeRecoveryFlag()
537
714
      && getNoOutputPriorPicsFlag() )
538
0
  {
539
0
    checkNoOutputPriorPics();
540
0
    setNoOutputPriorPicsFlag( false );
541
0
  }
542
752
#endif
543
544
545
  //For inference of PicOutputFlag
546
752
  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
752
  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
752
  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
752
  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
752
  m_prevSliceSkipped = false;
588
589
  //we should only get a different poc for a new picture (with CTU address==0)
590
752
  if(  m_apcSlicePilot->getPOC() != m_prevPOC
591
714
   && !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
752
  m_prevLayerID = nalu.m_nuhLayerId;
598
599
  //detect lost reference picture and insert copy of earlier frame.
600
752
  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
752
  xActivateParameterSets( nalu.m_nuhLayerId );
641
642
  // WARNING: don't use m_apcSlicePilot after this point, because it has been reallocated
643
644
752
  Slice* slice = m_pcParsePic->slices[m_uiSliceSegmentIdx];
645
646
752
  m_pcParsePic->neededForOutput = m_picHeader->getPicOutputFlag();
647
752
  if( m_pcParsePic->lastSliceOfPicPresent() )
648
714
  {
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
714
    {
658
714
      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
714
      if( !m_gdrRecovered[nalu.m_nuhLayerId]
664
714
          && ( 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
714
      const bool is_recovering_picture = slice->getAssociatedIRAPType() == NAL_UNIT_CODED_SLICE_GDR && m_pcParsePic->poc < m_gdrRecoveryPointPocVal[nalu.m_nuhLayerId];
671
714
      if( slice->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR && m_gdrRecovered[nalu.m_nuhLayerId] )
672
0
      {
673
0
        m_pcParsePic->neededForOutput = true;
674
0
      }
675
714
      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
714
      else if( ( slice->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR && m_picHeader->getNoOutputBeforeRecoveryFlag() )
680
714
               || ( is_recovering_picture && ( !m_gdrRecovered[nalu.m_nuhLayerId] || m_lastNoOutputBeforeRecoveryFlag[nalu.m_nuhLayerId] ) ) )
681
0
      {
682
0
        m_pcParsePic->neededForOutput = false;
683
0
      }
684
714
    }
685
714
  }
686
687
752
  return true;
688
752
}
689
690
bool DecLibParser::xDecodeSliceMain( InputNALUnit& nalu )
691
714
{
692
714
  ITT_TASKSTART( itt_domain_oth, itt_handle_start );
693
  // actual decoding starts here
694
714
  Slice* pcSlice = m_pcParsePic->slices[m_uiSliceSegmentIdx];
695
714
  m_pcParsePic->poc              = pcSlice->getPOC();
696
714
  m_pcParsePic->tempLayer        = pcSlice->getTLayer();
697
714
  m_pcParsePic->dpbReferenceMark = pcSlice->getPicHeader()->getNonReferencePictureFlag() ? Picture::unreferenced : Picture::ShortTerm;
698
714
  m_pcParsePic->stillReferenced  = !!m_pcParsePic->dpbReferenceMark;
699
714
  m_pcParsePic->isReferencePic   = !!m_pcParsePic->dpbReferenceMark;
700
714
  m_pcParsePic->eNalUnitType     = nalu.m_nalUnitType;
701
714
  m_pcParsePic->cts              = nalu.m_cts;
702
714
  m_pcParsePic->dts              = nalu.m_dts;
703
714
  m_pcParsePic->rap              = nalu.m_rap;
704
714
  m_pcParsePic->userData         = nalu.m_userData;
705
714
  m_pcParsePic->bits            += nalu.m_bits + m_nonVCLbits;
706
714
  m_pcParsePic->layerId          = nalu.m_nuhLayerId;
707
714
  m_pcParsePic->subLayerNonReferencePictureDueToSTSA = false;
708
709
714
  m_nonVCLbits = 0;
710
711
714
  CHECK( m_pcParsePic->tempLayer != nalu.m_temporalId,
712
714
         "Currently parsed pic should have the same temporal layer as the NAL unit" );
713
714
714
  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
714
  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
714
  if( pcSlice->getNalUnitLayerId() != pcSlice->getPPS()->getLayerId() )
747
1
  {
748
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" );
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
713
  if( m_bFirstSliceInPicture )
771
713
  {
772
713
    m_pcParsePic->setDecodingOrderNumber( m_decodingOrderCounter );
773
713
    m_decodingOrderCounter++;
774
775
713
    pcSlice->getPic()->subPictures.clear();
776
713
    pcSlice->getPic()->sliceSubpicIdx.clear();
777
778
1.42k
    for( int subPicIdx = 0; subPicIdx < pcSlice->getSPS()->getNumSubPics(); subPicIdx++ )
779
713
    {
780
713
      pcSlice->getPic()->subPictures.push_back( pcSlice->getPPS()->getSubPic( subPicIdx ) );
781
713
    }
782
713
  }
783
784
713
  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
713
  m_tmpSeenPocs.clear();
791
713
  m_tmpSeenPocs.reserve( m_dpbReferencePics.size() );
792
713
  for( auto& p: m_dpbReferencePics )
793
713
  {
794
713
    CHECK( m_tmpSeenPocs.count( p->poc ) != 0, "duplicate POC in DPB" );
795
713
    if( p->dpbReferenceMark )   // we only care about reference pictures in the DPB
796
713
    {
797
713
      m_tmpSeenPocs.insert( p->poc );
798
713
    }
799
713
  }
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
713
  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
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 )
818
0
  {
819
0
    CU::checkConformanceILRP(pcSlice);
820
0
  }
821
822
713
  pcSlice->scaleRefPicList( m_pcParsePic->cs->picHeader.get() );
823
824
825
713
  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
713
  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
713
  else
927
713
  {
928
713
    pcSlice->setBiDirPred( false, -1, -1 );
929
713
  }
930
931
  //---------------
932
713
  xCheckMixedNalUnit( pcSlice, nalu );
933
934
713
  if( m_bFirstSliceInPicture )
935
713
  {
936
713
#if RECO_WHILE_PARSE
937
9.96k
    for( int ctu = 0; ctu < pcSlice->getPPS()->pcv->sizeInCtus; ctu++ )
938
9.24k
    {
939
9.24k
      m_pcParsePic->ctuParsedBarrier[ctu].lock();
940
9.24k
    }
941
942
713
#endif
943
713
    m_parseFrameList.push_back( m_pcParsePic );
944
713
  }
945
946
713
  ITT_TASKEND( itt_domain_oth, itt_handle_start );
947
948
713
  static const auto parseTask = []( int threadId, void* param )
949
713
  {
950
713
    Slice* slice     = static_cast<Slice*>( param );
951
713
    auto&  decLib    = slice->parseTaskParams.decLibParser;
952
713
    auto&  bitstream = slice->parseTaskParams.bitstream;
953
713
    auto*  pic       = slice->getPic();
954
955
713
    try
956
713
    {
957
713
      pic->startProcessingTimer();
958
959
      //  Decode a picture
960
713
      ITT_TASKSTART( itt_domain_prs, itt_handle_parse );
961
713
      decLib->m_cSliceDecoder.parseSlice( slice, &bitstream, threadId );
962
713
      ITT_TASKEND( itt_domain_prs, itt_handle_parse );
963
964
713
      pic->stopProcessingTimer();
965
966
713
      bitstream.clearFifo();
967
713
      bitstream.clearEmulationPreventionByteLocation();
968
713
    }
969
713
    catch( ... )
970
713
    {
971
710
      pic->error = true;
972
710
      pic->parseDone.setException( std::current_exception() );
973
710
#if RECO_WHILE_PARSE
974
710
      for( auto& b: pic->ctuParsedBarrier )
975
9.23k
      {
976
9.23k
        b.setException( std::current_exception() );
977
9.23k
      }
978
710
#endif
979
710
      std::rethrow_exception( std::current_exception() );
980
710
    }
981
713
    return true;
982
713
  };
983
984
713
  pcSlice->parseTaskParams.init( this, std::move( nalu.getBitstream() ) );
985
713
  pcSlice->parseDone.lock();
986
987
713
  auto expected = Picture::init;
988
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
989
990
713
  if( m_threadPool && m_threadPool->numThreads() > 0 )
991
713
  {
992
713
    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
713
    else
999
713
    {
1000
713
      m_threadPool->addBarrierTask( TP_TASK_NAME_ARG( "POC:" + std::to_string( m_pcParsePic->poc ) + " parseTask" )
1001
713
                                    parseTask, pcSlice,  &m_pcParsePic->m_divTasksCounter, &pcSlice->parseDone );
1002
713
    }
1003
713
  }
1004
0
  else
1005
0
  {
1006
0
    parseTask( 0, pcSlice );
1007
0
    pcSlice->parseDone.unlock();
1008
0
    if( m_pcParsePic->slices.size() != 1 && !m_pcParsePic->parseDone.isBlocked() && m_numDecThreads == 0 )
1009
0
    {
1010
0
      while( !m_threadPool->processTasksOnMainThread() );
1011
0
    }
1012
0
  }
1013
1014
713
  if( pcSlice->getFirstCtuRsAddrInSlice() == 0 && !m_bFirstSliceInPicture )
1015
0
  {
1016
0
    if( m_prevPOC >= m_pocRandomAccess )
1017
0
    {
1018
0
      DTRACE_UPDATE( g_trace_ctx, std::make_pair( "final", 0 ) );
1019
0
    }
1020
0
  }
1021
713
  else
1022
713
  {
1023
713
    DTRACE_UPDATE( g_trace_ctx, std::make_pair( "final", 1 ) );
1024
713
  }
1025
713
  m_prevPOC = pcSlice->getPOC();
1026
1027
713
  m_bFirstSliceInSequence[nalu.m_nuhLayerId] = false;
1028
713
  m_bFirstSliceInBitstream                   = false;
1029
1030
1031
713
  const unsigned lastCtuInSlice = pcSlice->getCtuAddrInSlice( pcSlice->getNumCtuInSlice() - 1 );
1032
713
  if( lastCtuInSlice == pcSlice->getPPS()->pcv->sizeInCtus - 1 )
1033
713
  {
1034
713
    return true;
1035
713
  }
1036
1037
0
  return false;
1038
713
}
1039
1040
void DecLibParser::xActivateParameterSets( const int layerId )
1041
714
{
1042
714
  ParameterSetManager::ActivePSs paramSets;
1043
1044
714
  if( m_bFirstSliceInPicture )
1045
714
  {
1046
714
              paramSets = m_parameterSetManager.xActivateParameterSets( m_bFirstSliceInPicture, m_apcSlicePilot, m_picHeader.get() );
1047
714
    const SPS*  sps     = paramSets.sps;
1048
714
    const PPS*  pps     = paramSets.pps;
1049
714
    const APS** alfApss = paramSets.alfAPSs->data();
1050
714
    const APS*  lmcsAPS = paramSets.lmcsAps;
1051
714
    const APS*  scalingListAPS = paramSets.scalingListAps;
1052
1053
714
    xParsePrefixSEImessages();
1054
1055
714
    CHECK( sps->getBitDepth() > 12, "High bit depth support must be enabled at compile-time in order to decode this bitstream\n" );
1056
1057
714
    applyReferencePictureListBasedMarking( m_apcSlicePilot, layerId, *pps );
1058
1059
    //  Get a new picture buffer
1060
714
    m_pcParsePic = m_picListManager.getNewPicBuffer( *sps, *pps, m_apcSlicePilot->getTLayer(), layerId, m_parameterSetManager.getVPS( sps->getVPSId() ) );
1061
714
    CHECK( std::find( m_dpbReferencePics.cbegin(), m_dpbReferencePics.cend(), m_pcParsePic ) != m_dpbReferencePics.cend(), "reused picture shouldn't be in decoded picture buffer" );
1062
714
    m_dpbReferencePics.push_back( m_pcParsePic );
1063
    // assign these fields already, because they are needed by PicListManager::getPicListRange() and Slice::applyReferencePictureSet()
1064
714
    m_pcParsePic->poc          = m_apcSlicePilot->getPOC();
1065
714
    m_pcParsePic->eNalUnitType = m_apcSlicePilot->getNalUnitType();
1066
714
    m_pcParsePic->finalInit( &m_cuChunkCache, &m_tuChunkCache, sps, pps, m_picHeader, alfApss, lmcsAPS, scalingListAPS );
1067
1068
#if !DISABLE_CONFROMANCE_CHECK
1069
    m_apcSlicePilot->checkLeadingPictureRestrictions( m_dpbReferencePics );
1070
#endif
1071
1072
714
    m_pcParsePic->dpbReferenceMark = m_apcSlicePilot->getPicHeader()->getNonReferencePictureFlag() ? Picture::unreferenced : Picture::ShortTerm;
1073
714
    m_pcParsePic->stillReferenced  = !!m_pcParsePic->dpbReferenceMark;
1074
714
    m_pcParsePic->isReferencePic   = !!m_pcParsePic->dpbReferenceMark;
1075
1076
    // Set Field/Frame coding mode
1077
714
    bool isField    = false;
1078
714
    bool isTopField = false;
1079
714
    if(!m_seiMessageList.empty())
1080
0
    {
1081
      // Check if any new Frame Field Info SEI has arrived
1082
0
      seiMessages frameFieldSEIs = SEI_internal::getSeisByType( m_seiMessageList, VVDEC_FRAME_FIELD_INFO );
1083
0
      if(!frameFieldSEIs.empty())
1084
0
      {
1085
0
        const vvdecSEIFrameFieldInfo* ff = (vvdecSEIFrameFieldInfo*) frameFieldSEIs.front()->payload;
1086
0
        isField    = ff->fieldPicFlag;
1087
0
        isTopField = isField && (!ff->bottomFieldFlag);
1088
0
      }
1089
0
    }
1090
714
    m_pcParsePic->fieldPic = isField;
1091
714
    m_pcParsePic->topField = isTopField;
1092
1093
    // transfer any SEI messages that have been received to the picture
1094
714
    m_pcParsePic->seiMessageList = m_seiMessageList;
1095
714
    m_seiMessageList.clear();
1096
1097
714
    m_apcSlicePilot->setPicHeader( m_picHeader.get() );
1098
714
  }
1099
0
  else
1100
0
  {
1101
0
    paramSets = m_parameterSetManager.xActivateParameterSets( m_bFirstSliceInPicture, m_apcSlicePilot, m_picHeader.get() );
1102
0
    m_apcSlicePilot->setAlfApss( paramSets.alfAPSs->data() );
1103
1104
0
    for( int i = 0; i < ALF_CTB_MAX_NUM_APS; ++i )
1105
0
    {
1106
0
      m_pcParsePic->cs->alfApss[i] = paramSets.alfAPSs->data()[i] ? paramSets.alfAPSs->data()[i]->getSharedPtr() : nullptr;
1107
0
    }
1108
0
  }
1109
1110
  // make the slice-pilot a real slice, and set up the slice-pilot for the next slice
1111
714
  Slice* pSlice = m_pcParsePic->allocateNewSlice( &m_apcSlicePilot );
1112
714
  CHECK_FATAL( m_pcParsePic->slices.size() != ( m_uiSliceSegmentIdx + 1 ), "Invalid number of slices" );
1113
1114
714
  const VPS* vps = pSlice->getVPS_nothrow();
1115
714
  const SPS* sps = pSlice->getSPS();
1116
714
  const PPS* pps = pSlice->getPPS();
1117
1118
714
  if( !m_bFirstSliceInPicture )
1119
0
  {
1120
0
    const APS*  lmcsAPS = pSlice->getPicHeader()->getLmcsAPS().get();
1121
1122
    // check that the current active PPS has not changed...
1123
0
    CHECK( sps->getChangedFlag(), "Error - a new SPS has been decoded while processing a picture" );
1124
0
    CHECK( pps->getChangedFlag(), "Error - a new PPS has been decoded while processing a picture" );
1125
0
    for( int i = 0; i < ALF_CTB_MAX_NUM_APS; i++ )
1126
0
    {
1127
0
      const APS* aps = m_parameterSetManager.getAPS_nothrow( i, ALF_APS );
1128
0
      CHECK( aps && aps->getChangedFlag(), "Error - a new APS has been decoded while processing a picture" );
1129
0
    }
1130
0
    CHECK( lmcsAPS && lmcsAPS->getChangedFlag(), "Error - a new LMCS APS has been decoded while processing a picture" );
1131
1132
0
    xParsePrefixSEImessages();
1133
1134
    // Check if any new SEI has arrived
1135
0
    if( !m_seiMessageList.empty() )
1136
0
    {
1137
      // Currently only decoding Unit SEI message occurring between VCL NALUs copied
1138
0
      seiMessages& picSEI = m_pcParsePic->seiMessageList;
1139
0
      seiMessages decodingUnitInfos = SEI_internal::extractSeisByType( m_seiMessageList, VVDEC_DECODING_UNIT_INFO );
1140
0
      picSEI.insert( picSEI.end(), decodingUnitInfos.begin(), decodingUnitInfos.end() );
1141
0
      SEI_internal::deleteSEIs   ( m_seiMessageList );
1142
0
    }
1143
0
  }
1144
1145
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 " );
1146
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." );
1147
714
  CHECK( !sps->getUseWPBiPred() && pps->getWPBiPred(),
1148
714
         "When sps_weighted_bipred_flag is equal to 0, the value of pps_weighted_bipred_flag shall be equal to 0." );
1149
1150
714
  CHECK( !sps->getResChangeInClvsEnabledFlag() && pps->getPicWidthInLumaSamples() != sps->getMaxPicWidthInLumaSamples(),
1151
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." );
1152
714
  CHECK( !sps->getResChangeInClvsEnabledFlag() && pps->getPicHeightInLumaSamples() != sps->getMaxPicHeightInLumaSamples(),
1153
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." );
1154
714
  CHECK( sps->getResChangeInClvsEnabledFlag() && sps->getSubPicInfoPresentFlag() != 0,
1155
714
         "When res_change_in_clvs_allowed_flag is equal to 1, the value of subpic_info_present_flag shall be equal to 0." );
1156
714
  CHECK( sps->getResChangeInClvsEnabledFlag() && sps->getVirtualBoundariesEnabledFlag(),
1157
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" );
1158
714
  if( vps && vps->m_numOutputLayersInOls[vps->m_iTargetLayer] > 1 )
1159
0
  {
1160
0
    CHECK( sps->getMaxPicWidthInLumaSamples() > vps->getOlsDpbPicSize( vps->m_iTargetLayer ).width,
1161
0
           "pic_width_max_in_luma_samples shall be less than or equal to the value of ols_dpb_pic_width[ i ]" );
1162
0
    CHECK( sps->getMaxPicHeightInLumaSamples() > vps->getOlsDpbPicSize( vps->m_iTargetLayer ).height,
1163
0
           "pic_height_max_in_luma_samples shall be less than or equal to the value of ols_dpb_pic_height[ i ]" );
1164
0
  }
1165
1166
714
  CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getOneTilePerPicConstraintFlag() && pps->getNumTiles() != 1,
1167
714
         "When one_tile_per_pic_constraint_flag is equal to 1, each picture shall contain only one tile" );
1168
714
  CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getOneSlicePerPicConstraintFlag() && pps->getRectSliceFlag() && pps->getNumSlicesInPic() != 1,
1169
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" );
1170
714
  CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getNoRprConstraintFlag() && sps->getRprEnabledFlag(),
1171
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" );
1172
714
  CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getNoResChangeInClvsConstraintFlag() && sps->getResChangeInClvsEnabledFlag(),
1173
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" );
1174
714
  CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getNoIdrRplConstraintFlag() && sps->getIDRRefParamListPresent(),
1175
714
         "When gci_no_idr_rpl_constraint_flag equal to 1 , the value of sps_idr_rpl_present_flag shall be equal to 0" );
1176
714
  CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getNoMixedNaluTypesInPicConstraintFlag() && pps->getMixedNaluTypesInPicFlag(),
1177
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" );
1178
714
  CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getNoRectSliceConstraintFlag() && pps->getRectSliceFlag(),
1179
714
         "When gci_no_rectangular_slice_constraint_flag equal to 1, the value of pps_rect_slice_flag shall be equal to 0" );
1180
714
  CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getOneSlicePerSubpicConstraintFlag() && !pps->getSingleSlicePerSubPicFlag(),
1181
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" );
1182
714
  CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getNoSubpicInfoConstraintFlag() && sps->getSubPicInfoPresentFlag(),
1183
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" );
1184
1185
714
  if( sps->getProfileTierLevel()->getConstraintInfo()->getNoMttConstraintFlag() )
1186
0
  {
1187
0
    CHECK( sps->getMaxMTTHierarchyDepth() || sps->getMaxMTTHierarchyDepthI() || sps->getMaxMTTHierarchyDepthIChroma(),
1188
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"
1189
0
           " and sps_max_mtt_hierarchy_depth_intra_slice_chroma shall be equal to 0" );
1190
0
  }
1191
714
  if( sps->getProfileTierLevel()->getConstraintInfo()->getNoWeightedPredictionConstraintFlag() )
1192
0
  {
1193
0
    CHECK( sps->getUseWP() || sps->getUseWPBiPred(),
1194
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" );
1195
0
  }
1196
1197
714
  CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getNoChromaQpOffsetConstraintFlag() && pps->getCuChromaQpOffsetEnabledFlag(),
1198
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" );
1199
1200
714
  CHECK( sps->getCTUSize() > ( 1 << sps->getProfileTierLevel()->getConstraintInfo()->getMaxLog2CtuSizeConstraintIdc() ),
1201
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" );
1202
714
  CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getNoLumaTransformSize64ConstraintFlag() && sps->getLog2MaxTbSize() != 5,
1203
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" );
1204
1205
#if 0
1206
  if( vps && vps->getMaxLayers() > 1 )
1207
  {
1208
    // TODO: fix MT static maps
1209
    static std::unordered_map<int, int> m_layerChromaFormat;
1210
    static std::unordered_map<int, int> m_layerBitDepth;
1211
1212
    int curLayerIdx          = vps->getGeneralLayerIdx(layerId);
1213
    int curLayerChromaFormat = sps->getChromaFormatIdc();
1214
    int curLayerBitDepth     = sps->getBitDepth();
1215
1216
    if( pSlice->isClvssPu() && m_bFirstSliceInPicture )
1217
    {
1218
      m_layerChromaFormat[curLayerIdx] = curLayerChromaFormat;
1219
      m_layerBitDepth    [curLayerIdx] = curLayerBitDepth;
1220
    }
1221
    else
1222
    {
1223
      CHECK( m_layerChromaFormat[curLayerIdx] != curLayerChromaFormat, "Different chroma format in the same layer." );
1224
      CHECK( m_layerBitDepth    [curLayerIdx] != curLayerBitDepth, "Different bit-depth in the same layer." );
1225
    }
1226
1227
    for( int i = 0; i < curLayerIdx; i++ )
1228
    {
1229
      if( vps->getDirectRefLayerFlag( curLayerIdx, i ) )
1230
      {
1231
        int refLayerChromaFormat = m_layerChromaFormat[i];
1232
        CHECK( curLayerChromaFormat != refLayerChromaFormat, "The chroma formats of the current layer and the reference layer are different" );
1233
        int refLayerBitDepth = m_layerBitDepth[i];
1234
        CHECK( curLayerBitDepth != refLayerBitDepth, "The bit-depth of the current layer and the reference layer are different" );
1235
      }
1236
    }
1237
  }
1238
#endif
1239
1240
714
  const int minCuSize = 1 << sps->getLog2MinCodingBlockSize();
1241
714
  CHECK( ( pps->getPicWidthInLumaSamples()  % ( std::max( 8, minCuSize) ) ) != 0, "Coded frame width must be a multiple of Max(8, the minimum unit size)" );
1242
714
  CHECK( ( pps->getPicHeightInLumaSamples() % ( std::max( 8, minCuSize) ) ) != 0, "Coded frame height must be a multiple of Max(8, the minimum unit size)" );
1243
1244
714
  if( sps->getCTUSize() + 2 * ( 1 << sps->getLog2MinCodingBlockSize() ) > pps->getPicWidthInLumaSamples() )
1245
145
  {
1246
145
    CHECK( pps->getUseWrapAround(),
1247
145
           "Wraparound shall be disabled when the value of ( CtbSizeY / MinCbSizeY + 1) is greater than or equal to"
1248
145
           " ( pic_width_in_luma_samples / MinCbSizeY - 1 )" );
1249
145
  }
1250
1251
714
  if( pSlice->getPicHeader()->getGdrOrIrapPicFlag() && !pSlice->getPicHeader()->getGdrPicFlag()
1252
714
      && ( !vps || vps->getIndependentLayerFlag( vps->getGeneralLayerIdx( layerId ) ) ) )
1253
714
  {
1254
714
    CHECK( pSlice->getPicHeader()->getPicInterSliceAllowedFlag(),
1255
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 ] ] "
1256
714
           "is equal to 1, ph_inter_slice_allowed_flag shall be equal to 0" );
1257
714
  }
1258
1259
714
  if( sps->getVPSId() && vps && vps->m_numLayersInOls[vps->m_iTargetLayer] == 1 )
1260
0
  {
1261
0
    CHECK( !sps->getPtlDpbHrdParamsPresentFlag(),
1262
0
           "When sps_video_parameter_set_id is greater than 0 and there is an OLS that contains only one layer"
1263
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" );
1264
0
  }
1265
1266
714
  ProfileLevelTierFeatures ptlFeature;
1267
714
  ptlFeature.extractPTLInformation(*sps);
1268
1269
714
  const LevelTierFeatures* ltFeature = ptlFeature.getLevelTierFeatures();
1270
714
  const ProfileFeatures*   pFeature  = ptlFeature.getProfileFeatures();
1271
1272
714
  CHECK( ltFeature && pps->getNumTileColumns() > ltFeature->maxTileCols, "Num tile columns signaled in PPS exceed level limits" );
1273
714
  CHECK( ltFeature && pps->getNumTiles() > ltFeature->maxTilesPerAu, "Num tiles signaled in PPS exceed level limits" );
1274
714
  CHECK( pFeature && sps->getBitDepth() > pFeature->maxBitDepth, "Bit depth exceed profile limit" );
1275
714
  CHECK( pFeature && sps->getChromaFormatIdc() > pFeature->maxChromaFormat, "Chroma format exceed profile limit" );
1276
714
}
1277
1278
void DecLibParser::prepareUnavailablePicture( bool isLost, const PPS* pps, int iUnavailablePoc, const int layerId, const bool longTermFlag, const int temporalId )
1279
0
{
1280
0
  if( isLost )
1281
0
  {
1282
0
    CHECK( !( m_errHandlingFlags & ERR_HANDLING_TRY_CONTINUE ), "missing reference picture poc: " << iUnavailablePoc );
1283
1284
0
    if( !m_picListManager.getBackPic() )
1285
0
    {
1286
0
      THROW_RECOVERABLE( "no pictures yet." );
1287
0
      return;
1288
0
    }
1289
0
    msg( WARNING, "inserting lost poc : %d\n", iUnavailablePoc );
1290
0
  }
1291
0
  else
1292
0
  {
1293
0
    msg( INFO, "inserting unavailable poc : %d\n", iUnavailablePoc );
1294
0
  }
1295
0
  Picture* cFillPic = m_picListManager.getNewPicBuffer( *m_parameterSetManager.getFirstSPS(), *m_parameterSetManager.getFirstPPS(), 0, layerId, m_parameterSetManager.getVPS( m_parameterSetManager.getFirstSPS()->getVPSId() ) );
1296
0
  CHECK( std::find( m_dpbReferencePics.cbegin(), m_dpbReferencePics.cend(), cFillPic ) != m_dpbReferencePics.cend(), "reused picture shouldn't be in decoded picture buffer" );
1297
0
  m_dpbReferencePics.push_back( cFillPic );
1298
0
  const APS* nullAlfApss[ALF_CTB_MAX_NUM_APS] = { nullptr, };
1299
0
  cFillPic->finalInit( &m_cuChunkCache, &m_tuChunkCache, m_parameterSetManager.getFirstSPS(), m_parameterSetManager.getFirstPPS(), m_picHeader, nullAlfApss, nullptr, nullptr, false );
1300
0
  cFillPic->cs->initStructData();
1301
1302
0
  CHECK_FATAL( !cFillPic->slices.empty(), "fill pic should not contain slices, already." );
1303
0
  cFillPic->allocateNewSlice();
1304
0
  cFillPic->slices[0]->initSlice();
1305
0
  cFillPic->slices[0]->setPOC( iUnavailablePoc );
1306
0
  cFillPic->slices[0]->setTLayer( temporalId );
1307
0
  cFillPic->slices[0]->setNalUnitLayerId( layerId );
1308
1309
  // picture header is not derived for generated reference picture
1310
0
  cFillPic->slices[0]->setPicHeader( nullptr );
1311
0
  cFillPic->slices[0]->setPPS( pps );
1312
1313
0
  cFillPic->dpbReferenceMark        = longTermFlag ? Picture::LongTerm : Picture::ShortTerm;
1314
0
  cFillPic->stillReferenced         = true;
1315
0
  cFillPic->isReferencePic          = true;
1316
0
  cFillPic->poc                     = iUnavailablePoc;
1317
0
  cFillPic->neededForOutput         = false;
1318
0
  cFillPic->tempLayer               = temporalId;
1319
0
  cFillPic->nonReferencePictureFlag = false;
1320
0
  cFillPic->wasLost                 = isLost;
1321
1322
0
  if( cFillPic->slices[0]->getTLayer() == 0 &&
1323
0
      cFillPic->slices[0]->getNalUnitType() != NAL_UNIT_CODED_SLICE_RASL &&
1324
0
      cFillPic->slices[0]->getNalUnitType() != NAL_UNIT_CODED_SLICE_RADL )
1325
0
  {
1326
0
    m_prevTid0POC = cFillPic->slices[0]->getPOC();
1327
0
  }
1328
1329
0
  cFillPic->subPictures.clear();
1330
0
  cFillPic->sliceSubpicIdx.clear();
1331
1332
0
  for( int subPicIdx = 0; subPicIdx < pps->getNumSubPics(); subPicIdx++ )
1333
0
  {
1334
0
    cFillPic->subPictures.push_back( pps->getSubPic( subPicIdx ) );
1335
0
  }
1336
1337
0
  cFillPic->parseDone.unlock();
1338
1339
#if 0
1340
// NOT YET IMPLEMENTED
1341
  if( isLost && ( m_errHandlingFlags & ERR_HANDLING_COPY_CLOSEST ) )
1342
  {
1343
    // this will be filled in later, when closer pictures might have been reconstructed.
1344
1345
    cFillPic->progress = Picture::parsed;
1346
    m_parseFrameList.push_back( cFillPic );
1347
    return;
1348
  }
1349
#endif
1350
1351
0
  cFillPic->fillGrey( m_parameterSetManager.getFirstSPS() );
1352
1353
0
  if( m_pocRandomAccess == MAX_INT )
1354
0
  {
1355
0
    m_pocRandomAccess = iUnavailablePoc;
1356
0
  }
1357
0
}
1358
1359
#if 0
1360
// NOT YET IMPLEMENTED
1361
void DecLibParser::fillMissingPicBuf( Picture* pcPic, bool copyClosest )
1362
{
1363
  if( copyClosest )
1364
  {
1365
    CHECK_FATAL( pcPic->progress != Picture::parsed, "filled in picture should have been marked as parsed" );
1366
    CHECK_FATAL( pcPic->parseDone.isBlocked(), "parsed barrier should be unlocked" );
1367
1368
    auto closestPic = m_picListManager.findClosestPic( pcPic->poc );
1369
    if( closestPic )
1370
    {
1371
      CHECK_FATAL( closestPic->progress < Picture::reconstructed, "closest Picture is not yet reconstructed" )
1372
      // the next not-lost picture in the parseFrameList should be the one, that referenced this picture
1373
      auto referencedBy = std::find_if( m_parseFrameList.begin(), m_parseFrameList.end(), []( Picture* p ) { return !p->wasLost && !p->error; } );
1374
      msg( INFO, "copying picture %d to %d (%d)\n", closestPic->getPOC(), pcPic->poc, ( referencedBy != m_parseFrameList.end() ) ? ( *referencedBy )->poc : -1 );
1375
1376
      pcPic->getRecoBuf().copyFrom( closestPic->getRecoBuf() );
1377
1378
      pcPic->slices[0]->copySliceInfo( closestPic->slices[0] );
1379
      pcPic->slices[0]->setPOC( pcPic->poc );
1380
    }
1381
1382
    // currently we don't output filled-in reference pictures
1383
    // pcPic->neededForOutput = true;
1384
  }
1385
  else
1386
  {
1387
    pcPic->fillGrey( pcPic->cs->sps.get() );
1388
  }
1389
1390
  pcPic->progress = Picture::reconstructed;
1391
  pcPic->reconDone.unlock();
1392
}
1393
#endif
1394
1395
1396
// Function for applying picture marking based on the Reference Picture List
1397
void DecLibParser::applyReferencePictureListBasedMarking( Slice* currSlice, const int layerId, const PPS& pps )
1398
714
{
1399
  //  checkLeadingPictureRestrictions(rcListPic, pps);
1400
1401
  // mark long-term reference pictures in List0
1402
714
  for( const auto l: { REF_PIC_LIST_0, REF_PIC_LIST_1 } )
1403
1.42k
  {
1404
1.42k
    const ReferencePictureList* rpl = currSlice->getRPL( l );
1405
1406
1.42k
    for( int i = 0; i < rpl->getNumRefEntries(); i++ )
1407
0
    {
1408
0
      if( !rpl->isRefPicLongterm( i ) || rpl->isInterLayerRefPic( i ) )
1409
0
      {
1410
0
        continue;
1411
0
      }
1412
1413
0
      Picture* availableST = nullptr;
1414
0
      for( Picture* pic: m_dpbReferencePics )
1415
0
      {
1416
0
        if( !pic->dpbReferenceMark )
1417
0
        {
1418
0
          continue;
1419
0
        }
1420
1421
0
        const int bitsForPoc = pic->cs->sps->getBitsForPOC();
1422
0
        const int curPoc     = pic->getPOC();
1423
0
        const int ltRefPoc   = rpl->calcLTRefPOC( currSlice->getPOC(), bitsForPoc, i );
1424
0
        if( pic->dpbReferenceMark == Picture::LongTerm && isLTPocEqual( curPoc, ltRefPoc, bitsForPoc, rpl->getDeltaPocMSBPresentFlag( i ) ) )
1425
0
        {
1426
0
          break;
1427
0
        }
1428
1429
        // if there was no such long-term check the short terms
1430
0
        if( pic->dpbReferenceMark == Picture::ShortTerm && isLTPocEqual( curPoc, ltRefPoc, bitsForPoc, rpl->getDeltaPocMSBPresentFlag( i ) ) )
1431
0
        {
1432
0
          availableST = pic;
1433
          // but don't break here, because we might still find a LT
1434
0
        }
1435
0
      }
1436
1437
      // the found picture was not yet marked as long term, so we mark it here
1438
0
      if ( availableST )
1439
0
      {
1440
0
        availableST->dpbReferenceMark = Picture::LongTerm;
1441
0
      }
1442
0
    }
1443
1.42k
  }
1444
1445
714
  if( currSlice->isIDR() && !pps.getMixedNaluTypesInPicFlag() )
1446
714
  {
1447
714
    for( Picture* pic: m_dpbReferencePics )
1448
0
    {
1449
0
      pic->dpbReferenceMark = Picture::unreferenced;
1450
0
    }
1451
1452
    // ignore neededForOutput flag here, because we only care about reference pictures in the DPB
1453
714
    m_dpbReferencePics.remove_if( []( Picture* pic ) { return !pic->dpbReferenceMark; } );
1454
714
    return;
1455
714
  }
1456
1457
  // loop through all pictures in the reference picture buffer
1458
0
  for( Picture* pic: m_dpbReferencePics )
1459
0
  {
1460
0
    if( !pic->dpbReferenceMark )
1461
0
    {
1462
0
      continue;
1463
0
    }
1464
1465
0
    bool isReference = false;
1466
1467
0
    for( const auto l: { REF_PIC_LIST_0, REF_PIC_LIST_1 } )
1468
0
    {
1469
0
      if( currSlice->getRPL( l )->findInRefPicList( pic, currSlice->getPOC(), layerId ) )
1470
0
      {
1471
0
        isReference = true;
1472
0
        break;
1473
0
      }
1474
0
    }
1475
1476
    // mark the picture as "unused for reference" if it is not in
1477
    // the Reference Picture List
1478
0
    if( !isReference && pic->poc != currSlice->getPOC() && pic->layerId == layerId )
1479
0
    {
1480
0
      pic->dpbReferenceMark = Picture::unreferenced;
1481
0
    }
1482
1483
    // // sanity checks
1484
    // if( pic->referenced )
1485
    // {
1486
    //   // check that pictures of higher temporal layers are not used
1487
    //   CHECK_FATAL( pic->usedByCurr && pic->temporalId > this->getTLayer(), "Invalid state" );
1488
    // }
1489
0
  }
1490
1491
  // ignore neededForOutput flag here, because we only care about reference pictures in the DPB
1492
0
  m_dpbReferencePics.remove_if( []( Picture* pic ) { return !pic->dpbReferenceMark; } );
1493
0
}
1494
1495
void DecLibParser::xParsePrefixSEImessages()
1496
714
{
1497
714
  while( !m_prefixSEINALUs.empty() )
1498
0
  {
1499
0
    InputNALUnit& nalu = m_prefixSEINALUs.front();
1500
0
    const SPS *sps = m_parameterSetManager.getActiveSPS();
1501
0
    const VPS *vps = m_parameterSetManager.getVPS(sps->getVPSId());
1502
0
    m_seiReader.parseSEImessage( &(nalu.getBitstream()), m_seiMessageList, nalu.m_nalUnitType, nalu.m_nuhLayerId, nalu.m_temporalId, vps, sps, m_HRD, m_pDecodedSEIOutputStream );
1503
0
    m_prefixSEINALUs.pop_front();
1504
0
  }
1505
714
}
1506
1507
void DecLibParser::xParsePrefixSEIsForUnknownVCLNal()
1508
5
{
1509
5
  while (!m_prefixSEINALUs.empty())
1510
0
  {
1511
    // do nothing?
1512
0
    msg( VERBOSE, "Discarding Prefix SEI associated with unknown VCL NAL unit.\n");
1513
0
    m_prefixSEINALUs.pop_front();
1514
0
  }
1515
  // TODO: discard following suffix SEIs as well?
1516
5
}
1517
1518
void DecLibParser::xDecodePicHeader( InputNALUnit& nalu )
1519
0
{
1520
0
  m_HLSReader.setBitstream( &nalu.getBitstream() );
1521
0
  m_picHeader = std::make_shared<PicHeader>();
1522
0
  m_HLSReader.parsePictureHeader( m_picHeader.get(), &m_parameterSetManager, true );
1523
0
}
1524
1525
void DecLibParser::xDecodeVPS( InputNALUnit& nalu )
1526
2
{
1527
  // We don't parse the VPS, because the needed bounds checks in parseVPS() are not yet implemented, and we don't process it anyways
1528
#if 0
1529
  std::unique_ptr<VPS> vps( new VPS() );
1530
  m_HLSReader.setBitstream( &nalu.getBitstream() );
1531
  m_HLSReader.parseVPS( vps.get() );
1532
  m_parameterSetManager.storeVPS( vps.release(), nalu.getBitstream().getFifo() );
1533
#endif
1534
2
}
1535
1536
void DecLibParser::xDecodeDCI( InputNALUnit& nalu )
1537
9
{
1538
9
  m_HLSReader.setBitstream(&nalu.getBitstream());
1539
1540
9
  CHECK(nalu.m_temporalId, "The value of TemporalId of DCI NAL units shall be equal to 0");
1541
9
  if( !m_dci )
1542
9
  {
1543
9
    m_dci = new DCI;
1544
9
    m_HLSReader.parseDCI( m_dci );
1545
9
  }
1546
0
  else
1547
0
  {
1548
0
    DCI dupDCI;
1549
0
    m_HLSReader.parseDCI( &dupDCI );
1550
0
    CHECK( !m_dci->IsIndenticalDCI( dupDCI ), "Two signaled DCIs are different");
1551
0
  }
1552
9
}
1553
1554
void DecLibParser::xDecodeSPS( InputNALUnit& nalu )
1555
905
{
1556
905
  std::unique_ptr<SPS> sps( new SPS() );
1557
905
  m_HLSReader.setBitstream( &nalu.getBitstream() );
1558
905
  m_HLSReader.parseSPS( sps.get(), &m_parameterSetManager );
1559
905
  sps->setLayerId( nalu.m_nuhLayerId );
1560
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
1561
905
  m_parameterSetManager.storeSPS( sps.release(), nalu.getBitstream().getFifo() );
1562
905
}
1563
1564
void DecLibParser::xDecodePPS( InputNALUnit& nalu )
1565
817
{
1566
817
  std::unique_ptr<PPS> pps( new PPS() );
1567
817
  m_HLSReader.setBitstream( &nalu.getBitstream() );
1568
817
  m_HLSReader.parsePPS( pps.get(), &m_parameterSetManager );
1569
817
  pps->setLayerId( nalu.m_nuhLayerId );
1570
817
  m_parameterSetManager.storePPS( pps.release(), nalu.getBitstream().getFifo() );
1571
817
}
1572
1573
void DecLibParser::xDecodeAPS( InputNALUnit& nalu )
1574
795
{
1575
795
  std::unique_ptr<APS> aps( new APS() );
1576
795
  m_HLSReader.setBitstream( &nalu.getBitstream() );
1577
795
  if( !m_HLSReader.parseAPS( aps.get() ) )
1578
0
  {   // ignore unsupported APS types
1579
0
    return;
1580
0
  }
1581
795
  aps->setTemporalId( nalu.m_temporalId );
1582
795
  aps->setLayerId( nalu.m_nuhLayerId );
1583
795
  aps->setHasPrefixNalUnitType( nalu.m_nalUnitType == NAL_UNIT_PREFIX_APS );
1584
795
  m_parameterSetManager.storeAPS( aps.release(), nalu.getBitstream().getFifo() );
1585
795
}
1586
1587
void DecLibParser::xUpdatePreviousTid0POC(Slice * pSlice)
1588
714
{
1589
714
  if( pSlice->getTLayer() == 0 && pSlice->getNalUnitType() != NAL_UNIT_CODED_SLICE_RASL && pSlice->getNalUnitType() != NAL_UNIT_CODED_SLICE_RADL
1590
714
      && !pSlice->getPicHeader()->getNonReferencePictureFlag() )
1591
714
  {
1592
714
    m_prevTid0POC = pSlice->getPOC();
1593
714
  }
1594
714
}
1595
1596
1597
void DecLibParser::checkNoOutputPriorPics()
1598
0
{
1599
0
  if( !m_isNoOutputPriorPics )
1600
0
  {
1601
0
    return;
1602
0
  }
1603
1604
0
  for( auto& pcPicTmp: m_dpbReferencePics )
1605
0
  {
1606
0
    if( pcPicTmp->progress >= Picture::reconstructed && pcPicTmp->getPOC() < m_lastPOCNoOutputPriorPics )
1607
0
    {
1608
0
      pcPicTmp->neededForOutput = false;
1609
0
    }
1610
0
  }
1611
0
}
1612
1613
/** 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.
1614
 *  All pictures prior to the random access point indicated by the counter iSkipFrame are skipped.
1615
 *  It also checks the type of Nal unit type at the random access point.
1616
 *  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.
1617
 *  If the random access point is IDR all pictures after the random access point are decoded.
1618
 *  If the random access point is none of the above, a warning is issues, and decoding of pictures with POC
1619
 *  equal to or greater than the random access point POC is attempted. For non IDR/CRA/BLA random
1620
 *  access point there is no guarantee that the decoder will not crash.
1621
 */
1622
bool DecLibParser::isRandomAccessSkipPicture()
1623
714
{
1624
714
  if( m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP )
1625
714
  {
1626
714
    m_pocRandomAccess = -MAX_INT;   // no need to skip the reordered pictures in IDR, they are decodable.
1627
714
  }
1628
0
  else if( m_pocRandomAccess == MAX_INT )   // start of random access point, m_pocRandomAccess has not been set yet.
1629
0
  {
1630
0
#if GDR_ADJ
1631
0
    if( m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR )
1632
#else
1633
    if( m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA )
1634
#endif
1635
0
    {
1636
      // set the POC random access since we need to skip the reordered pictures in the case of CRA/CRANT/BLA/BLANT.
1637
0
      m_pocRandomAccess = m_apcSlicePilot->getPOC();
1638
0
    }
1639
0
    else
1640
0
    {
1641
0
      if( !m_warningMessageSkipPicture )
1642
0
      {
1643
0
        msg( WARNING, "Warning: this is not a valid random access point and the data is discarded until the first CRA picture\n" );
1644
0
        m_warningMessageSkipPicture = true;
1645
0
      }
1646
0
      return true;
1647
0
    }
1648
0
  }
1649
  // skip the reordered pictures, if necessary
1650
0
  else if( m_apcSlicePilot->getPOC() < m_pocRandomAccess && ( m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_RASL ) )
1651
0
  {
1652
0
    return true;
1653
0
  }
1654
  // if we reach here, then the picture is not skipped.
1655
714
  return false;
1656
714
}
1657
1658
void DecLibParser::xCheckMixedNalUnit( Slice* pcSlice, const InputNALUnit& nalu )
1659
713
{
1660
713
  if( pcSlice->getPPS()->getMixedNaluTypesInPicFlag() )
1661
0
  {
1662
0
    CHECK(pcSlice->getPPS()->getNumSlicesInPic() < 2, "mixed nal unit type picture, but with less than 2 slices");
1663
1664
0
    CHECK( pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR, "picture with mixed NAL unit type cannot have GDR slice");
1665
1666
    //Check that if current slice is IRAP type, the other type of NAL can only be TRAIL_NUT
1667
0
    if( pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL
1668
0
        || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP
1669
0
        || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA )
1670
0
    {
1671
0
      for( int i = 0; i < m_uiSliceSegmentIdx; i++ )
1672
0
      {
1673
0
        Slice* preSlice = m_pcParsePic->slices[i];
1674
0
        CHECK( pcSlice->getNalUnitType() != preSlice->getNalUnitType()
1675
0
                 && preSlice->getNalUnitType() != NAL_UNIT_CODED_SLICE_TRAIL,
1676
0
               "In a mixed NAL unt type picture, an IRAP slice can be mixed with Trail slice(s) only" );
1677
0
      }
1678
0
    }
1679
1680
    // if this is the last slice of the picture, check whether that there are at least two different NAL unit types in the picture
1681
0
    if( pcSlice->getPPS()->getNumSlicesInPic() == (m_uiSliceSegmentIdx + 1) )
1682
0
    {
1683
0
      bool hasDiffTypes = false;
1684
0
      for( int i = 1; !hasDiffTypes && i <= m_uiSliceSegmentIdx; i++ )
1685
0
      {
1686
0
        Slice* slice1 = m_pcParsePic->slices[i-1];
1687
0
        Slice* slice2 = m_pcParsePic->slices[i];
1688
0
        if( slice1->getNalUnitType() != slice2->getNalUnitType())
1689
0
        {
1690
0
          hasDiffTypes = true;
1691
0
        }
1692
0
      }
1693
0
      CHECK( !hasDiffTypes, "VCL NAL units of the picture shall have two or more different nal_unit_type values");
1694
0
    }
1695
0
  }
1696
713
  else   // all slices shall have the same nal unit type
1697
713
  {
1698
713
    bool sameNalUnitType = true;
1699
713
    for( int i = 0; i < m_uiSliceSegmentIdx; i++ )
1700
0
    {
1701
0
      Slice* PreSlice = m_pcParsePic->slices[i];
1702
0
      if( PreSlice->getNalUnitType() != pcSlice->getNalUnitType() )
1703
0
      {
1704
0
        sameNalUnitType = false;
1705
0
      }
1706
0
    }
1707
713
    CHECK( !sameNalUnitType, "mixed_nalu_types_in_pic_flag is zero, but have different nal unit types" );
1708
713
  }
1709
713
}
1710
1711
void DecLibParser::waitForPicsToFinishParsing( const std::vector<Picture*>& refPics )
1712
0
{
1713
0
  for( Picture* pic: refPics )
1714
0
  {
1715
0
    if( m_threadPool->numThreads() == 0 )
1716
0
    {
1717
0
      m_threadPool->processTasksOnMainThread();
1718
0
    }
1719
0
    try
1720
0
    {
1721
0
      pic->parseDone.wait();
1722
0
    }
1723
0
    catch( ... )
1724
0
    {
1725
0
      pic->waitForAllTasks();
1726
0
    }
1727
0
  }
1728
0
}
1729
1730
}   // namespace vvdec