1 /*****************************************************************************
2 * desc_25.h: ISO/IEC 13818-1 Descriptor 0x25 (Metadata pointer descriptor)
3 *****************************************************************************
4 * Copyright (C) 2011 Unix Solutions Ltd.
5 *
6 * Authors: Georgi Chorbadzhiyski <georgi@unixsol.org>
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining
9 * a copy of this software and associated documentation files (the
10 * "Software"), to deal in the Software without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sublicense, and/or sell copies of the Software, and to
13 * permit persons to whom the Software is furnished to do so, subject
14 * to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be
17 * included in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
23 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 *****************************************************************************/
27
28 /*
29 * Normative references:
30 * - ISO/IEC 13818-1:2007(E) (MPEG-2 Systems)
31 */
32
33 #ifndef __BITSTREAM_MPEG_DESC_25_H__
34 #define __BITSTREAM_MPEG_DESC_25_H__
35
36 #include <bitstream/common.h>
37 #include <bitstream/mpeg/psi/descriptors.h>
38 #include <bitstream/mpeg/psi/desc_24.h>
39
40 #ifdef __cplusplus
41 extern "C"
42 {
43 #endif
44
45 /*****************************************************************************
46 * Descriptor 0x25 (Metadata pointer descriptor)
47 *****************************************************************************/
48 #define DESC25_HEADER_SIZE (DESC_HEADER_SIZE + 5)
49
desc25_init(uint8_t * p_desc)50 static inline void desc25_init(uint8_t *p_desc)
51 {
52 desc_set_tag(p_desc, 0x25);
53 }
54
55 #define desc25_get_metadata_application_format desc24_get_metadata_application_format
56 #define desc25_set_metadata_application_format desc24_set_metadata_application_format
57 #define desc25_get_metadata_application_format_identifier desc24_get_metadata_application_format_identifier
58 #define desc25_set_metadata_application_format_identifier desc24_set_metadata_application_format_identifier
59
60 #define __ofs1 \
61 (4 + (desc25_get_metadata_application_format(p_desc) == 0xffff ? 4 : 0))
62
desc25_get_metadata_format(const uint8_t * p_desc)63 static inline uint8_t desc25_get_metadata_format(const uint8_t *p_desc)
64 {
65 return p_desc[__ofs1];
66 }
67
desc25_set_metadata_format(uint8_t * p_desc,uint8_t i_format)68 static inline void desc25_set_metadata_format(uint8_t *p_desc, uint8_t i_format)
69 {
70 p_desc[__ofs1] = i_format;
71 }
72
desc25_get_metadata_format_identifier(const uint8_t * p_desc)73 static inline uint32_t desc25_get_metadata_format_identifier(const uint8_t *p_desc)
74 {
75 if (desc25_get_metadata_format(p_desc) == 0xff) {
76 uint8_t ofs = __ofs1;
77 return (p_desc[ofs + 1] << 24) | (p_desc[ofs + 2] << 16) | (p_desc[ofs + 3] << 8) | p_desc[ofs + 4];
78 } else {
79 return 0;
80 }
81 }
82
desc25_set_metadata_format_identifier(uint8_t * p_desc,uint32_t i_identifier)83 static inline void desc25_set_metadata_format_identifier(uint8_t *p_desc, uint32_t i_identifier)
84 {
85 if (desc25_get_metadata_format(p_desc) == 0xff) {
86 uint8_t ofs = __ofs1;
87 p_desc[ofs + 1] = (i_identifier >> 24) & 0xff;
88 p_desc[ofs + 2] = (i_identifier >> 16) & 0xff;
89 p_desc[ofs + 3] = (i_identifier >> 8) & 0xff;
90 p_desc[ofs + 4] = i_identifier & 0xff;
91 }
92 }
93
94 #define __ofs2 \
95 (__ofs1 + 1 + (desc25_get_metadata_format(p_desc) == 0xff ? 4 : 0))
96
desc25_get_metadata_service_id(const uint8_t * p_desc)97 static inline uint8_t desc25_get_metadata_service_id(const uint8_t *p_desc)
98 {
99 return p_desc[__ofs2];
100 }
101
desc25_set_metadata_service_id(uint8_t * p_desc,uint8_t i_service_id)102 static inline void desc25_set_metadata_service_id(uint8_t *p_desc, uint8_t i_service_id)
103 {
104 p_desc[__ofs2] = i_service_id;
105 }
106
desc25_get_metadata_locator_record_flag(const uint8_t * p_desc)107 static inline bool desc25_get_metadata_locator_record_flag(const uint8_t *p_desc)
108 {
109 return (p_desc[__ofs2 + 1] & 0x80) == 0x80;
110 }
111
desc25_set_metadata_locator_record_flag(uint8_t * p_desc,bool b_flag)112 static inline void desc25_set_metadata_locator_record_flag(uint8_t *p_desc, bool b_flag)
113 {
114 uint8_t ofs = __ofs2;
115 p_desc[ofs + 1] = (b_flag ? (p_desc[ofs + 1] | 0x80) : (p_desc[ofs + 1] &~ 0x80)) | 0x1f;
116 }
117
desc25_get_mpeg_carriage_flags(const uint8_t * p_desc)118 static inline uint8_t desc25_get_mpeg_carriage_flags(const uint8_t *p_desc)
119 {
120 return (p_desc[__ofs2 + 1] & 0x60) >> 5;
121 }
122
desc25_set_mpeg_carriage_flags(uint8_t * p_desc,uint8_t i_flags)123 static inline void desc25_set_mpeg_carriage_flags(uint8_t *p_desc, uint8_t i_flags)
124 {
125 uint8_t ofs = __ofs2;
126 p_desc[ofs + 1] = ((p_desc[ofs + 1] & 0x80) | ((i_flags & 0x03) << 5)) | 0x1f;
127 }
128
129
desc25_get_metadata_locator_record_length(const uint8_t * p_desc)130 static inline uint8_t desc25_get_metadata_locator_record_length(const uint8_t *p_desc)
131 {
132 return desc25_get_metadata_locator_record_flag(p_desc) ? p_desc[__ofs2 + 2] : 0;
133 }
134
desc25_get_metadata_locator_record_data(const uint8_t * p_desc)135 static inline const uint8_t *desc25_get_metadata_locator_record_data(const uint8_t *p_desc)
136 {
137 return desc25_get_metadata_locator_record_flag(p_desc) ? p_desc + __ofs2 + 3 : NULL;
138 }
139
desc25_get_metadata_locator_record(const uint8_t * p_desc,uint8_t * i_length)140 static inline const uint8_t *desc25_get_metadata_locator_record(const uint8_t *p_desc, uint8_t *i_length)
141 {
142 *i_length = desc25_get_metadata_locator_record_length(p_desc);
143 return desc25_get_metadata_locator_record_data(p_desc);
144 }
145
desc25_set_metadata_locator_record(uint8_t * p_desc,uint8_t i_length,uint8_t * p_data)146 static inline void desc25_set_metadata_locator_record(uint8_t *p_desc, uint8_t i_length, uint8_t *p_data)
147 {
148 if (desc25_get_metadata_locator_record_flag(p_desc)) {
149 uint8_t ofs = __ofs2;
150 p_desc[ofs + 2] = i_length;
151 memcpy(p_desc + ofs + 3, p_data, i_length);
152 }
153 }
154
155
156 #define __ofs3 \
157 (__ofs2 + 1 + \
158 (desc25_get_metadata_locator_record_flag(p_desc) \
159 ? 1 + desc25_get_metadata_locator_record_length(p_desc) \
160 : 0 \
161 ) + 1 \
162 )
163
desc25_get_program_number(const uint8_t * p_desc)164 static inline uint16_t desc25_get_program_number(const uint8_t *p_desc)
165 {
166 uint8_t i_flags = desc25_get_mpeg_carriage_flags(p_desc);
167 if (i_flags == 0 || i_flags == 1 || i_flags == 2) {
168 uint8_t ofs = __ofs3;
169 return (p_desc[ofs + 0] << 8) | p_desc[ofs + 1];
170 } else {
171 return 0;
172 }
173 }
174
desc25_set_program_number(uint8_t * p_desc,uint16_t i_program)175 static inline void desc25_set_program_number(uint8_t *p_desc, uint16_t i_program)
176 {
177 uint8_t i_flags = desc25_get_mpeg_carriage_flags(p_desc);
178 if (i_flags == 0 || i_flags == 1 || i_flags == 2) {
179 uint8_t ofs = __ofs3;
180 p_desc[ofs + 0] = (i_program >> 8) & 0xff;
181 p_desc[ofs + 1] = i_program & 0xff;
182 }
183 }
184
desc25_get_ts_location(const uint8_t * p_desc)185 static inline uint16_t desc25_get_ts_location(const uint8_t *p_desc)
186 {
187 if (desc25_get_mpeg_carriage_flags(p_desc) == 1) {
188 uint8_t ofs = __ofs3;
189 return (p_desc[ofs + 2] << 8) | p_desc[ofs + 3];
190 } else {
191 return 0;
192 }
193 }
194
desc25_set_ts_location(uint8_t * p_desc,uint16_t i_ts_location)195 static inline void desc25_set_ts_location(uint8_t *p_desc, uint16_t i_ts_location)
196 {
197 if (desc25_get_mpeg_carriage_flags(p_desc) == 1) {
198 uint8_t ofs = __ofs3;
199 p_desc[ofs + 2] = (i_ts_location >> 8) & 0xff;
200 p_desc[ofs + 3] = i_ts_location & 0xff;
201 }
202 }
203
desc25_get_ts_id(const uint8_t * p_desc)204 static inline uint16_t desc25_get_ts_id(const uint8_t *p_desc)
205 {
206 if (desc25_get_mpeg_carriage_flags(p_desc) == 1) {
207 uint8_t ofs = __ofs3;
208 return (p_desc[ofs + 4] << 8) | p_desc[ofs + 5];
209 } else {
210 return 0;
211 }
212 }
213
desc25_set_ts_id(uint8_t * p_desc,uint16_t i_ts_id)214 static inline void desc25_set_ts_id(uint8_t *p_desc, uint16_t i_ts_id)
215 {
216 if (desc25_get_mpeg_carriage_flags(p_desc) == 1) {
217 uint8_t ofs = __ofs3;
218 p_desc[ofs + 4] = (i_ts_id >> 8) & 0xff;
219 p_desc[ofs + 5] = i_ts_id & 0xff;
220 }
221 }
222
223 #undef __ofs1
224 #undef __ofs2
225 #undef __ofs3
226
desc25_calc_length(const uint8_t * p_desc)227 static inline int desc25_calc_length(const uint8_t *p_desc)
228 {
229 int i_length = DESC25_HEADER_SIZE - DESC_HEADER_SIZE;
230 uint8_t i_flags = desc25_get_mpeg_carriage_flags(p_desc);
231 if (desc25_get_metadata_application_format(p_desc) == 0xffff)
232 i_length += 4;
233 if (desc25_get_metadata_format(p_desc) == 0xff)
234 i_length += 4;
235 if (desc25_get_metadata_locator_record_flag(p_desc))
236 i_length += 1 + desc25_get_metadata_locator_record_length(p_desc);
237 if (i_flags == 0 || i_flags == 1 || i_flags == 2)
238 i_length += 2;
239 if (i_flags == 1)
240 i_length += 4;
241 return i_length;
242 }
243
desc25_validate(const uint8_t * p_desc)244 static inline bool desc25_validate(const uint8_t *p_desc)
245 {
246 return desc25_calc_length(p_desc) <= desc_get_length(p_desc);
247 }
248
desc25_set_length(uint8_t * p_desc)249 static inline void desc25_set_length(uint8_t *p_desc)
250 {
251 desc_set_length(p_desc, desc25_calc_length(p_desc));
252 }
253
desc25_print(const uint8_t * p_desc,f_print pf_print,void * opaque,print_type_t i_print_type)254 static inline void desc25_print(const uint8_t *p_desc, f_print pf_print,
255 void *opaque, print_type_t i_print_type)
256 {
257 uint8_t i, i_metadata_locator_record_length;
258 const uint8_t *p_metadata_locator_record = desc25_get_metadata_locator_record(p_desc, &i_metadata_locator_record_length);
259 char psz_metadata_locator_record[2 * 255 + 1];
260
261 for (i = 0; i < i_metadata_locator_record_length; i++)
262 sprintf(psz_metadata_locator_record + 2 * i, "%02x", p_metadata_locator_record[i]);
263 psz_metadata_locator_record[2 * i] = '\0';
264
265 switch (i_print_type) {
266 case PRINT_XML:
267 pf_print(opaque,
268 "<METADATA_POINTER_DESC metadata_application_format=\"0x%04x\""
269 " metadata_application_format_identifier=\"0x%08x\""
270 " metadata_format=\"0x%02x\""
271 " metadata_format_identifier=\"0x%08x\""
272 " metadata_service_id=\"0x%02x\""
273 " metadata_locator_record_flag=\"%u\""
274 " metadata_locator_record_length=\"%u\""
275 " metadata_locator_record=\"%s\""
276 " mpeg_carriage_flags=\"%u\""
277 " program_number=\"%u\" ts_location=\"%u\" ts_id=\"%u\"/>",
278 desc25_get_metadata_application_format(p_desc),
279 desc25_get_metadata_application_format_identifier(p_desc),
280 desc25_get_metadata_format(p_desc),
281 desc25_get_metadata_format_identifier(p_desc),
282 desc25_get_metadata_service_id(p_desc),
283 desc25_get_metadata_locator_record_flag(p_desc),
284 desc25_get_metadata_locator_record_length(p_desc),
285 psz_metadata_locator_record, // desc25_get_metadata_locator_record_data(p_desc)
286 desc25_get_mpeg_carriage_flags(p_desc),
287 desc25_get_program_number(p_desc),
288 desc25_get_ts_location(p_desc),
289 desc25_get_ts_id(p_desc)
290 );
291 break;
292 default:
293 pf_print(opaque,
294 " - desc 25 metadata_pointer_desc metadata_application_format=0x%04x"
295 " metadata_application_format_identifier=0x%08x"
296 " metadata_format=0x%02x"
297 " metadata_format_identifier=0x%08x"
298 " metadata_service_id=0x%02x"
299 " metadata_locator_record_flag=%u"
300 " metadata_locator_record_length=%u"
301 " metadata_locator_record=\"%s\""
302 " mpeg_carriage_flags=%u"
303 " program_number=%u ts_location=%u ts_id=%u",
304 desc25_get_metadata_application_format(p_desc),
305 desc25_get_metadata_application_format_identifier(p_desc),
306 desc25_get_metadata_format(p_desc),
307 desc25_get_metadata_format_identifier(p_desc),
308 desc25_get_metadata_service_id(p_desc),
309 desc25_get_metadata_locator_record_flag(p_desc),
310 desc25_get_metadata_locator_record_length(p_desc),
311 psz_metadata_locator_record, // desc25_get_metadata_locator_record_data(p_desc)
312 desc25_get_mpeg_carriage_flags(p_desc),
313 desc25_get_program_number(p_desc),
314 desc25_get_ts_location(p_desc),
315 desc25_get_ts_id(p_desc)
316 );
317 }
318 }
319
320 #ifdef __cplusplus
321 }
322 #endif
323
324 #endif
325