Coverage Report

Created: 2026-05-30 06:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/vvdec/source/Lib/DecoderLib/DecLibParser.cpp
Line
Count
Source
1
/* -----------------------------------------------------------------------------
2
The copyright in this software is being made available under the Clear BSD
3
License, included below. No patent rights, trademark rights and/or 
4
other Intellectual Property Rights other than the copyrights concerning 
5
the Software are granted under this license.
6
7
The Clear BSD License
8
9
Copyright (c) 2018-2026, Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. & The VVdeC Authors.
10
All rights reserved.
11
12
Redistribution and use in source and binary forms, with or without modification,
13
are permitted (subject to the limitations in the disclaimer below) provided that
14
the following conditions are met:
15
16
     * Redistributions of source code must retain the above copyright notice,
17
     this list of conditions and the following disclaimer.
18
19
     * Redistributions in binary form must reproduce the above copyright
20
     notice, this list of conditions and the following disclaimer in the
21
     documentation and/or other materials provided with the distribution.
22
23
     * Neither the name of the copyright holder nor the names of its
24
     contributors may be used to endorse or promote products derived from this
25
     software without specific prior written permission.
26
27
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
28
THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
29
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
31
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
32
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
33
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
34
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
35
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
36
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38
POSSIBILITY OF SUCH DAMAGE.
39
40
41
------------------------------------------------------------------------------------------- */
42
43
#include "DecLib.h"
44
#include "DecLibParser.h"
45
#include "NALread.h"
46
47
#include "CommonLib/dtrace_next.h"
48
49
#include "UnitTools.h"
50
#include "Utilities/ThreadPool.h"
51
52
#include <unordered_map>
53
#include <utility>
54
55
namespace vvdec
56
{
57
template<class TArr, class TElem = decltype( std::declval<TArr>()[0] )>
58
void fill_array( TArr& array, const TElem& val )
59
0
{
60
0
  std::fill( std::begin( array ), std::end( array ), val );
61
0
}
Unexecuted instantiation: void vvdec::fill_array<vvdec::NalUnitType [64], vvdec::NalUnitType>(vvdec::NalUnitType (&) [64], vvdec::NalUnitType const&)
Unexecuted instantiation: void vvdec::fill_array<int [64], int>(int (&) [64], int const&)
Unexecuted instantiation: void vvdec::fill_array<bool [64], bool>(bool (&) [64], bool const&)
62
63
#ifdef TRACE_ENABLE_ITT
64
extern __itt_domain* itt_domain_prs;
65
extern __itt_domain* itt_domain_oth;
66
67
extern __itt_string_handle* itt_handle_parse;
68
extern __itt_string_handle* itt_handle_start;
69
70
#define ITT_TASKSTART( d, t ) __itt_task_begin( ( d ), __itt_null, __itt_null, ( t ) )
71
#define ITT_TASKEND( d, t )   __itt_task_end  ( ( d ) )
72
#else
73
#define ITT_TASKSTART( d, t )
74
#define ITT_TASKEND( d, t )
75
#endif
76
77
static const int INIT_POC = -MAX_INT;
78
79
DecLibParser::~DecLibParser()
80
0
{
81
0
  m_prefixSEINALUs.clear();
82
83
0
  destroy();
84
0
}
85
86
void DecLibParser::create( ThreadPool* tp, int parserFrameDelay, int numReconInst, int numDecThreads, ErrHandlingFlags errHandlingFlags )
87
0
{
88
0
  m_threadPool        = tp;
89
0
  m_parseFrameDelay   = parserFrameDelay;
90
0
  m_numDecThreads     = numDecThreads;
91
0
  m_maxPicReconSkip   = numReconInst - 1;
92
0
  m_errHandlingFlags  = errHandlingFlags;
93
94
0
  m_apcSlicePilot     = new Slice;
95
0
  m_uiSliceSegmentIdx = 0;
96
97
0
  fill_array( m_associatedIRAPType,     NAL_UNIT_INVALID );
98
0
  fill_array( m_pocCRA,                 INIT_POC );
99
0
  fill_array( m_gdrRecoveryPointPocVal, INIT_POC );
100
0
  fill_array( m_gdrRecovered,           false );
101
102
0
  m_cSliceDecoder.setContextStateVec( numDecThreads );
103
0
}
104
105
void DecLibParser::destroy()
106
0
{
107
0
  SEI_internal::deleteSEIs( m_seiMessageList );
108
109
0
  m_threadPool    = nullptr;
110
111
0
  delete m_apcSlicePilot;
112
0
  m_apcSlicePilot = nullptr;
113
  
114
0
  m_picHeader.reset();
115
  
116
0
  m_cSliceDecoder.destroy();
117
  
118
0
  if( m_dci )
119
0
  {
120
0
    delete m_dci;
121
0
    m_dci = NULL;
122
0
  }
123
0
}
124
125
bool DecLibParser::parse( InputNALUnit& nalu )
126
0
{
127
0
  if( !nalu.isVcl() )
128
0
  {
129
0
    if( nalu.m_nalUnitType == NAL_UNIT_SUFFIX_APS || nalu.m_nalUnitType == NAL_UNIT_SUFFIX_SEI )
130
0
    {
131
0
      if( m_pcParsePic )
132
0
      {
133
0
        m_pcParsePic->bits += nalu.m_bits;
134
0
      }
135
0
    }
136
0
    else
137
0
    {
138
0
      m_nonVCLbits += nalu.m_bits;
139
0
    }
140
0
  }
141
142
0
  GCC_EXTRA_WARNING_switch_enum;
143
0
  switch( nalu.m_nalUnitType )
144
0
  {
145
0
  case NAL_UNIT_CODED_SLICE_TRAIL:
146
0
  case NAL_UNIT_CODED_SLICE_STSA:
147
0
  case NAL_UNIT_CODED_SLICE_RADL:
148
0
  case NAL_UNIT_CODED_SLICE_RASL:
149
0
  case NAL_UNIT_CODED_SLICE_IDR_W_RADL:
150
0
  case NAL_UNIT_CODED_SLICE_IDR_N_LP:
151
0
  case NAL_UNIT_CODED_SLICE_CRA:
152
0
  case NAL_UNIT_CODED_SLICE_GDR:
153
0
    try
154
0
    {
155
0
      if( !xDecodeSliceHead( nalu ) )
156
0
      {
157
0
        return false;
158
0
      }
159
0
      if( !xDecodeSliceMain( nalu ) || m_parseFrameList.size() <= m_parseFrameDelay )
160
0
      {
161
0
        return false;
162
0
      }
163
0
      return true;
164
0
    }
165
0
    catch( ... )
166
0
    {
167
0
      if( m_pcParsePic )
168
0
      {
169
0
        m_pcParsePic->error              = true;
170
0
        m_pcParsePic->exceptionThrownOut = true;
171
0
        if( m_pcParsePic->parseDone.hasException() )   // this happens only in the single-threaded case.
172
0
        {                                              // multithreaded mode should see exceptions from the parse tasks later
173
0
          m_pcParsePic->parseDone.clearException();
174
0
        }
175
0
      }
176
177
0
      std::rethrow_exception( std::current_exception() );
178
0
    }
179
180
0
  case NAL_UNIT_OPI:
181
    // NOT IMPLEMENTED
182
0
    return false;
183
184
0
  case NAL_UNIT_DCI:
185
0
    xDecodeDCI( nalu );
186
0
    return false;
187
188
0
  case NAL_UNIT_VPS:
189
0
    xDecodeVPS( nalu );
190
    // m_vps->m_iTargetLayer = iTargetOlsIdx;
191
0
    return false;
192
193
0
  case NAL_UNIT_SPS:
194
0
    xDecodeSPS( nalu );
195
0
    return false;
196
197
0
  case NAL_UNIT_PPS:
198
0
    xDecodePPS( nalu );
199
0
    return false;
200
201
0
  case NAL_UNIT_PREFIX_APS:
202
0
  case NAL_UNIT_SUFFIX_APS:
203
0
    xDecodeAPS( nalu );
204
0
    return false;
205
206
0
  case NAL_UNIT_PH:
207
0
    xDecodePicHeader( nalu );
208
0
    return false;
209
210
0
  case NAL_UNIT_ACCESS_UNIT_DELIMITER:
211
0
  {
212
0
    AUDReader audReader;
213
0
    uint32_t  picType;
214
0
    audReader.parseAccessUnitDelimiter( &( nalu.getBitstream() ), picType );
215
0
    msg( VERBOSE, "Found NAL_UNIT_ACCESS_UNIT_DELIMITER\n" );
216
0
    return false;
217
0
  }
218
219
0
  case NAL_UNIT_EOS:
220
0
    m_associatedIRAPType[nalu.m_nuhLayerId]     = NAL_UNIT_INVALID;
221
0
    m_pocCRA[nalu.m_nuhLayerId]                 = INIT_POC;
222
0
    m_gdrRecoveryPointPocVal[nalu.m_nuhLayerId] = INIT_POC;
223
0
    m_gdrRecovered[nalu.m_nuhLayerId]           = false;
224
0
    m_pocRandomAccess                           = MAX_INT;
225
0
    m_prevPOC                                   = MAX_INT;
226
0
    m_prevSliceSkipped                          = false;
227
0
    m_skippedPOC                                = 0;
228
0
    m_bFirstSliceInSequence[nalu.m_nuhLayerId]  = true;
229
0
    m_bFirstSliceInPicture                      = true;
230
0
    m_picListManager.restart();
231
0
    return false;
232
233
0
  case NAL_UNIT_EOB:
234
0
    return false;
235
236
0
  case NAL_UNIT_PREFIX_SEI:
237
    // Buffer up prefix SEI messages until SPS of associated VCL is known.
238
0
    m_prefixSEINALUs.emplace_back( nalu );
239
0
    m_pictureSeiNalus.emplace_back( std::move( nalu ) );
240
0
    return false;
241
242
0
  case NAL_UNIT_SUFFIX_SEI:
243
0
    if( m_pcParsePic /*&& !m_pcParsePic->wasLost*/ )
244
0
    {
245
0
      m_pictureSeiNalus.emplace_back( nalu );
246
0
      const SPS* sps = m_parameterSetManager.getActiveSPS();
247
0
      const VPS* vps = m_parameterSetManager.getVPS( sps->getVPSId() );
248
0
      m_seiReader.parseSEImessage( &( nalu.getBitstream() ), m_pcParsePic->seiMessageList, nalu.m_nalUnitType, nalu.m_nuhLayerId, nalu.m_temporalId, vps, sps, m_HRD, m_pDecodedSEIOutputStream );
249
250
0
      if( m_parseFrameDelay == 0 && !m_pcParsePic->error )   // if m_parseFrameDelay > 0, it has to be done in finishPicture()
251
0
      {
252
        // if parallel parsing is disabled, wait for the picture to finish
253
0
        if( m_threadPool->numThreads() == 0 )
254
0
        {
255
0
          m_threadPool->processTasksOnMainThread();
256
0
        }
257
0
        m_pcParsePic->reconDone.wait();
258
0
        m_decLib.checkPictureHashSEI( m_pcParsePic );
259
0
      }
260
0
    }
261
0
    else
262
0
    {
263
0
      msg( NOTICE, "Received suffix SEI but no picture currently active.\n" );
264
0
    }
265
0
    return false;
266
267
0
  case NAL_UNIT_FD:
268
0
    return false;
269
270
0
  case NAL_UNIT_RESERVED_VCL_4:
271
0
  case NAL_UNIT_RESERVED_VCL_5:
272
0
  case NAL_UNIT_RESERVED_VCL_6:
273
0
  case NAL_UNIT_RESERVED_IRAP_VCL_11:
274
0
    msg( NOTICE, "Found reserved VCL NAL unit.\n" );
275
0
    xParsePrefixSEIsForUnknownVCLNal();
276
0
    return false;
277
0
  case NAL_UNIT_RESERVED_NVCL_26:
278
0
  case NAL_UNIT_RESERVED_NVCL_27:
279
0
    msg( NOTICE, "Found reserved NAL unit.\n" );
280
0
    return false;
281
0
  case NAL_UNIT_UNSPECIFIED_28:
282
0
  case NAL_UNIT_UNSPECIFIED_29:
283
0
  case NAL_UNIT_UNSPECIFIED_30:
284
0
  case NAL_UNIT_UNSPECIFIED_31:
285
0
    msg( NOTICE, "Found unspecified NAL unit.\n" );
286
0
    return false;
287
0
  case NAL_UNIT_INVALID:
288
0
  default:
289
0
    THROW_RECOVERABLE( "Invalid NAL unit type" );
290
0
    break;
291
0
  }
292
0
  GCC_WARNING_RESET;
293
294
0
  return false;
295
0
}
296
297
Picture* DecLibParser::getNextDecodablePicture()
298
0
{
299
0
  if( m_parseFrameList.empty() )
300
0
  {
301
0
    return nullptr;
302
0
  }
303
304
0
  if( m_threadPool->numThreads() == 0 || m_parseFrameDelay == 0 )
305
0
  {
306
    // adhere to strict decoding order if running singlethreaded
307
0
    Picture * pic = m_parseFrameList.front();
308
0
    m_parseFrameList.pop_front();
309
0
    return pic;
310
0
  }
311
312
0
  if( m_parseFrameList.front()->skippedDecCount >= MAX_OUT_OF_ORDER_PICS || m_parseFrameList.front()->error )
313
0
  {
314
0
    Picture* pic = m_parseFrameList.front();
315
0
    m_parseFrameList.pop_front();
316
0
    return pic;
317
0
  }
318
319
  // try to find next picture, that is parsed and has all reference pictures decoded
320
0
  for( auto picIt = m_parseFrameList.begin(); picIt != m_parseFrameList.end(); ++picIt )
321
0
  {
322
0
    Picture* pic = *picIt;
323
324
0
    if( pic->parseDone.getState() != Barrier::unlocked )   // this doesn't throw if the barrier has an exception set
325
0
      continue;
326
327
0
    if( pic->wasLost || pic->error )
328
0
      continue;
329
330
0
    bool allRefPicsDone = true;
331
0
    for( const Slice* slice: pic->slices )
332
0
    {
333
0
      if( slice->isIntra() )
334
0
      {
335
0
        continue;
336
0
      }
337
0
      for( int iDir = REF_PIC_LIST_0; iDir < NUM_REF_PIC_LIST_01 && allRefPicsDone; ++iDir )
338
0
      {
339
0
        for( int iRefIdx = 0; iRefIdx < slice->getNumRefIdx( (RefPicList) iDir ) && allRefPicsDone; iRefIdx++ )
340
0
        {
341
0
          const Picture* refPic = slice->getRefPic( (RefPicList) iDir, iRefIdx );
342
0
          if( refPic->progress < Picture::reconstructed )
343
0
          {
344
0
            allRefPicsDone = false;
345
0
            break;
346
0
          }
347
0
        }
348
0
      }
349
0
    }
350
351
0
    if( allRefPicsDone )
352
0
    {
353
      // increase skip count for all previous pictures
354
0
      for( auto& skipped: PicListRange{ m_parseFrameList.begin(), picIt } )
355
0
      {
356
0
        skipped->skippedDecCount++;
357
0
      }
358
359
0
      m_parseFrameList.erase( picIt );
360
0
      return pic;
361
0
    }
362
363
//    if( pic->getTLayer() < m_parseFrameList.front()->getTLayer() )
364
//    {
365
//      break;
366
//    }
367
0
  }
368
369
  // if no picture has all reference-pictures decoded, use next pic in (regular) decoding order.
370
0
  Picture * pic = m_parseFrameList.front();
371
0
  m_parseFrameList.pop_front();
372
0
  return pic;
373
0
}
374
375
void DecLibParser::checkAPSInPictureUnit()
376
0
{
377
0
  bool firstVCLFound  = false;
378
0
  bool suffixAPSFound = false;
379
380
0
  for( auto &nalu : m_pictureUnitNals )
381
0
  {
382
0
    if( NALUnit::isVclNalUnitType(nalu) )
383
0
    {
384
0
      firstVCLFound = true;
385
0
      CHECK( suffixAPSFound, "When any suffix APS NAL units are present in a PU, they shall follow the last VCL unit of the PU" );
386
0
    }
387
0
    else if( nalu == NAL_UNIT_PREFIX_APS )
388
0
    {
389
0
      CHECK( firstVCLFound, "When any prefix APS NAL units are present in a PU, they shall precede the first VCL unit of the PU");
390
0
    }
391
0
    else if( nalu == NAL_UNIT_SUFFIX_APS )
392
0
    {
393
0
      suffixAPSFound = true;
394
0
    }
395
0
  }
396
0
}
397
398
bool DecLibParser::xDecodeSliceHead( InputNALUnit& nalu )
399
0
{
400
  // all slices for the previous picture have been parsed
401
0
  if( m_pcParsePic && m_pcParsePic->lastSliceOfPicPresent() )
402
0
  {
403
0
    m_pcParsePic = nullptr;
404
0
  }
405
406
0
  m_apcSlicePilot->initSlice(); // the slice pilot is an object to prepare for a new slice
407
                                // it is not associated with picture, sps or pps structures.
408
409
0
  m_apcSlicePilot->setNalUnitType   ( nalu.m_nalUnitType );
410
0
  m_apcSlicePilot->setNalUnitLayerId( nalu.m_nuhLayerId  );
411
0
  m_apcSlicePilot->setTLayer        ( nalu.m_temporalId  );
412
413
0
  m_HLSReader.setBitstream( &nalu.getBitstream() );
414
415
0
  m_bFirstSliceInPicture = true;  // set for now, will be set correctly in parseSliceHeader
416
0
  m_HLSReader.parseSliceHeader( m_apcSlicePilot, m_picHeader, &m_parameterSetManager, m_prevTid0POC, m_bFirstSliceInPicture );
417
418
0
  CHECK( m_bFirstSliceInPicture != ( m_apcSlicePilot->getCtuAddrInSlice( 0 ) == 0 ), "first slice in picture should start at CTU-addr 0" );
419
420
0
  if( m_bFirstSliceInPicture )
421
0
  {
422
0
    m_uiSliceSegmentIdx = 0;
423
0
    m_apcSlicePilot->setPicHeader   ( m_picHeader.get() );
424
0
  }
425
0
  else // if it turns out, this was not the first slice in the picture, we need to parse the header again
426
0
  {
427
0
    m_uiSliceSegmentIdx++;
428
0
    CHECK( !m_pcParsePic, "m_pcParsePic should be initialized, when this is not the first slice in the picture" );
429
0
    CHECK( m_pcParsePic->slices.size() <= m_uiSliceSegmentIdx - 1 || m_pcParsePic->slices[m_uiSliceSegmentIdx - 1] == nullptr, "can't access previous slice" );
430
0
    CHECK( !m_pcParsePic->getMixedNaluTypesInPicFlag() && nalu.m_nalUnitType != m_pcParsePic->slices[m_uiSliceSegmentIdx - 1]->getNalUnitType(),
431
0
           "The value of NAL unit type shall be the same for all coded slice NAL units of a picture if pps_mixed_nalu_types_in_pic_flag is not set" );
432
433
0
    m_apcSlicePilot->copySliceInfo( m_pcParsePic->slices[m_uiSliceSegmentIdx - 1] );
434
435
0
    m_apcSlicePilot->setNalUnitType   ( nalu.m_nalUnitType );
436
0
    m_apcSlicePilot->setNalUnitLayerId( nalu.m_nuhLayerId );
437
0
    m_apcSlicePilot->setTLayer        ( nalu.m_temporalId );
438
439
0
    nalu.getBitstream().resetToStart();
440
0
    nalu.readNalUnitHeader();
441
0
    m_HLSReader.setBitstream        ( &nalu.getBitstream() );
442
443
0
    m_HLSReader.parseSliceHeader( m_apcSlicePilot, m_picHeader, &m_parameterSetManager, m_prevTid0POC, m_bFirstSliceInPicture );
444
0
  }
445
446
0
  const PPS* pps = static_cast<const ParameterSetManager&>( m_parameterSetManager ).getPPS( m_apcSlicePilot->getPicHeader()->getPPSId() );
447
0
  CHECK( pps == 0, "No PPS present" );
448
0
  const SPS* sps = static_cast<const ParameterSetManager&>( m_parameterSetManager ).getSPS( pps->getSPSId() );
449
0
  CHECK( sps == 0, "No SPS present" );
450
0
  const VPS* vps = static_cast<const ParameterSetManager&>( m_parameterSetManager ).getVPS( sps->getVPSId() );
451
0
  CHECK( sps->getVPSId() > 0 && vps == 0, "Invalid VPS" );
452
0
  if( sps->getVPSId() == 0 && m_prevLayerID != MAX_INT )
453
0
  {
454
0
    CHECK( m_prevLayerID != nalu.m_nuhLayerId, "All VCL NAL unit in the CVS shall have the same value of nuh_layer_id "
455
0
                                                           "when sps_video_parameter_set_id is equal to 0" );
456
0
  }
457
458
0
  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
0
  m_apcSlicePilot->setIndependentSliceIdx( m_uiSliceSegmentIdx );
462
463
0
  DTRACE_UPDATE( g_trace_ctx, std::make_pair( "poc", m_apcSlicePilot->getPOC() ) );
464
465
466
0
  if( m_bFirstSliceInPicture )
467
0
  {
468
0
    const auto pictureType = m_apcSlicePilot->getNalUnitType();
469
470
0
    if( !pps->getMixedNaluTypesInPicFlag()
471
0
        && ( 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
0
    {
476
0
      m_pocCRA            [nalu.m_nuhLayerId] = m_apcSlicePilot->getPOC();
477
0
      m_associatedIRAPType[nalu.m_nuhLayerId] = pictureType;
478
0
    }
479
0
  }
480
481
0
  xUpdatePreviousTid0POC( m_apcSlicePilot );
482
483
0
  m_apcSlicePilot->setAssociatedIRAPPOC ( m_pocCRA            [nalu.m_nuhLayerId] );
484
0
  m_apcSlicePilot->setAssociatedIRAPType( m_associatedIRAPType[nalu.m_nuhLayerId] );
485
486
0
  if( m_apcSlicePilot->getRapPicFlag() || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR )
487
0
  {
488
    // Derive NoOutputBeforeRecoveryFlag
489
0
    if( !pps->getMixedNaluTypesInPicFlag() )
490
0
    {
491
0
      if( m_bFirstSliceInSequence[nalu.m_nuhLayerId] )
492
0
      {
493
0
        m_picHeader->setNoOutputBeforeRecoveryFlag( true );
494
0
      }
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
0
    }
508
0
    else
509
0
    {
510
0
      m_picHeader->setNoOutputBeforeRecoveryFlag( false );
511
0
    }
512
513
0
    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
0
    if( m_apcSlicePilot->getNoOutputOfPriorPicsFlag() )
520
0
    {
521
0
      m_lastPOCNoOutputPriorPics = m_apcSlicePilot->getPOC();
522
0
      m_isNoOutputPriorPics      = true;
523
0
    }
524
0
    else
525
0
    {
526
0
      m_isNoOutputPriorPics = false;
527
0
    }
528
0
  }
529
530
0
#if !DISABLE_CHECK_NO_OUTPUT_PRIOR_PICS_FLAG
531
0
  if( m_bFirstSliceInPicture && m_apcSlicePilot->getPOC() != m_prevPOC
532
0
      && ( m_apcSlicePilot->getRapPicFlag() || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR )
533
0
      && m_picHeader->getNoOutputBeforeRecoveryFlag()
534
0
      && getNoOutputPriorPicsFlag() )
535
0
  {
536
0
    checkNoOutputPriorPics();
537
0
    setNoOutputPriorPicsFlag( false );
538
0
  }
539
0
#endif
540
541
542
  //For inference of PicOutputFlag
543
0
  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
0
  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
0
  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
0
  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
0
  m_prevSliceSkipped = false;
585
586
  //we should only get a different poc for a new picture (with CTU address==0)
587
0
  if(  m_apcSlicePilot->getPOC() != m_prevPOC
588
0
   && !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
0
  m_prevLayerID = nalu.m_nuhLayerId;
595
596
  //detect lost reference picture and insert copy of earlier frame.
597
0
  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
0
  xActivateParameterSets( nalu.m_nuhLayerId );
638
639
  // WARNING: don't use m_apcSlicePilot after this point, because it has been reallocated
640
641
0
  Slice* slice = m_pcParsePic->slices[m_uiSliceSegmentIdx];
642
643
0
  m_pcParsePic->neededForOutput = m_picHeader->getPicOutputFlag();
644
0
  if( m_pcParsePic->lastSliceOfPicPresent() )
645
0
  {
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
0
    {
655
0
      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
0
      if( !m_gdrRecovered[nalu.m_nuhLayerId]
661
0
          && ( 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
0
      const bool is_recovering_picture = slice->getAssociatedIRAPType() == NAL_UNIT_CODED_SLICE_GDR && m_pcParsePic->poc < m_gdrRecoveryPointPocVal[nalu.m_nuhLayerId];
668
0
      if( slice->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR && m_gdrRecovered[nalu.m_nuhLayerId] )
669
0
      {
670
0
        m_pcParsePic->neededForOutput = true;
671
0
      }
672
0
      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
0
      else if( ( slice->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR && m_picHeader->getNoOutputBeforeRecoveryFlag() )
677
0
               || ( is_recovering_picture && ( !m_gdrRecovered[nalu.m_nuhLayerId] || m_lastNoOutputBeforeRecoveryFlag[nalu.m_nuhLayerId] ) ) )
678
0
      {
679
0
        m_pcParsePic->neededForOutput = false;
680
0
      }
681
0
    }
682
0
  }
683
684
0
  return true;
685
0
}
686
687
bool DecLibParser::xDecodeSliceMain( InputNALUnit& nalu )
688
0
{
689
0
  ITT_TASKSTART( itt_domain_oth, itt_handle_start );
690
  // actual decoding starts here
691
0
  Slice* pcSlice = m_pcParsePic->slices[m_uiSliceSegmentIdx];
692
0
  m_pcParsePic->poc              = pcSlice->getPOC();
693
0
  m_pcParsePic->tempLayer        = pcSlice->getTLayer();
694
0
  m_pcParsePic->dpbReferenceMark = pcSlice->getPicHeader()->getNonReferencePictureFlag() ? Picture::unreferenced : Picture::ShortTerm;
695
0
  m_pcParsePic->stillReferenced  = !!m_pcParsePic->dpbReferenceMark;
696
0
  m_pcParsePic->isReferencePic   = !!m_pcParsePic->dpbReferenceMark;
697
0
  m_pcParsePic->eNalUnitType     = nalu.m_nalUnitType;
698
0
  m_pcParsePic->cts              = nalu.m_cts;
699
0
  m_pcParsePic->dts              = nalu.m_dts;
700
0
  m_pcParsePic->rap              = nalu.m_rap;
701
0
  m_pcParsePic->userData         = nalu.m_userData;
702
0
  m_pcParsePic->bits            += nalu.m_bits + m_nonVCLbits;
703
0
  m_pcParsePic->layerId          = nalu.m_nuhLayerId;
704
0
  m_pcParsePic->subLayerNonReferencePictureDueToSTSA = false;
705
706
0
  m_nonVCLbits = 0;
707
708
0
  CHECK( m_pcParsePic->tempLayer != nalu.m_temporalId,
709
0
         "Currently parsed pic should have the same temporal layer as the NAL unit" );
710
711
0
  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
0
  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
0
  if( pcSlice->getNalUnitLayerId() != pcSlice->getPPS()->getLayerId() )
744
0
  {
745
0
    CHECK( pcSlice->getPPS()->getLayerId() > pcSlice->getNalUnitLayerId(), "Layer Id of PPS cannot be greater than layer Id of VCL NAL unit the refer to it" );
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
0
  if( m_bFirstSliceInPicture )
768
0
  {
769
0
    m_pcParsePic->setDecodingOrderNumber( m_decodingOrderCounter );
770
0
    m_decodingOrderCounter++;
771
772
0
    pcSlice->getPic()->subPictures.clear();
773
0
    pcSlice->getPic()->sliceSubpicIdx.clear();
774
775
0
    for( int subPicIdx = 0; subPicIdx < pcSlice->getSPS()->getNumSubPics(); subPicIdx++ )
776
0
    {
777
0
      pcSlice->getPic()->subPictures.push_back( pcSlice->getPPS()->getSubPic( subPicIdx ) );
778
0
    }
779
0
  }
780
781
0
  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
0
  m_tmpSeenPocs.clear();
788
0
  m_tmpSeenPocs.reserve( m_dpbReferencePics.size() );
789
0
  for( auto& p: m_dpbReferencePics )
790
0
  {
791
0
    CHECK( m_tmpSeenPocs.count( p->poc ) != 0, "duplicate POC in DPB" );
792
0
    if( p->dpbReferenceMark )   // we only care about reference pictures in the DPB
793
0
    {
794
0
      m_tmpSeenPocs.insert( p->poc );
795
0
    }
796
0
  }
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
0
  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
0
  if( m_pcParsePic->cs->vps && !m_pcParsePic->cs->vps->getIndependentLayerFlag( m_pcParsePic->cs->vps->getGeneralLayerIdx( nalu.m_nuhLayerId ) ) && m_pcParsePic->cs->pps->getNumSubPics() > 1 )
815
0
  {
816
0
    CU::checkConformanceILRP(pcSlice);
817
0
  }
818
819
0
  pcSlice->scaleRefPicList( m_pcParsePic->cs->picHeader.get() );
820
821
822
0
  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
0
  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
0
  else
924
0
  {
925
0
    pcSlice->setBiDirPred( false, -1, -1 );
926
0
  }
927
928
  //---------------
929
0
  xCheckMixedNalUnit( pcSlice, nalu );
930
931
0
  if( m_bFirstSliceInPicture )
932
0
  {
933
0
#if RECO_WHILE_PARSE
934
0
    for( int ctu = 0; ctu < pcSlice->getPPS()->pcv->sizeInCtus; ctu++ )
935
0
    {
936
0
      m_pcParsePic->ctuParsedBarrier[ctu].lock();
937
0
    }
938
939
0
#endif
940
0
    m_parseFrameList.push_back( m_pcParsePic );
941
0
  }
942
943
0
  ITT_TASKEND( itt_domain_oth, itt_handle_start );
944
945
0
  static const auto parseTask = []( int threadId, void* param )
946
0
  {
947
0
    Slice* slice     = static_cast<Slice*>( param );
948
0
    auto&  decLib    = slice->parseTaskParams.decLibParser;
949
0
    auto&  bitstream = slice->parseTaskParams.bitstream;
950
0
    auto*  pic       = slice->getPic();
951
952
0
    try
953
0
    {
954
0
      pic->startProcessingTimer();
955
956
      //  Decode a picture
957
0
      ITT_TASKSTART( itt_domain_prs, itt_handle_parse );
958
0
      decLib->m_cSliceDecoder.parseSlice( slice, &bitstream, threadId );
959
0
      ITT_TASKEND( itt_domain_prs, itt_handle_parse );
960
961
0
      pic->stopProcessingTimer();
962
963
0
      bitstream.clearFifo();
964
0
      bitstream.clearEmulationPreventionByteLocation();
965
0
    }
966
0
    catch( ... )
967
0
    {
968
0
      pic->error = true;
969
0
      pic->parseDone.setException( std::current_exception() );
970
0
#if RECO_WHILE_PARSE
971
0
      for( auto& b: pic->ctuParsedBarrier )
972
0
      {
973
0
        b.setException( std::current_exception() );
974
0
      }
975
0
#endif
976
0
      std::rethrow_exception( std::current_exception() );
977
0
    }
978
0
    return true;
979
0
  };
980
981
0
  pcSlice->parseTaskParams.init( this, std::move( nalu.getBitstream() ) );
982
0
  pcSlice->parseDone.lock();
983
984
0
  auto expected = Picture::init;
985
0
  m_pcParsePic->progress.compare_exchange_strong( expected, Picture::parsing );   // if RECO_WHILE_PARSE reconstruction can already have started, so we make sure to not overwrite that state
986
987
0
  if( m_threadPool && m_threadPool->numThreads() > 0 )
988
0
  {
989
0
    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
0
    else
996
0
    {
997
0
      m_threadPool->addBarrierTask( TP_TASK_NAME_ARG( "POC:" + std::to_string( m_pcParsePic->poc ) + " parseTask" )
998
0
                                    parseTask, pcSlice,  &m_pcParsePic->m_divTasksCounter, &pcSlice->parseDone );
999
0
    }
1000
0
  }
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
0
  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
0
  else
1019
0
  {
1020
0
    DTRACE_UPDATE( g_trace_ctx, std::make_pair( "final", 1 ) );
1021
0
  }
1022
0
  m_prevPOC = pcSlice->getPOC();
1023
1024
0
  m_bFirstSliceInSequence[nalu.m_nuhLayerId] = false;
1025
0
  m_bFirstSliceInBitstream                   = false;
1026
1027
1028
0
  const unsigned lastCtuInSlice = pcSlice->getCtuAddrInSlice( pcSlice->getNumCtuInSlice() - 1 );
1029
0
  if( lastCtuInSlice == pcSlice->getPPS()->pcv->sizeInCtus - 1 )
1030
0
  {
1031
0
    return true;
1032
0
  }
1033
1034
0
  return false;
1035
0
}
1036
1037
void DecLibParser::xActivateParameterSets( const int layerId )
1038
0
{
1039
0
  ParameterSetManager::ActivePSs paramSets;
1040
1041
0
  if( m_bFirstSliceInPicture )
1042
0
  {
1043
0
              paramSets = m_parameterSetManager.xActivateParameterSets( m_bFirstSliceInPicture, m_apcSlicePilot, m_picHeader.get() );
1044
0
    const SPS*  sps     = paramSets.sps;
1045
0
    const PPS*  pps     = paramSets.pps;
1046
0
    const APS** alfApss = paramSets.alfAPSs->data();
1047
0
    const APS*  lmcsAPS = paramSets.lmcsAps;
1048
0
    const APS*  scalingListAPS = paramSets.scalingListAps;
1049
1050
0
    xParsePrefixSEImessages();
1051
1052
0
    CHECK( sps->getBitDepth() > 12, "High bit depth support must be enabled at compile-time in order to decode this bitstream\n" );
1053
1054
0
    applyReferencePictureListBasedMarking( m_apcSlicePilot, layerId, *pps );
1055
1056
    //  Get a new picture buffer
1057
0
    m_pcParsePic = m_picListManager.getNewPicBuffer( *sps, *pps, m_apcSlicePilot->getTLayer(), layerId, m_parameterSetManager.getVPS( sps->getVPSId() ) );
1058
0
    CHECK( std::find( m_dpbReferencePics.cbegin(), m_dpbReferencePics.cend(), m_pcParsePic ) != m_dpbReferencePics.cend(), "reused picture shouldn't be in decoded picture buffer" );
1059
0
    m_dpbReferencePics.push_back( m_pcParsePic );
1060
    // assign these fields already, because they are needed by PicListManager::getPicListRange() and Slice::applyReferencePictureSet()
1061
0
    m_pcParsePic->poc          = m_apcSlicePilot->getPOC();
1062
0
    m_pcParsePic->eNalUnitType = m_apcSlicePilot->getNalUnitType();
1063
0
    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
0
    m_pcParsePic->dpbReferenceMark = m_apcSlicePilot->getPicHeader()->getNonReferencePictureFlag() ? Picture::unreferenced : Picture::ShortTerm;
1070
0
    m_pcParsePic->stillReferenced  = !!m_pcParsePic->dpbReferenceMark;
1071
0
    m_pcParsePic->isReferencePic   = !!m_pcParsePic->dpbReferenceMark;
1072
1073
    // Set Field/Frame coding mode
1074
0
    bool isField    = false;
1075
0
    bool isTopField = false;
1076
0
    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
0
    m_pcParsePic->fieldPic = isField;
1088
0
    m_pcParsePic->topField = isTopField;
1089
1090
    // transfer any SEI messages that have been received to the picture
1091
0
    m_pcParsePic->seiMessageList = m_seiMessageList;
1092
0
    m_seiMessageList.clear();
1093
1094
0
    m_apcSlicePilot->setPicHeader( m_picHeader.get() );
1095
0
  }
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
0
  Slice* pSlice = m_pcParsePic->allocateNewSlice( &m_apcSlicePilot );
1109
0
  CHECK_FATAL( m_pcParsePic->slices.size() != ( m_uiSliceSegmentIdx + 1 ), "Invalid number of slices" );
1110
1111
0
  const VPS* vps = pSlice->getVPS_nothrow();
1112
0
  const SPS* sps = pSlice->getSPS();
1113
0
  const PPS* pps = pSlice->getPPS();
1114
1115
0
  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
0
  CHECK( !sps->getGDREnabledFlag() && m_picHeader->getGdrPicFlag(), "When gdr_enabled_flag is equal to 0, the value of gdr_pic_flag shall be equal to 0 " );
1143
0
  CHECK( !sps->getUseWP() && pps->getUseWP(), "When sps_weighted_pred_flag is equal to 0, the value of pps_weighted_pred_flag shall be equal to 0." );
1144
0
  CHECK( !sps->getUseWPBiPred() && pps->getWPBiPred(),
1145
0
         "When sps_weighted_bipred_flag is equal to 0, the value of pps_weighted_bipred_flag shall be equal to 0." );
1146
1147
0
  CHECK( !sps->getResChangeInClvsEnabledFlag() && pps->getPicWidthInLumaSamples() != sps->getMaxPicWidthInLumaSamples(),
1148
0
         "When res_change_in_clvs_allowed_flag equal to 0, the value of pic_width_in_luma_samples shall be equal to pic_width_max_in_luma_samples." );
1149
0
  CHECK( !sps->getResChangeInClvsEnabledFlag() && pps->getPicHeightInLumaSamples() != sps->getMaxPicHeightInLumaSamples(),
1150
0
         "When res_change_in_clvs_allowed_flag equal to 0, the value of pic_height_in_luma_samples shall be equal to pic_height_max_in_luma_samples." );
1151
0
  CHECK( sps->getResChangeInClvsEnabledFlag() && sps->getSubPicInfoPresentFlag() != 0,
1152
0
         "When res_change_in_clvs_allowed_flag is equal to 1, the value of subpic_info_present_flag shall be equal to 0." );
1153
0
  CHECK( sps->getResChangeInClvsEnabledFlag() && sps->getVirtualBoundariesEnabledFlag(),
1154
0
         "when the value of res_change_in_clvs_allowed_flag is equal to 1, the value of sps_virtual_boundaries_present_flag shall be equal to 0" );
1155
0
  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
0
  CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getOneTilePerPicConstraintFlag() && pps->getNumTiles() != 1,
1164
0
         "When one_tile_per_pic_constraint_flag is equal to 1, each picture shall contain only one tile" );
1165
0
  CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getOneSlicePerPicConstraintFlag() && pps->getRectSliceFlag() && pps->getNumSlicesInPic() != 1,
1166
0
         "When one_slice_per_pic_constraint_flag is equal to 1 and if pps_rect_slice_flag is equal to 1, the value of num_slices_in_pic_minus1 shall be equal to 0" );
1167
0
  CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getNoRprConstraintFlag() && sps->getRprEnabledFlag(),
1168
0
         "When gci_no_ref_pic_resampling_constraint_flag is equal to 1, the value of sps_ref_pic_resampling_enabled_flag shall be equal to 0" );
1169
0
  CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getNoResChangeInClvsConstraintFlag() && sps->getResChangeInClvsEnabledFlag(),
1170
0
         "When gci_no_res_change_in_clvs_constraint_flag is equal to 1, the value of sps_res_change_in_clvs_allowed_flag shall be equal to 0" );
1171
0
  CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getNoIdrRplConstraintFlag() && sps->getIDRRefParamListPresent(),
1172
0
         "When gci_no_idr_rpl_constraint_flag equal to 1 , the value of sps_idr_rpl_present_flag shall be equal to 0" );
1173
0
  CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getNoMixedNaluTypesInPicConstraintFlag() && pps->getMixedNaluTypesInPicFlag(),
1174
0
         "When gci_no_mixed_nalu_types_in_pic_constraint_flag equal to 1, the value of pps_mixed_nalu_types_in_pic_flag shall be equal to 0" );
1175
0
  CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getNoRectSliceConstraintFlag() && pps->getRectSliceFlag(),
1176
0
         "When gci_no_rectangular_slice_constraint_flag equal to 1, the value of pps_rect_slice_flag shall be equal to 0" );
1177
0
  CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getOneSlicePerSubpicConstraintFlag() && !pps->getSingleSlicePerSubPicFlag(),
1178
0
         "When gci_one_slice_per_subpic_constraint_flag equal to 1, the value of pps_single_slice_per_subpic_flag shall be equal to 1" );
