Coverage Report

Created: 2026-07-16 06:32

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