Coverage Report

Created: 2026-09-14 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/vvdec/source/Lib/DecoderLib/SEIread.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
/**
44
 \file     SEIread.cpp
45
 \brief    reading funtionality for SEI messages
46
 */
47
48
#include "CommonLib/CommonDef.h"
49
#include "CommonLib/BitStream.h"
50
#include "CommonLib/Slice.h"
51
#include "VLCReader.h"
52
#include "SEIread.h"
53
#include "CommonLib/Picture.h"
54
#include "CommonLib/dtrace_next.h"
55
#include <iomanip>
56
57
#include "vvdec/sei.h"
58
59
namespace vvdec
60
{
61
62
#if ENABLE_TRACING
63
void  xTraceSEIHeader()
64
{
65
  DTRACE( g_trace_ctx, D_HEADER, "=========== SEI message ===========\n");
66
}
67
68
void  xTraceSEIMessageType(vvdecSEIPayloadType payloadType)
69
{
70
  DTRACE( g_trace_ctx, D_HEADER, "=========== %s SEI message ===========\n", SEI_internal::getSEIMessageString( payloadType ) );
71
}
72
#endif
73
74
void SEIReader::sei_read_scode(std::ostream *pOS, uint32_t length, int& code, const char *pSymbolName)
75
0
{
76
0
  READ_SCODE(length, code, pSymbolName);
77
0
  if (pOS)
78
0
  {
79
0
    (*pOS) << "  " << std::setw(55) << pSymbolName << ": " << code << "\n";
80
0
  }
81
0
}
82
83
void SEIReader::sei_read_code(std::ostream *pOS, uint32_t uiLength, uint32_t& ruiCode, const char *pSymbolName)
84
0
{
85
0
  READ_CODE(uiLength, ruiCode, pSymbolName);
86
0
  if (pOS)
87
0
  {
88
0
    (*pOS) << "  " << std::setw(55) << pSymbolName << ": " << ruiCode << "\n";
89
0
  }
90
0
}
91
92
void SEIReader::sei_read_uvlc(std::ostream *pOS, uint32_t& ruiCode, const char *pSymbolName)
93
0
{
94
0
  READ_UVLC(ruiCode, pSymbolName);
95
0
  if (pOS)
96
0
  {
97
0
    (*pOS) << "  " << std::setw(55) << pSymbolName << ": " << ruiCode << "\n";
98
0
  }
99
0
}
100
101
void SEIReader::sei_read_svlc(std::ostream *pOS, int& ruiCode, const char *pSymbolName)
102
0
{
103
0
  READ_SVLC(ruiCode, pSymbolName);
104
0
  if (pOS)
105
0
  {
106
0
    (*pOS) << "  " << std::setw(55) << pSymbolName << ": " << ruiCode << "\n";
107
0
  }
108
0
}
109
110
void SEIReader::sei_read_flag(std::ostream *pOS, uint32_t& ruiCode, const char *pSymbolName)
111
0
{
112
0
  READ_FLAG(ruiCode, pSymbolName);
113
0
  if (pOS)
114
0
  {
115
0
    (*pOS) << "  " << std::setw(55) << pSymbolName << ": " << (ruiCode?1:0) << "\n";
116
0
  }
117
0
}
118
119
static inline void output_sei_message_header(vvdecSEI* sei, std::ostream *pDecodedMessageOutputStream, uint32_t payloadSize)
120
0
{
121
0
  if (pDecodedMessageOutputStream)
122
0
  {
123
0
    std::string seiMessageHdr(SEI_internal::getSEIMessageString(sei->payloadType)); seiMessageHdr+=" SEI message";
124
0
    (*pDecodedMessageOutputStream) << std::setfill('-') << std::setw((int)seiMessageHdr.size()) << "-" << std::setfill(' ') << "\n" << seiMessageHdr << " (" << payloadSize << " bytes)"<< "\n";
125
0
  }
126
0
}
127
128
#undef READ_CODE
129
#undef READ_SCODE
130
#undef READ_SVLC
131
#undef READ_UVLC
132
#undef READ_FLAG
133
134
135
/**
136
 * unmarshal a single SEI message from bitstream bs
137
 */
138
void SEIReader::parseSEImessage(InputBitstream* bs, seiMessages& seiList,
139
                                const NalUnitType nalUnitType, const uint32_t nuh_layer_id, const uint32_t temporalId,
140
                                const VPS *vps, const SPS *sps, HRD &hrd, std::ostream *pDecodedMessageOutputStream )
141
0
{
142
0
  setBitstream(bs);
143
0
  CHECK(m_pcBitstream->getNumBitsUntilByteAligned(), "Bitstream not aligned");
144
145
0
  seiMessages seiListInCurNalu;
146
0
  do
147
0
  {
148
0
    xReadSEImessage( seiList, nalUnitType, nuh_layer_id, temporalId, vps, sps, hrd, pDecodedMessageOutputStream);
149
0
    if( !seiList.empty() ){  seiListInCurNalu.push_back(seiList.back()); }
150
    /* SEI messages are an integer number of bytes, something has failed
151
    * in the parsing if bitstream not byte-aligned */
152
0
    CHECK(m_pcBitstream->getNumBitsUntilByteAligned(), "Bitstream not aligned");
153
0
  }
154
0
  while (m_pcBitstream->getNumBitsLeft() > 8);
155
156
0
  seiMessages fillerData = SEI_internal::getSeisByType(seiListInCurNalu, VVDEC_FILLER_PAYLOAD);
157
0
  CHECK(fillerData.size() > 0 && fillerData.size() != seiListInCurNalu.size(), "When an SEI NAL unit contains an SEI message with payloadType equal to filler payload, the SEI NAL unit shall not contain any other SEI message with payloadType not equal to filler payload");
158
159
0
  xReadRbspTrailingBits();
160
0
}
161
162
void SEIReader::xReadSEImessage( seiMessages& seiList, const NalUnitType nalUnitType, const uint32_t nuh_layer_id,
163
                                const uint32_t temporalId, const VPS *vps, const SPS *sps, HRD &hrd, std::ostream *pDecodedMessageOutputStream)
164
0
{
165
#if ENABLE_TRACING
166
  xTraceSEIHeader();
167
#endif
168
0
  int payloadType = 0;
169
0
  uint32_t val = 0;
170
171
0
  do
172
0
  {
173
0
    sei_read_code(NULL, 8, val, "payload_type");
174
0
    payloadType += val;
175
0
  } while (val==0xFF);
176
177
0
  uint32_t payloadSize = 0;
178
0
  do
179
0
  {
180
0
    sei_read_code(NULL, 8, val, "payload_size");
181
0
    payloadSize += val;
182
0
  } while (val==0xFF);
183
184
#if ENABLE_TRACING
185
  xTraceSEIMessageType((vvdecSEIPayloadType)payloadType);
186
#endif
187
188
  /* extract the payload for this single SEI message.
189
   * This allows greater safety in erroneous parsing of an SEI message
190
   * from affecting subsequent messages.
191
   * After parsing the payload, bs needs to be restored as the primary
192
   * bitstream.
193
   */
194
0
  InputBitstream *bs = getBitstream();
195
0
  auto substream = bs->extractSubstream( payloadSize * 8 );
196
0
  setBitstream( substream.get() );
197
198
0
  const vvdecSEIBufferingPeriod *bp = NULL;
199
200
0
  vvdecSEI *s = NULL;
201
0
  vvdecSEIPayloadType type = (vvdecSEIPayloadType)payloadType;
202
203
0
  try
204
0
  {
205
0
    if(nalUnitType == NAL_UNIT_PREFIX_SEI)
206
0
    {
207
0
      switch (payloadType)
208
0
      {
209
0
      case VVDEC_USER_DATA_REGISTERED_ITU_T_T35:
210
0
            s = SEI_internal::allocSEI( type ) ;
211
0
            xParseSEIUserDataRegistered( s, payloadSize, pDecodedMessageOutputStream);
212
0
            break;
213
0
      case VVDEC_USER_DATA_UNREGISTERED:
214
0
            s = SEI_internal::allocSEI( type ) ;
215
0
            xParseSEIuserDataUnregistered(s, payloadSize, pDecodedMessageOutputStream);
216
0
        break;
217
0
      case VVDEC_DECODING_UNIT_INFO:
218
0
        bp = hrd.getBufferingPeriodSEI();
219
0
        if (!bp)
220
0
        {
221
0
          msg( WARNING, "Warning: Found Decoding unit information SEI message, but no active buffering period is available. Ignoring.");
222
0
        }
223
0
        else
224
0
        {
225
0
          s = SEI_internal::allocSEI( type ) ;
226
0
          xParseSEIDecodingUnitInfo( s, payloadSize, *bp, temporalId, pDecodedMessageOutputStream);
227
0
        }
228
0
        break;
229
0
      case VVDEC_BUFFERING_PERIOD:
230
0
          s = SEI_internal::allocSEI( type ) ;
231
0
          xParseSEIBufferingPeriod(s, payloadSize, pDecodedMessageOutputStream);
232
0
          if( s )
233
0
          {
234
0
            vvdecSEIBufferingPeriod* bufferingPeriod = reinterpret_cast<vvdecSEIBufferingPeriod *>(s->payload);
235
0
            hrd.setBufferingPeriodSEI(bufferingPeriod);
236
0
          }
237
0
        break;
238
0
      case VVDEC_PICTURE_TIMING:
239
0
        {
240
0
          bp = hrd.getBufferingPeriodSEI();
241
0
          if (!bp)
242
0
          {
243
0
            msg( WARNING, "Warning: Found Picture timing SEI message, but no active buffering period is available. Ignoring.");
244
0
          }
245
0
          else
246
0
          {
247
0
            s = SEI_internal::allocSEI( type ) ;
248
0
            xParseSEIPictureTiming(s, payloadSize, temporalId, *bp, pDecodedMessageOutputStream);
249
0
            if( s )
250
0
            {
251
0
              vvdecSEIPictureTiming* picTiming= reinterpret_cast<vvdecSEIPictureTiming *>(s->payload);
252
0
              hrd.setPictureTimingSEI( picTiming );
253
0
            }
254
0
          }
255
0
        }
256
0
        break;
257
0
      case VVDEC_SCALABLE_NESTING:
258
0
          s = SEI_internal::allocSEI( type ) ;
259
0
          xParseSEIScalableNesting(s, nalUnitType, nuh_layer_id, payloadSize, vps, sps, pDecodedMessageOutputStream);
260
0
        break;
261
0
      case VVDEC_FRAME_FIELD_INFO:
262
0
          s = SEI_internal::allocSEI( type ) ;
263
0
          xParseSEIFrameFieldinfo( s, payloadSize, pDecodedMessageOutputStream);
264
0
        break;
265
0
      case VVDEC_DEPENDENT_RAP_INDICATION:
266
0
          s = SEI_internal::allocSEI( type ) ;
267
0
          xParseSEIDependentRAPIndication( s, payloadSize, pDecodedMessageOutputStream);
268
0
        break;
269
0
      case VVDEC_FRAME_PACKING:
270
0
          s = SEI_internal::allocSEI( type ) ;
271
0
          xParseSEIFramePacking( s, payloadSize, pDecodedMessageOutputStream);
272
0
        break;
273
0
      case VVDEC_PARAMETER_SETS_INCLUSION_INDICATION:
274
0
          s = SEI_internal::allocSEI( type ) ;
275
0
          xParseSEIParameterSetsInclusionIndication( s, payloadSize, pDecodedMessageOutputStream);
276
0
        break;
277
0
      case VVDEC_MASTERING_DISPLAY_COLOUR_VOLUME:
278
0
          s = SEI_internal::allocSEI( type ) ;
279
0
          xParseSEIMasteringDisplayColourVolume( s, payloadSize, pDecodedMessageOutputStream);
280
0
        break;
281
0
  #if U0033_ALTERNATIVE_TRANSFER_CHARACTERISTICS_SEI
282
0
      case VVDEC_ALTERNATIVE_TRANSFER_CHARACTERISTICS:
283
0
          s = SEI_internal::allocSEI( type ) ;
284
0
          xParseSEIAlternativeTransferCharacteristics( s, payloadSize, pDecodedMessageOutputStream);
285
0
        break;
286
0
  #endif
287
0
      case VVDEC_EQUIRECTANGULAR_PROJECTION:
288
0
          s = SEI_internal::allocSEI( type ) ;
289
0
          xParseSEIEquirectangularProjection( s, payloadSize, pDecodedMessageOutputStream);
290
0
        break;
291
0
      case VVDEC_SPHERE_ROTATION:
292
0
          s = SEI_internal::allocSEI( type ) ;
293
0
          xParseSEISphereRotation( s, payloadSize, pDecodedMessageOutputStream);
294
0
        break;
295
0
      case VVDEC_OMNI_VIEWPORT:
296
0
          s = SEI_internal::allocSEI( type ) ;
297
0
          xParseSEIOmniViewport( s, payloadSize, pDecodedMessageOutputStream);
298
0
        break;
299
0
      case VVDEC_REGION_WISE_PACKING:
300
0
          s = SEI_internal::allocSEI( type ) ;
301
0
          xParseSEIRegionWisePacking( s, payloadSize, pDecodedMessageOutputStream);
302
0
        break;
303
0
      case VVDEC_GENERALIZED_CUBEMAP_PROJECTION:
304
0
          s = SEI_internal::allocSEI( type ) ;
305
0
          xParseSEIGeneralizedCubemapProjection( s, payloadSize, pDecodedMessageOutputStream);
306
0
        break;
307
0
      case VVDEC_SUBPICTURE_LEVEL_INFO:
308
0
          s = SEI_internal::allocSEI( type ) ;
309
0
          xParseSEISubpictureLevelInfo(s, payloadSize, pDecodedMessageOutputStream);
310
0
        break;
311
0
      case VVDEC_SAMPLE_ASPECT_RATIO_INFO:
312
0
          s = SEI_internal::allocSEI( type ) ;
313
0
          xParseSEISampleAspectRatioInfo( s, payloadSize, pDecodedMessageOutputStream);
314
0
        break;
315
0
      case VVDEC_FILM_GRAIN_CHARACTERISTICS:
316
0
          s = SEI_internal::allocSEI( type ) ;
317
0
          xParseSEIFilmGrainCharacteristics(s, payloadSize, pDecodedMessageOutputStream);
318
0
        break;
319
0
      case VVDEC_CONTENT_LIGHT_LEVEL_INFO:
320
0
          s = SEI_internal::allocSEI( type ) ;
321
0
          xParseSEIContentLightLevelInfo( s, payloadSize, pDecodedMessageOutputStream);
322
0
        break;
323
0
      case VVDEC_AMBIENT_VIEWING_ENVIRONMENT:
324
0
          s = SEI_internal::allocSEI( type ) ;
325
0
          xParseSEIAmbientViewingEnvironment( s, payloadSize, pDecodedMessageOutputStream);
326
0
        break;
327
0
      case VVDEC_CONTENT_COLOUR_VOLUME:
328
0
          s = SEI_internal::allocSEI( type ) ;
329
0
          xParseSEIContentColourVolume( s, payloadSize, pDecodedMessageOutputStream);
330
0
        break;
331
0
      default:
332
0
        for (uint32_t i = 0; i < payloadSize; i++)
333
0
        {
334
0
          uint32_t seiByte;
335
0
          sei_read_code (NULL, 8, seiByte, "unknown prefix SEI payload byte");
336
0
        }
337
0
        msg( WARNING, "Unknown prefix SEI message (payloadType = %d) was found!\n", payloadType);
338
0
        if (pDecodedMessageOutputStream)
339
0
        {
340
0
          (*pDecodedMessageOutputStream) << "Unknown prefix SEI message (payloadType = " << payloadType << ") was found!\n";
341
0
        }
342
0
        break;
343
0
      }
344
0
    }
345
0
    else
346
0
    {
347
0
      switch (payloadType)
348
0
      {
349
0
        case VVDEC_USER_DATA_UNREGISTERED:
350
0
          s = SEI_internal::allocSEI( type ) ;
351
0
          xParseSEIuserDataUnregistered(s, payloadSize, pDecodedMessageOutputStream);
352
0
          break;
353
0
        case  VVDEC_DECODED_PICTURE_HASH:
354
0
          s = SEI_internal::allocSEI( type ) ;
355
0
          xParseSEIDecodedPictureHash(s, payloadSize, pDecodedMessageOutputStream);
356
0
          break;
357
0
        case VVDEC_SCALABLE_NESTING:
358
0
          s = SEI_internal::allocSEI( type ) ;
359
0
          xParseSEIScalableNesting(s, nalUnitType, nuh_layer_id, payloadSize, vps, sps, pDecodedMessageOutputStream);
360
0
          break;
361
0
        default:
362
0
          for (uint32_t i = 0; i < payloadSize; i++)
363
0
          {
364
0
            uint32_t seiByte;
365
0
            sei_read_code( NULL, 8, seiByte, "unknown suffix SEI payload byte");
366
0
          }
367
0
          msg( WARNING, "Unknown suffix SEI message (payloadType = %d) was found!\n", payloadType);
368
0
          if (pDecodedMessageOutputStream)
369
0
          {
370
0
            (*pDecodedMessageOutputStream) << "Unknown suffix SEI message (payloadType = " << payloadType << ") was found!\n";
371
0
          }
372
0
          break;
373
0
      }
374
0
    }
375
376
0
    if( s )
377
0
    {
378
0
      seiList.push_back(s);
379
0
    }
380
0
  }
381
0
  catch( ... )
382
0
  {
383
0
    SEI_internal::deleteSEI( s );
384
0
    throw;
385
0
  }
386
387
  /* By definition the underlying bitstream terminates in a byte-aligned manner.
388
   * 1. Extract all bar the last MIN(bitsremaining,nine) bits as reserved_payload_extension_data
389
   * 2. Examine the final 8 bits to determine the payload_bit_equal_to_one marker
390
   * 3. Extract the remainingreserved_payload_extension_data bits.
391
   *
392
   * If there are fewer than 9 bits available, extract them.
393
   */
394
0
  int payloadBitsRemaining = getBitstream()->getNumBitsLeft();
395
0
  if (payloadBitsRemaining) /* more_data_in_payload() */
396
0
  {
397
0
    for (; payloadBitsRemaining > 9; payloadBitsRemaining--)
398
0
    {
399
0
      uint32_t reservedPayloadExtensionData;
400
0
      sei_read_code ( pDecodedMessageOutputStream, 1, reservedPayloadExtensionData, "reserved_payload_extension_data");
401
0
    }
402
403
    /* 2 */
404
0
    int finalBits = getBitstream()->peekBits(payloadBitsRemaining);
405
0
    int finalPayloadBits = 0;
406
0
    for (int mask = 0xff; finalBits & (mask >> finalPayloadBits); finalPayloadBits++)
407
0
    {
408
0
      continue;
409
0
    }
410
411
    /* 3 */
412
0
    for (; payloadBitsRemaining > 9 - finalPayloadBits; payloadBitsRemaining--)
413
0
    {
414
0
      uint32_t reservedPayloadExtensionData;
415
0
      sei_read_flag ( 0, reservedPayloadExtensionData, "reserved_payload_extension_data");
416
0
    }
417
418
0
    uint32_t dummy;
419
0
    sei_read_flag( 0, dummy, "payload_bit_equal_to_one"); payloadBitsRemaining--;
420
0
    while (payloadBitsRemaining)
421
0
    {
422
0
      sei_read_flag( 0, dummy, "payload_bit_equal_to_zero"); payloadBitsRemaining--;
423
0
    }
424
0
  }
425
426
  /* restore primary bitstream for sei_message */
427
0
  setBitstream( bs );
428
0
}
429
430
431
432
/**
433
 * parse bitstream bs and unpack a decoded picture hash SEI message
434
 * of payloadSize bytes into sei.
435
 */
436
void SEIReader::xParseSEIDecodedPictureHash(vvdecSEI* s, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream)
437
0
{
438
0
  uint32_t bytesRead = 0;
439
0
  output_sei_message_header(s, pDecodedMessageOutputStream, payloadSize);
440
441
0
  CHECK_FATAL( !s || s->payload == NULL, "allocation error in vvdecSEIDecodedPictureHash" );
442
443
0
  vvdecSEIDecodedPictureHash* sei =(vvdecSEIDecodedPictureHash*)s->payload;
444
0
  ::memset(sei, 0, sizeof(vvdecSEIDecodedPictureHash));
445
446
0
  uint32_t val;
447
0
  sei_read_code( pDecodedMessageOutputStream, 8, val, "dph_sei_hash_type" );
448
0
  CHECK_READ_RANGE( val, 0, VVDEC_HASHTYPE_NONE, "dph_sei_hash_type" );
449
0
  sei->method = static_cast<vvdecHashType>(val); bytesRead++;
450
0
  sei_read_code( pDecodedMessageOutputStream, 1, val, "dph_sei_single_component_flag");
451
0
  sei->singleCompFlag = val;
452
0
  sei_read_code( pDecodedMessageOutputStream, 7, val, "dph_sei_reserved_zero_7bits");
453
0
  bytesRead++;
454
0
  uint32_t expectedSize = ( sei->singleCompFlag ? 1 : 3 ) * (sei->method == 0 ? 16 : (sei->method == 1 ? 2 : 4));
455
0
  CHECK ((payloadSize - bytesRead) != expectedSize, "The size of the decoded picture hash does not match the expected size.");
456
457
0
  const char *traceString="\0";
458
0
  switch (sei->method)
459
0
  {
460
0
    case VVDEC_HASHTYPE_MD5: traceString="picture_md5"; break;
461
0
    case VVDEC_HASHTYPE_CRC: traceString="picture_crc"; break;
462
0
    case VVDEC_HASHTYPE_CHECKSUM: traceString="picture_checksum"; break;
463
0
    default: THROW_RECOVERABLE("Unknown hash type"); break;
464
0
  }
465
466
0
  if (pDecodedMessageOutputStream)
467
0
  {
468
0
    (*pDecodedMessageOutputStream) << "  " << std::setw(55) << traceString << ": " << std::hex << std::setfill('0');
469
0
  }
470
471
0
  CHECK( payloadSize-bytesRead > 48, "payload size of digest must be <= 48 in vvdecSEIDecodedPictureHash" );
472
0
  for(int i=0;bytesRead < payloadSize; bytesRead++,i++)
473
0
  {
474
0
    sei_read_code( NULL, 8, val, traceString);
475
0
    sei->digest[i] = (uint8_t)val;
476
0
    sei->digest_length++;
477
478
0
    if (pDecodedMessageOutputStream)
479
0
    {
480
0
      (*pDecodedMessageOutputStream) << std::setw(2) << val;
481
0
    }
482
0
  }
483
484
0
  if (pDecodedMessageOutputStream)
485
0
  {
486
0
    (*pDecodedMessageOutputStream) << std::dec << std::setfill(' ') << "\n";
487
0
  }
488
0
}
489
490
void SEIReader::xParseSEIScalableNesting(vvdecSEI* s, const NalUnitType nalUnitType, const uint32_t nuhLayerId, uint32_t payloadSize, const VPS *vps, const SPS *sps, std::ostream *decodedMessageOutputStream)
491
0
{
492
0
  uint32_t symbol;
493
0
  output_sei_message_header(s, decodedMessageOutputStream, payloadSize);
494
495
0
  CHECK_FATAL( !s || s->payload == NULL, "allocation error in vvdecSEIScalableNesting" );
496
0
  vvdecSEIScalableNesting* sei =(vvdecSEIScalableNesting*)s->payload;
497
0
  ::memset(sei, 0, sizeof(vvdecSEIScalableNesting));
498
499
0
  sei_read_flag(decodedMessageOutputStream, symbol, "sn_ols_flag");    sei->snOlsFlag = symbol;
500
0
  sei_read_flag(decodedMessageOutputStream, symbol, "sn_subpic_flag"); sei->snSubpicFlag = symbol;
501
0
  if (sei->snOlsFlag)
502
0
  {
503
0
    sei_read_uvlc(decodedMessageOutputStream, symbol, "sn_num_olss_minus1"); sei->snNumOlss = symbol+1;
504
0
    CHECK( sei->snNumOlss > 64, "sn_num_olss_minus1 must be < 64 in vvdecSEIScalableNesting" );
505
506
0
    for (uint32_t i = 0; i < sei->snNumOlss; i++)
507
0
    {
508
0
      sei_read_uvlc(decodedMessageOutputStream, symbol, "sn_ols_idx_delta_minus1[i]"); sei->snOlsIdxDelta[i] = symbol+1;
509
0
    }
510
0
    for (uint32_t i = 0; i < sei->snNumOlss; i++)
511
0
    {
512
0
      if (i == 0)
513
0
      {
514
0
        sei->snOlsIdx[i] = sei->snOlsIdxDelta[i]-1;
515
0
      }
516
0
      else
517
0
      {
518
0
        sei->snOlsIdx[i] = sei->snOlsIdxDelta[i]-1 + sei->snOlsIdxDelta[i - 1];
519
0
      }
520
0
    }
521
0
    if (vps && vps->getVPSId() != 0)
522
0
    {
523
0
      uint32_t lowestLayerId = MAX_UINT;
524
0
      for (uint32_t olsIdxForSEI = 0; olsIdxForSEI < sei->snNumOlss; olsIdxForSEI++)
525
0
      {
526
0
        int olsIdx = sei->snOlsIdx[olsIdxForSEI];
527
0
        for (int layerIdx = 0; layerIdx < vps->getNumLayersInOls(olsIdx); layerIdx++)
528
0
        {
529
0
          if (lowestLayerId > vps->getLayerIdInOls(olsIdx, layerIdx))
530
0
          {
531
0
            lowestLayerId = vps->getLayerIdInOls(olsIdx, layerIdx);
532
0
          }
533
0
        }
534
0
      }
535
0
      CHECK(lowestLayerId!= nuhLayerId, "nuh_layer_id is not equal to the lowest layer among Olss that the scalable SEI applies");
536
0
    }
537
0
  }
538
0
  else
539
0
  {
540
0
    sei_read_flag(decodedMessageOutputStream, symbol, "sn_all_layers_flag"); sei->snAllLayersFlag = symbol;
541
0
    if (!sei->snAllLayersFlag)
542
0
    {
543
0
      sei_read_uvlc(decodedMessageOutputStream, symbol, "sn_num_layers_minus1"); sei->snNumLayers = symbol+1;
544
0
      CHECK( sei->snNumLayers > 64, "sn_num_layers_minus1 must be < 64 in vvdecSEIScalableNesting" );
545
0
      sei->snLayerId[0] = nuhLayerId;
546
0
      for (uint32_t i = 1; i < sei->snNumLayers; i++)
547
0
      {
548
0
        sei_read_code(decodedMessageOutputStream, 6, symbol, "sn_layer_id[i]"); sei->snLayerId[i] = symbol;
549
0
      }
550
0
    }
551
0
  }
552
0
  if (sei->snSubpicFlag)
553
0
  {
554
0
    sei_read_uvlc(decodedMessageOutputStream, symbol, "sn_num_subpics_minus1"); sei->snNumSubpics = symbol + 1;
555
0
    CHECK( sei->snNumSubpics > 64, "sn_num_subpics_minus1 must be < 64 in vvdecSEIScalableNesting" );
556
0
    sei_read_uvlc(decodedMessageOutputStream, symbol, "sn_subpic_id_len_minus1"); sei->snSubpicIdLen = symbol + 1;
557
0
    CHECK( sei->snSubpicIdLen > 16, "sn_subpic_id_len_minus1 must be < 16 in vvdecSEIScalableNesting" );
558
0
    for (uint32_t i = 0; i < sei->snNumSubpics; i++)
559
0
    {
560
0
      sei_read_code(decodedMessageOutputStream, sei->snSubpicIdLen, symbol, "sn_subpic_id[i]"); sei->snSubpicId[i] = symbol;
561
0
    }
562
0
  }
563
564
0
  sei_read_uvlc(decodedMessageOutputStream, symbol, "sn_num_seis_minus1"); sei->snNumSEIs = symbol + 1;
565
0
  CHECK (sei->snNumSEIs > 64, "The value of sn_num_seis_minus1 shall be in the range of 0 to 63");
566
567
  // byte alignment
568
0
  while( m_pcBitstream->getNumBitsUntilByteAligned() )
569
0
  {
570
0
    sei_read_flag(decodedMessageOutputStream, symbol, "sn_zero_bit");
571
0
  }
572
573
  // read nested SEI messages
574
0
  for (uint32_t i=0; i<sei->snNumSEIs; i++)
575
0
  {
576
0
    seiMessages tmpSeiList;
577
0
    xReadSEImessage(tmpSeiList, nalUnitType, nuhLayerId, 0, vps, sps, m_nestedHrd, decodedMessageOutputStream);
578
0
    CHECK( tmpSeiList.empty(), "read empty nested sei list." );
579
580
0
    sei->nestedSEIs[i] = tmpSeiList.front();
581
0
  }
582
583
0
  xCheckScalableNestingConstraints(sei, nalUnitType, vps);
584
585
0
  if (decodedMessageOutputStream)
586
0
  {
587
0
    (*decodedMessageOutputStream) << "End of scalable nesting SEI message\n";
588
0
  }
589
0
}
590
591
void SEIReader::xCheckScalableNestingConstraints(const vvdecSEIScalableNesting* sei, const NalUnitType nalUnitType, const VPS* vps)
592
0
{
593
0
  const std::vector<int> vclAssociatedSeiList { 3, 19, 45, 129, 137, 144, 145, 147, 148, 149, 150, 153, 154, 155, 156, 168, 204 };
594
595
0
  bool containBPorPTorDUIorSLI = false;
596
0
  bool containNoBPorPTorDUIorSLI = false;
597
598
0
  for (auto* nestedsei : sei->nestedSEIs)
599
0
  {
600
0
    if( !nestedsei )
601
0
    {
602
0
      continue;
603
0
    }
604
0
    CHECK(nestedsei->payloadType == VVDEC_FILLER_PAYLOAD || nestedsei->payloadType == VVDEC_SCALABLE_NESTING, "An SEI message that has payloadType equal to filler payload or scalable nesting shall not be contained in a scalable nesting SEI message");
605
606
0
    CHECK(nestedsei->payloadType != VVDEC_FILLER_PAYLOAD && nestedsei->payloadType != VVDEC_DECODED_PICTURE_HASH && nalUnitType != NAL_UNIT_PREFIX_SEI, "When a scalable nesting SEI message contains an SEI message that has payloadType not equal to filler payload or decoded picture hash, the SEI NAL unit containing the scalable nesting SEI message shall have nal_unit_type equal to PREFIX_SEI_NUT");
607
608
0
    CHECK(nestedsei->payloadType == VVDEC_DECODED_PICTURE_HASH && nalUnitType != NAL_UNIT_SUFFIX_SEI, "When a scalable nesting SEI message contains an SEI message that has payloadType equal to decoded picture hash, the SEI NAL unit containing the scalable nesting SEI message shall have nal_unit_type equal to SUFFIX_SEI_NUT");
609
610
0
    CHECK(nestedsei->payloadType == VVDEC_DECODED_PICTURE_HASH && !sei->snSubpicFlag, "When the scalable nesting SEI message contains an SEI message that has payloadType equal to decoded picture hash, the value of sn_subpic_flag shall be equal to 1");
611
612
0
    CHECK(nestedsei->payloadType == VVDEC_SUBPICTURE_LEVEL_INFO && sei->snSubpicFlag, "When the scalable nesting SEI message contains an SEI message that has payloadType equal to SLI, the value of sn_subpic_flag shall be equal to 0");
613
614
0
    if( vps )
615
0
    {
616
0
      CHECK( vps->getGeneralHrdParameters()->getGeneralSamePicTimingInAllOlsFlag() && nestedsei->payloadType == VVDEC_PICTURE_TIMING,
617
0
             "When general_same_pic_timing_in_all_ols_flag is equal to 1, there shall be no SEI NAL unit that contain a scalable-nested SEI message with payloadType equal to PT" );
618
0
    }
619
620
0
    for (int i = 0; i < (int)vclAssociatedSeiList.size(); i++)
621
0
    {
622
0
      CHECK(nestedsei->payloadType == vclAssociatedSeiList[i] && sei->snOlsFlag, "When the scalable nesting SEI message contains an SEI message that has payloadType equal to a value in vclAssociatedSeiList, the value of sn_ols_flag shall be equal to 0");
623
0
    }
624
625
0
    if (nestedsei->payloadType == VVDEC_BUFFERING_PERIOD || nestedsei->payloadType == VVDEC_PICTURE_TIMING || nestedsei->payloadType == VVDEC_DECODING_UNIT_INFO || nestedsei->payloadType == VVDEC_SUBPICTURE_LEVEL_INFO)
626
0
    {
627
0
      containBPorPTorDUIorSLI = true;
628
0
      CHECK(!sei->snOlsFlag, "When the scalable nesting SEI message contains an SEI message that has payloadType equal to BP, PT, or DUI, or SLI, the value of sn_ols_flag shall be equal to 1");
629
0
    }
630
0
    if (!(nestedsei->payloadType == VVDEC_BUFFERING_PERIOD || nestedsei->payloadType == VVDEC_PICTURE_TIMING || nestedsei->payloadType == VVDEC_DECODING_UNIT_INFO || nestedsei->payloadType == VVDEC_SUBPICTURE_LEVEL_INFO))
631
0
    {
632
0
      containNoBPorPTorDUIorSLI = true;
633
0
    }
634
0
  }
635
0
  CHECK(containBPorPTorDUIorSLI && containNoBPorPTorDUIorSLI, "When a scalable nesting SEI message contains a BP, PT, DUI, or SLI SEI message, the scalable nesting SEI message shall not contain any other SEI message with payloadType not equal to BP, PT, DUI, or SLI");
636
0
}
637
638
void SEIReader::xParseSEIDecodingUnitInfo(vvdecSEI* s, uint32_t payloadSize, const vvdecSEIBufferingPeriod& bp, const uint32_t temporalId, std::ostream *pDecodedMessageOutputStream)
639
0
{
640
0
  uint32_t val;
641
642
0
  output_sei_message_header(s, pDecodedMessageOutputStream, payloadSize);
643
0
  CHECK_FATAL( !s || s->payload == NULL, "allocation error in vvdecSEIDecodingUnitInfo" );
644
0
  vvdecSEIDecodingUnitInfo* sei =(vvdecSEIDecodingUnitInfo*)s->payload;
645
0
  ::memset(sei, 0, sizeof(vvdecSEIDecodingUnitInfo));
646
647
0
  sei_read_uvlc( pDecodedMessageOutputStream, val, "decoding_unit_idx");
648
0
  sei->decodingUnitIdx = val;
649
650
0
  if(!bp.decodingUnitCpbParamsInPicTimingSeiFlag)
651
0
  {
652
0
    for (int i = temporalId; i <= bp.bpMaxSubLayers - 1; i++)
653
0
    {
654
0
      if (i < (bp.bpMaxSubLayers - 1))
655
0
      {
656
0
        sei_read_flag( pDecodedMessageOutputStream, val, "dui_sub_layer_delays_present_flag[i]" );
657
0
        sei->duiSubLayerDelaysPresentFlag[i] = val;
658
0
      }
659
0
      else
660
0
      {
661
0
        sei->duiSubLayerDelaysPresentFlag[i] = 1;
662
0
      }
663
0
      if( sei->duiSubLayerDelaysPresentFlag[i] )
664
0
      {
665
0
        sei_read_code( pDecodedMessageOutputStream, bp.duCpbRemovalDelayIncrementLength, val, "du_spt_cpb_removal_delay_increment[i]");
666
0
        sei->duSptCpbRemovalDelayIncrement[i] = val;
667
0
      }
668
0
      else
669
0
      {
670
0
        sei->duSptCpbRemovalDelayIncrement[i] = 0;
671
0
      }
672
0
    }
673
0
  }
674
0
  else
675
0
  {
676
0
    for( int i = temporalId; i < bp.bpMaxSubLayers - 1; i ++ )
677
0
    {
678
0
      sei->duSptCpbRemovalDelayIncrement[i] = 0;
679
0
    }
680
0
  }
681
0
  if (bp.decodingUnitDpbDuParamsInPicTimingSeiFlag)
682
0
  {
683
0
    sei_read_flag( pDecodedMessageOutputStream, val, "dpb_output_du_delay_present_flag"); sei->dpbOutputDuDelayPresentFlag = (val != 0);
684
0
  }
685
0
  else
686
0
  {
687
0
    sei->dpbOutputDuDelayPresentFlag = false;
688
0
  }
689
0
  if(sei->dpbOutputDuDelayPresentFlag)
690
0
  {
691
0
    sei_read_code( pDecodedMessageOutputStream, bp.dpbOutputDelayDuLength, val, "pic_spt_dpb_output_du_delay");
692
0
    sei->picSptDpbOutputDuDelay = val;
693
0
  }
694
0
}
695
696
void SEIReader::xParseSEIBufferingPeriod(vvdecSEI* s, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream)
697
0
{
698
0
  int i, nalOrVcl;
699
0
  uint32_t code;
700
701
0
  output_sei_message_header(s, pDecodedMessageOutputStream, payloadSize);
702
0
  CHECK_FATAL( !s || s->payload == NULL, "allocation error in vvdecSEIBufferingPeriod" );
703
0
  vvdecSEIBufferingPeriod* sei =(vvdecSEIBufferingPeriod*)s->payload;
704
0
  ::memset(sei, 0, sizeof(vvdecSEIBufferingPeriod));
705
706
0
  sei_read_flag( pDecodedMessageOutputStream, code, "bp_nal_hrd_parameters_present_flag" );             sei->bpNalCpbParamsPresentFlag = code;
707
0
  sei_read_flag( pDecodedMessageOutputStream, code, "bp_vcl_hrd_parameters_present_flag" );             sei->bpVclCpbParamsPresentFlag = code;
708
709
0
  sei_read_code( pDecodedMessageOutputStream, 5, code, "initial_cpb_removal_delay_length_minus1" );     sei->initialCpbRemovalDelayLength = code + 1;
710
0
  sei_read_code( pDecodedMessageOutputStream, 5, code, "cpb_removal_delay_length_minus1" );             sei->cpbRemovalDelayLength        = code + 1;
711
0
  sei_read_code( pDecodedMessageOutputStream, 5, code, "dpb_output_delay_length_minus1" );              sei->dpbOutputDelayLength         = code + 1;
712
0
  sei_read_flag( pDecodedMessageOutputStream, code, "bp_decoding_unit_hrd_params_present_flag" );       sei->bpDecodingUnitHrdParamsPresentFlag = code;
713
0
  if( sei->bpDecodingUnitHrdParamsPresentFlag )
714
0
  {
715
0
    sei_read_code( pDecodedMessageOutputStream, 5, code, "du_cpb_removal_delay_increment_length_minus1" );  sei->duCpbRemovalDelayIncrementLength = code + 1;
716
0
    sei_read_code( pDecodedMessageOutputStream, 5, code, "dpb_output_delay_du_length_minus1" );             sei->dpbOutputDelayDuLength = code + 1;
717
0
    sei_read_flag( pDecodedMessageOutputStream, code, "decoding_unit_cpb_params_in_pic_timing_sei_flag" );  sei->decodingUnitCpbParamsInPicTimingSeiFlag = code;
718
0
    sei_read_flag(pDecodedMessageOutputStream, code, "decoding_unit_dpb_du_params_in_pic_timing_sei_flag"); sei->decodingUnitDpbDuParamsInPicTimingSeiFlag = code;
719
0
  }
720
0
  else
721
0
  {
722
0
    sei->duCpbRemovalDelayIncrementLength = 24;
723
0
    sei->dpbOutputDelayDuLength = 24;
724
0
    sei->decodingUnitDpbDuParamsInPicTimingSeiFlag = false;
725
0
  }
726
727
0
  CHECK(sei->altCpbParamsPresentFlag && sei->bpDecodingUnitHrdParamsPresentFlag,"When bp_alt_cpb_params_present_flag is equal to 1, the value of bp_du_hrd_params_present_flag shall be equal to 0");
728
729
0
  sei_read_flag( pDecodedMessageOutputStream, code, "concatenation_flag");
730
0
  sei->concatenationFlag = code;
731
0
  sei_read_flag ( pDecodedMessageOutputStream, code, "additional_concatenation_info_present_flag");
732
0
  sei->additionalConcatenationInfoPresentFlag = code;
733
0
  if (sei->additionalConcatenationInfoPresentFlag)
734
0
  {
735
0
    sei_read_code( pDecodedMessageOutputStream, sei->initialCpbRemovalDelayLength, code, "max_initial_removal_delay_for_concatenation" );
736
0
    sei->maxInitialRemovalDelayForConcatenation = code;
737
0
  }
738
739
0
  sei_read_code( pDecodedMessageOutputStream, ( sei->cpbRemovalDelayLength ), code, "au_cpb_removal_delay_delta_minus1" );
740
0
  sei->auCpbRemovalDelayDelta = code + 1;
741
742
0
  sei_read_code(pDecodedMessageOutputStream, 3, code, "bp_max_sub_layers_minus1");
743
0
  sei->bpMaxSubLayers = code + 1;
744
0
  CHECK( sei->bpMaxSubLayers > 7, "bp_max_sub_layers_minus1 must be <= 6 in vvdecSEIBufferingPeriod" );
745
0
  if (sei->bpMaxSubLayers - 1 > 0)
746
0
  {
747
0
    sei_read_flag(pDecodedMessageOutputStream, code, "cpb_removal_delay_deltas_present_flag");
748
0
    sei->cpbRemovalDelayDeltasPresentFlag = code;
749
0
  }
750
0
  else
751
0
  {
752
0
    sei->cpbRemovalDelayDeltasPresentFlag = false;
753
0
  }
754
0
  if (sei->cpbRemovalDelayDeltasPresentFlag)
755
0
  {
756
0
    sei_read_uvlc( pDecodedMessageOutputStream, code, "num_cpb_removal_delay_deltas_minus1" );             sei->numCpbRemovalDelayDeltas = code + 1;
757
0
    CHECK( sei->numCpbRemovalDelayDeltas > 14, "num_cpb_removal_delay_deltas_minus1 must be <= 13 in vvdecSEIBufferingPeriod" );
758
759
0
    for( i = 0; i < sei->numCpbRemovalDelayDeltas; i ++ )
760
0
    {
761
0
      sei_read_code( pDecodedMessageOutputStream, ( sei->cpbRemovalDelayLength ), code, "cpb_removal_delay_delta[i]" );
762
0
      sei->cpbRemovalDelayDelta[ i ] = code;
763
0
    }
764
0
  }
765
0
  sei_read_uvlc( pDecodedMessageOutputStream, code, "bp_cpb_cnt_minus1" ); sei->bpCpbCnt = code + 1;
766
0
  CHECK( sei->bpCpbCnt > 32, "bp_cpb_cnt_minus1 must be <= 31 in vvdecSEIBufferingPeriod" );
767
0
  if (sei->bpMaxSubLayers - 1 > 0)
768
0
  {
769
0
    sei_read_flag(pDecodedMessageOutputStream, code, "bp_sublayer_initial_cpb_removal_delay_present_flag");
770
0
    sei->sublayerInitialCpbRemovalDelayPresentFlag = code;
771
0
  }
772
0
  else
773
0
  {
774
0
    sei->sublayerInitialCpbRemovalDelayPresentFlag = false;
775
0
  }
776
0
  for (i = (sei->sublayerInitialCpbRemovalDelayPresentFlag ? 0 : sei->bpMaxSubLayers - 1); i < sei->bpMaxSubLayers; i++)
777
0
  {
778
0
    for( nalOrVcl = 0; nalOrVcl < 2; nalOrVcl ++ )
779
0
    {
780
0
      if( ( ( nalOrVcl == 0 ) && ( sei->bpNalCpbParamsPresentFlag ) ) ||
781
0
         ( ( nalOrVcl == 1 ) && ( sei->bpVclCpbParamsPresentFlag ) ) )
782
0
      {
783
0
        for( int j = 0; j < ( sei->bpCpbCnt ); j ++ )
784
0
        {
785
0
          sei_read_code( pDecodedMessageOutputStream, sei->initialCpbRemovalDelayLength, code, nalOrVcl ? "vcl_initial_cpb_removal_delay[i][j]" : "nal_initial_cpb_removal_delay[i][j]" );
786
0
          sei->initialCpbRemovalDelay[i][j][nalOrVcl] = code;
787
0
          sei_read_code( pDecodedMessageOutputStream, sei->initialCpbRemovalDelayLength, code, nalOrVcl ? "vcl_initial_cpb_removal_offset[i][j]" : "nal_initial_cpb_removal_offset[i][j]" );
788
0
          sei->initialCpbRemovalDelay[i][j][nalOrVcl] = code;
789
0
        }
790
0
      }
791
0
    }
792
0
  }
793
0
  if (sei->bpMaxSubLayers-1 > 0)
794
0
  {
795
0
    sei_read_flag(pDecodedMessageOutputStream, code, "bp_sublayer_dpb_output_offsets_present_flag");
796
0
    sei->sublayerDpbOutputOffsetsPresentFlag = code;
797
0
  }
798
0
  else
799
0
  {
800
0
    sei->sublayerDpbOutputOffsetsPresentFlag = false;
801
0
  }
802
0
  if(sei->sublayerDpbOutputOffsetsPresentFlag)
803
0
  {
804
0
    for(int i = 0; i < sei->bpMaxSubLayers - 1; i++)
805
0
    {
806
0
      sei_read_uvlc( pDecodedMessageOutputStream, code, "dpb_output_tid_offset[i]" );
807
0
      sei->dpbOutputTidOffset[i] = code;
808
0
    }
809
0
    sei->dpbOutputTidOffset[sei->bpMaxSubLayers-1] = 0;
810
0
  }
811
0
  sei_read_flag(pDecodedMessageOutputStream, code, "bp_alt_cpb_params_present_flag");
812
0
  sei->altCpbParamsPresentFlag = code;
813
0
  if (sei->altCpbParamsPresentFlag)
814
0
  {
815
0
    sei_read_flag(pDecodedMessageOutputStream, code, "use_alt_cpb_params_flag"); sei->useAltCpbParamsFlag = code;
816
0
  }
817
818
0
}
819
820
void SEIReader::xParseSEIPictureTiming(vvdecSEI* s, uint32_t payloadSize, const uint32_t temporalId, const vvdecSEIBufferingPeriod& bp, std::ostream *pDecodedMessageOutputStream)
821
0
{
822
0
  CHECK_FATAL( !s || s->payload == NULL, "allocation error in vvdecSEIPictureTiming" );
823
824
0
  output_sei_message_header(s, pDecodedMessageOutputStream, payloadSize);
825
826
0
  vvdecSEIPictureTiming* sei =(vvdecSEIPictureTiming*)s->payload;
827
0
  ::memset(sei, 0, sizeof(vvdecSEIPictureTiming));
828
829
0
  uint32_t symbol;
830
0
  sei_read_code( pDecodedMessageOutputStream, bp.cpbRemovalDelayLength, symbol, "pt_cpb_removal_delay_minus1[bp_max_sub_layers_minus1]" );
831
0
  sei->auCpbRemovalDelay[bp.bpMaxSubLayers - 1] = symbol + 1;
832
0
  for (int i = temporalId; i < bp.bpMaxSubLayers - 1; i++)
833
0
  {
834
0
    sei_read_flag(pDecodedMessageOutputStream, symbol, "pt_sub_layer_delays_present_flag[i]");
835
0
    sei->ptSubLayerDelaysPresentFlag[i] = (symbol == 1);
836
0
    if (sei->ptSubLayerDelaysPresentFlag[i])
837
0
    {
838
0
      if (bp.cpbRemovalDelayDeltasPresentFlag)
839
0
      {
840
0
        sei_read_flag(pDecodedMessageOutputStream, symbol, "pt_cpb_removal_delay_delta_enabled_flag[i]");
841
0
        sei->cpbRemovalDelayDeltaEnabledFlag[i] = (symbol == 1);
842
0
      }
843
0
      else
844
0
      {
845
0
        sei->cpbRemovalDelayDeltaEnabledFlag[i] = false;
846
0
      }
847
0
      if (sei->cpbRemovalDelayDeltaEnabledFlag[i])
848
0
      {
849
0
        if ((bp.numCpbRemovalDelayDeltas - 1) > 0)
850
0
        {
851
0
          sei_read_code(pDecodedMessageOutputStream, (int)ceil(log2(bp.numCpbRemovalDelayDeltas)), symbol, "pt_cpb_removal_delay_delta_idx[i]");
852
0
          sei->cpbRemovalDelayDeltaIdx[i] = symbol;
853
0
        }
854
0
        else
855
0
        {
856
0
          sei->cpbRemovalDelayDeltaIdx[i] = 0;
857
0
        }
858
0
      }
859
0
      else
860
0
      {
861
0
        sei_read_code(pDecodedMessageOutputStream, bp.cpbRemovalDelayLength, symbol, "pt_cpb_removal_delay_minus1[i]");
862
0
        sei->auCpbRemovalDelay[i] = symbol + 1;
863
0
      }
864
0
    }
865
0
  }
866
0
  sei_read_code(pDecodedMessageOutputStream, bp.dpbOutputDelayLength, symbol, "pt_dpb_output_delay");
867
0
  sei->picDpbOutputDelay = symbol;
868
869
0
  if( bp.altCpbParamsPresentFlag )
870
0
  {
871
0
    sei_read_flag( pDecodedMessageOutputStream, symbol, "cpb_alt_timing_info_present_flag" ); sei->cpbAltTimingInfoPresentFlag = symbol;
872
0
    if( sei->cpbAltTimingInfoPresentFlag )
873
0
    {
874
0
      if (bp.bpNalCpbParamsPresentFlag)
875
0
      {
876
0
        for (int i = (bp.sublayerInitialCpbRemovalDelayPresentFlag ? 0 : bp.bpMaxSubLayers - 1);
877
0
             i <= bp.bpMaxSubLayers - 1; ++i)
878
0
        {
879
0
          for (int j = 0; j < bp.bpCpbCnt; j++)
880
0
          {
881
0
            sei_read_code(pDecodedMessageOutputStream, bp.initialCpbRemovalDelayLength, symbol,
882
0
                          "nal_cpb_alt_initial_cpb_removal_delay_delta[ i ][ j ]");
883
0
            sei->nalCpbAltInitialRemovalDelayDelta[i][j] = symbol;
884
0
            sei_read_code(pDecodedMessageOutputStream, bp.initialCpbRemovalDelayLength, symbol,
885
0
                          "nal_cpb_alt_initial_cpb_removal_offset_delta[ i ][ j ]");
886
0
            sei->nalCpbAltInitialRemovalOffsetDelta[i][j] = symbol;
887
0
          }
888
0
          sei_read_code(pDecodedMessageOutputStream, bp.initialCpbRemovalDelayLength, sei->nalCpbDelayOffset[i],
889
0
                        "nal_cpb_delay_offset[ i ]");
890
0
          sei_read_code(pDecodedMessageOutputStream, bp.initialCpbRemovalDelayLength, sei->nalDpbDelayOffset[i],
891
0
                        "nal_dpb_delay_offset[ i ]");
892
0
        }
893
0
      }
894
895
0
      if (bp.bpVclCpbParamsPresentFlag)
896
0
      {
897
0
        for (int i = (bp.sublayerInitialCpbRemovalDelayPresentFlag ? 0 : bp.bpMaxSubLayers - 1);
898
0
             i <= bp.bpMaxSubLayers - 1; ++i)
899
0
        {
900
0
          for (int j = 0; j < bp.bpCpbCnt; j++)
901
0
          {
902
0
            sei_read_code(pDecodedMessageOutputStream, bp.initialCpbRemovalDelayLength, symbol,
903
0
                          "vcl_cpb_alt_initial_cpb_removal_delay_delta[ i ][ j ]");
904
0
            sei->vclCpbAltInitialRemovalDelayDelta[i][j] = symbol;
905
0
            sei_read_code(pDecodedMessageOutputStream, bp.initialCpbRemovalDelayLength, symbol,
906
0
                          "vcl_cpb_alt_initial_cpb_removal_offset_delta[ i ][ j ]");
907
0
            sei->vclCpbAltInitialRemovalOffsetDelta[i][j] = symbol;
908
0
          }
909
0
          sei_read_code(pDecodedMessageOutputStream, bp.initialCpbRemovalDelayLength, sei->vclCpbDelayOffset[i],
910
0
                        "vcl_cpb_delay_offset[ i ]");
911
0
          sei_read_code(pDecodedMessageOutputStream, bp.initialCpbRemovalDelayLength, sei->vclDpbDelayOffset[i],
912
0
                        "vcl_dpb_delay_offset[ i ]");
913
0
        }
914
0
      }
915
0
    }
916
0
  }
917
0
  else
918
0
  {
919
0
    sei->cpbAltTimingInfoPresentFlag = false;
920
0
  }
921
922
0
  if ( bp.bpDecodingUnitHrdParamsPresentFlag && bp.decodingUnitDpbDuParamsInPicTimingSeiFlag )
923
0
  {
924
0
    sei_read_code( pDecodedMessageOutputStream, bp.dpbOutputDelayDuLength, symbol, "pic_dpb_output_du_delay" );
925
0
    sei->picDpbOutputDuDelay = symbol;
926
0
  }
927
0
  if( bp.bpDecodingUnitHrdParamsPresentFlag && bp.decodingUnitCpbParamsInPicTimingSeiFlag )
928
0
  {
929
0
    sei_read_uvlc( pDecodedMessageOutputStream, symbol, "num_decoding_units_minus1" );
930
0
    sei->numDecodingUnits = symbol+1;
931
0
    CHECK( sei->numDecodingUnits > 32, "num_decoding_units_minus1 must be <= 31 in vvdecSEIPictureTiming" );
932
933
0
    if (sei->numDecodingUnits > 1)
934
0
    {
935
0
    sei_read_flag( pDecodedMessageOutputStream, symbol, "du_common_cpb_removal_delay_flag" );
936
0
    sei->duCommonCpbRemovalDelayFlag = symbol;
937
0
    if( sei->duCommonCpbRemovalDelayFlag )
938
0
    {
939
0
      for( int i = temporalId; i < bp.bpMaxSubLayers - 1; i ++ )
940
0
      {
941
0
        if( sei->ptSubLayerDelaysPresentFlag[i] )
942
0
        {
943
0
          sei_read_code( pDecodedMessageOutputStream, bp.duCpbRemovalDelayIncrementLength, symbol, "du_common_cpb_removal_delay_increment_minus1[i]" );
944
0
          sei->duCommonCpbRemovalDelay[i] = symbol+1;
945
0
        }
946
0
      }
947
0
    }
948
0
    for( uint32_t i = 0; i < sei->numDecodingUnits; i ++ )
949
0
    {
950
0
      sei_read_uvlc( pDecodedMessageOutputStream, symbol, "num_nalus_in_du_minus1[i]" );
951
0
      sei->numNalusInDu[i] = symbol+1;
952
0
      if( !sei->duCommonCpbRemovalDelayFlag && i < (sei->numDecodingUnits-1) )
953
0
      {
954
0
        for( int j = temporalId; j < bp.bpMaxSubLayers - 1; j ++ )
955
0
        {
956
0
          if( sei->ptSubLayerDelaysPresentFlag[j] )
957
0
          {
958
0
            sei_read_code( pDecodedMessageOutputStream, bp.duCpbRemovalDelayIncrementLength, symbol, "du_cpb_removal_delay_increment_minus1[i][j]" );
959
0
            sei->duCpbRemovalDelay[i * bp.bpMaxSubLayers + j] = symbol+1;
960
0
          }
961
0
        }
962
0
      }
963
0
    }
964
0
    }
965
0
    else
966
0
    {
967
0
      sei->duCommonCpbRemovalDelayFlag = 0;
968
0
    }
969
0
  }
970
0
  sei_read_code( pDecodedMessageOutputStream, 8, symbol, "pt_display_elemental_periods_minus1" );
971
0
  sei->ptDisplayElementalPeriods = symbol+1;
972
0
}
973
974
void SEIReader::xParseSEIFrameFieldinfo(vvdecSEI* s, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream)
975
0
{
976
0
  CHECK_FATAL( !s || s->payload == NULL, "allocation error in vvdecSEIFrameFieldInfo" );
977
978
0
  uint32_t symbol;
979
0
  output_sei_message_header(s, pDecodedMessageOutputStream, payloadSize);
980
981
0
  vvdecSEIFrameFieldInfo* sei =(vvdecSEIFrameFieldInfo*)s->payload;
982
0
  ::memset(sei, 0, sizeof(vvdecSEIFrameFieldInfo));
983
984
0
  sei_read_flag( pDecodedMessageOutputStream, symbol,      "field_pic_flag" );
985
0
  sei->fieldPicFlag= symbol;
986
0
  if (sei->fieldPicFlag)
987
0
  {
988
0
    sei_read_flag( pDecodedMessageOutputStream, symbol,    "bottofield_flag" );
989
0
    sei->bottomFieldFlag = symbol;
990
0
    sei_read_flag( pDecodedMessageOutputStream, symbol,    "pairing_indicated_flag" );
991
0
    sei->pairingIndicatedFlag = symbol;
992
0
    if (sei->pairingIndicatedFlag)
993
0
    {
994
0
      sei_read_flag( pDecodedMessageOutputStream, symbol,  "paired_with_next_field_flag" );
995
0
      sei->pairedWithNextFieldFlag = symbol;
996
0
    }
997
0
  }
998
0
  else
999
0
  {
1000
0
    sei_read_flag( pDecodedMessageOutputStream, symbol,    "display_fields_froframe_flag" );
1001
0
    sei->displayFieldsFromFrameFlag = symbol;
1002
0
    if (sei->displayFieldsFromFrameFlag)
1003
0
    {
1004
0
      sei_read_flag( pDecodedMessageOutputStream, symbol,  "display_fields_froframe_flag" );
1005
0
      sei->topFieldFirstFlag = symbol;
1006
0
    }
1007
0
    sei_read_code( pDecodedMessageOutputStream, 8, symbol, "ffi_display_elemental_periods_minus1" );
1008
0
    sei->displayElementalPeriods = symbol+1;
1009
0
  }
1010
0
  sei_read_code( pDecodedMessageOutputStream, 2, symbol,   "source_scan_type" );
1011
0
  sei->sourceScanType = symbol;
1012
0
  sei_read_flag( pDecodedMessageOutputStream, symbol,      "duplicate_flag" );
1013
0
  sei->duplicateFlag = symbol;
1014
0
}
1015
1016
void SEIReader::xParseSEIDependentRAPIndication( vvdecSEI* s, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream )
1017
0
{
1018
0
  CHECK_FATAL( !s || s->payload == NULL, "allocation error in vvdecSeidependent_rap_indication_t" );
1019
1020
0
  output_sei_message_header(s, pDecodedMessageOutputStream, payloadSize);
1021
0
}
1022
1023
void SEIReader::xParseSEIFramePacking(vvdecSEI* s, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream)
1024
0
{
1025
0
  uint32_t val;
1026
0
  CHECK_FATAL( !s || s->payload == NULL, "allocation error in vvdecSEIFramePacking" );
1027
1028
0
  output_sei_message_header(s, pDecodedMessageOutputStream, payloadSize);
1029
1030
0
  vvdecSEIFramePacking* sei =(vvdecSEIFramePacking*)s->payload;
1031
0
  ::memset(sei, 0, sizeof(vvdecSEIFramePacking));
1032
1033
0
  sei_read_uvlc( pDecodedMessageOutputStream, val, "frame_packing_arrangement_id" );                 sei->arrangementId = val;
1034
0
  sei_read_flag( pDecodedMessageOutputStream, val, "frame_packing_arrangement_cancel_flag" );        sei->arrangementCancelFlag = val;
1035
1036
0
  if( !sei->arrangementCancelFlag )
1037
0
  {
1038
0
    sei_read_code( pDecodedMessageOutputStream, 7, val, "frame_packing_arrangement_type" );          sei->arrangementType = val;
1039
0
    CHECK( ( sei->arrangementType <= 2 ) || ( sei->arrangementType >= 6 ), "Invalid arrangement type" );
1040
1041
0
    sei_read_flag( pDecodedMessageOutputStream, val, "quincunx_sampling_flag" );                     sei->quincunxSamplingFlag = val;
1042
1043
0
    sei_read_code( pDecodedMessageOutputStream, 6, val, "content_interpretation_type" );             sei->contentInterpretationType = val;
1044
0
    sei_read_flag( pDecodedMessageOutputStream, val, "spatial_flipping_flag" );                      sei->spatialFlippingFlag = val;
1045
0
    sei_read_flag( pDecodedMessageOutputStream, val, "frame0_flipped_flag" );                        sei->frame0FlippedFlag = val;
1046
0
    sei_read_flag( pDecodedMessageOutputStream, val, "field_views_flag" );                           sei->fieldViewsFlag = val;
1047
0
    sei_read_flag( pDecodedMessageOutputStream, val, "current_frame_is_frame0_flag" );               sei->currentFrameIsFrame0Flag = val;
1048
0
    sei_read_flag( pDecodedMessageOutputStream, val, "frame0_self_contained_flag" );                 sei->frame0SelfContainedFlag = val;
1049
0
    sei_read_flag( pDecodedMessageOutputStream, val, "frame1_self_contained_flag" );                 sei->frame1SelfContainedFlag = val;
1050
1051
0
    if ( sei->quincunxSamplingFlag == 0 && sei->arrangementType != 5)
1052
0
    {
1053
0
      sei_read_code( pDecodedMessageOutputStream, 4, val, "frame0_grid_position_x" );                sei->frame0GridPositionX = val;
1054
0
      sei_read_code( pDecodedMessageOutputStream, 4, val, "frame0_grid_position_y" );                sei->frame0GridPositionY = val;
1055
0
      sei_read_code( pDecodedMessageOutputStream, 4, val, "frame1_grid_position_x" );                sei->frame1GridPositionX = val;
1056
0
      sei_read_code( pDecodedMessageOutputStream, 4, val, "frame1_grid_position_y" );                sei->frame1GridPositionY = val;
1057
0
    }
1058
1059
0
    sei_read_code( pDecodedMessageOutputStream, 8, val, "frame_packing_arrangement_reserved_byte" ); sei->arrangementReservedByte = val;
1060
0
    sei_read_flag( pDecodedMessageOutputStream, val,  "frame_packing_arrangement_persistence_flag" );sei->arrangementPersistenceFlag = (val != 0);
1061
0
  }
1062
0
  sei_read_flag( pDecodedMessageOutputStream, val, "upsampled_aspect_ratio_flag" );                  sei->upsampledAspectRatio = val;
1063
0
}
1064
1065
void SEIReader::xParseSEIParameterSetsInclusionIndication(vvdecSEI* s, uint32_t payloadSize, std::ostream* pDecodedMessageOutputStream)
1066
0
{
1067
0
  uint32_t val;
1068
0
  CHECK_FATAL( !s || s->payload == NULL, "allocation error in vvdecSEIParameterSetsInclusionIndication" );
1069
1070
0
  output_sei_message_header(s, pDecodedMessageOutputStream, payloadSize);
1071
1072
0
  vvdecSEIParameterSetsInclusionIndication* sei =(vvdecSEIParameterSetsInclusionIndication*)s->payload;
1073
1074
0
  sei_read_flag( pDecodedMessageOutputStream, val, "self_contained_clvs_flag" ); sei->selfContainedClvsFlag = val;
1075
0
}
1076
1077
void SEIReader::xParseSEIMasteringDisplayColourVolume( vvdecSEI* s, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream)
1078
0
{
1079
0
  uint32_t code;
1080
0
  CHECK_FATAL( !s || s->payload == NULL, "allocation error in vvdecSEIMasteringDisplayColourVolume" );
1081
1082
0
  output_sei_message_header(s, pDecodedMessageOutputStream, payloadSize);
1083
  
1084
0
  vvdecSEIMasteringDisplayColourVolume* sei =(vvdecSEIMasteringDisplayColourVolume*)s->payload;
1085
0
  ::memset(sei, 0, sizeof(vvdecSEIMasteringDisplayColourVolume));
1086
1087
0
  sei_read_code( pDecodedMessageOutputStream, 16, code, "display_primaries_x[0]" ); sei->primaries[0][0] = code;
1088
0
  sei_read_code( pDecodedMessageOutputStream, 16, code, "display_primaries_y[0]" ); sei->primaries[0][1] = code;
1089
1090
0
  sei_read_code( pDecodedMessageOutputStream, 16, code, "display_primaries_x[1]" ); sei->primaries[1][0] = code;
1091
0
  sei_read_code( pDecodedMessageOutputStream, 16, code, "display_primaries_y[1]" ); sei->primaries[1][1] = code;
1092
1093
0
  sei_read_code( pDecodedMessageOutputStream, 16, code, "display_primaries_x[2]" ); sei->primaries[2][0] = code;
1094
0
  sei_read_code( pDecodedMessageOutputStream, 16, code, "display_primaries_y[2]" ); sei->primaries[2][1] = code;
1095
1096
0
  sei_read_code( pDecodedMessageOutputStream, 16, code, "white_point_x" ); sei->whitePoint[0] = code;
1097
0
  sei_read_code( pDecodedMessageOutputStream, 16, code, "white_point_y" ); sei->whitePoint[1] = code;
1098
1099
0
  sei_read_code( pDecodedMessageOutputStream, 32, code, "max_display_mastering_luminance" ); sei->maxLuminance = code;
1100
0
  sei_read_code( pDecodedMessageOutputStream, 32, code, "min_display_mastering_luminance" ); sei->minLuminance = code;
1101
0
}
1102
1103
#if U0033_ALTERNATIVE_TRANSFER_CHARACTERISTICS_SEI
1104
void SEIReader::xParseSEIAlternativeTransferCharacteristics(vvdecSEI* s, uint32_t payloadSize, std::ostream* pDecodedMessageOutputStream)
1105
0
{
1106
0
  uint32_t code;
1107
0
  CHECK_FATAL( !s || s->payload == NULL, "allocation error in vvdecSEIAlternativeTransferCharacteristics" );
1108
1109
0
  output_sei_message_header(s, pDecodedMessageOutputStream, payloadSize);
1110
  
1111
0
  vvdecSEIAlternativeTransferCharacteristics* sei =(vvdecSEIAlternativeTransferCharacteristics*)s->payload;
1112
1113
0
  sei_read_code(pDecodedMessageOutputStream, 8, code, "preferred_transfer_characteristics"); sei->preferred_transfer_characteristics = code;
1114
0
}
1115
#endif
1116
void SEIReader::xParseSEIUserDataRegistered(vvdecSEI* sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream)
1117
0
{
1118
0
  uint32_t code;
1119
0
  CHECK_FATAL( !sei || sei->payload == NULL, "allocation error in vvdecSEIUserDataRegistered" );
1120
1121
0
  output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize);
1122
1123
0
  vvdecSEIUserDataRegistered t;
1124
1125
0
  CHECK(payloadSize == 0, "no payload" );
1126
0
  sei_read_code(pDecodedMessageOutputStream, 8, code, "itu_t_t35_country_code"); payloadSize--;
1127
0
  if (code == 255)
1128
0
  {
1129
0
    CHECK(payloadSize == 0, "no payload" );
1130
0
    sei_read_code(pDecodedMessageOutputStream, 8, code, "itu_t_t35_country_code_extension_byte"); payloadSize--;
1131
0
    code += 255;
1132
0
  }
1133
0
  t.ituCountryCode = code;
1134
0
  t.userDataLength = payloadSize;
1135
1136
0
  if( !payloadSize )
1137
0
  {
1138
0
    t.userData = 0;
1139
0
    ::memcpy(sei->payload, &t, sizeof(vvdecSEIUserDataRegistered));
1140
0
    return;
1141
0
  }
1142
1143
0
  if( sei->payload )
1144
0
      free( sei->payload );
1145
1146
0
  SEI_internal::allocSEIPayload( sei, sizeof( vvdecSEIUserDataRegistered ) + sizeof( uint8_t )*(t.userDataLength + 1) );
1147
0
  CHECK_FATAL( sei->payload == NULL, "allocation error in vvdecSEIUserDataRegistered" );
1148
1149
0
  vvdecSEIUserDataRegistered* target = (vvdecSEIUserDataRegistered*)sei->payload;
1150
0
  target->ituCountryCode = t.ituCountryCode;
1151
0
  target->userDataLength = t.userDataLength;
1152
0
  target->userData = (uint8_t*)((uint8_t*)sei->payload + sizeof( vvdecSEIUserDataRegistered ));
1153
1154
0
  for (uint32_t i = 0; i < target->userDataLength; i++)
1155
0
  {
1156
0
    sei_read_code(NULL, 8, code, "itu_t_t35_payload_byte");
1157
0
    target->userData[i] = code;
1158
0
  }
1159
1160
0
  if (pDecodedMessageOutputStream)
1161
0
  {
1162
0
    (*pDecodedMessageOutputStream) << "  itu_t_t35 payload size: " << target->userDataLength << "\n";
1163
0
  }
1164
0
}
1165
1166
/**
1167
 * parse bitstream bs and unpack a user_data_unregistered SEI message
1168
 * of payloasSize bytes into sei.
1169
 */