1179
0
  CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getNoSubpicInfoConstraintFlag() && sps->getSubPicInfoPresentFlag(),
1180
0
         "When gci_no_subpic_info_constraint_flag is equal to 1, the value of sps_subpic_info_present_flag shall be equal to 0" );
1181
1182
0
  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
0
  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
0
  CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getNoChromaQpOffsetConstraintFlag() && pps->getCuChromaQpOffsetEnabledFlag(),
1195
0
         "When gci_no_ChromaQpOffset_constraint_flag is equal to 1, the values of pps_cu_chroma_qp_offset_list_enabled_flag shall be equal to 0" );
1196
1197
0
  CHECK( sps->getCTUSize() > ( 1 << sps->getProfileTierLevel()->getConstraintInfo()->getMaxLog2CtuSizeConstraintIdc() ),
1198
0
         "The CTU size specified by sps_log2_ctu_size_minus5 shall not exceed the constraint specified by gci_three_minus_max_log2_ctu_size_constraint_idc" );
1199
0
  CHECK( sps->getProfileTierLevel()->getConstraintInfo()->getNoLumaTransformSize64ConstraintFlag() && sps->getLog2MaxTbSize() != 5,
1200
0
         "When gci_no_luma_transform_size_64_constraint_flag is equal to 1, the value of sps_max_luma_transform_size_64_flag shall be equal to 0" );
