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