Coverage Report

Created: 2026-02-26 06:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/x265/source/encoder/sei.h
Line
Count
Source
1
/*****************************************************************************
2
* Copyright (C) 2013-2020 MulticoreWare, Inc
3
*
4
* Authors: Steve Borho <steve@borho.org>
5
*
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
10
*
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
* GNU General Public License for more details.
15
*
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
19
*
20
* This program is also available under a commercial proprietary license.
21
* For more information, contact us at license @ x265.com.
22
*****************************************************************************/
23
24
#ifndef X265_SEI_H
25
#define X265_SEI_H
26
27
#include "common.h"
28
#include "bitstream.h"
29
#include "slice.h"
30
#include "nal.h"
31
#include "md5.h"
32
33
namespace X265_NS {
34
// private namespace
35
36
class SEI : public SyntaxElementWriter
37
{
38
public:
39
    /* SEI users call writeSEImessages() to marshal an SEI to a bitstream.
40
    * The writeSEImessages() method calls writeSEI() which encodes the header */
41
    void writeSEImessages(Bitstream& bs, const SPS& sps, NalUnitType nalUnitType, NALList& list, int isNested, int layerId = 0);
42
    void setSize(uint32_t size);
43
    static char* base64Decode(char encodedString[], int base64EncodeLength, char* base64Decode);
44
0
    virtual ~SEI() {}
45
protected:
46
    SEIPayloadType  m_payloadType;
47
    uint32_t        m_payloadSize;
48
    virtual void writeSEI(const SPS&) = 0;
49
    void writeByteAlign();
50
};
51
52
//seongnam.oh@samsung.com :: for the Creative Intent Meta Data Encoding
53
class SEIuserDataRegistered : public SEI
54
{
55
public:
56
    SEIuserDataRegistered()
57
0
    {
58
0
        m_payloadType = USER_DATA_REGISTERED_ITU_T_T35;
59
0
        m_payloadSize = 0;
60
0
    }
61
62
    uint8_t *m_userData;
63
64
    // daniel.vt@samsung.com :: for the Creative Intent Meta Data Encoding ( seongnam.oh@samsung.com )
65
    void writeSEI(const SPS&)
66
0
    {
67
0
        if (!m_userData)
68
0
            return;
69
70
0
        uint32_t i = 0;
71
0
        for (; i < m_payloadSize; ++i)
72
0
            WRITE_CODE(m_userData[i], 8, "creative_intent_metadata");
73
0
    }
74
};
75
76
/* Film grain characteristics */
77
class FilmGrainCharacteristics : public SEI
78
{
79
  public:
80
81
    FilmGrainCharacteristics()
82
0
    {
83
0
        m_payloadType = FILM_GRAIN_CHARACTERISTICS;
84
0
        m_payloadSize = 0;
85
0
    }
86
87
    struct CompModelIntensityValues
88
    {
89
        uint8_t intensityIntervalLowerBound;
90
        uint8_t intensityIntervalUpperBound;
91
        int*    compModelValue;
92
    };
93
94
    struct CompModel
95
    {
96
        bool    bPresentFlag;
97
        uint8_t numModelValues;
98
        uint8_t m_filmGrainNumIntensityIntervalMinus1;
99
        CompModelIntensityValues* intensityValues;
100
    };
101
102
    CompModel   m_compModel[MAX_NUM_COMPONENT];
103
    bool        m_filmGrainCharacteristicsPersistenceFlag;
104
    bool        m_filmGrainCharacteristicsCancelFlag;
105
    bool        m_separateColourDescriptionPresentFlag;
106
    bool        m_filmGrainFullRangeFlag;
107
    uint8_t     m_filmGrainModelId;
108
    uint8_t     m_blendingModeId;
109
    uint8_t     m_log2ScaleFactor;
110
    uint8_t     m_filmGrainBitDepthLumaMinus8;
111
    uint8_t     m_filmGrainBitDepthChromaMinus8;
112
    uint8_t     m_filmGrainColourPrimaries;
113
    uint8_t     m_filmGrainTransferCharacteristics;
114
    uint8_t     m_filmGrainMatrixCoeffs;
115
116
    void writeSEI(const SPS&)
117
0
    {
118
0
        WRITE_FLAG(m_filmGrainCharacteristicsCancelFlag, "film_grain_characteristics_cancel_flag");
119
120
0
        if (!m_filmGrainCharacteristicsCancelFlag)
121
0
        {
122
0
            WRITE_CODE(m_filmGrainModelId, 2, "film_grain_model_id");
123
0
            WRITE_FLAG(m_separateColourDescriptionPresentFlag, "separate_colour_description_present_flag");
124
0
            if (m_separateColourDescriptionPresentFlag)
125
0
            {
126
0
                WRITE_CODE(m_filmGrainBitDepthLumaMinus8, 3, "film_grain_bit_depth_luma_minus8");
127
0
                WRITE_CODE(m_filmGrainBitDepthChromaMinus8, 3, "film_grain_bit_depth_chroma_minus8");
128
0
                WRITE_FLAG(m_filmGrainFullRangeFlag, "film_grain_full_range_flag");
129
0
                WRITE_CODE(m_filmGrainColourPrimaries, X265_BYTE, "film_grain_colour_primaries");
130
0
                WRITE_CODE(m_filmGrainTransferCharacteristics, X265_BYTE, "film_grain_transfer_characteristics");
131
0
                WRITE_CODE(m_filmGrainMatrixCoeffs, X265_BYTE, "film_grain_matrix_coeffs");
132
0
            }
133
0
            WRITE_CODE(m_blendingModeId, 2, "blending_mode_id");
134
0
            WRITE_CODE(m_log2ScaleFactor, 4, "log2_scale_factor");
135
0
            for (uint8_t c = 0; c < 3; c++)
136
0
            {
137
0
                WRITE_FLAG(m_compModel[c].bPresentFlag && m_compModel[c].m_filmGrainNumIntensityIntervalMinus1 + 1 > 0 && m_compModel[c].numModelValues > 0, "comp_model_present_flag[c]");
138
0
            }
139
0
            for (uint8_t c = 0; c < 3; c++)
140
0
            {
141
0
                if (m_compModel[c].bPresentFlag && m_compModel[c].m_filmGrainNumIntensityIntervalMinus1 + 1 > 0 && m_compModel[c].numModelValues > 0)
142
0
                {
143
0
                    assert(m_compModel[c].m_filmGrainNumIntensityIntervalMinus1 + 1 <= 256);
144
0
                    assert(m_compModel[c].numModelValues <= X265_BYTE);
145
0
                    WRITE_CODE(m_compModel[c].m_filmGrainNumIntensityIntervalMinus1 , X265_BYTE, "num_intensity_intervals_minus1[c]");
146
0
                    WRITE_CODE(m_compModel[c].numModelValues - 1, 3, "num_model_values_minus1[c]");
147
0
                    for (uint8_t interval = 0; interval < m_compModel[c].m_filmGrainNumIntensityIntervalMinus1 + 1; interval++)
148
0
                    {
149
0
                        WRITE_CODE(m_compModel[c].intensityValues[interval].intensityIntervalLowerBound, X265_BYTE, "intensity_interval_lower_bound[c][i]");
150
0
                        WRITE_CODE(m_compModel[c].intensityValues[interval].intensityIntervalUpperBound, X265_BYTE, "intensity_interval_upper_bound[c][i]");
151
0
                        for (uint8_t j = 0; j < m_compModel[c].numModelValues; j++)
152
0
                        {
153
0
                            WRITE_SVLC(m_compModel[c].intensityValues[interval].compModelValue[j],"comp_model_value[c][i]");
154
0
                        }
155
0
                    }
156
0
                }
157
0
            }
158
0
            WRITE_FLAG(m_filmGrainCharacteristicsPersistenceFlag, "film_grain_characteristics_persistence_flag");
159
0
        }
160
0
        if (m_bitIf->getNumberOfWrittenBits() % X265_BYTE != 0)
161
0
        {
162
0
            WRITE_FLAG(1, "payload_bit_equal_to_one");
163
0
            while (m_bitIf->getNumberOfWrittenBits() % X265_BYTE != 0)
164
0
            {
165
0
                WRITE_FLAG(0, "payload_bit_equal_to_zero");
166
0
            }
167
0
        }
168
0
    }
169
};
170
171
class AomFilmGrainCharacteristics : public SEI {
172
173
public:
174
175
    AomFilmGrainCharacteristics()
176
0
    {
177
0
        m_payloadType = USER_DATA_REGISTERED_ITU_T_T35;
178
0
        m_payloadSize = 0;
179
0
    }
180
181
    int32_t     m_apply_grain;
182
    int32_t     m_update_grain;
183
    int32_t     m_scaling_points_y[14][2];
184
    int32_t     m_num_y_points;
185
    int32_t     m_scaling_points_cb[10][2];
186
    int32_t     m_num_cb_points;
187
    int32_t     m_scaling_points_cr[10][2];
188
    int32_t     m_num_cr_points;
189
    int32_t     m_scaling_shift;
190
    int32_t     m_ar_coeff_lag;
191
    int32_t     m_ar_coeffs_y[24];
192
    int32_t     m_ar_coeffs_cb[25];
193
    int32_t     m_ar_coeffs_cr[25];
194
    int32_t     m_ar_coeff_shift;
195
    int32_t     m_cb_mult;
196
    int32_t     m_cb_luma_mult;
197
    int32_t     m_cb_offset;
198
    int32_t     m_cr_mult;
199
    int32_t     m_cr_luma_mult;
200
    int32_t     m_cr_offset;
201
    int32_t     m_overlap_flag;
202
    int32_t     m_clip_to_restricted_range;
203
    int32_t     m_bitDepth;
204
    int32_t     m_chroma_scaling_from_luma;
205
    int32_t     m_grain_scale_shift;
206
    uint16_t    m_grain_seed;
207
    bool        subsamplingX;
208
    bool        subsamplingY;
209
    bool        predict_scaling_flag;
210
    bool        predict_y_scaling_flag;
211
    bool        predict_cb_scaling_flag;
212
    bool        predict_cr_scaling_flag;
213
    int         units_resolution_log2;
214
    int         horz_resolution;
215
    int         vert_resolution;
216
    bool        luma_only_flag;
217
    int         point_y_value_increment_bits;
218
    int         point_y_scaling_bits;
219
    int         point_cb_value_increment_bits;
220
    int         point_cb_scaling_bits;
221
    int         point_cr_value_increment_bits;
222
    int         point_cr_scaling_bits;
223
    int         cb_scaling_offset;
224
    int         cr_scaling_offset;
225
    int         payload_size;
226
    int         payload_bits;
227
228
    void writeSEI(const SPS& sps)
229
0
    {
230
0
        WRITE_CODE(0xB5, 8, "country_code");
231
0
        WRITE_CODE(0x5890, 16, "provider_code");
232
0
        WRITE_CODE(0x0001, 8, "provider_oriented_code");
233
0
        WRITE_FLAG(1, "afgs1_enable_flag");
234
0
        WRITE_CODE(0, 4, "reserved_4bits");
235
0
        WRITE_CODE(0, 3, "num_film_grain_sets_minus1");
236
0
        WRITE_FLAG(payload_size < 4 ? 1 : 0, "payload_less_than_4byte_flag");
237
0
        WRITE_CODE(payload_size, payload_bits, "payload_size");
238
239
0
        WRITE_CODE(0, 3, "film_grain_param_set_idx");
240
0
        WRITE_FLAG(m_apply_grain, "apply_grain_flag");
241
0
        WRITE_CODE(m_grain_seed, 16, "grain_seed");
242
0
        WRITE_FLAG(1, "update_grain_flag");
243
0
        WRITE_CODE(units_resolution_log2, 4, "apply_units_resolution_log2");
244
0
        WRITE_CODE(horz_resolution, 12, "apply_horz_resolution");
245
0
        WRITE_CODE(vert_resolution, 12, "apply_vert_resolution");
246
0
        WRITE_FLAG(luma_only_flag, "luma_only_flag");
247
0
        if (!luma_only_flag) {
248
0
            WRITE_FLAG(subsamplingX, "subsampling_x");
249
0
            WRITE_FLAG(subsamplingY, "subsampling_y");
250
0
        }
251
0
        WRITE_FLAG(sps.vuiParameters.videoSignalTypePresentFlag, "video_signal_characteristics_flag");
252
0
        if (sps.vuiParameters.videoSignalTypePresentFlag)
253
0
        {
254
0
            WRITE_CODE(m_bitDepth - 8, 3, "bit_depth_minus8");
255
0
            WRITE_FLAG(sps.vuiParameters.colourDescriptionPresentFlag, "cicp_info_present_flag");
256
0
            if (sps.vuiParameters.colourDescriptionPresentFlag)
257
0
            {
258
0
                WRITE_CODE(sps.vuiParameters.colourPrimaries, 8, "colour_primaries");
259
0
                WRITE_CODE(sps.vuiParameters.transferCharacteristics, 8, "transfer_characteristics");
260
0
                WRITE_CODE(sps.vuiParameters.matrixCoefficients, 8, "matrix_coefficients");
261
0
                WRITE_FLAG(sps.vuiParameters.videoFullRangeFlag, "video_full_range_flag");
262
0
            }
263
0
        }
264
0
        WRITE_FLAG(predict_scaling_flag, "predict_scaling_flag");
265
0
        if (predict_scaling_flag) {
266
0
            WRITE_FLAG(predict_y_scaling_flag, "predict_y_scaling_flag");
267
0
        }
268
269
0
        WRITE_CODE(m_num_y_points, 4, "num_y_points");
270
0
        if (m_num_y_points) {
271
0
            WRITE_CODE(point_y_value_increment_bits - 1, 3, "point_y_value_increment_bits_minus1");
272
0
            int bitsIncr = point_y_value_increment_bits;
273
0
            WRITE_CODE(point_y_scaling_bits - 5, 2, "point_y_scaling_bits_minus5");
274
0
            int bitsScal = point_y_scaling_bits;
275
0
            for (int i = 0; i < m_num_y_points; i++) {
276
0
                if (i)
277
0
                    WRITE_CODE(m_scaling_points_y[i][0] - m_scaling_points_y[i - 1][0], bitsIncr, "point_y_value_increment[i]");
278
0
                else
279
0
                    WRITE_CODE(m_scaling_points_y[i][0], bitsIncr, "point_y_value_increment[i]");
280
0
                WRITE_CODE(m_scaling_points_y[i][1], bitsScal, "point_y_scaling[i]");
281
0
            }
282
0
        }
283
284
0
        if (!luma_only_flag)
285
0
            WRITE_FLAG(m_chroma_scaling_from_luma, "chroma_scaling_from_luma");
286
287
0
        if (luma_only_flag || m_chroma_scaling_from_luma) {
288
0
            m_num_cb_points = 0;
289
0
            m_num_cr_points = 0;
290
0
        }
291
0
        else {
292
0
            if (predict_scaling_flag)
293
0
                WRITE_FLAG(predict_cb_scaling_flag, "predict_cb_scaling_flag");
294
295
0
            WRITE_CODE(m_num_cb_points, 4, "num_cb_points");
296
0
            if (m_num_cb_points) {
297
0
                WRITE_CODE(point_cb_value_increment_bits - 1, 3, "point_cb_value_increment_bits_minus1");
298
0
                int bitsIncr = point_cb_value_increment_bits;
299
0
                WRITE_CODE(point_cb_scaling_bits - 5, 2, "point_cb_scaling_bits_minus5");
300
0
                int bitsScal = point_cb_scaling_bits;
301
0
                WRITE_CODE(cb_scaling_offset, 8, "cb_scaling_offset");
302
303
0
                for (int i = 0; i < m_num_cb_points; i++) {
304
0
                    if (i)
305
0
                        WRITE_CODE(m_scaling_points_cb[i][0] - m_scaling_points_cb[i - 1][0], bitsIncr, "point_cb_value_increment[i]");
306
0
                    else
307
0
                        WRITE_CODE(m_scaling_points_cb[i][0], bitsIncr, "point_cb_value_increment[i]");
308
0
                    WRITE_CODE(m_scaling_points_cb[i][1], bitsScal, "point_cb_scaling[i]");
309
0
                }
310
0
            }
311
312
0
            if (predict_scaling_flag)
313
0
                WRITE_FLAG(predict_cr_scaling_flag, "predict_cr_scaling_flag");
314
315
0
            WRITE_CODE(m_num_cr_points, 4, "num_cr_points");
316
0
            if (m_num_cr_points) {
317
0
                WRITE_CODE(point_cr_value_increment_bits - 1, 3, "point_cr_value_increment_bits_minus1");
318
0
                int bitsIncr = point_cr_value_increment_bits;
319
0
                WRITE_CODE(point_cr_scaling_bits - 5, 2, "point_cr_scaling_bits_minus5");
320
0
                int bitsScal = point_cr_scaling_bits;
321
0
                WRITE_CODE(cr_scaling_offset, 8, "cr_scaling_offset");
322
323
0
                for (int i = 0; i < m_num_cr_points; i++) {
324
0
                    if (i)
325
0
                        WRITE_CODE(m_scaling_points_cr[i][0] - m_scaling_points_cr[i - 1][0], bitsIncr, "point_cr_value_increment[i]");
326
0
                    else
327
0
                        WRITE_CODE(m_scaling_points_cr[i][0], bitsIncr, "point_cr_value_increment[i]");
328
0
                    WRITE_CODE(m_scaling_points_cr[i][1], bitsScal, "point_cr_scaling[i]");
329
0
                }
330
0
            }
331
0
        }
332
333
0
        WRITE_CODE(m_scaling_shift - 8, 2, "grain_scaling_minus8");
334
0
        WRITE_CODE(m_ar_coeff_lag, 2, "ar_coeff_lag");
335
0
        int bits_per_ar_coef = 8;
336
0
        if (m_num_y_points || predict_y_scaling_flag)
337
0
        {
338
0
            WRITE_CODE(bits_per_ar_coef - 5, 2, "bits_per_ar_coeff_y_minus5");
339
340
0
            for (int i = 0; i < 24; i++)
341
0
            {
342
0
                WRITE_CODE(m_ar_coeffs_y[i] + (1 << (bits_per_ar_coef - 1)), bits_per_ar_coef, "ar_coeff_y[i]");
343
0
            }
344
0
        }
345
0
        if (m_num_cb_points || m_chroma_scaling_from_luma || predict_cb_scaling_flag)
346
0
        {
347
0
            WRITE_CODE(bits_per_ar_coef - 5, 2, "bits_per_ar_coeff_cb_minus5");
348
349
0
            for (int i = 0; i < 25; i++)
350
0
            {
351
0
                WRITE_CODE(m_ar_coeffs_cb[i] + (1 << (bits_per_ar_coef - 1)), bits_per_ar_coef, "ar_coeff_cb[i]");
352
0
            }
353
0
        }
354
0
        if (m_num_cr_points || m_chroma_scaling_from_luma || predict_cr_scaling_flag)
355
0
        {
356
0
            WRITE_CODE(bits_per_ar_coef - 5, 2, "bits_per_ar_coeff_cr_minus5");
357
358
0
            for (int i = 0; i < 25; i++)
359
0
            {
360
0
                WRITE_CODE(m_ar_coeffs_cr[i] + (1 << (bits_per_ar_coef - 1)), bits_per_ar_coef, "ar_coeff_cr[i]");
361
0
            }
362
0
        }
363
0
        WRITE_CODE(m_ar_coeff_shift - 6, 2, "ar_coeff_shift");
364
0
        WRITE_CODE(m_grain_scale_shift, 2, "grain_scale_shift");
365
0
        if (m_num_cb_points && !predict_cb_scaling_flag)
366
0
        {
367
0
            WRITE_CODE(m_cb_mult, 8, "cb_mult");
368
0
            WRITE_CODE(m_cb_luma_mult, 8, "cb_luma_mult");
369
0
            WRITE_CODE(m_cb_offset, 9, "cb_offset");
370
0
        }
371
0
        if (m_num_cr_points && !predict_cr_scaling_flag)
372
0
        {
373
0
            WRITE_CODE(m_cr_mult, 8, "cr_mult");
374
0
            WRITE_CODE(m_cr_luma_mult, 8, "cr_luma_mult");
375
0
            WRITE_CODE(m_cr_offset, 9, "cr_offset");
376
0
        }
377
0
        WRITE_FLAG(m_overlap_flag, "overlap_flag");
378
0
        WRITE_FLAG(m_clip_to_restricted_range, "clip_to_restricted_range");
379
0
        if (m_bitIf->getNumberOfWrittenBits() % X265_BYTE != 0)
380
0
        {
381
0
            WRITE_FLAG(1, "payload_bit_equal_to_one");
382
0
            while (m_bitIf->getNumberOfWrittenBits() % X265_BYTE != 0)
383
0
            {
384
0
                WRITE_FLAG(0, "payload_bit_equal_to_zero");
385
0
            }
386
0
        }
387
0
    }
388
};
389
390
static const uint32_t ISO_IEC_11578_LEN = 16;
391
392
class SEIuserDataUnregistered : public SEI
393
{
394
public:
395
0
    SEIuserDataUnregistered() : m_userData(NULL)
396
0
    {
397
0
        m_payloadType = USER_DATA_UNREGISTERED;
398
0
        m_payloadSize = 0;
399
0
    }
400
    static const uint8_t m_uuid_iso_iec_11578[ISO_IEC_11578_LEN];
401
    uint8_t *m_userData;
402
    void writeSEI(const SPS&)
403
0
    {
404
0
        for (uint32_t i = 0; i < ISO_IEC_11578_LEN; i++)
405
0
            WRITE_CODE(m_uuid_iso_iec_11578[i], 8, "sei.uuid_iso_iec_11578[i]");
406
0
        for (uint32_t i = 0; i < m_payloadSize; i++)
407
0
            WRITE_CODE(m_userData[i], 8, "user_data");
408
0
    }
409
};
410
411
#if ENABLE_ALPHA
412
class SEIAlphaChannelInfo : public SEI
413
{
414
public:
415
    SEIAlphaChannelInfo()
416
    {
417
        m_payloadType = ALPHA_CHANNEL_INFO;
418
        m_payloadSize = 0;
419
    }
420
421
    bool alpha_channel_cancel_flag;
422
    void writeSEI(const SPS&)
423
    {
424
        WRITE_CODE(alpha_channel_cancel_flag, 1, "alpha_channel_cancel_flag");
425
        if (!alpha_channel_cancel_flag)
426
        {
427
            WRITE_CODE(0, 3, "alpha_channel_use_idc");
428
            WRITE_CODE(0, 3, "alpha_channel_bit_depth_minus8");
429
            WRITE_CODE(0, 9, "alpha_transparent_value");
430
            WRITE_CODE(255, 9, "alpha_opaque_value");
431
            WRITE_CODE(0, 1, "alpha_channel_incr_flag");
432
            WRITE_CODE(0, 1, "alpha_channel_clip_flag");
433
        }
434
        if (m_bitIf->getNumberOfWrittenBits() % X265_BYTE != 0)
435
        {
436
            WRITE_FLAG(1, "payload_bit_equal_to_one");
437
            while (m_bitIf->getNumberOfWrittenBits() % X265_BYTE != 0)
438
            {
439
                WRITE_FLAG(0, "payload_bit_equal_to_zero");
440
            }
441
        }
442
    }
443
};
444
#endif
445
446
#if ENABLE_MULTIVIEW
447
class SEIThreeDimensionalReferenceDisplaysInfo : public SEI
448
{
449
public:
450
    SEIThreeDimensionalReferenceDisplaysInfo()
451
        : m_numRefDisplaysMinus1(0),
452
        m_refViewingDistanceFlag(false),
453
        m_additionalShiftPresentFlag(false)
454
    {
455
        m_payloadType = THREE_DIMENSIONAL_REFERENCE_DISPLAYS_INFO;
456
        m_payloadSize = 0;
457
    }
458
459
    int m_numRefDisplaysMinus1;
460
    bool m_refViewingDistanceFlag;
461
    bool m_additionalShiftPresentFlag;
462
    void writeSEI(const SPS&)
463
    {
464
        WRITE_UVLC(31, "prec_ref_display_width");
465
        WRITE_FLAG(m_refViewingDistanceFlag, "ref_viewing_distance_flag");
466
        if (m_refViewingDistanceFlag)
467
        {
468
            WRITE_UVLC(0, "prec_ref_viewing_dist");
469
        }
470
        WRITE_UVLC(0, "num_ref_displays_minus1");
471
        for (int i = 0; i <= m_numRefDisplaysMinus1; i++)
472
        {
473
            WRITE_UVLC(0, "left_view_id");
474
            WRITE_UVLC(1, "right_view_id");
475
            WRITE_CODE(0, 6, "exponent_ref_display_width");
476
            WRITE_CODE(0, 2, "mantissa_ref_display_width");
477
            if (m_refViewingDistanceFlag)
478
            {
479
                WRITE_CODE(0, 6, "exponent_ref_viewing_distance");
480
                WRITE_CODE(0, 1, "mantissa_ref_viewing_distance");
481
            }
482
            WRITE_FLAG(m_additionalShiftPresentFlag, "additional_shift_present_flag");
483
            if (m_additionalShiftPresentFlag)
484
            {
485
                WRITE_CODE(0, 10, "num_sample_shift_plus512");
486
            }
487
        }
488
        WRITE_FLAG(0, "three_dimensional_reference_displays_extension_flag");
489
490
        if (m_bitIf->getNumberOfWrittenBits() % X265_BYTE != 0)
491
        {
492
            WRITE_FLAG(1, "payload_bit_equal_to_one");
493
            while (m_bitIf->getNumberOfWrittenBits() % X265_BYTE != 0)
494
            {
495
                WRITE_FLAG(0, "payload_bit_equal_to_zero");
496
            }
497
        }
498
    }
499
500
};
501
502
class SEIMultiviewSceneInfo : public SEI
503
{
504
public:
505
    SEIMultiviewSceneInfo()
506
    {
507
        m_payloadType = MULTIVIEW_SCENE_INFO;
508
        m_payloadSize = 0;
509
    }
510
    void writeSEI(const SPS&)
511
    {
512
        WRITE_SVLC(-333, "min_disparity");
513
        WRITE_UVLC(2047, "max_disparity_range");
514
515
        if (m_bitIf->getNumberOfWrittenBits() % X265_BYTE != 0)
516
        {
517
            WRITE_FLAG(1, "payload_bit_equal_to_one");
518
            while (m_bitIf->getNumberOfWrittenBits() % X265_BYTE != 0)
519
            {
520
                WRITE_FLAG(0, "payload_bit_equal_to_zero");
521
            }
522
        }
523
    }
524
};
525
526
static int temp_sign_r[3][3] = { {0,1,0},{1,0,0},{0,1,1} };
527
static int temp_exponent_r[3][3] = { {10,20,11},{10,5,11},{2,20,11} };
528
static int temp_mantissa_r[3][3] = { {4,9,1},{0,3,4},{3,3,7} };
529
static int temp_sign_t[1][3] = { { 0,1,0  } };
530
static int temp_exponent_t[1][3] = { { 0,10,5 } };
531
static int temp_mantissa_t[1][3] = { { 1,8,9 } };
532
static int temp_length_mantissa_r[3][3] = { {10,20,11},{10,5,11},{2,20,11} };
533
static int temp_length_mantissa_t[1][3] = { { 1,10,5 } };
534
535
class SEIMultiviewAcquisitionInfo : public SEI
536
{
537
public:
538
    SEIMultiviewAcquisitionInfo()
539
        :sign_r(),
540
        exponent_r(),
541
        mantissa_r(),
542
        sign_t(),
543
        exponent_t(),
544
        mantissa_t(),
545
        length_mantissa_r(),
546
        length_mantissa_t(),
547
        m_intrinsicParamFlag(true),
548
        m_extrinsicParamFlag(true),
549
        m_intrinsicParamsEqualFlag(true)
550
    {
551
        m_payloadType = MULTIVIEW_ACQUISITION_INFO;
552
        m_payloadSize = 0;
553
554
        for (int i = 0; i <= 0; i++)
555
        {
556
            for (int j = 0; j <= 2; j++)  /* row */
557
            {
558
                for (int k = 0; k <= 2; k++)  /* column */
559
                {
560
                    sign_r[j][k] = temp_sign_r[j][k];
561
                    exponent_r[j][k] = temp_exponent_r[j][k];
562
                    mantissa_r[j][k] = temp_mantissa_r[j][k];
563
                    length_mantissa_r[j][k] = temp_length_mantissa_r[j][k];
564
                }
565
                sign_t[i][j] = temp_sign_t[i][j];
566
                exponent_t[i][j] = temp_exponent_t[i][j];
567
                mantissa_t[i][j] = temp_mantissa_t[i][j];
568
                length_mantissa_t[i][j] = temp_length_mantissa_t[i][j];
569
            }
570
        }
571
    }
572
573
    int sign_r[3][3];
574
    int exponent_r[3][3];
575
    int mantissa_r[3][3];
576
    int sign_t[1][3];
577
    int exponent_t[1][3];
578
    int mantissa_t[1][3];
579
    int length_mantissa_r[3][3];
580
    int length_mantissa_t[1][3];
581
582
    bool m_intrinsicParamFlag;
583
    bool m_extrinsicParamFlag;
584
    bool m_intrinsicParamsEqualFlag;
585
586
    void writeSEI(const SPS& sps)
587
    {
588
        WRITE_FLAG(m_intrinsicParamFlag, "intrinsic_param_flag");
589
        WRITE_FLAG(m_extrinsicParamFlag, "extrinsic_param_flag");
590
        if (m_intrinsicParamFlag)
591
        {
592
            WRITE_FLAG(m_intrinsicParamsEqualFlag, "intrinsic_params_equal_flag");
593
            WRITE_UVLC(31, "prec_focal_length");
594
            WRITE_UVLC(31, "prec_principal_point");
595
            WRITE_UVLC(31, "prec_skew_factor");
596
597
            for (int i = 0; i <= (m_intrinsicParamsEqualFlag ? 0 : sps.maxViews - 1); i++)
598
            {
599
                WRITE_FLAG(0, "sign_focal_length_x");
600
                WRITE_CODE(0, 6, "exponent_focal_length_x");
601
                WRITE_CODE(0, 1, "mantissa_focal_length_x");
602
                WRITE_FLAG(0, "sign_focal_length_y");
603
                WRITE_CODE(0, 6, "exponent_focal_length_y");
604
                WRITE_CODE(0, 1, "mantissa_focal_length_y");
605
                WRITE_FLAG(0, "sign_principal_point_x");
606
                WRITE_CODE(0, 6, "exponent_principal_point_x");
607
                WRITE_CODE(0, 1, "mantissa_principal_point_x");
608
                WRITE_FLAG(0, "sign_principal_point_y");
609
                WRITE_CODE(0, 6, "exponent_principal_point_y");
610
                WRITE_CODE(0, 1, "mantissa_principal_point_y");
611
                WRITE_FLAG(0, "sign_skew_factor");
612
                WRITE_CODE(0, 6, "exponent_skew_factor");
613
                WRITE_CODE(0, 1, "mantissa_skew_factor");
614
            }
615
        }
616
617
        if (m_extrinsicParamFlag)
618
        {
619
            WRITE_UVLC(31, "prec_rotation_param");
620
            WRITE_UVLC(31, "prec_translation_param");
621
            for (int i = 0; i <= 0; i++)
622
            {
623
                for (int j = 0; j <= 2; j++)  /* row */
624
                {
625
                    for (int k = 0; k <= 2; k++)  /* column */
626
                    {
627
                        WRITE_FLAG(sign_r[j][k], "sign_r");
628
                        WRITE_CODE(exponent_r[j][k], 6, "exponent_r");
629
                        WRITE_CODE(mantissa_r[j][k], length_mantissa_r[j][k], "mantissa_r");
630
                    }
631
                    WRITE_FLAG(sign_t[i][j], "sign_t");
632
                    WRITE_CODE(exponent_t[i][j], 6, "exponent_t");
633
                    WRITE_CODE(mantissa_t[i][j], length_mantissa_t[i][j], "mantissa_t");
634
                }
635
            }
636
        }
637
        if (m_bitIf->getNumberOfWrittenBits() % X265_BYTE != 0)
638
        {
639
            WRITE_FLAG(1, "payload_bit_equal_to_one");
640
            while (m_bitIf->getNumberOfWrittenBits() % X265_BYTE != 0)
641
            {
642
                WRITE_FLAG(0, "payload_bit_equal_to_zero");
643
            }
644
        }
645
    }
646
};
647
648
class SEIMultiviewViewPosition : public SEI
649
{
650
public:
651
    SEIMultiviewViewPosition()
652
    {
653
        m_payloadType = MULTIVIEW_VIEW_POSITION;
654
        m_payloadSize = 0;
655
    }
656
    void writeSEI(const SPS& sps)
657
    {
658
        WRITE_UVLC(sps.maxViews - 1, "num_views_minus1");
659
        for (int i = 0; i <= sps.maxViews - 1; i++)
660
        {
661
            WRITE_UVLC(!i, "view_position");
662
        }
663
664
        if (m_bitIf->getNumberOfWrittenBits() % X265_BYTE != 0)
665
        {
666
            WRITE_FLAG(1, "payload_bit_equal_to_one");
667
            while (m_bitIf->getNumberOfWrittenBits() % X265_BYTE != 0)
668
            {
669
                WRITE_FLAG(0, "payload_bit_equal_to_zero");
670
            }
671
        }
672
    }
673
};
674
#endif
675
676
class SEIMasteringDisplayColorVolume : public SEI
677
{
678
public:
679
    SEIMasteringDisplayColorVolume()
680
0
    {
681
0
        m_payloadType = MASTERING_DISPLAY_INFO;
682
0
        m_payloadSize = (8 * 2 + 2 * 4);
683
0
    }
684
    uint16_t displayPrimaryX[3];
685
    uint16_t displayPrimaryY[3];
686
    uint16_t whitePointX, whitePointY;
687
    uint32_t maxDisplayMasteringLuminance;
688
    uint32_t minDisplayMasteringLuminance;
689
    bool parse(const char* value)
690
0
    {
691
0
        return sscanf(value, "G(%hu,%hu)B(%hu,%hu)R(%hu,%hu)WP(%hu,%hu)L(%u,%u)",
692
0
                      &displayPrimaryX[0], &displayPrimaryY[0],
693
0
                      &displayPrimaryX[1], &displayPrimaryY[1],
694
0
                      &displayPrimaryX[2], &displayPrimaryY[2],
695
0
                      &whitePointX, &whitePointY,
696
0
                      &maxDisplayMasteringLuminance, &minDisplayMasteringLuminance) == 10;
697
0
    }
698
    void writeSEI(const SPS&)
699
0
    {
700
0
        for (uint32_t i = 0; i < 3; i++)
701
0
        {
702
0
            WRITE_CODE(displayPrimaryX[i], 16, "display_primaries_x[ c ]");
703
0
            WRITE_CODE(displayPrimaryY[i], 16, "display_primaries_y[ c ]");
704
0
        }
705
0
        WRITE_CODE(whitePointX, 16, "white_point_x");
706
0
        WRITE_CODE(whitePointY, 16, "white_point_y");
707
0
        WRITE_CODE(maxDisplayMasteringLuminance, 32, "max_display_mastering_luminance");
708
0
        WRITE_CODE(minDisplayMasteringLuminance, 32, "min_display_mastering_luminance");
709
0
    }
710
};
711
712
class SEIContentLightLevel : public SEI
713
{
714
public:
715
    SEIContentLightLevel()
716
0
    {
717
0
        m_payloadType = CONTENT_LIGHT_LEVEL_INFO;
718
0
        m_payloadSize = 4;
719
0
    }
720
    uint16_t max_content_light_level;
721
    uint16_t max_pic_average_light_level;
722
    void writeSEI(const SPS&)
723
0
    {
724
0
        WRITE_CODE(max_content_light_level,     16, "max_content_light_level");
725
0
        WRITE_CODE(max_pic_average_light_level, 16, "max_pic_average_light_level");
726
0
    }
727
};
728
729
class SEIDecodedPictureHash : public SEI
730
{
731
public:
732
    SEIDecodedPictureHash()
733
0
    {
734
0
        m_payloadType = DECODED_PICTURE_HASH;
735
0
        m_payloadSize = 0;
736
0
    }
737
    enum Method
738
    {
739
        MD5,
740
        CRC,
741
        CHECKSUM,
742
    } m_method;
743
744
    MD5Context m_state[3];
745
    uint32_t   m_crc[3];
746
    uint32_t   m_checksum[3];
747
    uint8_t    m_digest[3][16];
748
749
    void writeSEI(const SPS& sps)
750
0
    {
751
0
        int planes = (sps.chromaFormatIdc != X265_CSP_I400) ? 3 : 1;
752
0
        WRITE_CODE(m_method, 8, "hash_type");
753
0
        for (int yuvIdx = 0; yuvIdx < planes; yuvIdx++)
754
0
        {
755
0
            if (m_method == MD5)
756
0
            {
757
0
                for (uint32_t i = 0; i < 16; i++)
758
0
                    WRITE_CODE(m_digest[yuvIdx][i], 8, "picture_md5");
759
0
            }
760
0
            else if (m_method == CRC)
761
0
            {
762
0
                uint32_t val = (m_digest[yuvIdx][0] << 8) + m_digest[yuvIdx][1];
763
0
                WRITE_CODE(val, 16, "picture_crc");
764
0
            }
765
0
            else if (m_method == CHECKSUM)
766
0
            {
767
0
                uint32_t val = (m_digest[yuvIdx][0] << 24) + (m_digest[yuvIdx][1] << 16) + (m_digest[yuvIdx][2] << 8) + m_digest[yuvIdx][3];
768
0
                WRITE_CODE(val, 32, "picture_checksum");
769
0
            }
770
0
        }
771
0
    }
772
};
773
774
class SEIActiveParameterSets : public SEI
775
{
776
public:
777
    SEIActiveParameterSets()
778
0
    {
779
0
        m_payloadType = ACTIVE_PARAMETER_SETS;
780
0
        m_payloadSize = 0;
781
0
    }
782
    bool m_selfContainedCvsFlag;
783
    bool m_noParamSetUpdateFlag;
784
785
    void writeSEI(const SPS&)
786
0
    {
787
0
        WRITE_CODE(0, 4, "active_vps_id");
788
0
        WRITE_FLAG(m_selfContainedCvsFlag, "self_contained_cvs_flag");
789
0
        WRITE_FLAG(m_noParamSetUpdateFlag, "no_param_set_update_flag");
790
0
        WRITE_UVLC(0, "num_sps_ids_minus1");
791
0
        WRITE_UVLC(0, "active_seq_param_set_id");
792
0
        writeByteAlign();
793
0
    }
794
};
795
796
class SEIBufferingPeriod : public SEI
797
{
798
public:
799
    SEIBufferingPeriod()
800
0
        : m_cpbDelayOffset(0)
801
0
        , m_dpbDelayOffset(0)
802
0
        , m_concatenationFlag(0)
803
0
        , m_auCpbRemovalDelayDelta(1)
804
0
    {
805
0
        m_payloadType = BUFFERING_PERIOD;
806
0
        m_payloadSize = 0;
807
0
    }
808
    bool     m_cpbDelayOffset;
809
    bool     m_dpbDelayOffset;
810
    bool     m_concatenationFlag;
811
    uint32_t m_initialCpbRemovalDelay;
812
    uint32_t m_initialCpbRemovalDelayOffset;
813
    uint32_t m_auCpbRemovalDelayDelta;
814
815
    void writeSEI(const SPS& sps)
816
0
    {
817
0
        const HRDInfo& hrd = sps.vuiParameters.hrdParameters;
818
819
0
        WRITE_UVLC(0, "bp_seq_parameter_set_id");
820
0
        WRITE_FLAG(0, "rap_cpb_params_present_flag");
821
0
        WRITE_FLAG(m_concatenationFlag, "concatenation_flag");
822
0
        WRITE_CODE(m_auCpbRemovalDelayDelta - 1,   hrd.cpbRemovalDelayLength,       "au_cpb_removal_delay_delta_minus1");
823
0
        WRITE_CODE(m_initialCpbRemovalDelay,       hrd.initialCpbRemovalDelayLength,        "initial_cpb_removal_delay");
824
0
        WRITE_CODE(m_initialCpbRemovalDelayOffset, hrd.initialCpbRemovalDelayLength, "initial_cpb_removal_delay_offset");
825
826
0
        writeByteAlign();
827
0
    }
828
};
829
830
class SEIPictureTiming : public SEI
831
{
832
public:
833
    SEIPictureTiming()
834
0
    {
835
0
        m_payloadType = PICTURE_TIMING;
836
0
        m_payloadSize = 0;
837
0
    }
838
    uint32_t  m_picStruct;
839
    uint32_t  m_sourceScanType;
840
    bool      m_duplicateFlag;
841
842
    uint32_t  m_auCpbRemovalDelay;
843
    uint32_t  m_picDpbOutputDelay;
844
845
    void writeSEI(const SPS& sps)
846
0
    {
847
0
        const VUI *vui = &sps.vuiParameters;
848
0
        const HRDInfo *hrd = &vui->hrdParameters;
849
850
0
        if (vui->frameFieldInfoPresentFlag)
851
0
        {
852
0
            WRITE_CODE(m_picStruct, 4,          "pic_struct");
853
0
            WRITE_CODE(m_sourceScanType, 2,     "source_scan_type");
854
0
            WRITE_FLAG(m_duplicateFlag,         "duplicate_flag");
855
0
        }
856
857
0
        if (vui->hrdParametersPresentFlag)
858
0
        {
859
0
            WRITE_CODE(m_auCpbRemovalDelay - 1, hrd->cpbRemovalDelayLength, "au_cpb_removal_delay_minus1");
860
0
            WRITE_CODE(m_picDpbOutputDelay, hrd->dpbOutputDelayLength, "pic_dpb_output_delay");
861
            /* Removed sub-pic signaling June 2014 */
862
0
        }
863
0
        writeByteAlign();
864
0
    }
865
};
866
867
class SEIRecoveryPoint : public SEI
868
{
869
public:
870
    SEIRecoveryPoint()
871
0
    {
872
0
        m_payloadType = RECOVERY_POINT;
873
0
        m_payloadSize = 0;
874
0
    }
875
    int  m_recoveryPocCnt;
876
    bool m_exactMatchingFlag;
877
    bool m_brokenLinkFlag;
878
879
    void writeSEI(const SPS&)
880
0
    {
881
0
        WRITE_SVLC(m_recoveryPocCnt,    "recovery_poc_cnt");
882
0
        WRITE_FLAG(m_exactMatchingFlag, "exact_matching_flag");
883
0
        WRITE_FLAG(m_brokenLinkFlag,    "broken_link_flag");
884
0
        writeByteAlign();
885
0
    }
886
};
887
888
class SEIAlternativeTC : public SEI
889
{
890
public:
891
    int m_preferredTransferCharacteristics;
892
    SEIAlternativeTC()
893
0
    {
894
0
        m_payloadType = ALTERNATIVE_TRANSFER_CHARACTERISTICS;
895
0
        m_payloadSize = 0;
896
0
        m_preferredTransferCharacteristics = -1;
897
0
    }
898
899
    void writeSEI(const SPS&)
900
0
    {
901
0
        WRITE_CODE(m_preferredTransferCharacteristics, 8, "Preferred transfer characteristics");
902
0
    }
903
};
904
905
}
906
#endif // ifndef X265_SEI_H