1170
void SEIReader::xParseSEIuserDataUnregistered(vvdecSEI* sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream)
1171
0
{
1172
0
  CHECK(payloadSize < 16, "Payload too small");
1173
0
  CHECK_FATAL( !sei || sei->payload == NULL, "allocation error in vvdecSEIUserDataUnregistered" );
1174
1175
0
  uint32_t val;
1176
1177
0
  output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize);
1178
1179
0
  vvdecSEIUserDataUnregistered t;
1180
1181
0
  for (uint32_t i = 0; i < 16; i++)
1182
0
  {
1183
0
    sei_read_code( pDecodedMessageOutputStream, 8, val, "uuid_iso_iec_11578"); t.uuid_iso_iec_11578[i] = val;
1184
0
  }
1185
1186
0
  t.userDataLength = payloadSize - 16;
1187
0
  if (!t.userDataLength)
1188
0
  {
1189
0
    t.userData = 0;
1190
0
    ::memcpy(sei->payload, &t, sizeof(vvdecSEIUserDataUnregistered));
1191
0
    return;
1192
0
  }
1193
1194
0
  if( sei->payload )
1195
0
      free( sei->payload );
1196
1197
0
  SEI_internal::allocSEIPayload( sei,  sizeof( vvdecSEIUserDataUnregistered ) + sizeof( uint8_t )*(t.userDataLength + 1) );