1201
1202
  // TODO: fix MT static maps
1203
0
  static std::unordered_map<int, int> m_layerChromaFormat;
1204
0
  static std::unordered_map<int, int> m_layerBitDepth;
1205
1206
0
  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
0
  const int minCuSize = 1 << sps->getLog2MinCodingBlockSize();
1236
0
  CHECK( ( pps->getPicWidthInLumaSamples()  % ( std::max( 8, minCuSize) ) ) != 0, "Coded frame width must be a multiple of Max(8, the minimum unit size)" );
1237
0
  CHECK( ( pps->getPicHeightInLumaSamples() % ( std::max( 8, minCuSize) ) ) != 0, "Coded frame height must be a multiple of Max(8, the minimum unit size)" );
1238
1239
0
  if( sps->getCTUSize() + 2 * ( 1 << sps->getLog2MinCodingBlockSize() ) > pps->getPicWidthInLumaSamples() )
1240
0
  {
1241
0
    CHECK( pps->getUseWrapAround(),
1242
0
           "Wraparound shall be disabled when the value of ( CtbSizeY / MinCbSizeY + 1) is greater than or equal to"
1243
0
           " ( pic_width_in_luma_samples / MinCbSizeY - 1 )" );
1244
0
  }
1245
1246
0
  if( pSlice->getPicHeader()->getGdrOrIrapPicFlag() && !pSlice->getPicHeader()->getGdrPicFlag()
1247
0
      && ( !vps || vps->getIndependentLayerFlag( vps->getGeneralLayerIdx( layerId ) ) ) )
