Commit | Line | Data |
---|---|---|
72b9787e JB |
1 | /***************************************************************************** |
2 | * Copyright (C) 2013 x265 project | |
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 | ||
31 | namespace x265 { | |
32 | // private namespace | |
33 | ||
34 | class SEI : public SyntaxElementWriter | |
35 | { | |
36 | public: | |
37 | ||
38 | /* SEI users call write() to marshal an SEI to a bitstream. SEI | |
39 | * subclasses may implement write() or accept the default write() | |
40 | * method which calls writeSEI() with a bitcounter to determine | |
41 | * the size, then it encodes the header and calls writeSEI a | |
42 | * second time for the real encode. */ | |
43 | virtual void write(Bitstream& bs, const SPS& sps); | |
44 | ||
45 | virtual ~SEI() {} | |
46 | ||
47 | protected: | |
48 | ||
49 | enum PayloadType | |
50 | { | |
51 | BUFFERING_PERIOD = 0, | |
52 | PICTURE_TIMING = 1, | |
53 | PAN_SCAN_RECT = 2, | |
54 | FILLER_PAYLOAD = 3, | |
55 | USER_DATA_REGISTERED_ITU_T_T35 = 4, | |
56 | USER_DATA_UNREGISTERED = 5, | |
57 | RECOVERY_POINT = 6, | |
58 | SCENE_INFO = 9, | |
59 | FULL_FRAME_SNAPSHOT = 15, | |
60 | PROGRESSIVE_REFINEMENT_SEGMENT_START = 16, | |
61 | PROGRESSIVE_REFINEMENT_SEGMENT_END = 17, | |
62 | FILM_GRAIN_CHARACTERISTICS = 19, | |
63 | POST_FILTER_HINT = 22, | |
64 | TONE_MAPPING_INFO = 23, | |
65 | FRAME_PACKING = 45, | |
66 | DISPLAY_ORIENTATION = 47, | |
67 | SOP_DESCRIPTION = 128, | |
68 | ACTIVE_PARAMETER_SETS = 129, | |
69 | DECODING_UNIT_INFO = 130, | |
70 | TEMPORAL_LEVEL0_INDEX = 131, | |
71 | DECODED_PICTURE_HASH = 132, | |
72 | SCALABLE_NESTING = 133, | |
73 | REGION_REFRESH_INFO = 134, | |
74 | }; | |
75 | ||
76 | virtual PayloadType payloadType() const = 0; | |
77 | ||
78 | virtual void writeSEI(const SPS&) { X265_CHECK(0, "empty writeSEI method called\n"); } | |
79 | ||
80 | void writeByteAlign(); | |
81 | }; | |
82 | ||
83 | class SEIuserDataUnregistered : public SEI | |
84 | { | |
85 | public: | |
86 | ||
87 | PayloadType payloadType() const { return USER_DATA_UNREGISTERED; } | |
88 | ||
89 | SEIuserDataUnregistered() : m_userData(NULL) {} | |
90 | ||
91 | static const uint8_t m_uuid_iso_iec_11578[16]; | |
92 | uint32_t m_userDataLength; | |
93 | uint8_t *m_userData; | |
94 | ||
95 | void write(Bitstream& bs, const SPS&) | |
96 | { | |
97 | m_bitIf = &bs; | |
98 | ||
99 | WRITE_CODE(USER_DATA_UNREGISTERED, 8, "payload_type"); | |
100 | ||
101 | uint32_t payloadSize = 16 + m_userDataLength; | |
102 | for (; payloadSize >= 0xff; payloadSize -= 0xff) | |
103 | WRITE_CODE(0xff, 8, "payload_size"); | |
104 | WRITE_CODE(payloadSize, 8, "payload_size"); | |
105 | ||
106 | for (uint32_t i = 0; i < 16; i++) | |
107 | WRITE_CODE(m_uuid_iso_iec_11578[i], 8, "sei.uuid_iso_iec_11578[i]"); | |
108 | ||
109 | for (uint32_t i = 0; i < m_userDataLength; i++) | |
110 | WRITE_CODE(m_userData[i], 8, "user_data"); | |
111 | } | |
112 | }; | |
113 | ||
114 | class SEIDecodedPictureHash : public SEI | |
115 | { | |
116 | public: | |
117 | ||
118 | PayloadType payloadType() const { return DECODED_PICTURE_HASH; } | |
119 | ||
120 | enum Method | |
121 | { | |
122 | MD5, | |
123 | CRC, | |
124 | CHECKSUM, | |
125 | } m_method; | |
126 | ||
127 | uint8_t m_digest[3][16]; | |
128 | ||
129 | void write(Bitstream& bs, const SPS&) | |
130 | { | |
131 | m_bitIf = &bs; | |
132 | ||
133 | WRITE_CODE(DECODED_PICTURE_HASH, 8, "payload_type"); | |
134 | ||
135 | switch (m_method) | |
136 | { | |
137 | case MD5: | |
138 | WRITE_CODE(1 + 16 * 3, 8, "payload_size"); | |
139 | WRITE_CODE(MD5, 8, "hash_type"); | |
140 | break; | |
141 | case CRC: | |
142 | WRITE_CODE(1 + 2 * 3, 8, "payload_size"); | |
143 | WRITE_CODE(CRC, 8, "hash_type"); | |
144 | break; | |
145 | case CHECKSUM: | |
146 | WRITE_CODE(1 + 4 * 3, 8, "payload_size"); | |
147 | WRITE_CODE(CHECKSUM, 8, "hash_type"); | |
148 | break; | |
149 | } | |
150 | ||
151 | for (int yuvIdx = 0; yuvIdx < 3; yuvIdx++) | |
152 | { | |
153 | if (m_method == MD5) | |
154 | { | |
155 | for (uint32_t i = 0; i < 16; i++) | |
156 | WRITE_CODE(m_digest[yuvIdx][i], 8, "picture_md5"); | |
157 | } | |
158 | else if (m_method == CRC) | |
159 | { | |
160 | uint32_t val = (m_digest[yuvIdx][0] << 8) + m_digest[yuvIdx][1]; | |
161 | WRITE_CODE(val, 16, "picture_crc"); | |
162 | } | |
163 | else if (m_method == CHECKSUM) | |
164 | { | |
165 | uint32_t val = (m_digest[yuvIdx][0] << 24) + (m_digest[yuvIdx][1] << 16) + (m_digest[yuvIdx][2] << 8) + m_digest[yuvIdx][3]; | |
166 | WRITE_CODE(val, 32, "picture_checksum"); | |
167 | } | |
168 | } | |
169 | } | |
170 | }; | |
171 | ||
172 | class SEIActiveParameterSets : public SEI | |
173 | { | |
174 | public: | |
175 | ||
176 | PayloadType payloadType() const { return ACTIVE_PARAMETER_SETS; } | |
177 | ||
178 | bool m_selfContainedCvsFlag; | |
179 | bool m_noParamSetUpdateFlag; | |
180 | ||
181 | void writeSEI(const SPS&) | |
182 | { | |
183 | WRITE_CODE(0, 4, "active_vps_id"); | |
184 | WRITE_FLAG(m_selfContainedCvsFlag, "self_contained_cvs_flag"); | |
185 | WRITE_FLAG(m_noParamSetUpdateFlag, "no_param_set_update_flag"); | |
186 | WRITE_UVLC(0, "num_sps_ids_minus1"); | |
187 | WRITE_UVLC(0, "active_seq_param_set_id"); | |
188 | writeByteAlign(); | |
189 | } | |
190 | }; | |
191 | ||
192 | class SEIBufferingPeriod : public SEI | |
193 | { | |
194 | public: | |
195 | ||
196 | PayloadType payloadType() const { return BUFFERING_PERIOD; } | |
197 | ||
198 | SEIBufferingPeriod() | |
199 | : m_cpbDelayOffset(0) | |
200 | , m_dpbDelayOffset(0) | |
201 | , m_auCpbRemovalDelayDelta(1) | |
202 | { | |
203 | } | |
204 | ||
205 | bool m_cpbDelayOffset; | |
206 | bool m_dpbDelayOffset; | |
207 | uint32_t m_initialCpbRemovalDelay; | |
208 | uint32_t m_initialCpbRemovalDelayOffset; | |
209 | uint32_t m_auCpbRemovalDelayDelta; | |
210 | ||
211 | void writeSEI(const SPS& sps) | |
212 | { | |
213 | const HRDInfo& hrd = sps.vuiParameters.hrdParameters; | |
214 | ||
215 | WRITE_UVLC(0, "bp_seq_parameter_set_id"); | |
216 | WRITE_FLAG(0, "rap_cpb_params_present_flag"); | |
217 | WRITE_FLAG(0, "concatenation_flag"); | |
218 | WRITE_CODE(m_auCpbRemovalDelayDelta - 1, hrd.cpbRemovalDelayLength, "au_cpb_removal_delay_delta_minus1"); | |
219 | WRITE_CODE(m_initialCpbRemovalDelay, hrd.initialCpbRemovalDelayLength, "initial_cpb_removal_delay"); | |
220 | WRITE_CODE(m_initialCpbRemovalDelayOffset, hrd.initialCpbRemovalDelayLength, "initial_cpb_removal_delay_offset"); | |
221 | ||
222 | writeByteAlign(); | |
223 | } | |
224 | }; | |
225 | ||
226 | class SEIPictureTiming : public SEI | |
227 | { | |
228 | public: | |
229 | ||
230 | PayloadType payloadType() const { return PICTURE_TIMING; } | |
231 | ||
232 | uint32_t m_picStruct; | |
233 | uint32_t m_sourceScanType; | |
234 | bool m_duplicateFlag; | |
235 | ||
236 | uint32_t m_auCpbRemovalDelay; | |
237 | uint32_t m_picDpbOutputDelay; | |
238 | ||
239 | void writeSEI(const SPS& sps) | |
240 | { | |
241 | const VUI *vui = &sps.vuiParameters; | |
242 | const HRDInfo *hrd = &vui->hrdParameters; | |
243 | ||
244 | if (vui->frameFieldInfoPresentFlag) | |
245 | { | |
246 | WRITE_CODE(m_picStruct, 4, "pic_struct"); | |
247 | WRITE_CODE(m_sourceScanType, 2, "source_scan_type"); | |
248 | WRITE_FLAG(m_duplicateFlag, "duplicate_flag"); | |
249 | } | |
250 | ||
251 | if (vui->hrdParametersPresentFlag) | |
252 | { | |
253 | WRITE_CODE(m_auCpbRemovalDelay - 1, hrd->cpbRemovalDelayLength, "au_cpb_removal_delay_minus1"); | |
254 | WRITE_CODE(m_picDpbOutputDelay, hrd->dpbOutputDelayLength, "pic_dpb_output_delay"); | |
255 | /* Removed sub-pic signaling June 2014 */ | |
256 | } | |
257 | writeByteAlign(); | |
258 | } | |
259 | }; | |
260 | ||
261 | class SEIRecoveryPoint : public SEI | |
262 | { | |
263 | public: | |
264 | ||
265 | PayloadType payloadType() const { return RECOVERY_POINT; } | |
266 | ||
267 | int m_recoveryPocCnt; | |
268 | bool m_exactMatchingFlag; | |
269 | bool m_brokenLinkFlag; | |
270 | ||
271 | void writeSEI(const SPS&) | |
272 | { | |
273 | WRITE_SVLC(m_recoveryPocCnt, "recovery_poc_cnt"); | |
274 | WRITE_FLAG(m_exactMatchingFlag, "exact_matching_flag"); | |
275 | WRITE_FLAG(m_brokenLinkFlag, "broken_link_flag"); | |
276 | writeByteAlign(); | |
277 | } | |
278 | }; | |
279 | } | |
280 | ||
281 | #endif // ifndef X265_SEI_H |