Coverage Report

Created: 2026-04-01 07:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vvenc/source/Lib/EncoderLib/SEIwrite.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) 2019-2026, Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. & The VVenC 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
#include "SEIwrite.h"
45
#include "CommonLib/BitStream.h"
46
#include "CommonLib/SEI.h"
47
#include "CommonLib/Slice.h"
48
#include "CommonLib/Picture.h"
49
#include "CommonLib/dtrace_next.h"
50
51
//! \ingroup EncoderLib
52
//! \{
53
54
namespace vvenc {
55
56
void SEIWriter::xWriteSEIpayloadData(OutputBitstream &bs, const SEI& sei, HRD &hrd, const uint32_t temporalId)
57
0
{
58
0
  const SEIBufferingPeriod *bp = NULL;
59
0
  switch (sei.payloadType())
60
0
  {
61
0
  case SEI::USER_DATA_UNREGISTERED:
62
0
    xWriteSEIuserDataUnregistered(*static_cast<const SEIuserDataUnregistered*>(&sei));
63
0
    break;
64
0
  case SEI::DECODING_UNIT_INFO:
65
0
    bp = &hrd.bufferingPeriodSEI;
66
0
    CHECK (bp == nullptr, "Buffering Period need to be initialized in HRD to allow writing of Decoding Unit Information SEI");
67
0
    xWriteSEIDecodingUnitInfo(*static_cast<const SEIDecodingUnitInfo*>(& sei), *bp, temporalId);
68
0
    break;
69
0
  case SEI::SCALABLE_NESTING:
70
0
    xWriteSEIScalableNesting(bs, *static_cast<const SEIScalableNesting*>(&sei));
71
0
    break;
72
0
  case SEI::DECODED_PICTURE_HASH:
73
0
    xWriteSEIDecodedPictureHash(*static_cast<const SEIDecodedPictureHash*>(&sei));
74
0
    break;
75
0
  case SEI::BUFFERING_PERIOD:
76
0
    xWriteSEIBufferingPeriod(*static_cast<const SEIBufferingPeriod*>(&sei));
77
0
    hrd.bufferingPeriodSEI = *(static_cast<const SEIBufferingPeriod*>(&sei));
78
0
    break;
79
0
  case SEI::PICTURE_TIMING:
80
0
    {
81
0
      bp = &hrd.bufferingPeriodSEI;
82
0
      CHECK (bp == nullptr, "Buffering Period need to be initialized in HRD to allow writing of Picture Timing SEI");
83
0
      xWriteSEIPictureTiming(*static_cast<const SEIPictureTiming*>(&sei), *bp, temporalId);
84
0
    }
85
0
    break;
86
0
  case SEI::FRAME_FIELD_INFO:
87
0
    xWriteSEIFrameFieldInfo(*static_cast<const SEIFrameFieldInfo*>(&sei));
88
0
    break;
89
0
  case SEI::DEPENDENT_RAP_INDICATION:
90
0
    xWriteSEIDependentRAPIndication(*static_cast<const SEIDependentRAPIndication*>(&sei));
91
0
    break;
92
0
  case SEI::FRAME_PACKING:
93
0
    xWriteSEIFramePacking(*static_cast<const SEIFramePacking*>(&sei));
94
0
    break;
95
0
  case SEI::PARAMETER_SETS_INCLUSION_INDICATION:
96
0
    xWriteSEIParameterSetsInclusionIndication(*static_cast<const SEIParameterSetsInclusionIndication*>(&sei));
97
0
    break;
98
0
  case SEI::MASTERING_DISPLAY_COLOUR_VOLUME:
99
0
    xWriteSEIMasteringDisplayColourVolume(*static_cast<const SEIMasteringDisplayColourVolume*>(&sei));
100
0
    break;
101
0
  case SEI::ALTERNATIVE_TRANSFER_CHARACTERISTICS:
102
0
    xWriteSEIAlternativeTransferCharacteristics(*static_cast<const SEIAlternativeTransferCharacteristics*>(&sei));
103
0
    break;
104
0
  case SEI::EQUIRECTANGULAR_PROJECTION:
105
0
    xWriteSEIEquirectangularProjection(*static_cast<const SEIEquirectangularProjection*>(&sei));
106
0
    break;
107
0
  case SEI::SPHERE_ROTATION:
108
0
    xWriteSEISphereRotation(*static_cast<const SEISphereRotation*>(&sei));
109
0
    break;
110
0
  case SEI::OMNI_VIEWPORT:
111
0
    xWriteSEIOmniViewport(*static_cast<const SEIOmniViewport*>(&sei));
112
0
    break;
113
0
  case SEI::REGION_WISE_PACKING:
114
0
    xWriteSEIRegionWisePacking(*static_cast<const SEIRegionWisePacking*>(&sei));
115
0
    break;
116
0
  case SEI::GENERALIZED_CUBEMAP_PROJECTION:
117
0
    xWriteSEIGeneralizedCubemapProjection(*static_cast<const SEIGeneralizedCubemapProjection*>(&sei));
118
0
    break;
119
0
  case SEI::USER_DATA_REGISTERED_ITU_T_T35:
120
0
    xWriteSEIUserDataRegistered(*static_cast<const SEIUserDataRegistered*>(&sei));
121
0
    break;
122
0
  case SEI::FILM_GRAIN_CHARACTERISTICS:
123
0
    xWriteSeiFgc(*static_cast<const SeiFgc*>(&sei));
124
0
    break;
125
0
  case SEI::CONTENT_LIGHT_LEVEL_INFO:
126
0
    xWriteSEIContentLightLevelInfo(*static_cast<const SEIContentLightLevelInfo*>(&sei));
127
0
    break;
128
0
  case SEI::AMBIENT_VIEWING_ENVIRONMENT:
129
0
    xWriteSEIAmbientViewingEnvironment(*static_cast<const SEIAmbientViewingEnvironment*>(&sei));
130
0
    break;
131
0
  case SEI::CONTENT_COLOUR_VOLUME:
132
0
    xWriteSEIContentColourVolume(*static_cast<const SEIContentColourVolume*>(&sei));
133
0
    break;
134
0
  case SEI::SUBPICTURE_LEVEL_INFO:
135
0
    xWriteSEISubpictureLevelInfo(*static_cast<const SEISubpicureLevelInfo*>(&sei));
136
0
    break;
137
0
  case SEI::SAMPLE_ASPECT_RATIO_INFO:
138
0
    xWriteSEISampleAspectRatioInfo(*static_cast<const SEISampleAspectRatioInfo*>(&sei));
139
0
    break;
140
0
  default:
141
0
    THROW("Trying to write unhandled SEI message");
142
0
    break;
143
0
  }
144
0
  xWriteByteAlign();
145
0
}
146
147
/**
148
 * marshal all SEI messages in provided list into one bitstream bs
149
 */
150
void SEIWriter::writeSEImessages(OutputBitstream& bs, const SEIMessages &seiList, HRD &hrd, bool isNested, const uint32_t temporalId)
151
0
{
152
#if ENABLE_TRACING
153
  if (g_HLSTraceEnable)
154
      DTRACE( g_trace_ctx, D_HEADER, "=========== SEI message ===========\n" );
155
#endif
156
0
  OutputBitstream bs_count;
157
158
0
  for (SEIMessages::const_iterator sei=seiList.begin(); sei!=seiList.end(); sei++)
159
0
  {
160
    // calculate how large the payload data is
161
    // TODO: this would be far nicer if it used vectored buffers
162
0
    bs_count.clear();
163
0
    setBitstream(&bs_count);
164
165
#if ENABLE_TRACING
166
    bool traceEnable = g_HLSTraceEnable;
167
    g_HLSTraceEnable = false;
168
#endif
169
0
    xWriteSEIpayloadData(bs_count, **sei, hrd, temporalId);
170
#if ENABLE_TRACING
171
    g_HLSTraceEnable = traceEnable;
172
#endif
173
0
    uint32_t payload_data_num_bits = bs_count.getNumberOfWrittenBits();
174
0
    CHECK(0 != payload_data_num_bits % 8, "Invalid number of payload data bits");
175
176
0
    setBitstream(&bs);
177
0
    uint32_t payloadType = (*sei)->payloadType();
178
0
    for (; payloadType >= 0xff; payloadType -= 0xff)
179
0
    {
180
0
      WRITE_CODE(0xff, 8, "payload_type");
181
0
    }
182
0
    WRITE_CODE(payloadType, 8, "payload_type");
183
184
0
    uint32_t payloadSize = payload_data_num_bits/8;
185
0
    for (; payloadSize >= 0xff; payloadSize -= 0xff)
186
0
    {
187
0
      WRITE_CODE(0xff, 8, "payload_size");
188
0
    }
189
0
    WRITE_CODE(payloadSize, 8, "payload_size");
190
191
    /* payloadData */
192
#if ENABLE_TRACING
193
    if (g_HLSTraceEnable)
194
      DTRACE( g_trace_ctx, D_HEADER, "=========== %s SEI message ===========\n", SEI::getSEIMessageString( (SEI::PayloadType)payloadType ) );
195
#endif
196
197
0
    xWriteSEIpayloadData(bs, **sei, hrd, temporalId);
198
0
  }
199
0
  if (!isNested)
200
0
  {
201
0
    xWriteRbspTrailingBits();
202
0
  }
203
0
}
204
205
/**
206
 * marshal a user_data_unregistered SEI message sei, storing the marshalled
207
 * representation in bitstream bs.
208
 */
209
void SEIWriter::xWriteSEIuserDataUnregistered(const SEIuserDataUnregistered &sei)
210
0
{
211
0
  for (uint32_t i = 0; i < ISO_IEC_11578_LEN; i++)
212
0
  {
213
0
    WRITE_CODE(sei.uuid_iso_iec_11578[i], 8 , "sei.uuid_iso_iec_11578[i]");
214
0
  }
215
216
0
  for (uint32_t i = 0; i < sei.userDataLength; i++)
217
0
  {
218
0
    WRITE_CODE(sei.userData[i], 8 , "user_data_payload_byte");
219
0
  }
220
0
}
221
222
/**
223
 * marshal a decoded picture hash SEI message, storing the marshalled
224
 * representation in bitstream bs.
225
 */
226
void SEIWriter::xWriteSEIDecodedPictureHash(const SEIDecodedPictureHash& sei)
227
0
{
228
0
  const char *traceString="\0";
229
0
  switch (sei.method)
230
0
  {
231
0
    case VVENC_HASHTYPE_MD5: traceString="picture_md5"; break;
232
0
    case VVENC_HASHTYPE_CRC: traceString="picture_crc"; break;
233
0
    case VVENC_HASHTYPE_CHECKSUM: traceString="picture_checksum"; break;
234
0
    default: THROW("Unknown hash type"); break;
235
0
  }
236
237
0
  if (traceString != 0) //use of this variable is needed to avoid a compiler error with G++ 4.6.1
238
0
  {
239
0
    WRITE_CODE(sei.method, 8, "dph_sei_hash_type");
240
0
    WRITE_CODE(sei.singleCompFlag, 1, "dph_sei_single_component_flag");
241
0
    WRITE_CODE(0, 7, "dph_sei_reserved_zero_7bits");
242
0
    for(uint32_t i=0; i<uint32_t(sei.pictureHash.hash.size()); i++)
243
0
    {
244
0
      WRITE_CODE(sei.pictureHash.hash[i], 8, traceString);
245
0
    }
246
0
  }
247
0
}
248
249
250
void SEIWriter::xWriteSEIDecodingUnitInfo(const SEIDecodingUnitInfo& sei, const SEIBufferingPeriod& bp, const uint32_t temporalId)
251
0
{
252
0
  WRITE_UVLC(sei.decodingUnitIdx, "decoding_unit_idx");
253
0
  if( !bp.decodingUnitCpbParamsInPicTimingSeiFlag )
254
0
  {
255
0
    for (int i = temporalId; i <= bp.bpMaxSubLayers - 1; i++)
256
0
    {
257
0
      if (i < bp.bpMaxSubLayers - 1)
258
0
      {
259
0
      WRITE_FLAG(sei.duiSubLayerDelaysPresent[i], "dui_sub_layer_delays_present_flag[i]");
260
0
      }
261
0
      if( sei.duiSubLayerDelaysPresent[i] )
262
0
        WRITE_CODE( sei.duSptCpbRemovalDelayIncrement[i], bp.duCpbRemovalDelayIncrementLength, "du_spt_cpb_removal_delay_increment[i]");
263
0
    }
264
0
  }
265
0
  if (bp.decodingUnitDpbDuParamsInPicTimingSeiFlag)
266
0
  {
267
0
    WRITE_FLAG(sei.dpbOutputDuDelayPresent, "dpb_output_du_delay_present_flag");
268
0
  }
269
0
  if(sei.dpbOutputDuDelayPresent)
270
0
  {
271
0
    WRITE_CODE(sei.picSptDpbOutputDuDelay, bp.dpbOutputDelayDuLength, "pic_spt_dpb_output_du_delay");
272
0
  }
273
0
}
274
275
void SEIWriter::xWriteSEIBufferingPeriod(const SEIBufferingPeriod& sei)
276
0
{
277
0
  WRITE_FLAG( sei.bpNalCpbParamsPresent, "bp_nal_hrd_parameters_present_flag");
278
0
  WRITE_FLAG( sei.bpVclCpbParamsPresent, "bp_vcl_hrd_parameters_present_flag");
279
0
  CHECK(!sei.bpNalCpbParamsPresent && !sei.bpVclCpbParamsPresent, "bp_nal_hrd_parameters_present_flag and/or bp_vcl_hrd_parameters_present_flag must be true");
280
0
  CHECK (sei.initialCpbRemovalDelayLength < 1, "sei.initialCpbRemovalDelayLength must be > 0");
281
0
  WRITE_CODE( sei.initialCpbRemovalDelayLength - 1, 5, "initial_cpb_removal_delay_length_minus1" );
282
0
  CHECK (sei.cpbRemovalDelayLength < 1, "sei.cpbRemovalDelayLength must be > 0");
283
0
  WRITE_CODE( sei.cpbRemovalDelayLength - 1,        5, "cpb_removal_delay_length_minus1" );
284
0
  CHECK (sei.dpbOutputDelayLength < 1, "sei.dpbOutputDelayLength must be > 0");
285
0
  WRITE_CODE( sei.dpbOutputDelayLength - 1,         5, "dpb_output_delay_length_minus1" );
286
0
  WRITE_FLAG( sei.bpDecodingUnitHrdParamsPresent, "bp_decoding_unit_hrd_params_present_flag"  );
287
0
  if( sei.bpDecodingUnitHrdParamsPresent )
288
0
  {
289
0
    CHECK (sei.duCpbRemovalDelayIncrementLength < 1, "sei.duCpbRemovalDelayIncrementLength must be > 0");
290
0
    WRITE_CODE( sei.duCpbRemovalDelayIncrementLength - 1, 5, "du_cpb_removal_delay_increment_length_minus1" );
291
0
    CHECK (sei.dpbOutputDelayDuLength < 1, "sei.dpbOutputDelayDuLength must be > 0");
292
0
    WRITE_CODE( sei.dpbOutputDelayDuLength - 1, 5, "dpb_output_delay_du_length_minus1" );
293
0
    WRITE_FLAG( sei.decodingUnitCpbParamsInPicTimingSeiFlag, "decoding_unit_cpb_params_in_pic_timing_sei_flag" );
294
0
    WRITE_FLAG(sei.decodingUnitDpbDuParamsInPicTimingSeiFlag, "decoding_unit_dpb_du_params_in_pic_timing_sei_flag");
295
0
  }
296
297
0
  WRITE_FLAG( sei.concatenationFlag, "concatenation_flag");
298
0
  WRITE_FLAG( sei.additionalConcatenationInfoPresent, "additional_concatenation_info_present_flag");
299
0
  if (sei.additionalConcatenationInfoPresent)
300
0
  {
301
0
    WRITE_CODE( sei.maxInitialRemovalDelayForConcatenation, sei.initialCpbRemovalDelayLength, "max_initial_removal_delay_for_concatenation" );
302
0
  }
303
304
0
  CHECK (sei.auCpbRemovalDelayDelta < 1, "sei.auCpbRemovalDelayDelta must be > 0");
305
0
  WRITE_CODE( sei.auCpbRemovalDelayDelta - 1, sei.cpbRemovalDelayLength, "au_cpb_removal_delay_delta_minus1" );
306
307
0
  CHECK(sei.bpMaxSubLayers < 1, "bp_max_sub_layers_minus1 must be > 0");
308
0
  WRITE_CODE(sei.bpMaxSubLayers - 1, 3, "bp_max_sub_layers_minus1");
309
0
  if (sei.bpMaxSubLayers - 1 > 0)
310
0
  {
311
0
    WRITE_FLAG(sei.cpbRemovalDelayDeltasPresent, "cpb_removal_delay_deltas_present_flag");
312
0
  }
313
314
0
  if (sei.cpbRemovalDelayDeltasPresent)
315
0
  {
316
0
    CHECK (sei.numCpbRemovalDelayDeltas < 1, "m_numCpbRemovalDelayDeltas must be > 0");
317
0
    WRITE_UVLC( sei.numCpbRemovalDelayDeltas - 1, "num_cpb_removal_delay_deltas_minus1" );
318
0
    for( int i = 0; i < sei.numCpbRemovalDelayDeltas; i ++ )
319
0
    {
320
0
      WRITE_CODE( sei.cpbRemovalDelayDelta[i],        sei.cpbRemovalDelayLength, "cpb_removal_delay_delta[i]" );
321
0
    }
322
0
  }
323
0
  CHECK (sei.bpCpbCnt < 1, "sei.bpCpbCnt must be > 0");
324
0
  WRITE_UVLC( sei.bpCpbCnt - 1, "bp_cpb_cnt_minus1");
325
0
  if (sei.bpMaxSubLayers - 1 > 0)
326
0
  {
327
0
    WRITE_FLAG(sei.sublayerInitialCpbRemovalDelayPresent, "bp_sublayer_initial_cpb_removal_delay_present_flag");
328
0
  }
329
0
  for (int i = (sei.sublayerInitialCpbRemovalDelayPresent ? 0 : sei.bpMaxSubLayers - 1); i < sei.bpMaxSubLayers; i++)
330
0
  {
331
0
    for( int nalOrVcl = 0; nalOrVcl < 2; nalOrVcl ++ )
332
0
    {
333
0
      if( ( ( nalOrVcl == 0 ) && ( sei.bpNalCpbParamsPresent ) ) ||
334
0
         ( ( nalOrVcl == 1 ) && ( sei.bpVclCpbParamsPresent ) ) )
335
0
      {
336
0
        for( int j = 0; j < sei.bpCpbCnt; j ++ )
337
0
        {
338
0
          WRITE_CODE( sei.initialCpbRemovalDelay[j][i][nalOrVcl],  sei.initialCpbRemovalDelayLength,           "initial_cpb_removal_delay[j][i][nalOrVcl]" );
339
0
          WRITE_CODE( sei.initialCpbRemovalOffset[j][i][nalOrVcl], sei.initialCpbRemovalDelayLength,           "initial_cpb_removal_delay_offset[j][i][nalOrVcl]" );
340
0
        }
341
0
      }
342
0
    }
343
0
  }
344
0
  if (sei.bpMaxSubLayers-1 > 0) 
345
0
  {
346
0
    WRITE_FLAG(sei.sublayerDpbOutputOffsetsPresent, "bp_sublayer_dpb_output_offsets_present_flag");
347
0
  }
348
349
0
  if(sei.sublayerDpbOutputOffsetsPresent)
350
0
  {
351
0
    for(int i = 0; i < sei.bpMaxSubLayers - 1; i++)
352
0
    {
353
0
      WRITE_UVLC( sei.dpbOutputTidOffset[i], "dpb_output_tid_offset[i]" );
354
0
    }
355
0
  }
356
0
  WRITE_FLAG(sei.altCpbParamsPresent, "bp_alt_cpb_params_present_flag");
357
0
  if (sei.altCpbParamsPresent)
358
0
  {
359
0
    WRITE_FLAG(sei.useAltCpbParamsFlag, "use_alt_cpb_params_flag");
360
0
  }
361
362
0
}
363
364
void SEIWriter::xWriteSEIPictureTiming(const SEIPictureTiming& sei, const SEIBufferingPeriod &bp, const uint32_t temporalId)
365
0
{
366
0
  WRITE_CODE( sei.auCpbRemovalDelay[bp.bpMaxSubLayers - 1] - 1, bp.cpbRemovalDelayLength,               "pt_cpb_removal_delay_minus1[bp_max_sub_layers_minus1]" );
367
0
  for (int i = temporalId; i < bp.bpMaxSubLayers - 1; i++)
368
0
  {
369
0
    WRITE_FLAG(sei.ptSubLayerDelaysPresent[i], "pt_sub_layer_delays_present_flag[i]");
370
0
    if (sei.ptSubLayerDelaysPresent[i])
371
0
    {
372
0
      if (bp.cpbRemovalDelayDeltasPresent)
373
0
      {
374
0
        WRITE_FLAG(sei.cpbRemovalDelayDeltaEnabledFlag[i], "pt_cpb_removal_delay_delta_enabled_flag[i]");
375
0
      }
376
0
      if (sei.cpbRemovalDelayDeltaEnabledFlag[i])
377
0
      {
378
0
        if ((bp.numCpbRemovalDelayDeltas - 1) > 0)
379
0
        {
380
0
          WRITE_CODE(sei.cpbRemovalDelayDeltaIdx[i], ceilLog2(bp.numCpbRemovalDelayDeltas), "pt_cpb_removal_delay_delta_idx[i]");
381
0
        }
382
0
      }
383
0
      else
384
0
      {
385
0
        WRITE_CODE(sei.auCpbRemovalDelay[i] - 1, bp.cpbRemovalDelayLength, "pt_cpb_removal_delay_minus1[i]");
386
0
      }
387
0
    }
388
0
  }
389
0
  WRITE_CODE(sei.picDpbOutputDelay, bp.dpbOutputDelayLength, "pt_dpb_output_delay");
390
0
  if( bp.altCpbParamsPresent )
391
0
  {
392
0
    WRITE_FLAG( sei.cpbAltTimingInfoPresent, "cpb_alt_timing_info_present_flag" );
393
0
    if( sei.cpbAltTimingInfoPresent )
394
0
    {
395
0
      if (bp.bpNalCpbParamsPresent)
396
0
      {
397
0
        for (int i = (bp.sublayerInitialCpbRemovalDelayPresent ? 0 : bp.bpMaxSubLayers - 1); i <= bp.bpMaxSubLayers - 1; ++i)
398
0
        {
399
0
          for (int j = 0; j < bp.bpCpbCnt; j++)
400
0
          {
401
0
            WRITE_CODE(sei.nalCpbAltInitialRemovalDelayDelta[i][j], bp.initialCpbRemovalDelayLength,
402
0
                       "nal_cpb_alt_initial_cpb_removal_delay_delta[ i ][ j ]");
403
0
            WRITE_CODE(sei.nalCpbAltInitialRemovalOffsetDelta[i][j], bp.initialCpbRemovalDelayLength,
404
0
                       "nal_cpb_alt_initial_cpb_removal_offset_delta[ i ][ j ]");
405
0
          }
406
0
          WRITE_CODE(sei.nalCpbDelayOffset[i], bp.cpbRemovalDelayLength, "nal_cpb_delay_offset[ i ]");
407
0
          WRITE_CODE(sei.nalDpbDelayOffset[i], bp.dpbOutputDelayLength, "nal_dpb_delay_offset[ i ]");
408
0
        }
409
0
      }
410
411
0
      if (bp.bpVclCpbParamsPresent)
412
0
      {
413
0
        for (int i = (bp.sublayerInitialCpbRemovalDelayPresent ? 0 : bp.bpMaxSubLayers - 1); i <= bp.bpMaxSubLayers - 1; ++i)
414
0
        {
415
0
          for (int j = 0; j < bp.bpCpbCnt; j++)
416
0
          {
417
0
            WRITE_CODE(sei.vclCpbAltInitialRemovalDelayDelta[i][j], bp.initialCpbRemovalDelayLength,
418
0
                       "vcl_cpb_alt_initial_cpb_removal_delay_delta[ i ][ j ]");
419
0
            WRITE_CODE(sei.vclCpbAltInitialRemovalOffsetDelta[i][j], bp.initialCpbRemovalDelayLength,
420
0
                       "vcl_cpb_alt_initial_cpb_removal_offset_delta[ i ][ j ]");
421
0
          }
422
0
          WRITE_CODE(sei.vclCpbDelayOffset[i], bp.cpbRemovalDelayLength, "vcl_cpb_delay_offset[ i ]");
423
0
          WRITE_CODE(sei.vclDpbDelayOffset[i], bp.dpbOutputDelayLength,  "vcl_dpb_delay_offset[ i ]");
424
0
        }
425
0
      }
426
0
    }
427
0
  }
428
0
  if (bp.bpDecodingUnitHrdParamsPresent && bp.decodingUnitDpbDuParamsInPicTimingSeiFlag)
429
0
  {
430
0
    WRITE_CODE( sei.picDpbOutputDuDelay, bp.dpbOutputDelayDuLength, "pic_dpb_output_du_delay" );
431
0
  }
432
0
  if( bp.bpDecodingUnitHrdParamsPresent && bp.decodingUnitCpbParamsInPicTimingSeiFlag )
433
0
  {
434
0
    WRITE_UVLC( sei.numDecodingUnitsMinus1, "num_decoding_units_minus1" );
435
0
    if (sei.numDecodingUnitsMinus1 > 0)
436
0
    {
437
0
      WRITE_FLAG( sei.duCommonCpbRemovalDelayFlag, "du_commmon_cpb_removal_delay_flag" );
438
0
      if( sei.duCommonCpbRemovalDelayFlag )
439
0
      {
440
0
        for( int i = temporalId; i < bp.bpMaxSubLayers - 1; i ++ )
441
0
        {
442
0
          if( sei.ptSubLayerDelaysPresent[i] )
443
0
            WRITE_CODE( sei.duCommonCpbRemovalDelayMinus1[i], bp.duCpbRemovalDelayIncrementLength, "du_common_cpb_removal_delay_increment_minus1[i]" );
444
0
        }
445
0
      }
446
0
      for( int i = 0; i <= sei.numDecodingUnitsMinus1; i ++ )
447
0
      {
448
0
        WRITE_UVLC( sei.numNalusInDuMinus1[i], "num_nalus_in_du_minus1[i]" );
449
0
        if( !sei.duCommonCpbRemovalDelayFlag && i < sei.numDecodingUnitsMinus1 )
450
0
        {
451
0
          for( int j = temporalId; j < bp.bpMaxSubLayers - 1; j ++ )
452
0
          {
453
0
            if( sei.ptSubLayerDelaysPresent[j] )
454
0
              WRITE_CODE( sei.duCpbRemovalDelayMinus1[i * bp.bpMaxSubLayers + j], bp.duCpbRemovalDelayIncrementLength, "du_cpb_removal_delay_increment_minus1[i][j]" );
455
0
          }
456
0
        }
457
0
      }
458
0
    }
459
0
  }
460
461
0
  if (bp.additionalConcatenationInfoPresent)
462
0
  {
463
0
    WRITE_FLAG( sei.delayForConcatenationEnsureFlag, "pt_delay_for_concatenation_ensured_flag" );
464
0
  }
465
0
  WRITE_CODE( sei.ptDisplayElementalPeriodsMinus1, 8, "pt_display_elemental_periods_minus1" );
466
0
}
467
468
void SEIWriter::xWriteSEIFrameFieldInfo(const SEIFrameFieldInfo& sei)
469
0
{
470
0
  WRITE_FLAG( sei.fieldPicFlag ? 1 : 0,                    "ffi_field_pic_flag" );
471
0
  if (sei.fieldPicFlag)
472
0
  {
473
0
    WRITE_FLAG( sei.bottomFieldFlag ? 1 : 0,               "ffi_bottom_field_flag" );
474
0
    WRITE_FLAG( sei.pairingIndicatedFlag ? 1 : 0,          "ffi_pairing_indicated_flag" );
475
0
    if (sei.pairingIndicatedFlag)
476
0
    {
477
0
      WRITE_FLAG( sei.pairedWithNextFieldFlag ? 1 : 0,     "ffi_paired_with_next_field_flag" );
478
0
    }
479
0
  }
480
0
  else
481
0
  {
482
0
    WRITE_FLAG( sei.displayFieldsFromFrameFlag ? 1 : 0,     "ffi_display_fields_from_frame_flag" );
483
0
    if (sei.displayFieldsFromFrameFlag)
484
0
    {
485
0
      WRITE_FLAG( sei.topFieldFirstFlag ? 1 : 0,            "ffi_display_fields_from_frame_flag" );
486
0
    }
487
0
    WRITE_CODE( sei.displayElementalPeriodsMinus1, 8,       "ffi_display_elemental_periods_minus1" );
488
0
  }
489
0
  WRITE_CODE( sei.sourceScanType, 2,                        "ffi_source_scan_type" );
490
0
  WRITE_FLAG( sei.duplicateFlag ? 1 : 0,                    "ffi_duplicate_flag" );
491
0
}
492
493
void SEIWriter::xWriteSEIDependentRAPIndication(const SEIDependentRAPIndication& /*sei*/)
494
0
{
495
  // intentionally empty
496
0
}
497
498
void SEIWriter::xWriteSEIScalableNesting(OutputBitstream& bs, const SEIScalableNesting& sei)
499
0
{
500
0
  CHECK (sei.nestedSEIs.size()<1, "There must be at lease one SEI message nested in the scalable nesting SEI.")
501
502
0
  WRITE_FLAG(sei.snOlsFlag, "sn_ols_flag");
503
0
  WRITE_FLAG(sei.snSubpicFlag, "sn_subpic_flag");
504
0
  if (sei.snOlsFlag)
505
0
  {
506
0
    WRITE_UVLC(sei.snNumOlssMinus1, "sn_num_olss_minus1");
507
0
    for (uint32_t i = 0; i <= sei.snNumOlssMinus1; i++)
508
0
    {
509
0
      WRITE_UVLC(sei.snOlsIdxDeltaMinus1[i], "sn_ols_idx_delta_minus1[i]");
510
0
    }
511
0
  }
512
0
  else
513
0
  {
514
0
    WRITE_FLAG(sei.snAllLayersFlag, "sn_all_layers_flag");
515
0
    if (!sei.snAllLayersFlag)
516
0
    {
517
0
      WRITE_UVLC(sei.snNumLayersMinus1, "sn_num_layers");
518
0
      for (uint32_t i = 1; i <= sei.snNumLayersMinus1; i++)
519
0
      {
520
0
        WRITE_CODE(sei.snLayerId[i], 6, "sn_layer_id");
521
0
      }
522
0
    }
523
0
  }
524
0
  if (sei.snSubpicFlag)
525
0
  {
526
0
    WRITE_UVLC( sei.snNumSubpics - 1, "sn_num_subpics_minus1");
527
0
    CHECK(sei.snSubpicIdLen < 1, "sn_subpic_id_len_minus1 must be >= 0");
528
0
    WRITE_UVLC( sei.snSubpicIdLen - 1, "sn_subpic_id_len_minus1");
529
0
    for (uint32_t i = 0; i < sei.snNumSubpics; i++)
530
0
    {
531
0
      WRITE_CODE(sei.snSubpicId[i], sei.snSubpicIdLen, "sn_subpic_id[i]");
532
0
    }
533
0
  }
534
535
0
  WRITE_UVLC( (uint32_t)sei.nestedSEIs.size() - 1, "sn_num_seis_minus1");
536
537
  // byte alignment
538
0
  while (m_pcBitIf->getNumberOfWrittenBits() % 8 != 0)
539
0
  {
540
0
    WRITE_FLAG(0, "sn_zero_bit");
541
0
  }
542
543
0
  SEIMessages bufferingPeriod = getSeisByType(sei.nestedSEIs, SEI::BUFFERING_PERIOD);
544
0
  if (!bufferingPeriod.empty())
545
0
  {
546
0
    SEIBufferingPeriod *bp = (SEIBufferingPeriod*)bufferingPeriod.front();
547
0
    m_nestingHrd.bufferingPeriodSEI = *(bp);
548
0
  }
549
550
  // write nested SEI messages
551
0
  writeSEImessages(bs, sei.nestedSEIs, m_nestingHrd, true, 0);
552
0
}
553
554
void SEIWriter::xWriteSEIFramePacking(const SEIFramePacking& sei)
555
0
{
556
0
  WRITE_UVLC( sei.arrangementId,                  "fp_arrangement_id" );
557
0
  WRITE_FLAG( sei.arrangementCancelFlag,          "fp_arrangement_cancel_flag" );
558
559
0
  if( sei.arrangementCancelFlag == 0 )
560
0
  {
561
0
    WRITE_CODE( sei.arrangementType, 7,           "fp_arrangement_type" );
562
563
0
    WRITE_FLAG( sei.quincunxSamplingFlag,         "fp_quincunx_sampling_flag" );
564
0
    WRITE_CODE( sei.contentInterpretationType, 6, "fp_content_interpretation_type" );
565
0
    WRITE_FLAG( sei.spatialFlippingFlag,          "fp_spatial_flipping_flag" );
566
0
    WRITE_FLAG( sei.frame0FlippedFlag,            "fp_frame0_flipped_flag" );
567
0
    WRITE_FLAG( sei.fieldViewsFlag,               "fp_field_views_flag" );
568
0
    WRITE_FLAG( sei.currentFrameIsFrame0Flag,     "fp_current_frame_is_frame0_flag" );
569
570
0
    WRITE_FLAG( sei.frame0SelfContainedFlag,      "fp_frame0_self_contained_flag" );
571
0
    WRITE_FLAG( sei.frame1SelfContainedFlag,      "fp_frame1_self_contained_flag" );
572
573
0
    if(sei.quincunxSamplingFlag == 0 && sei.arrangementType != 5)
574
0
    {
575
0
      WRITE_CODE( sei.frame0GridPositionX, 4,     "fp_frame0_grid_position_x" );
576
0
      WRITE_CODE( sei.frame0GridPositionY, 4,     "fp_frame0_grid_position_y" );
577
0
      WRITE_CODE( sei.frame1GridPositionX, 4,     "fp_frame1_grid_position_x" );
578
0
      WRITE_CODE( sei.frame1GridPositionY, 4,     "fp_frame1_grid_position_y" );
579
0
    }
580
581
0
    WRITE_CODE( sei.arrangementReservedByte, 8,   "fp_frame_packing_arrangement_reserved_byte" );
582
0
    WRITE_FLAG( sei.arrangementPersistenceFlag,   "fp_frame_packing_arrangement_persistence_flag" );
583
0
  }
584
585
0
  WRITE_FLAG( sei.upsampledAspectRatio,           "fp_upsampled_aspect_ratio" );
586
0
}
587
588
589
void SEIWriter::xWriteSEIParameterSetsInclusionIndication(const SEIParameterSetsInclusionIndication& sei)
590
0
{
591
0
  WRITE_FLAG(sei.selfContainedClvsFlag, "psii_self_contained_clvs_flag");
592
0
}
593
594
void SEIWriter::xWriteSEIMasteringDisplayColourVolume(const SEIMasteringDisplayColourVolume& sei)
595
0
{
596
0
  WRITE_CODE( sei.values.primaries[0][0],  16,  "mdcv_display_primaries_x[0]" );
597
0
  WRITE_CODE( sei.values.primaries[0][1],  16,  "mdcv_display_primaries_y[0]" );
598
599
0
  WRITE_CODE( sei.values.primaries[1][0],  16,  "mdcv_display_primaries_x[1]" );
600
0
  WRITE_CODE( sei.values.primaries[1][1],  16,  "mdcv_display_primaries_y[1]" );
601
602
0
  WRITE_CODE( sei.values.primaries[2][0],  16,  "mdcv_display_primaries_x[2]" );
603
0
  WRITE_CODE( sei.values.primaries[2][1],  16,  "mdcv_display_primaries_y[2]" );
604
605
0
  WRITE_CODE( sei.values.whitePoint[0],    16,  "mdcv_white_point_x" );
606
0
  WRITE_CODE( sei.values.whitePoint[1],    16,  "mdcv_white_point_y" );
607
608
0
  WRITE_CODE( sei.values.maxLuminance,     32,  "mdcv_max_display_mastering_luminance" );
609
0
  WRITE_CODE( sei.values.minLuminance,     32,  "mdcv_min_display_mastering_luminance" );
610
0
}
611
612
void SEIWriter::xWriteByteAlign()
613
0
{
614
0
  if( m_pcBitIf->getNumberOfWrittenBits() % 8 != 0)
615
0
  {
616
0
    WRITE_FLAG( 1, "payload_bit_equal_to_one" );
617
0
    while( m_pcBitIf->getNumberOfWrittenBits() % 8 != 0 )
618
0
    {
619
0
      WRITE_FLAG( 0, "payload_bit_equal_to_zero" );
620
0
    }
621
0
  }
622
0
}
623
624
void SEIWriter::xWriteSEIAlternativeTransferCharacteristics(const SEIAlternativeTransferCharacteristics& sei)
625
0
{
626
0
  WRITE_CODE(sei.preferredTransferCharacteristics, 8, "preferred_transfer_characteristics");
627
0
}
628
629
void SEIWriter::xWriteSEIEquirectangularProjection(const SEIEquirectangularProjection &sei)
630
0
{
631
0
  WRITE_FLAG( sei.erpCancelFlag, "erp_cancel_flag" );
632
0
  if( !sei.erpCancelFlag )
633
0
  {
634
0
    WRITE_FLAG( sei.erpPersistenceFlag, "erp_persistence_flag" );
635
0
    WRITE_FLAG( sei.erpGuardBandFlag,   "erp_guard_band_flag" );
636
0
    WRITE_CODE( 0, 2, "erp_reserved_zero_2bits" );
637
0
    if ( sei.erpGuardBandFlag == 1)
638
0
    {
639
0
      WRITE_CODE( sei.erpGuardBandType,       3, "erp_guard_band_type" );
640
0
      WRITE_CODE( sei.erpLeftGuardBandWidth,  8, "erp_left_guard_band_width" );
641
0
      WRITE_CODE( sei.erpRightGuardBandWidth, 8, "erp_right_guard_band_width" );
642
0
    }
643
0
  }
644
0
}
645
646
void SEIWriter::xWriteSEISphereRotation(const SEISphereRotation &sei)
647
0
{
648
0
  WRITE_FLAG( sei.sphereRotationCancelFlag, "sphere_rotation_cancel_flag" );
649
0
  if( !sei.sphereRotationCancelFlag )
650
0
  {
651
0
    WRITE_FLAG( sei.sphereRotationPersistenceFlag,    "sphere_rotation_persistence_flag" );
652
0
    WRITE_CODE( 0,                                   6, "sphere_rotation_reserved_zero_6bits" );
653
0
    WRITE_SCODE(sei.sphereRotationYaw,            32, "sphere_rotation_yaw" );
654
0
    WRITE_SCODE(sei.sphereRotationPitch,          32, "sphere_rotation_pitch" );
655
0
    WRITE_SCODE(sei.sphereRotationRoll,           32, "sphere_rotation_roll" );
656
0
  }
657
0
}
658
659
void SEIWriter::xWriteSEIOmniViewport(const SEIOmniViewport &sei)
660
0
{
661
0
  WRITE_CODE( sei.omniViewportId,     10,    "omni_viewport_id" );
662
0
  WRITE_FLAG( sei.omniViewportCancelFlag, "omni_viewport_cancel_flag" );
663
0
  if ( !sei.omniViewportCancelFlag )
664
0
  {
665
0
    WRITE_FLAG( sei.omniViewportPersistenceFlag, "omni_viewport_persistence_flag" );
666
0
    const uint32_t numRegions = (uint32_t) sei.omniViewportRegions.size();
667
0
    WRITE_CODE( numRegions - 1, 4, "omni_viewport_cnt_minus1" );
668
0
    for(uint32_t region=0; region<numRegions; region++)
669
0
    {
670
0
      const SEIOmniViewport::OmniViewport &viewport=sei.omniViewportRegions[region];
671
0
      WRITE_SCODE( viewport.azimuthCentre,     32,  "omni_viewport_azimuth_centre"   );
672
0
      WRITE_SCODE( viewport.elevationCentre,   32,  "omni_viewport_elevation_centre" );
673
0
      WRITE_SCODE( viewport.tiltCentre,        32,  "omni_viewport_tilt_center" );
674
0
      WRITE_CODE( viewport.horRange,           32, "omni_viewport_hor_range[i]" );
675
0
      WRITE_CODE( viewport.verRange,           32, "omni_viewport_ver_range[i]" );
676
0
    }
677
0
  }
678
0
}
679
680
void SEIWriter::xWriteSEIRegionWisePacking(const SEIRegionWisePacking &sei)
681
0
{
682
0
  WRITE_FLAG( sei.rwpCancelFlag,                                           "rwp_cancel_flag" );
683
0
  if(!sei.rwpCancelFlag)
684
0
  {
685
0
    WRITE_FLAG( sei.rwpPersistenceFlag,                                    "rwp_persistence_flag" );
686
0
    WRITE_FLAG( sei.constituentPictureMatchingFlag,                        "rwp_constituent_picture_matching_flag" );
687
0
    WRITE_CODE( 0, 5,                                                        "rwp_reserved_zero_5bits" );
688
0
    WRITE_CODE( (uint32_t)sei.numPackedRegions,                 8,             "rwp_num_packed_regions" );
689
0
    WRITE_CODE( (uint32_t)sei.projPictureWidth,                 32,            "rwp_proj_picture_width" );
690
0
    WRITE_CODE( (uint32_t)sei.projPictureHeight,                32,            "rwp_proj_picture_height" );
691
0
    WRITE_CODE( (uint32_t)sei.packedPictureWidth,               16,            "rwp_packed_picture_width" );
692
0
    WRITE_CODE( (uint32_t)sei.packedPictureHeight,              16,            "rwp_packed_picture_height" );
693
0
    for( int i=0; i < sei.numPackedRegions; i++ )
694
0
    {
695
0
      WRITE_CODE( 0, 4,                                                      "rwp_reserved_zero_4bits" );
696
0
      WRITE_CODE( (uint32_t)sei.rwpTransformType[i],            3,             "rwp_tTransform_type" );
697
0
      WRITE_FLAG( sei.rwpGuardBandFlag[i],                                 "rwp_guard_band_flag" );
698
0
      WRITE_CODE( (uint32_t)sei.projRegionWidth[i],             32,            "rwp_proj_region_width" );
699
0
      WRITE_CODE( (uint32_t)sei.projRegionHeight[i],            32,            "rwp_proj_region_height" );
700
0
      WRITE_CODE( (uint32_t)sei.rwpProjRegionTop[i],            32,            "rwp_proj_regionTop" );
701
0
      WRITE_CODE( (uint32_t)sei.projRegionLeft[i],              32,            "rwp_proj_region_left" );
702
0
      WRITE_CODE( (uint32_t)sei.packedRegionWidth[i],           16,            "rwp_packed_region_width" );
703
0
      WRITE_CODE( (uint32_t)sei.packedRegionHeight[i],          16,            "rwp_packed_region_height" );
704
0
      WRITE_CODE( (uint32_t)sei.packedRegionTop[i],             16,            "rwp_packed_region_top" );
705
0
      WRITE_CODE( (uint32_t)sei.packedRegionLeft[i],            16,            "rwp_packed_region_left" );
706
0
      if( sei.rwpGuardBandFlag[i] )
707
0
      {
708
0
        WRITE_CODE( (uint32_t)sei.rwpLeftGuardBandWidth[i],     8,             "rwp_left_guard_band_width");
709
0
        WRITE_CODE( (uint32_t)sei.rwpRightGuardBandWidth[i],    8,             "rwp_right_guard_band_width");
710
0
        WRITE_CODE( (uint32_t)sei.rwpTopGuardBandHeight[i],     8,             "rwp_top_guard_band_height");
711
0
        WRITE_CODE( (uint32_t)sei.rwpBottomGuardBandHeight[i], 8,             "rwp_bottom_guard_band_height");
712
0
        WRITE_FLAG( sei.rwpGuardBandNotUsedForPredFlag[i],                 "rwp_guard_band_not_used_forPred_flag" );
713
0
        for( int j=0; j < 4; j++ )
714
0
        {
715
0
          WRITE_CODE( (uint32_t)sei.rwpGuardBandType[i*4 + j],  3,             "rwp_guard_band_type");
716
0
          }
717
0
        WRITE_CODE( 0, 3,                                                    "rwp_guard_band_reserved_zero_3bits" );
718
0
        }
719
0
      }
720
0
    }
721
0
}
722
723
void SEIWriter::xWriteSEIGeneralizedCubemapProjection(const SEIGeneralizedCubemapProjection &sei)
724
0
{
725
0
  WRITE_FLAG( sei.gcmpCancelFlag,                           "gcmp_cancel_flag" );
726
0
  if (!sei.gcmpCancelFlag)
727
0
  {
728
0
    WRITE_FLAG( sei.gcmpPersistenceFlag,                    "gcmp_persistence_flag" );
729
0
    WRITE_CODE( sei.gcmpPackingType,                     3, "gcmp_packing_type" );
730
0
    WRITE_CODE( sei.gcmpMappingFunctionType,             2, "gcmp_mapping_function_type" );
731
0
    int numFace = sei.gcmpPackingType == 4 || sei.gcmpPackingType == 5 ? 5 : 6;
732
0
    for (int i = 0; i < numFace; i++)
733
0
    {
734
0
      WRITE_CODE( sei.gcmpFaceIndex[i],                  3, "gcmp_face_index" );
735
0
      WRITE_CODE( sei.gcmpFaceRotation[i],               2, "gcmp_face_rotation" );
736
0
      if (sei.gcmpMappingFunctionType == 2)
737
0
      {
738
0
        WRITE_CODE( sei.gcmpFunctionCoeffU[i],           7, "gcmp_function_coeff_u" );
739
0
        WRITE_FLAG( sei.gcmpFunctionUAffectedByVFlag[i],    "gcmp_function_u_affected_by_v_flag" );
740
0
        WRITE_CODE( sei.gcmpFunctionCoeffV[i],           7, "gcmp_function_coeff_v" );
741
0
        WRITE_FLAG( sei.gcmpFunctionVAffectedByUFlag[i],    "gcmp_function_v_affected_by_u_flag" );
742
0
      }
743
0
    }
744
0
    WRITE_FLAG( sei.gcmpGuardBandFlag,                      "gcmp_guard_band_flag" );
745
0
    if (sei.gcmpGuardBandFlag)
746
0
    {
747
0
      WRITE_CODE( sei.gcmpGuardBandType,                 3, "gcmp_guard_band_type" );
748
0
      WRITE_FLAG( sei.gcmpGuardBandBoundaryExteriorFlag,    "gcmp_guard_band_boundary_exterior_flag" );
749
0
      WRITE_CODE( sei.gcmpGuardBandSamplesMinus1,        4, "gcmp_guard_band_samples_minus1" );
750
0
    }
751
0
  }
752
0
}
753
754
void SEIWriter::xWriteSEISubpictureLevelInfo(const SEISubpicureLevelInfo &sei)
755
0
{
756
0
  CHECK(sei.numRefLevels < 1, "SEISubpicureLevelInfo: numRefLevels must be greater than zero");
757
0
  CHECK(sei.numRefLevels != (int)sei.refLevelIdc.size(), "SEISubpicureLevelInfo: numRefLevels must be equal to the number of levels");
758
0
  if (sei.explicitFractionPresent)
759
0
  {
760
0
    CHECK(sei.numRefLevels != (int)sei.refLevelFraction.size(), "SEISubpicureLevelInfo: numRefLevels must be equal to the number of fractions");
761
0
  }
762
0
  WRITE_CODE( (uint32_t)sei.numRefLevels - 1, 3,                            "sli_num_ref_levels_minus1");
763
0
  WRITE_FLAG(           sei.cbrConstraintFlag,                              "sli_cbr_constraint_flag");
764
0
  WRITE_FLAG(           sei.explicitFractionPresent,                    "sli_explicit_fraction_present_flag");
765
0
  if (sei.explicitFractionPresent)
766
0
  {
767
0
    WRITE_UVLC(         sei.numSubpics -1 ,                                 "sli_num_subpics_minus1");
768
0
    WRITE_CODE( (uint32_t)sei.sliMaxSublayers - 1, 3,                       "sli_max_sublayers_minus1");
769
0
    WRITE_FLAG(           sei.sliSublayerInfoPresent,                   "sli_sublayer_info_present_flag");
770
0
    while (!isByteAligned())
771
0
    {
772
0
      WRITE_FLAG(       0,                                                    "sli_alignment_zero_bit");
773
0
    }
774
0
  }
775
776
0
  for (int k = sei.sliSublayerInfoPresent ? 0 : sei.sliMaxSublayers - 1; k < sei.sliMaxSublayers; k++)
777
0
  {
778
0
    for (int i = 0; i < sei.numRefLevels; i++)
779
0
    {
780
0
      WRITE_CODE((uint32_t)sei.nonSubpicLayersFraction[i][k], 8, "sli_non_subpic_layers_fraction[i][k]");
781
0
      WRITE_CODE((uint32_t)sei.refLevelIdc[i][k], 8, "sli_ref_level_idc[i][k]");
782
0
      if (sei.explicitFractionPresent)
783
0
      {
784
0
        CHECK(sei.numSubpics != (int)sei.refLevelFraction[i].size(), "SEISubpicureLevelInfo: number of fractions differs from number of subpictures");
785
0
        for (int j = 0; j < sei.numSubpics; j++)
786
0
        {
787
0
          WRITE_CODE((uint32_t)sei.refLevelFraction[i][j][k], 8, "sli_ref_level_fraction_minus1[i][j][k]");
788
0
        }
789
0
      }
790
0
    }
791
0
  }
792
0
}
793
794
void SEIWriter::xWriteSEISampleAspectRatioInfo(const SEISampleAspectRatioInfo &sei)
795
0
{
796
0
  WRITE_FLAG( sei.sariCancelFlag,                                           "sari_cancel_flag" );
797
0
  if(!sei.sariCancelFlag)
798
0
  {
799
0
    WRITE_FLAG( sei.sariPersistenceFlag,                                    "sari_persistence_flag" );
800
0
    WRITE_CODE( (uint32_t)sei.sariAspectRatioIdc, 8,                        "sari_aspect_ratio_idc");
801
0
    if (sei.sariAspectRatioIdc == 255)
802
0
    {
803
0
      WRITE_CODE( (uint32_t)sei.sariSarWidth, 16,                           "sari_sar_width");
804
0
      WRITE_CODE( (uint32_t)sei.sariSarHeight, 16,                           "sari_sar_height");
805
0
    }
806
0
  }
807
0
}
808
809
void SEIWriter::xWriteSEIUserDataRegistered(const SEIUserDataRegistered &sei)
810
0
{
811
0
  WRITE_CODE((sei.ituCountryCode>255) ? 0xff : sei.ituCountryCode, 8, "itu_t_t35_country_code");
812
0
  if (sei.ituCountryCode >= 255)
813
0
  {
814
0
    assert(sei.ituCountryCode < 255 + 256);
815
0
    WRITE_CODE(sei.ituCountryCode - 255, 8, "itu_t_t35_country_code_extension_byte");
816
0
  }
817
0
  for (uint32_t i = 0; i<sei.userData.size(); i++)
818
0
  {
819
0
    WRITE_CODE(sei.userData[i], 8, "itu_t_t35_payload_byte");
820
0
  }
821
0
}
822
823
void SEIWriter::xWriteSeiFgc(const SeiFgc &sei)
824
0
{
825
0
  WRITE_FLAG(sei.fgcCancelFlag,                             "fg_characteristics_cancel_flag");
826
0
  if (!sei.fgcCancelFlag)
827
0
  {
828
0
    WRITE_CODE(sei.filmGrainModelId, 2,                     "fg_model_id");
829
0
    WRITE_FLAG(sei.separateColourDescriptionPresent,        "fg_separate_colour_description_present_flag");
830
0
    if (sei.separateColourDescriptionPresent)
831
0
    {
832
0
      WRITE_CODE(sei.filmGrainBitDepthLumaMinus8, 3,        "fg_bit_depth_luma_minus8");
833
0
      WRITE_CODE(sei.filmGrainBitDepthChromaMinus8, 3,      "fg_bit_depth_chroma_minus8");
834
0
      WRITE_FLAG(sei.filmGrainFullRangeFlag,                "fg_full_range_flag");
835
0
      WRITE_CODE(sei.filmGrainColourPrimaries, 8,           "fg_colour_primaries");
836
0
      WRITE_CODE(sei.filmGrainTransferCharacteristics, 8,   "fg_transfer_characteristics");
837
0
      WRITE_CODE(sei.filmGrainMatrixCoeffs, 8,              "fg_matrix_coeffs");
838
0
    }
839
0
    WRITE_CODE(sei.blendingModeId, 2,                       "fg_blending_mode_id");
840
0
    WRITE_CODE(sei.log2ScaleFactor, 4,                      "fg_log2_scale_factor");
841
0
    for (int c = 0; c<3; c++)
842
0
    {
843
0
      const SeiFgc::CompModel &cm = sei.compModel[c];
844
0
      const uint32_t numIntensityIntervals = static_cast<uint32_t>(cm.numIntensityIntervals);
845
0
      const uint32_t numModelValues = cm.numModelValues;
846
0
      WRITE_FLAG(sei.compModel[c].presentFlag && numIntensityIntervals>0 && numModelValues>0, "fg_comp_model_present_flag[c]");
847
0
    }
848
0
    for (uint32_t c = 0; c<3; c++)
849
0
    {
850
0
      const SeiFgc::CompModel &cm = sei.compModel[c];
851
0
      const uint32_t numIntensityIntervals = static_cast<uint32_t>(cm.numIntensityIntervals);
852
0
      const uint32_t numModelValues = cm.numModelValues;
853
0
      if (cm.presentFlag && numIntensityIntervals>0 && numModelValues>0)
854
0
      {
855
0
        assert(numIntensityIntervals <= VVENC_MAX_NUM_INTENSITIES);
856
0
        assert(numModelValues <= VVENC_MAX_NUM_INTENSITIES);
857
0
        WRITE_CODE(numIntensityIntervals - 1, 8,            "fg_num_intensity_intervals_minus1[c]");
858
0
        WRITE_CODE(numModelValues - 1, 3,                   "fg_num_model_values_minus1[c]");
859
0
        for (uint32_t interval = 0; interval<numIntensityIntervals; interval++)
860
0
        {
861
0
          const SeiFgc::CompModelIntensityValues &cmiv = cm.intensityValues[interval];
862
0
          WRITE_CODE(cmiv.intensityIntervalLowerBound, 8,   "fg_intensity_interval_lower_bound[c][i]");
863
0
          WRITE_CODE(cmiv.intensityIntervalUpperBound, 8,   "fg_intensity_interval_upper_bound[c][i]");
864
0
          assert(cmiv.compModelValue.size() == numModelValues);
865
0
          for (uint32_t j = 0; j<cm.numModelValues; j++)
866
0
          {
867
0
            WRITE_SVLC(cmiv.compModelValue[j],              "fg_comp_model_value[c][i]");
868
0
          }
869
0
        }
870
0
      }
871
0
    } // for c
872
0
    WRITE_FLAG(sei.fgcPersistenceFlag, "fg_characteristics_persistence_flag");
873
0
  } // cancel flag
874
0
}
875
876
void SEIWriter::xWriteSEIContentLightLevelInfo(const SEIContentLightLevelInfo& sei)
877
0
{
878
0
  WRITE_CODE( sei.maxContentLightLevel,    16, "clli_max_content_light_level"     );
879
0
  WRITE_CODE( sei.maxPicAverageLightLevel, 16, "clli_max_pic_average_light_level" );
880
0
}
881
882
void SEIWriter::xWriteSEIAmbientViewingEnvironment(const SEIAmbientViewingEnvironment& sei)
883
0
{
884
0
  WRITE_CODE(sei.ambientIlluminance, 32, "ambient_illuminance" );
885
0
  WRITE_CODE(sei.ambientLightX,      16, "ambient_light_x" );
886
0
  WRITE_CODE(sei.ambientLightY,      16, "ambient_light_y" );
887
0
}
888
889
void SEIWriter::xWriteSEIContentColourVolume(const SEIContentColourVolume &sei)
890
0
{
891
0
  WRITE_FLAG(sei.ccvCancelFlag, "ccv_cancel_flag");
892
0
  if (!sei.ccvCancelFlag)
893
0
  {
894
0
    WRITE_FLAG(sei.ccvPersistenceFlag, "ccv_persistence_flag");
895
0
    WRITE_FLAG(sei.ccvPrimariesPresent, "ccv_primaries_present_flag");
896
0
    WRITE_FLAG(sei.ccvMinLuminanceValuePresent, "ccv_min_luminance_value_present_flag");
897
0
    WRITE_FLAG(sei.ccvMaxLuminanceValuePresent, "ccv_max_luminance_value_present_flag");
898
0
    WRITE_FLAG(sei.ccvAvgLuminanceValuePresent, "ccv_avg_luminance_value_present_flag");
899
900
0
    if (sei.ccvPrimariesPresent == true)
901
0
    {
902
0
      for (int i = 0; i < MAX_NUM_COMP; i++)
903
0
      {
904
0
        WRITE_SCODE((int32_t)sei.ccvPrimariesX[i], 32, "ccv_primaries_x[i]");
905
0
        WRITE_SCODE((int32_t)sei.ccvPrimariesY[i], 32, "ccv_primaries_y[i]");
906
0
      }
907
0
    }
908
909
0
    if (sei.ccvMinLuminanceValuePresent == true)
910
0
    {
911
0
      WRITE_CODE((uint32_t)sei.ccvMinLuminanceValue, 32, "ccv_min_luminance_value");
912
0
    }
913
0
    if (sei.ccvMinLuminanceValuePresent == true)
914
0
    {
915
0
      WRITE_CODE((uint32_t)sei.ccvMaxLuminanceValue, 32, "ccv_max_luminance_value");
916
0
    }
917
0
    if (sei.ccvMinLuminanceValuePresent == true)
918
0
    {
919
0
      WRITE_CODE((uint32_t)sei.ccvAvgLuminanceValue, 32, "ccv_avg_luminance_value");
920
0
    }
921
0
  }
922
0
}
923
924
} // namespace vvenc
925
926
//! \}
927