1248
0
  {
1249
0
    CHECK( pSlice->getPicHeader()->getPicInterSliceAllowedFlag(),
1250
0
           "When gdr_or_irap_pic_flag is equal to 1 and gdr_pic_flag is equal to 0 and vps_independent_layer_flag[ GeneralLayerIdx[ nuh_layer_id ] ] "
1251
0
           "is equal to 1, ph_inter_slice_allowed_flag shall be equal to 0" );
1252
0
  }
1253
1254
0
  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
0
  ProfileLevelTierFeatures ptlFeature;
1262
0
  ptlFeature.extractPTLInformation(*sps);
1263
1264
0
  const LevelTierFeatures* ltFeature = ptlFeature.getLevelTierFeatures();
1265
0
  const ProfileFeatures*   pFeature  = ptlFeature.getProfileFeatures();
1266
1267
0
  CHECK( ltFeature && pps->getNumTileColumns() > ltFeature->maxTileCols, "Num tile columns signaled in PPS exceed level limits" );
1268
0
  CHECK( ltFeature && pps->getNumTiles() > ltFeature->maxTilesPerAu, "Num tiles signaled in PPS exceed level limits" );
1269
0
  CHECK( pFeature && sps->getBitDepth() > pFeature->maxBitDepth, "Bit depth exceed profile limit" );
