Coverage Report

Created: 2026-04-01 07:49

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