1198
0
  CHECK_FATAL( sei->payload == NULL, "allocation error in vvdecSEIUserDataUnregistered" );
1199
1200
0
  vvdecSEIUserDataUnregistered* target = (vvdecSEIUserDataUnregistered*)sei->payload;
1201
0
  target->userDataLength = t.userDataLength;
1202
0
  target->userData = (uint8_t*)((uint8_t*)sei->payload + sizeof( vvdecSEIUserDataUnregistered ));
1203
1204
0
  for (uint32_t i = 0; i < target->userDataLength; i++)
1205
0
  {
1206
0
    sei_read_code(NULL, 8, val, "user_data_payload_byte");
1207
0
    target->userData[i] = val;
1208
0
  }
1209
1210
0
  if (pDecodedMessageOutputStream)
1211
0
  {
1212
0
    (*pDecodedMessageOutputStream) << "  User data payload size: " << target->userDataLength << "\n";
1213
0
  }
1214
0
}
1215
1216
void SEIReader::xParseSEIFilmGrainCharacteristics(vvdecSEI* s, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream)
1217
0
{
1218
0
  uint32_t code;
1219
0
  CHECK_FATAL( !s || s->payload == NULL, "allocation error in vvdecSEIFilmGrainCharacteristics" );
1220
1221
0
  output_sei_message_header(s, pDecodedMessageOutputStream, payloadSize);
1222
1223
0
  vvdecSEIFilmGrainCharacteristics* sei =(vvdecSEIFilmGrainCharacteristics*)s->payload;
1224
0
  ::memset(sei, 0, sizeof(vvdecSEIFilmGrainCharacteristics));
1225
1226
0
  sei_read_flag(pDecodedMessageOutputStream, code, "filgrain_characteristics_cancel_flag");     sei->filmGrainCharacteristicsCancelFlag = code != 0;
1227
0
  if (!sei->filmGrainCharacteristicsCancelFlag)
1228
0
  {
1229
0
    sei_read_code(pDecodedMessageOutputStream, 2, code, "filgrain_model_id");                   sei->filmGrainModelId = code;
1230
0
    sei_read_flag(pDecodedMessageOutputStream, code, "separate_colour_description_present_flag"); sei->separateColourDescriptionPresentFlag = code != 0;
1231
0
    if (sei->separateColourDescriptionPresentFlag)
1232
0
    {
1233
0
      sei_read_code(pDecodedMessageOutputStream, 3, code, "filgrain_bit_depth_luma_minus8");    sei->filmGrainBitDepthLuma = code+8;
1234
0
      sei_read_code(pDecodedMessageOutputStream, 3, code, "filgrain_bit_depth_chroma_minus8");  sei->filmGrainBitDepthChroma = code+8;
1235
0
      sei_read_flag(pDecodedMessageOutputStream, code, "filgrain_full_range_flag");             sei->filmGrainFullRangeFlag = code != 0;
1236
0
      sei_read_code(pDecodedMessageOutputStream, 8, code, "filgrain_colour_primaries");         sei->filmGrainColourPrimaries = code;
1237
0
      sei_read_code(pDecodedMessageOutputStream, 8, code, "filgrain_transfer_characteristics"); sei->filmGrainTransferCharacteristics = code;
1238
0
      sei_read_code(pDecodedMessageOutputStream, 8, code, "filgrain_matrix_coeffs");            sei->filmGrainMatrixCoeffs = code;
1239
0
    }
1240
0
    sei_read_code(pDecodedMessageOutputStream, 2, code, "blending_mode_id");                      sei->blendingModeId = code;
1241
0
    sei_read_code(pDecodedMessageOutputStream, 4, code, "log2_scale_factor");                     sei->log2ScaleFactor = code;
1242
0
    for (int c = 0; c<3; c++)
1243
0
    {
1244
0
      sei_read_flag(pDecodedMessageOutputStream, code, "comp_model_present_flag[c]");             sei->compModel[c].presentFlag = code != 0;
1245
0
    }
1246
0
    for (int c = 0; c<3; c++)
1247
0
    {
1248
0
      vvdecCompModel &cm = sei->compModel[c];
1249
0
      if (cm.presentFlag)
1250
0
      {
1251
0
        sei_read_code(pDecodedMessageOutputStream, 8, code, "num_intensity_intervals_minus1[c]"); cm.numIntensityIntervals = code + 1;
1252
0
        sei_read_code(pDecodedMessageOutputStream, 3, code, "num_model_values_minus1[c]");        cm.numModelValues = code + 1;
1253
1254
0
        CHECK ( cm.numIntensityIntervals > 256, "num_intensity_intervals_minus1[c] out of range" );
1255
0
        CHECK ( cm.numModelValues > 6, "num_model_values_minus1[c] out of range" );
1256
1257
0
        for (uint32_t interval = 0; interval < cm.numIntensityIntervals; interval++)
1258
0
        {
1259
0
          vvdecCompModelIntensityValues &cmiv = cm.intensityValues[interval];
1260
0
          sei_read_code(pDecodedMessageOutputStream, 8, code, "intensity_interval_lower_bound[c][i]"); cmiv.intensityIntervalLowerBound = code;
1261
0
          sei_read_code(pDecodedMessageOutputStream, 8, code, "intensity_interval_upper_bound[c][i]"); cmiv.intensityIntervalUpperBound = code;
1262
0
          for (uint32_t j = 0; j<cm.numModelValues; j++)
1263
0
          {
1264
0
            sei_read_svlc(pDecodedMessageOutputStream, cmiv.compModelValue[j], "comp_model_value[c][i]");
1265
0
          }
1266
0
        }
1267
0
      }
1268
0
    } // for c
1269
0
    sei_read_flag(pDecodedMessageOutputStream, code, "filgrain_characteristics_persistence_flag"); sei->filmGrainCharacteristicsPersistenceFlag = code != 0;
1270
0
  } // cancel flag
1271
0
}
1272
1273
void SEIReader::xParseSEIContentLightLevelInfo(vvdecSEI* s, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream)
1274
0
{
1275
0
  uint32_t code;
1276
0
  CHECK_FATAL( !s || s->payload == NULL, "allocation error in vvdecSEIContentLightLevelInfo" );
1277
1278
0
  output_sei_message_header(s, pDecodedMessageOutputStream, payloadSize);
1279
1280
0
  vvdecSEIContentLightLevelInfo* sei =(vvdecSEIContentLightLevelInfo*)s->payload;
1281
0
  ::memset(sei, 0, sizeof(vvdecSEIContentLightLevelInfo));
1282
1283
0
  sei_read_code(pDecodedMessageOutputStream, 16, code, "max_content_light_level");     sei->maxContentLightLevel    = code;
1284
0
  sei_read_code(pDecodedMessageOutputStream, 16, code, "max_pic_average_light_level"); sei->maxPicAverageLightLevel = code;
1285
0
}
1286
1287
void SEIReader::xParseSEIAmbientViewingEnvironment(vvdecSEI* s, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream)
1288
0
{
1289
0
  uint32_t code;
1290
0
  CHECK_FATAL( !s || s->payload == NULL, "allocation error in vvdecSEIAmbientViewingEnvironment" );
1291
1292
0
  output_sei_message_header(s, pDecodedMessageOutputStream, payloadSize);
1293
1294
0
  vvdecSEIAmbientViewingEnvironment* sei =(vvdecSEIAmbientViewingEnvironment*)s->payload;
1295
0
  ::memset(sei, 0, sizeof(vvdecSEIAmbientViewingEnvironment));
1296
1297
0
  sei_read_code(pDecodedMessageOutputStream, 32, code, "ambient_illuminance"); sei->ambientIlluminance = code;
1298
0
  sei_read_code(pDecodedMessageOutputStream, 16, code, "ambient_light_x");     sei->ambientLightX = (uint16_t)code;
1299
0
  sei_read_code(pDecodedMessageOutputStream, 16, code, "ambient_light_y");     sei->ambientLightY = (uint16_t)code;
1300
0
}
1301
1302
void SEIReader::xParseSEIContentColourVolume(vvdecSEI* s, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream)
1303
0
  {
1304
0
  int i;
1305
0
  uint32_t val;
1306
0
  CHECK_FATAL( !s || s->payload == NULL, "allocation error in vvdecSEIContentColourVolume" );
1307
1308
0
  output_sei_message_header(s, pDecodedMessageOutputStream, payloadSize);
1309
1310
0
  vvdecSEIContentColourVolume* sei =(vvdecSEIContentColourVolume*)s->payload;
1311
0
  ::memset(sei, 0, sizeof(vvdecSEIContentColourVolume));
1312
1313
0
  sei_read_flag(pDecodedMessageOutputStream, val, "ccv_cancel_flag");          sei->ccvCancelFlag = val;
1314
0
  if (!sei->ccvCancelFlag)
1315
0
    {
1316
0
    int iVal;
1317
0
    sei_read_flag(pDecodedMessageOutputStream, val, "ccv_persistence_flag");                   sei->ccvPersistenceFlag = val;
1318
0
    sei_read_flag(pDecodedMessageOutputStream, val, "ccv_primaries_present_flag");             sei->ccvPrimariesPresentFlag = val;
1319
0
    sei_read_flag(pDecodedMessageOutputStream, val, "ccv_min_luminance_value_present_flag");   sei->ccvMinLuminanceValuePresentFlag = val;
1320
0
    sei_read_flag(pDecodedMessageOutputStream, val, "ccv_max_luminance_value_present_flag");   sei->ccvMaxLuminanceValuePresentFlag = val;
1321
0
    sei_read_flag(pDecodedMessageOutputStream, val, "ccv_avg_luminance_value_present_flag");   sei->ccvAvgLuminanceValuePresentFlag = val;
1322
1323
0
    if (sei->ccvPrimariesPresentFlag)
1324
0
    {
1325
0
      for (i = 0; i < MAX_NUM_COMPONENT; i++)
1326
0
    {
1327
0
        sei_read_scode(pDecodedMessageOutputStream, 32, iVal, "ccv_primaries_x[i]");          sei->ccvPrimariesX[i] = iVal;
1328
0
        sei_read_scode(pDecodedMessageOutputStream, 32, iVal, "ccv_primaries_y[i]");          sei->ccvPrimariesY[i] = iVal;
1329
0
    }
1330
0
  }
1331
0
    if (sei->ccvMinLuminanceValuePresentFlag)
1332
0
  {
1333
0
      sei_read_code(pDecodedMessageOutputStream, 32, val, "ccv_min_luminance_value");   sei->ccvMinLuminanceValue = val;
1334
0
    }
1335
0
    if (sei->ccvMaxLuminanceValuePresentFlag)
1336
0
    {
1337
0
      sei_read_code(pDecodedMessageOutputStream, 32, val, "ccv_max_luminance_value");   sei->ccvMaxLuminanceValue = val;
1338
0
    }
1339
0
    if (sei->ccvAvgLuminanceValuePresentFlag)
1340
0
    {
1341
0
      sei_read_code(pDecodedMessageOutputStream, 32, val, "ccv_avg_luminance_value");   sei->ccvAvgLuminanceValue = val;
1342
0
    }
1343
0
  }
1344
0
}
1345
void SEIReader::xParseSEIEquirectangularProjection(vvdecSEI* s, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream)
1346
0
{
1347
0
  uint32_t val;
1348
0
  CHECK_FATAL( !s || s->payload == NULL, "allocation error in vvdecSEIEquirectangularProjection" );
1349
1350
0
  output_sei_message_header(s, pDecodedMessageOutputStream, payloadSize);
1351
1352
0
  vvdecSEIEquirectangularProjection* sei =(vvdecSEIEquirectangularProjection*)s->payload;
1353
0
  ::memset(sei, 0, sizeof(vvdecSEIEquirectangularProjection));
1354
1355
0
  sei_read_flag( pDecodedMessageOutputStream, val,       "erp_cancel_flag" );              sei->erpCancelFlag = val;
1356
0
  if( !sei->erpCancelFlag )
1357
0
  {
1358
0
    sei_read_flag( pDecodedMessageOutputStream, val,      "erp_persistence_flag"    );     sei->erpPersistenceFlag   = val;
1359
0
    sei_read_flag( pDecodedMessageOutputStream, val,      "erp_guard_band_flag"     );     sei->erpGuardBandFlag     = val;
1360
0
    sei_read_code( pDecodedMessageOutputStream, 2, val,   "erp_reserved_zero_2bits" );
1361
0
    if ( sei->erpGuardBandFlag == 1)
1362
0
    {
1363
0
      sei_read_code( pDecodedMessageOutputStream, 3, val,     "erp_guard_band_type"       );   sei->erpGuardBandType  = val;
1364
0
      sei_read_code( pDecodedMessageOutputStream, 8, val,     "erp_left_guard_band_width" );   sei->erpLeftGuardBandWidth = val;
1365
0
      sei_read_code( pDecodedMessageOutputStream, 8, val,     "erp_right_guard_band_width");   sei->erpRightGuardBandWidth = val;
1366
0
    }
1367
0
  }
1368
0
}
1369
1370
void SEIReader::xParseSEISphereRotation(vvdecSEI* s, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream)
1371
0
{
1372
0
  uint32_t val;
1373
0
  int  sval;
1374
0
  CHECK_FATAL( !s || s->payload == NULL, "allocation error in vvdecSEISphereRotation" );
1375
0
  output_sei_message_header(s, pDecodedMessageOutputStream, payloadSize);
1376
1377
0
  vvdecSEISphereRotation* sei =(vvdecSEISphereRotation*)s->payload;
1378
0
  ::memset(sei, 0, sizeof(vvdecSEISphereRotation));
1379
1380
0
  sei_read_flag( pDecodedMessageOutputStream, val,       "sphere_rotation_cancel_flag" );              sei->sphereRotationCancelFlag = val;
1381
0
  if( !sei->sphereRotationCancelFlag )
1382
0
    {
1383
0
    sei_read_flag ( pDecodedMessageOutputStream,      val,   "sphere_rotation_persistence_flag"    );     sei->sphereRotationPersistenceFlag = val;
1384
0
    sei_read_code ( pDecodedMessageOutputStream, 6,   val,   "sphere_rotation_reserved_zero_6bits" );
1385
0
    sei_read_scode( pDecodedMessageOutputStream, 32, sval,   "sphere_rotation_yaw"                 );     sei->sphereRotationYaw = sval;
1386
0
    sei_read_scode( pDecodedMessageOutputStream, 32, sval,   "sphere_rotation_pitch"               );     sei->sphereRotationPitch = sval;
1387
0
    sei_read_scode( pDecodedMessageOutputStream, 32, sval,   "sphere_rotation_roll"                );     sei->sphereRotationRoll = sval;
1388
0
  }
1389
0
}
1390
1391
void SEIReader::xParseSEIOmniViewport(vvdecSEI* s, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream)
1392
0
{
1393
0
  uint32_t code;
1394
0
  int  scode;
1395
0
  CHECK_FATAL( !s || s->payload == NULL, "allocation error in vvdecSEIOmniViewport" );
1396
0
  output_sei_message_header(s, pDecodedMessageOutputStream, payloadSize);
1397
1398
0
  vvdecSEIOmniViewport* sei =(vvdecSEIOmniViewport*)s->payload;
1399
0
  ::memset(sei, 0, sizeof(vvdecSEIOmniViewport));
1400
1401
0
  sei_read_code( pDecodedMessageOutputStream, 10, code, "omni_viewport_id"          ); sei->omniViewportId         = code;
1402
0
  sei_read_flag( pDecodedMessageOutputStream,     code, "omni_viewport_cancel_flag" ); sei->omniViewportCancelFlag = code;
1403
1404
0
  if (!sei->omniViewportCancelFlag)
1405
0
  {
1406
0
    sei_read_flag( pDecodedMessageOutputStream,    code, "omni_viewport_persistence_flag" );  sei->omniViewportPersistenceFlag = code;
1407
0
    sei_read_code( pDecodedMessageOutputStream, 4, code, "omni_viewport_cnt_minus1"       );  sei->omniViewportCnt =  code+1;
1408
0
    CHECK( sei->omniViewportCnt > 16, "omni_viewport_cnt_minus1 must be < 16 in vvdecSEIOmniViewport" );
1409
1410
0
    for(uint32_t region=0; region < sei->omniViewportCnt; region++)
1411
0
    {
1412
0
      vvdecOmniViewportRegion &viewport = sei->omniViewportRegions[region];
1413
0
      sei_read_scode( pDecodedMessageOutputStream, 32, scode, "omni_viewport_azimuth_centre"   );   viewport.azimuthCentre   = scode;
1414
0
      sei_read_scode( pDecodedMessageOutputStream, 32, scode, "omni_viewport_elevation_centre" );   viewport.elevationCentre = scode;
1415
0
      sei_read_scode( pDecodedMessageOutputStream, 32, scode, "omni_viewport_tilt_centre"      );   viewport.tiltCentre      = code;
1416
0
      sei_read_code( pDecodedMessageOutputStream,  32, code , "omni_viewport_hor_range"        );   viewport.horRange        = code;
1417
0
      sei_read_code( pDecodedMessageOutputStream,  32, code , "omni_viewport_ver_range"        );   viewport.verRange        = code;
1418
0
    }
1419
0
  }
1420
0
  else
1421
0
  {
1422
0
    sei->omniViewportPersistenceFlag=false;
1423
0
  }
1424
0
}
1425
1426
void SEIReader::xParseSEIRegionWisePacking(vvdecSEI* s, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream)
1427
0
{
1428
0
  uint32_t val;
1429
0
  CHECK_FATAL( !s || s->payload == NULL, "allocation error in vvdecSEIRegionWisePacking" );
1430
0
  output_sei_message_header(s, pDecodedMessageOutputStream, payloadSize);
1431
1432
0
  vvdecSEIRegionWisePacking* sei =(vvdecSEIRegionWisePacking*)s->payload;
1433
0
  ::memset(sei, 0, sizeof(vvdecSEIRegionWisePacking));
1434
1435
0
  if (!sei->rwpCancelFlag)
1436
0
    {
1437
0
    sei_read_flag( pDecodedMessageOutputStream,           val,    "rwp_persistence_flag" );                 sei->rwpPersistenceFlag = val;
1438
0
    sei_read_flag( pDecodedMessageOutputStream,           val,    "constituent_picture_matching_flag" );    sei->constituentPictureMatchingFlag = val;
1439
0
    sei_read_code( pDecodedMessageOutputStream,       5,  val,    "rwp_reserved_zero_5bits" );
1440
0
    sei_read_code( pDecodedMessageOutputStream,       8,  val,    "num_packed_regions" );                   sei->numPackedRegions    = val;
1441
0
    sei_read_code( pDecodedMessageOutputStream,       32, val,    "proj_picture_width" );                   sei->projPictureWidth    = val;
1442
0
    sei_read_code( pDecodedMessageOutputStream,       32, val,    "proj_picture_height" );                  sei->projPictureHeight   = val;
1443
0
    sei_read_code( pDecodedMessageOutputStream,       16, val,    "packed_picture_width" );                 sei->packedPictureWidth  = val;
1444
0
    sei_read_code( pDecodedMessageOutputStream,       16, val,    "packed_picture_height" );                sei->packedPictureHeight = val;
1445
1446
0
    for( int i=0; i < sei->numPackedRegions; i++ )
1447
0
    {
1448
0
      sei_read_code( pDecodedMessageOutputStream,     4,  val,    "rwp_reserved_zero_4bits" );
1449
0
      sei_read_code( pDecodedMessageOutputStream,     3,  val,    "rwp_tTransfortype" );                  sei->rwpTransformType[i]   = val;
1450
0
      sei_read_flag( pDecodedMessageOutputStream,         val,    "rwp_guard_band_flag" );                  sei->rwpGuardBandFlag[i]   = val;
1451
0
      sei_read_code( pDecodedMessageOutputStream,     32, val,    "proj_region_width" );                    sei->projRegionWidth[i]    = val;
1452
0
      sei_read_code( pDecodedMessageOutputStream,     32, val,    "proj_region_height" );                   sei->projRegionHeight[i]   = val;
1453
0
      sei_read_code( pDecodedMessageOutputStream,     32, val,    "rwp_proj_regionTop" );                   sei->rwpProjRegionTop[i]   = val;
1454
0
      sei_read_code( pDecodedMessageOutputStream,     32, val,    "proj_region_left" );                     sei->projRegionLeft[i]     = val;
1455
0
      sei_read_code( pDecodedMessageOutputStream,     16, val,    "packed_region_width" );                  sei->packedRegionWidth[i]  = val;
1456
0
      sei_read_code( pDecodedMessageOutputStream,     16, val,    "packed_region_height" );                 sei->packedRegionHeight[i] = val;
1457
0
      sei_read_code( pDecodedMessageOutputStream,     16, val,    "packed_region_top" );                    sei->packedRegionTop[i]    = val;
1458
0
      sei_read_code( pDecodedMessageOutputStream,     16, val,    "packed_region_left" );                   sei->packedRegionLeft[i]   = val;
1459
0
      if( sei->rwpGuardBandFlag[i] )
1460
0
        {
1461
0
        sei_read_code( pDecodedMessageOutputStream,   8,  val,    "rwp_left_guard_band_width" );            sei->rwpLeftGuardBandWidth[i]     = val;
1462
0
        sei_read_code( pDecodedMessageOutputStream,   8,  val,    "rwp_right_guard_band_width" );           sei->rwpRightGuardBandWidth[i]    = val;
1463
0
        sei_read_code( pDecodedMessageOutputStream,   8,  val,    "rwp_top_guard_band_height" );            sei->rwpTopGuardBandHeight[i]     = val;
1464
0
        sei_read_code( pDecodedMessageOutputStream,   8,  val,    "rwp_bottoguard_band_height" );         sei->rwpBottomGuardBandHeight[i]  = val;
1465
0
        sei_read_flag( pDecodedMessageOutputStream,       val,    "rwp_guard_band_not_used_forPred_flag" ); sei->rwpGuardBandNotUsedForPredFlag[i] = val;
1466
0
        for( int j=0; j < 4; j++ )
1467
0
          {
1468
0
          sei_read_code( pDecodedMessageOutputStream, 3,  val,     "rwp_guard_band_type" ); sei->rwpGuardBandType[i*4 + j] = val;
1469
0
        }
1470
0
        sei_read_code( pDecodedMessageOutputStream,   3,  val,    "rwp_guard_band_reserved_zero_3bits" );
1471
0
      }
1472
0
    }
1473
0
  }
1474
0
}
1475
1476
void SEIReader::xParseSEIGeneralizedCubemapProjection(vvdecSEI* s, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream)
1477
0
{
1478
0
  uint32_t val;
1479
1480
0
  CHECK_FATAL( !s || s->payload == NULL, "allocation error in vvdecSEIGeneralizedCubemapProjection" );
1481
0
  output_sei_message_header(s, pDecodedMessageOutputStream, payloadSize);
1482
  
1483
0
  vvdecSEIGeneralizedCubemapProjection* sei =(vvdecSEIGeneralizedCubemapProjection*)s->payload;
1484
0
  ::memset(sei, 0, sizeof(vvdecSEIGeneralizedCubemapProjection));
1485
1486
0
  sei_read_flag( pDecodedMessageOutputStream,          val,    "gcmp_cancel_flag" );                      sei->gcmpCancelFlag = val;
1487
0
  if (!sei->gcmpCancelFlag)
1488
0
  {
1489
0
    sei_read_flag( pDecodedMessageOutputStream,        val,    "gcmp_persistence_flag"    );              sei->gcmpPersistenceFlag = val;
1490
0
    sei_read_code( pDecodedMessageOutputStream,     3, val,    "gcmp_packing_type" );                     sei->gcmpPackingType = val;
1491
0
    sei_read_code( pDecodedMessageOutputStream,     2, val,    "gcmp_mapping_function_type"     );        sei->gcmpMappingFunctionType = val;
1492
1493
0
    int numFace = sei->gcmpPackingType == 4 || sei->gcmpPackingType == 5 ? 5 : 6;
1494
1495
0
    for (int i = 0; i < numFace; i++)
1496
0
    {
1497
0
      sei_read_code( pDecodedMessageOutputStream,   3, val,    "gcmp_face_index" );                       sei->gcmpFaceIndex[i] = val;
1498
0
      sei_read_code( pDecodedMessageOutputStream,   2, val,    "gcmp_face_rotation" );                    sei->gcmpFaceRotation[i] = val;
1499
0
      if (sei->gcmpMappingFunctionType == 2)
1500
0
      {
1501
0
        sei_read_code( pDecodedMessageOutputStream, 7, val,    "gcmp_function_coeff_u" );                 sei->gcmpFunctionCoeffU[i] = val;
1502
0
        sei_read_flag( pDecodedMessageOutputStream,    val,    "gcmp_function_u_affected_by_v_flag"    ); sei->gcmpFunctionUAffectedByVFlag[i] = val;
1503
0
        sei_read_code( pDecodedMessageOutputStream, 7, val,    "gcmp_function_coeff_v" );                 sei->gcmpFunctionCoeffV[i] = val;
1504
0
        sei_read_flag( pDecodedMessageOutputStream,    val,    "gcmp_function_v_affected_by_u_flag"    ); sei->gcmpFunctionVAffectedByUFlag[i] = val;
1505
0
      }
1506
0
    }
1507
0
    sei_read_flag( pDecodedMessageOutputStream,        val,    "gcmp_guard_band_flag" );                  sei->gcmpGuardBandFlag = val;
1508
0
    if (sei->gcmpGuardBandFlag)
1509
0
    {
1510
0
      sei_read_code( pDecodedMessageOutputStream,   3, val,    "gcmp_guard_band_type" );                   sei->gcmpGuardBandType = val;
1511
0
      sei_read_flag( pDecodedMessageOutputStream,      val,    "gcmp_guard_band_boundary_exterior_flag" ); sei->gcmpGuardBandBoundaryExteriorFlag = val;
1512
0
      sei_read_code( pDecodedMessageOutputStream,   4, val,    "gcmp_guard_band_samples_minus1" );         sei->gcmpGuardBandSamples = val+1;
1513
0
    }
1514
0
  }
1515
0
}
1516
1517
void SEIReader::xParseSEISubpictureLevelInfo(vvdecSEI* s, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream)
1518
0
{
1519
0
  CHECK_FATAL( !s || s->payload == NULL, "allocation error in vvdecSEISubpictureLevelInfo" );
1520
0
  output_sei_message_header(s, pDecodedMessageOutputStream, payloadSize);
1521
0
  vvdecSEISubpictureLevelInfo* sei =(vvdecSEISubpictureLevelInfo*)s->payload;
1522
0
  ::memset(sei, 0, sizeof(vvdecSEISubpictureLevelInfo));
1523
1524
0
  uint32_t val;
1525
0
  sei_read_code( pDecodedMessageOutputStream,   3,  val,    "sli_nuref_levels_minus1" );              sei->numRefLevels  = val + 1;
1526
0
  CHECK( sei->numRefLevels > 6, "sli_nuref_levels_minus1 must be < 6 in vvdecSEISubpictureLevelInfo" );
1527
1528
0
  sei_read_flag( pDecodedMessageOutputStream,       val,    "sli_cbr_constraint_flag" );              sei->cbrConstraintFlag = val;
1529
0
  sei_read_flag( pDecodedMessageOutputStream,       val,    "sli_explicit_fraction_present_flag" );   sei->explicitFractionPresentFlag = val;
1530
0
  if (sei->explicitFractionPresentFlag)
1531
0
  {
1532
0
    sei_read_uvlc(pDecodedMessageOutputStream,      val,    "sli_nusubpics_minus1");                  sei->numSubpics = val + 1;
1533
0
    CHECK( sei->numSubpics > 64, "sli_nusubpics_minus1 must be < 64 in vvdecSEISubpictureLevelInfo" );
1534
0
  }
1535
0
  sei_read_code(pDecodedMessageOutputStream,    3,  val,    "sli_max_sublayers_minus1"  );            sei->sliMaxSublayers = val + 1;
1536
0
  CHECK( sei->sliMaxSublayers > 6, "sli_max_sublayers_minus1 must be < 6 in vvdecSEISubpictureLevelInfo" );
1537
1538
0
  sei_read_flag(pDecodedMessageOutputStream,        val,    "sli_sublayer_info_present_flag");        sei->sliSublayerInfoPresentFlag = val;
1539
0
  while (!isByteAligned())
1540
0
  {
1541
0
    sei_read_flag( pDecodedMessageOutputStream,     val,    "sli_alignment_zero_bit" );           CHECK (val != 0, "sli_alignment_zero_bit not equal to zero" );
1542
0
  }
1543
1544
  // sei parameters initialization
1545
0
  for (int i = 0; i < sei->numRefLevels; i++)
1546
0
  {
1547
0
    for (int k = 0; k < sei->sliMaxSublayers; k++)
1548
0
    {
1549
0
      sei->refLevelIdc[i][k] = vvdecLevel::VVDEC_LEVEL15_5;
1550
0
    }
1551
0
  }
1552
0
  if (sei->explicitFractionPresentFlag)
1553
0
  {
1554
0
    for (int i = 0; i < sei->numRefLevels; i++)
1555
0
    {
1556
0
      for (int j = 0; j < sei->numSubpics; j++)
1557
0
      {
1558
0
        for (int k = 0; k < sei->sliMaxSublayers; k++)
1559
0
        {
1560
0
          sei->refLevelFraction[i][j][k] = 0;
1561
0
        }
1562
0
      }
1563
0
    }
1564
0
  }
1565
1566
  // parsing
1567
0
  for (int k = sei->sliSublayerInfoPresentFlag ? 0 : sei->sliMaxSublayers - 1; k < sei->sliMaxSublayers; k++)
1568
0
  {
1569
0
    for (int i = 0; i < sei->numRefLevels; i++)
1570
0
    {
1571
0
      sei_read_code(pDecodedMessageOutputStream, 8, val, "sli_non_subpic_layers_fraction[i][k]");    sei->nonSubpicLayersFraction[i][k] = (vvdecLevel) val;
1572
0
      sei_read_code(pDecodedMessageOutputStream, 8, val, "sli_ref_level_idc[i][k]");                 sei->refLevelIdc[i][k] = (vvdecLevel) val;
1573
1574
0
      if (sei->explicitFractionPresentFlag)
1575
0
      {
1576
0
        for (int j = 0; j < sei->numSubpics; j++)
1577
0
        {
1578
0
          sei_read_code(pDecodedMessageOutputStream, 8, val, "sli_ref_level_fraction_minus1[i][j][k]");  sei->refLevelFraction[i][j][k] = val;
1579
0
        }
1580
0
      }
1581
0
    }
1582
0
  }
1583
1584
  // update the inference of refLevelIdc[][] and refLevelFraction[][][]
1585
0
  if (!sei->sliSublayerInfoPresentFlag)
1586
0
  {
1587
0
    for (int k = sei->sliMaxSublayers - 2; k >= 0; k--)
1588
0
    {
1589
0
      for (int i = 0; i < sei->numRefLevels; i++)
1590
0
      {
1591
0
        sei->nonSubpicLayersFraction[i][k] = sei->nonSubpicLayersFraction[i][sei->sliMaxSublayers - 1];
1592
0
        sei->refLevelIdc            [i][k] = sei->refLevelIdc            [i][sei->sliMaxSublayers - 1];
1593
0
        if (sei->explicitFractionPresentFlag)
1594
0
        {
1595
0
          for (int j = 0; j < sei->numSubpics; j++)
1596
0
          {
1597
0
            sei->refLevelFraction[i][j][k] = sei->refLevelFraction[i][j][sei->sliMaxSublayers - 1];
1598
0
          }
1599
0
        }
1600
0
      }
1601
0
    }
1602
0
  }
1603
0
}
1604
1605
void SEIReader::xParseSEISampleAspectRatioInfo(vvdecSEI* s, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream)
1606
0
{
1607
0
  uint32_t val;
1608
0
  CHECK_FATAL( !s || s->payload == NULL, "allocation error in vvdecSEISampleAspectRatioInfo" );
1609
0
  output_sei_message_header(s, pDecodedMessageOutputStream, payloadSize);
1610
1611
0
  vvdecSEISampleAspectRatioInfo* sei =(vvdecSEISampleAspectRatioInfo*)s->payload;
1612
0
  ::memset(sei, 0, sizeof(vvdecSEISampleAspectRatioInfo));
1613
1614
0
  sei_read_flag( pDecodedMessageOutputStream,           val,    "sari_cancel_flag" );                      sei->sariCancelFlag = val;
1615
0
  if (!sei->sariCancelFlag)
1616
0
  {
1617
0
    sei_read_flag( pDecodedMessageOutputStream,         val,    "sari_persistence_flag" );                 sei->sariPersistenceFlag = val;
1618
0
    sei_read_code( pDecodedMessageOutputStream,     8,  val,    "sari_aspect_ratio_idc" );                 sei->sariAspectRatioIdc = val;
1619
0
    if (sei->sariAspectRatioIdc == 255)
1620
0
    {
1621
0
      sei_read_code( pDecodedMessageOutputStream,  16,  val,    "sari_sar_width" );                        sei->sariSarWidth = val;
1622
0
      sei_read_code( pDecodedMessageOutputStream,  16,  val,    "sari_sar_height" );                       sei->sariSarHeight = val;
1623
0
    }
1624
0
  }
1625
0
}
1626
1627
#if JVET_S0257_DUMP_360SEI_MESSAGE
1628
void SeiCfgFileDump::write360SeiDump (std::string decoded360MessageFileName, SEIMessages& seis, const SPS* sps)
1629
{
1630
  if (360SEIMessageDumped)
1631
  {
1632
    return;
1633
  }
1634
1635
  SEIMessages equirectangularProjectionSEIs = getSeisByType(seis, EQUIRECTANGULAR_PROJECTION);
1636
  if (!equirectangularProjectionSEIs.empty())
1637
  {
1638
    SEIEquirectangularProjection* sei = (SEIEquirectangularProjection*)equirectangularProjectionSEIs.front();
1639
    xDumpSEIEquirectangularProjection(*sei, sps, decoded360MessageFileName);
1640
    360SEIMessageDumped = true;
1641
  }
1642
  else
1643
  {
1644
    SEIMessages generalizedCubemapProjectionSEIs = getSeisByType(seis, GENERALIZED_CUBEMAP_PROJECTION);
1645
    if (!generalizedCubemapProjectionSEIs.empty())
1646
    {
1647
      SEIGeneralizedCubemapProjection* sei = (SEIGeneralizedCubemapProjection*)generalizedCubemapProjectionSEIs.front();
1648
      xDumpSEIGeneralizedCubemapProjection(*sei, sps, decoded360MessageFileName);
1649
      360SEIMessageDumped = true;
1650
    }
1651
  }
1652
}
1653
1654
void SeiCfgFileDump::xDumpSEIEquirectangularProjection     (SEIEquirectangularProjection &sei, const SPS* sps, std::string decoded360MessageFileName)
1655
{
1656
  if (!decoded360MessageFileName.empty())
1657
  {
1658
    FILE *fp = fopen(decoded360MessageFileName.c_str(), "w");
1659
    if (fp)
1660
    {
1661
      int chromaFormatTable[4] = {400, 420, 422, 444};
1662
      fprintf(fp, "InputBitDepth                 : %d    # Input bitdepth\n", sps->getBitDepth(CHANNEL_TYPE_LUMA));
1663
      fprintf(fp, "InputChromaFormat             : %d    # Ratio of luminance to chrominance samples\n", chromaFormatTable[sps->getChromaFormatIdc()]);
1664
      fprintf(fp, "SourceWidth                   : %d    # Input  frame width\n", sps->getMaxPicWidthInLumaSamples());
1665
      fprintf(fp, "SourceHeight                  : %d    # Input  frame height\n\n", sps->getMaxPicHeightInLumaSamples());
1666
1667
      fprintf(fp, "InputGeometryType             : 0     # 0: equirectangular; 1: cubemap; 2: equalarea; this should be in the cfg of per sequence.\n");
1668
      if (sei.erpGuardBandFlag == 1)
1669
      {
1670
        fprintf(fp, "InputPERP                     : 1     # 0: original ERP input; 1: padded ERP input\n");
1671
        fprintf(fp, "CodingPERP                    : 0     # 0: coding with original ERP size; 1: coding with padded ERP\n");
1672
      }
1673
      fclose(fp);
1674
      360SEIMessageDumped = true;
1675
    }
1676
    else
1677
    {
1678
      msg( ERROR, "File %s could not be opened.\n", decoded360MessageFileName.c_str() );
1679
    }
1680
  }
1681
}
1682
void SeiCfgFileDump::xDumpSEIGeneralizedCubemapProjection  (SEIGeneralizedCubemapProjection &sei, const SPS* sps, std::string decoded360MessageFileName)
1683
{
1684
  if (!sei.gcmpCancelFlag)
1685
  {
1686
    int numFace = sei.gcmpPackingType == 4 || sei.gcmpPackingType == 5 ? 5 : 6;
1687
    int packingTypeTable[6][2] = {{6, 1}, {3, 2}, {2, 3}, {1, 6}, {1, 5}, {5, 1}};
1688
    int rotationTable[4] = {0, 90, 180, 270};
1689
    std::string packingTypeStr = "";
1690
    std::string gcmpsettingsStr = "";
1691
    std::ostringstream oss;
1692
1693
    packingTypeStr += "SourceFPStructure                 : " + std::to_string(packingTypeTable[sei.gcmpPackingType][0]) + " " + std::to_string(packingTypeTable[sei.gcmpPackingType][1]);
1694
    gcmpsettingsStr += "InputGCMPSettings                 : ";
1695
1696
    for (int i = 0; i < numFace; i++)
1697
    {
1698
      int rotation = rotationTable[sei.gcmpFaceRotation[i]];
1699
      if (sei.gcmpFaceIndex[i] == 1)
1700
      {
1701
        rotation = (rotation + 270) % 360 + 360;
1702
      }
1703
      else if (sei.gcmpFaceIndex[i] == 2)
1704
      {
1705
        rotation = (rotation + 180) % 360 + 360;
1706
      }
1707
      else
1708
      {
1709
        rotation += 360;
1710
      }
1711
      if (i % packingTypeTable[sei.gcmpPackingType][1] == 0)
1712
      {
1713
        packingTypeStr += "   ";
1714
      }
1715
      packingTypeStr += std::to_string(sei.gcmpFaceIndex[i]) + " " + std::to_string(rotation) + " ";
1716
1717
      if (sei.gcmpMappingFunctionType == 2)
1718
      {
1719
        double a = ((int)sei.gcmpFunctionCoeffU[i] + 1) / 128.0;
1720
        double b = ((int)sei.gcmpFunctionCoeffV[i] + 1) / 128.0;
1721
        oss.str("");
1722
        oss<<a;
1723
        std::string a_str = oss.str();
1724
        oss.str("");
1725
        oss<<b;
1726
        std::string b_str = oss.str();
1727
        gcmpsettingsStr += a_str + " " + std::to_string(sei.gcmpFunctionUAffectedByVFlag[i]) + " " + b_str + " " + std::to_string(sei.gcmpFunctionVAffectedByUFlag[i]) + "   ";
1728
      }
1729
    }
1730
    if (!decoded360MessageFileName.empty())
1731
    {
1732
      FILE *fp = fopen(decoded360MessageFileName.c_str(), "w");
1733
      if (fp)
1734
      {
1735
        int chromaFormatTable[4] = {400, 420, 422, 444};
1736
        fprintf(fp, "InputBitDepth                 : %d    # Input bitdepth\n", sps->getBitDepth(CHANNEL_TYPE_LUMA));
1737
        fprintf(fp, "InputChromaFormat             : %d    # Ratio of luminance to chrominance samples\n", chromaFormatTable[sps->getChromaFormatIdc()]);
1738
        fprintf(fp, "SourceWidth                   : %d    # Input  frame width\n", sps->getMaxPicWidthInLumaSamples());
1739
        fprintf(fp, "SourceHeight                  : %d    # Input  frame height\n\n", sps->getMaxPicHeightInLumaSamples());
1740
1741
        fprintf(fp, "InputGeometryType             : 15    # 0: equirectangular; 1: cubemap; 2: equalarea; this should be in the cfg of per sequence.\n");
1742
1743
        packingTypeStr += " # frame packing order: numRows numCols Row0Idx0 ROT Row0Idx1 ROT ... Row1...";
1744
        gcmpsettingsStr += " # mapping function parameters for each face: u coefficient, u affected by v flag, v coefficient, v affected by u flag";
1745
        fprintf(fp, "%s\n", packingTypeStr.c_str());
1746
        fprintf(fp, "InputGCMPMappingType              : %d                                    # 0: CMP; 1: EAC; 2: parameterized CMP\n", (int)sei.gcmpMappingFunctionType);
1747
        if ((int)sei.gcmpMappingFunctionType == 2)
1748
          fprintf(fp, "%s\n", gcmpsettingsStr.c_str());
1749
        fprintf(fp, "InputGCMPPaddingFlag              : %d                                   # 0: input without guard bands; 1: input with guard bands\n", sei.gcmpGuardBandFlag);
1750
        if (sei.gcmpGuardBandFlag)
1751
        {
1752
          fprintf(fp, "InputGCMPPaddingType              : %d                                   # 0: unspecified(repetitive padding is used); 1: repetitive padding; 2: copy from neighboring face; 3: geometry padding\n", (int)sei.gcmpGuardBandType);
1753
          fprintf(fp, "InputGCMPPaddingExteriorFlag      : %d                                   # 0: guard bands only on discontinuous edges; 1: guard bands on both discontinuous edges and frame boundaries\n", sei.gcmpGuardBandBoundaryExteriorFlag);
1754
          fprintf(fp, "InputGCMPPaddingSize              : %d                                   # guard band size for input GCMP\n", (int)sei.gcmpGuardBandSamplesMinus1 + 1);
1755
        }
1756
        fclose(fp);
1757
        360SEIMessageDumped = true;
1758
      }
1759
      else
1760
      {
1761
        msg( ERROR, "File %s could not be opened.\n", decoded360MessageFileName.c_str() );
1762
      }
1763
    }
1764
  }
1765
}
1766
1767
#endif
1768
1769
}