1270
0
  CHECK( pFeature && sps->getChromaFormatIdc() > pFeature->maxChromaFormat, "Chroma format exceed profile limit" );
1271
0
}
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
0
{
1394
  //  checkLeadingPictureRestrictions(rcListPic, pps);
1395
1396
  // mark long-term reference pictures in List0
1397
0
  for( const auto l: { REF_PIC_LIST_0, REF_PIC_LIST_1 } )
1398
0
  {
1399
0
    const ReferencePictureList* rpl = currSlice->getRPL( l );
1400
1401
0
    for( int i = 0; i < rpl->getNumRefEntries(); i++ )
1402
0
    {
1403
0
      if( !rpl->isRefPicLongterm( i ) || rpl->isInterLayerRefPic( i ) )
1404
0
      {
1405
0
        continue;
1406
0
      }
1407
1408
0
      Picture* availableST = nullptr;
1409
0
      for( Picture* pic: m_dpbReferencePics )
1410
0
      {
1411
0
        if( !pic->dpbReferenceMark )
1412
0
        {
1413
0
          continue;
1414
0
        }
1415
1416
0
        const int bitsForPoc = pic->cs->sps->getBitsForPOC();
1417
0
        const int curPoc     = pic->getPOC();
1418
0
        const int ltRefPoc   = rpl->calcLTRefPOC( currSlice->getPOC(), bitsForPoc, i );
1419
0
        if( pic->dpbReferenceMark == Picture::LongTerm && isLTPocEqual( curPoc, ltRefPoc, bitsForPoc, rpl->getDeltaPocMSBPresentFlag( i ) ) )
1420
0
        {
1421
0
          break;
1422
0
        }
1423
1424
        // if there was no such long-term check the short terms
1425
0
        if( pic->dpbReferenceMark == Picture::ShortTerm && isLTPocEqual( curPoc, ltRefPoc, bitsForPoc, rpl->getDeltaPocMSBPresentFlag( i ) ) )
1426
0
        {
1427
0
          availableST = pic;
1428
          // but don't break here, because we might still find a LT
1429
0
        }
1430
0
      }
1431
1432
      // the found picture was not yet marked as long term, so we mark it here
1433
0
      if ( availableST )
1434
0
      {
1435
0
        availableST->dpbReferenceMark = Picture::LongTerm;
1436
0
      }
1437
0
    }
1438
0
  }
1439
1440
0
  if( currSlice->isIDR() && !pps.getMixedNaluTypesInPicFlag() )
1441
0
  {
1442
0
    for( Picture* pic: m_dpbReferencePics )
1443
0
    {
1444
0
      pic->dpbReferenceMark = Picture::unreferenced;
1445
0
    }
1446
1447
    // ignore neededForOutput flag here, because we only care about reference pictures in the DPB
1448
0
    m_dpbReferencePics.remove_if( []( Picture* pic ) { return !pic->dpbReferenceMark; } );
1449
0
    return;
1450
0
  }
1451
1452
  // loop through all pictures in the reference picture buffer
1453
0
  for( Picture* pic: m_dpbReferencePics )
1454
0
  {
1455
0
    if( !pic->dpbReferenceMark )
1456
0
    {
1457
0
      continue;
1458
0
    }
1459
1460
0
    bool isReference = false;
1461
1462
0
    for( const auto l: { REF_PIC_LIST_0, REF_PIC_LIST_1 } )
1463
0
    {
1464
0
      if( currSlice->getRPL( l )->findInRefPicList( pic, currSlice->getPOC(), layerId ) )
1465
0
      {
1466
0
        isReference = true;
1467
0
        break;
1468
0
      }
1469
0
    }
1470
1471
    // mark the picture as "unused for reference" if it is not in
1472
    // the Reference Picture List
1473
0
    if( !isReference && pic->poc != currSlice->getPOC() && pic->layerId == layerId )
1474
0
    {
1475
0
      pic->dpbReferenceMark = Picture::unreferenced;
1476
0
    }
1477
1478
    // // sanity checks
1479
    // if( pic->referenced )
1480
    // {
1481
    //   // check that pictures of higher temporal layers are not used
1482
    //   CHECK_FATAL( pic->usedByCurr && pic->temporalId > this->getTLayer(), "Invalid state" );
1483
    // }
1484
0
  }
1485
1486
  // ignore neededForOutput flag here, because we only care about reference pictures in the DPB
1487
0
  m_dpbReferencePics.remove_if( []( Picture* pic ) { return !pic->dpbReferenceMark; } );
1488
0
}
1489
1490
void DecLibParser::xParsePrefixSEImessages()
1491
0
{
1492
0
  while( !m_prefixSEINALUs.empty() )
1493
0
  {
1494
0
    InputNALUnit& nalu = m_prefixSEINALUs.front();
1495
0
    const SPS *sps = m_parameterSetManager.getActiveSPS();
1496
0
    const VPS *vps = m_parameterSetManager.getVPS(sps->getVPSId());
1497
0
    m_seiReader.parseSEImessage( &(nalu.getBitstream()), m_seiMessageList, nalu.m_nalUnitType, nalu.m_nuhLayerId, nalu.m_temporalId, vps, sps, m_HRD, m_pDecodedSEIOutputStream );
1498
0
    m_prefixSEINALUs.pop_front();
1499
0
  }
1500
0
}
1501
1502
void DecLibParser::xParsePrefixSEIsForUnknownVCLNal()
1503
0
{
1504
0
  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
0
}
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
0
{
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
0
}
1530
1531
void DecLibParser::xDecodeDCI( InputNALUnit& nalu )
1532
0
{
1533
0
  m_HLSReader.setBitstream(&nalu.getBitstream());
1534
1535
0
  CHECK(nalu.m_temporalId, "The value of TemporalId of DCI NAL units shall be equal to 0");
1536
0
  if( !m_dci )
1537
0
  {
1538
0
    m_dci = new DCI;
1539
0
    m_HLSReader.parseDCI( m_dci );
1540
0
  }
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
0
}
1548
1549
void DecLibParser::xDecodeSPS( InputNALUnit& nalu )
1550
0
{
1551
0
  std::unique_ptr<SPS> sps( new SPS() );
1552
0
  m_HLSReader.setBitstream( &nalu.getBitstream() );
1553
0
  m_HLSReader.parseSPS( sps.get(), &m_parameterSetManager );
1554
0
  sps->setLayerId( nalu.m_nuhLayerId );
1555
0
  DTRACE( g_trace_ctx, D_QP_PER_CTU, "CTU Size: %dx%d", sps->getMaxCUWidth(), sps->getMaxCUHeight() );  // don't move after storeSPS, because SPS could have been deleted
1556
0
  m_parameterSetManager.storeSPS( sps.release(), nalu.getBitstream().getFifo() );
1557
0
}
1558
1559
void DecLibParser::xDecodePPS( InputNALUnit& nalu )
1560
0
{
1561
0
  std::unique_ptr<PPS> pps( new PPS() );
1562
0
  m_HLSReader.setBitstream( &nalu.getBitstream() );
1563
0
  m_HLSReader.parsePPS( pps.get(), &m_parameterSetManager );
1564
0
  pps->setLayerId( nalu.m_nuhLayerId );
1565
0
  m_parameterSetManager.storePPS( pps.release(), nalu.getBitstream().getFifo() );
1566
0
}
1567
1568
void DecLibParser::xDecodeAPS( InputNALUnit& nalu )
1569
0
{
1570
0
  std::unique_ptr<APS> aps( new APS() );
1571
0
  m_HLSReader.setBitstream( &nalu.getBitstream() );
1572
0
  if( !m_HLSReader.parseAPS( aps.get() ) )
1573
0
  {   // ignore unsupported APS types
1574
0
    return;
1575
0
  }
1576
0
  aps->setTemporalId( nalu.m_temporalId );
1577
0
  aps->setLayerId( nalu.m_nuhLayerId );
1578
0
  aps->setHasPrefixNalUnitType( nalu.m_nalUnitType == NAL_UNIT_PREFIX_APS );
1579
0
  m_parameterSetManager.storeAPS( aps.release(), nalu.getBitstream().getFifo() );
1580
0
}
1581
1582
void DecLibParser::xUpdatePreviousTid0POC(Slice * pSlice)
1583
0
{
1584
0
  if( pSlice->getTLayer() == 0 && pSlice->getNalUnitType() != NAL_UNIT_CODED_SLICE_RASL && pSlice->getNalUnitType() != NAL_UNIT_CODED_SLICE_RADL
1585
0
      && !pSlice->getPicHeader()->getNonReferencePictureFlag() )
1586
0
  {
1587
0
    m_prevTid0POC = pSlice->getPOC();
1588
0
  }
1589
0
}
1590
1591
1592
void DecLibParser::checkNoOutputPriorPics()
1593
0
{
1594
0
  if( !m_isNoOutputPriorPics )
1595
0
  {
1596
0
    return;
1597
0
  }
1598
1599
0
  for( auto& pcPicTmp: m_dpbReferencePics )
1600
0
  {
1601
0
    if( pcPicTmp->progress >= Picture::reconstructed && pcPicTmp->getPOC() < m_lastPOCNoOutputPriorPics )
1602
0
    {
1603
0
      pcPicTmp->neededForOutput = false;
1604
0
    }
1605
0
  }
1606
0
}
1607
1608
/** Function for checking if picture should be skipped because of random access. This function checks the skipping of pictures in the case of -s option random access.
1609
 *  All pictures prior to the random access point indicated by the counter iSkipFrame are skipped.
1610
 *  It also checks the type of Nal unit type at the random access point.
1611
 *  If the random access point is CRA/CRANT/BLA/BLANT, TFD pictures with POC less than the POC of the random access point are skipped.
1612
 *  If the random access point is IDR all pictures after the random access point are decoded.
1613
 *  If the random access point is none of the above, a warning is issues, and decoding of pictures with POC
1614
 *  equal to or greater than the random access point POC is attempted. For non IDR/CRA/BLA random
1615
 *  access point there is no guarantee that the decoder will not crash.
1616
 */
