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);
42     void setSize(uint32_t size);
43     static char* base64Decode(char encodedString[], int base64EncodeLength);
~SEI()44     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:
SEIuserDataRegistered()56     SEIuserDataRegistered()
57     {
58         m_payloadType = USER_DATA_REGISTERED_ITU_T_T35;
59         m_payloadSize = 0;
60     }
61 
62     uint8_t *m_userData;
63 
64     // daniel.vt@samsung.com :: for the Creative Intent Meta Data Encoding ( seongnam.oh@samsung.com )
writeSEI(const SPS &)65     void writeSEI(const SPS&)
66     {
67         if (!m_userData)
68             return;
69 
70         uint32_t i = 0;
71         for (; i < m_payloadSize; ++i)
72             WRITE_CODE(m_userData[i], 8, "creative_intent_metadata");
73     }
74 };
75 
76 static const uint32_t ISO_IEC_11578_LEN = 16;
77 
78 class SEIuserDataUnregistered : public SEI
79 {
80 public:
SEIuserDataUnregistered()81     SEIuserDataUnregistered() : m_userData(NULL)
82     {
83         m_payloadType = USER_DATA_UNREGISTERED;
84         m_payloadSize = 0;
85     }
86     static const uint8_t m_uuid_iso_iec_11578[ISO_IEC_11578_LEN];
87     uint8_t *m_userData;
writeSEI(const SPS &)88     void writeSEI(const SPS&)
89     {
90         for (uint32_t i = 0; i < ISO_IEC_11578_LEN; i++)
91             WRITE_CODE(m_uuid_iso_iec_11578[i], 8, "sei.uuid_iso_iec_11578[i]");
92         for (uint32_t i = 0; i < m_payloadSize; i++)
93             WRITE_CODE(m_userData[i], 8, "user_data");
94     }
95 };
96 
97 class SEIMasteringDisplayColorVolume : public SEI
98 {
99 public:
SEIMasteringDisplayColorVolume()100     SEIMasteringDisplayColorVolume()
101     {
102         m_payloadType = MASTERING_DISPLAY_INFO;
103         m_payloadSize = (8 * 2 + 2 * 4);
104     }
105     uint16_t displayPrimaryX[3];
106     uint16_t displayPrimaryY[3];
107     uint16_t whitePointX, whitePointY;
108     uint32_t maxDisplayMasteringLuminance;
109     uint32_t minDisplayMasteringLuminance;
parse(const char * value)110     bool parse(const char* value)
111     {
112         return sscanf(value, "G(%hu,%hu)B(%hu,%hu)R(%hu,%hu)WP(%hu,%hu)L(%u,%u)",
113                       &displayPrimaryX[0], &displayPrimaryY[0],
114                       &displayPrimaryX[1], &displayPrimaryY[1],
115                       &displayPrimaryX[2], &displayPrimaryY[2],
116                       &whitePointX, &whitePointY,
117                       &maxDisplayMasteringLuminance, &minDisplayMasteringLuminance) == 10;
118     }
writeSEI(const SPS &)119     void writeSEI(const SPS&)
120     {
121         for (uint32_t i = 0; i < 3; i++)
122         {
123             WRITE_CODE(displayPrimaryX[i], 16, "display_primaries_x[ c ]");
124             WRITE_CODE(displayPrimaryY[i], 16, "display_primaries_y[ c ]");
125         }
126         WRITE_CODE(whitePointX, 16, "white_point_x");
127         WRITE_CODE(whitePointY, 16, "white_point_y");
128         WRITE_CODE(maxDisplayMasteringLuminance, 32, "max_display_mastering_luminance");
129         WRITE_CODE(minDisplayMasteringLuminance, 32, "min_display_mastering_luminance");
130     }
131 };
132 
133 class SEIContentLightLevel : public SEI
134 {
135 public:
SEIContentLightLevel()136     SEIContentLightLevel()
137     {
138         m_payloadType = CONTENT_LIGHT_LEVEL_INFO;
139         m_payloadSize = 4;
140     }
141     uint16_t max_content_light_level;
142     uint16_t max_pic_average_light_level;
writeSEI(const SPS &)143     void writeSEI(const SPS&)
144     {
145         WRITE_CODE(max_content_light_level,     16, "max_content_light_level");
146         WRITE_CODE(max_pic_average_light_level, 16, "max_pic_average_light_level");
147     }
148 };
149 
150 class SEIDecodedPictureHash : public SEI
151 {
152 public:
SEIDecodedPictureHash()153     SEIDecodedPictureHash()
154     {
155         m_payloadType = DECODED_PICTURE_HASH;
156         m_payloadSize = 0;
157     }
158     enum Method
159     {
160         MD5,
161         CRC,
162         CHECKSUM,
163     } m_method;
164 
165     MD5Context m_state[3];
166     uint32_t   m_crc[3];
167     uint32_t   m_checksum[3];
168     uint8_t    m_digest[3][16];
169 
writeSEI(const SPS & sps)170     void writeSEI(const SPS& sps)
171     {
172         int planes = (sps.chromaFormatIdc != X265_CSP_I400) ? 3 : 1;
173         WRITE_CODE(m_method, 8, "hash_type");
174         for (int yuvIdx = 0; yuvIdx < planes; yuvIdx++)
175         {
176             if (m_method == MD5)
177             {
178                 for (uint32_t i = 0; i < 16; i++)
179                     WRITE_CODE(m_digest[yuvIdx][i], 8, "picture_md5");
180             }
181             else if (m_method == CRC)
182             {
183                 uint32_t val = (m_digest[yuvIdx][0] << 8) + m_digest[yuvIdx][1];
184                 WRITE_CODE(val, 16, "picture_crc");
185             }
186             else if (m_method == CHECKSUM)
187             {
188                 uint32_t val = (m_digest[yuvIdx][0] << 24) + (m_digest[yuvIdx][1] << 16) + (m_digest[yuvIdx][2] << 8) + m_digest[yuvIdx][3];
189                 WRITE_CODE(val, 32, "picture_checksum");
190             }
191         }
192     }
193 };
194 
195 class SEIActiveParameterSets : public SEI
196 {
197 public:
SEIActiveParameterSets()198     SEIActiveParameterSets()
199     {
200         m_payloadType = ACTIVE_PARAMETER_SETS;
201         m_payloadSize = 0;
202     }
203     bool m_selfContainedCvsFlag;
204     bool m_noParamSetUpdateFlag;
205 
writeSEI(const SPS &)206     void writeSEI(const SPS&)
207     {
208         WRITE_CODE(0, 4, "active_vps_id");
209         WRITE_FLAG(m_selfContainedCvsFlag, "self_contained_cvs_flag");
210         WRITE_FLAG(m_noParamSetUpdateFlag, "no_param_set_update_flag");
211         WRITE_UVLC(0, "num_sps_ids_minus1");
212         WRITE_UVLC(0, "active_seq_param_set_id");
213         writeByteAlign();
214     }
215 };
216 
217 class SEIBufferingPeriod : public SEI
218 {
219 public:
SEIBufferingPeriod()220     SEIBufferingPeriod()
221         : m_cpbDelayOffset(0)
222         , m_dpbDelayOffset(0)
223         , m_concatenationFlag(0)
224         , m_auCpbRemovalDelayDelta(1)
225     {
226         m_payloadType = BUFFERING_PERIOD;
227         m_payloadSize = 0;
228     }
229     bool     m_cpbDelayOffset;
230     bool     m_dpbDelayOffset;
231     bool     m_concatenationFlag;
232     uint32_t m_initialCpbRemovalDelay;
233     uint32_t m_initialCpbRemovalDelayOffset;
234     uint32_t m_auCpbRemovalDelayDelta;
235 
writeSEI(const SPS & sps)236     void writeSEI(const SPS& sps)
237     {
238         const HRDInfo& hrd = sps.vuiParameters.hrdParameters;
239 
240         WRITE_UVLC(0, "bp_seq_parameter_set_id");
241         WRITE_FLAG(0, "rap_cpb_params_present_flag");
242         WRITE_FLAG(m_concatenationFlag, "concatenation_flag");
243         WRITE_CODE(m_auCpbRemovalDelayDelta - 1,   hrd.cpbRemovalDelayLength,       "au_cpb_removal_delay_delta_minus1");
244         WRITE_CODE(m_initialCpbRemovalDelay,       hrd.initialCpbRemovalDelayLength,        "initial_cpb_removal_delay");
245         WRITE_CODE(m_initialCpbRemovalDelayOffset, hrd.initialCpbRemovalDelayLength, "initial_cpb_removal_delay_offset");
246 
247         writeByteAlign();
248     }
249 };
250 
251 class SEIPictureTiming : public SEI
252 {
253 public:
SEIPictureTiming()254     SEIPictureTiming()
255     {
256         m_payloadType = PICTURE_TIMING;
257         m_payloadSize = 0;
258     }
259     uint32_t  m_picStruct;
260     uint32_t  m_sourceScanType;
261     bool      m_duplicateFlag;
262 
263     uint32_t  m_auCpbRemovalDelay;
264     uint32_t  m_picDpbOutputDelay;
265 
writeSEI(const SPS & sps)266     void writeSEI(const SPS& sps)
267     {
268         const VUI *vui = &sps.vuiParameters;
269         const HRDInfo *hrd = &vui->hrdParameters;
270 
271         if (vui->frameFieldInfoPresentFlag)
272         {
273             WRITE_CODE(m_picStruct, 4,          "pic_struct");
274             WRITE_CODE(m_sourceScanType, 2,     "source_scan_type");
275             WRITE_FLAG(m_duplicateFlag,         "duplicate_flag");
276         }
277 
278         if (vui->hrdParametersPresentFlag)
279         {
280             WRITE_CODE(m_auCpbRemovalDelay - 1, hrd->cpbRemovalDelayLength, "au_cpb_removal_delay_minus1");
281             WRITE_CODE(m_picDpbOutputDelay, hrd->dpbOutputDelayLength, "pic_dpb_output_delay");
282             /* Removed sub-pic signaling June 2014 */
283         }
284         writeByteAlign();
285     }
286 };
287 
288 class SEIRecoveryPoint : public SEI
289 {
290 public:
SEIRecoveryPoint()291     SEIRecoveryPoint()
292     {
293         m_payloadType = RECOVERY_POINT;
294         m_payloadSize = 0;
295     }
296     int  m_recoveryPocCnt;
297     bool m_exactMatchingFlag;
298     bool m_brokenLinkFlag;
299 
writeSEI(const SPS &)300     void writeSEI(const SPS&)
301     {
302         WRITE_SVLC(m_recoveryPocCnt,    "recovery_poc_cnt");
303         WRITE_FLAG(m_exactMatchingFlag, "exact_matching_flag");
304         WRITE_FLAG(m_brokenLinkFlag,    "broken_link_flag");
305         writeByteAlign();
306     }
307 };
308 
309 class SEIAlternativeTC : public SEI
310 {
311 public:
312     int m_preferredTransferCharacteristics;
SEIAlternativeTC()313     SEIAlternativeTC()
314     {
315         m_payloadType = ALTERNATIVE_TRANSFER_CHARACTERISTICS;
316         m_payloadSize = 0;
317         m_preferredTransferCharacteristics = -1;
318     }
319 
writeSEI(const SPS &)320     void writeSEI(const SPS&)
321     {
322         WRITE_CODE(m_preferredTransferCharacteristics, 8, "Preferred transfer characteristics");
323     }
324 };
325 
326 }
327 #endif // ifndef X265_SEI_H
328