1617
bool DecLibParser::isRandomAccessSkipPicture()
1618
0
{
1619
0
  if( m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP )
1620
0
  {
1621
0
    m_pocRandomAccess = -MAX_INT;   // no need to skip the reordered pictures in IDR, they are decodable.
1622
0
  }
1623
0
  else if( m_pocRandomAccess == MAX_INT )   // start of random access point, m_pocRandomAccess has not been set yet.
1624
0
  {
1625
0
#if GDR_ADJ
1626
0
    if( m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR )
1627
#else
1628
    if( m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA )
1629
#endif
1630
0
    {
1631
      // set the POC random access since we need to skip the reordered pictures in the case of CRA/CRANT/BLA/BLANT.
1632
0
      m_pocRandomAccess = m_apcSlicePilot->getPOC();
1633
0
    }
1634
0
    else
1635
0
    {
1636
0
      if( !m_warningMessageSkipPicture )
1637
0
      {
1638
0
        msg( WARNING, "Warning: this is not a valid random access point and the data is discarded until the first CRA picture\n" );
1639
0
        m_warningMessageSkipPicture = true;
1640
0
      }
1641
0
      return true;
1642
0
    }
1643
0
  }
1644
  // skip the reordered pictures, if necessary
1645
0
  else if( m_apcSlicePilot->getPOC() < m_pocRandomAccess && ( m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_RASL ) )
1646
0
  {
1647
0
    return true;
1648
0
  }
1649
  // if we reach here, then the picture is not skipped.
1650
0
  return false;
1651
0
}
1652
1653
void DecLibParser::xCheckMixedNalUnit( Slice* pcSlice, const InputNALUnit& nalu )
1654
0
{
1655
0
  if( pcSlice->getPPS()->getMixedNaluTypesInPicFlag() )
1656
0
  {
1657
0
    CHECK(pcSlice->getPPS()->getNumSlicesInPic() < 2, "mixed nal unit type picture, but with less than 2 slices");
1658
1659
0
    CHECK( pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR, "picture with mixed NAL unit type cannot have GDR slice");
1660
1661
    //Check that if current slice is IRAP type, the other type of NAL can only be TRAIL_NUT
1662
0
    if( pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL
1663
0
        || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP
1664
0
        || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA )
1665
0
    {
1666
0
      for( int i = 0; i < m_uiSliceSegmentIdx; i++ )
1667
0
      {
1668
0
        Slice* preSlice = m_pcParsePic->slices[i];
1669
0
        CHECK( pcSlice->getNalUnitType() != preSlice->getNalUnitType()
1670
0
                 && preSlice->getNalUnitType() != NAL_UNIT_CODED_SLICE_TRAIL,
1671
0
               "In a mixed NAL unt type picture, an IRAP slice can be mixed with Trail slice(s) only" );
1672
0
      }
1673
0
    }
1674
1675
    // if this is the last slice of the picture, check whether that there are at least two different NAL unit types in the picture
1676
0
    if( pcSlice->getPPS()->getNumSlicesInPic() == (m_uiSliceSegmentIdx + 1) )
1677
0
    {
1678
0
      bool hasDiffTypes = false;
1679
0
      for( int i = 1; !hasDiffTypes && i <= m_uiSliceSegmentIdx; i++ )
1680
0
      {
1681
0
        Slice* slice1 = m_pcParsePic->slices[i-1];
1682
0
        Slice* slice2 = m_pcParsePic->slices[i];
1683
0
        if( slice1->getNalUnitType() != slice2->getNalUnitType())
1684
0
        {
1685
0
          hasDiffTypes = true;
1686
0
        }
1687
0
      }
1688
0
      CHECK( !hasDiffTypes, "VCL NAL units of the picture shall have two or more different nal_unit_type values");
1689
0
    }
1690
0
  }
1691
0
  else   // all slices shall have the same nal unit type
1692
0
  {
1693
0
    bool sameNalUnitType = true;
1694
0
    for( int i = 0; i < m_uiSliceSegmentIdx; i++ )
1695
0
    {
1696
0
      Slice* PreSlice = m_pcParsePic->slices[i];
1697
0
      if( PreSlice->getNalUnitType() != pcSlice->getNalUnitType() )
1698
0
      {
1699
0
        sameNalUnitType = false;
1700
0
      }
1701
0
    }
1702
0
    CHECK( !sameNalUnitType, "mixed_nalu_types_in_pic_flag is zero, but have different nal unit types" );
1703
0
  }
1704
0
}
1705
1706
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