1 /*****************************************************************************
2 * desc_26.h: ISO/IEC 13818-1 Descriptor 0x26 (Metadata 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_26_H__
34 #define __BITSTREAM_MPEG_DESC_26_H__
35
36 #include <bitstream/common.h>
37 #include <bitstream/mpeg/psi/descriptors.h>
38 #include <bitstream/mpeg/psi/desc_25.h>
39
40 #ifdef __cplusplus
41 extern "C"
42 {
43 #endif
44
45 /*****************************************************************************
46 * Descriptor 0x26 (Metadata descriptor)
47 *****************************************************************************/
48 #define DESC26_HEADER_SIZE (DESC_HEADER_SIZE + 5)
49
desc26_init(uint8_t * p_desc)50 static inline void desc26_init(uint8_t *p_desc)
51 {
52 desc_set_tag(p_desc, 0x26);
53 }
54
55 #define desc26_get_metadata_application_format desc25_get_metadata_application_format
56 #define desc26_set_metadata_application_format desc25_set_metadata_application_format
57 #define desc26_get_metadata_application_format_identifier desc25_get_metadata_application_format_identifier
58 #define desc26_set_metadata_application_format_identifier desc25_set_metadata_application_format_identifier
59
60 #define __ofs1 \
61 (4 + (desc26_get_metadata_application_format(p_desc) == 0xffff ? 4 : 0))
62
63 #define desc26_get_metadata_format desc25_get_metadata_format
64 #define desc26_set_metadata_format desc25_set_metadata_format
65 #define desc26_get_metadata_format_identifier desc25_get_metadata_format_identifier
66 #define desc26_set_metadata_format_identifier desc25_set_metadata_format_identifier
67
68 #define __ofs2 \
69 (__ofs1 + 1 + (desc26_get_metadata_format(p_desc) == 0xff ? 4 : 0))
70
71 #define desc26_get_metadata_service_id desc25_get_metadata_service_id
72 #define desc26_set_metadata_service_id desc25_set_metadata_service_id
73
desc26_get_decoder_config_flags(const uint8_t * p_desc)74 static inline uint8_t desc26_get_decoder_config_flags(const uint8_t *p_desc)
75 {
76 return (p_desc[__ofs2 + 1] & 0xe0) >> 5;
77 }
78
desc26_set_decoder_config_flags(uint8_t * p_desc,uint8_t i_flags)79 static inline void desc26_set_decoder_config_flags(uint8_t *p_desc, uint8_t i_flags)
80 {
81 uint8_t ofs = __ofs2;
82 p_desc[ofs + 1] = ((i_flags & 0x07) << 5) | (p_desc[ofs + 1] & 0x1f) | 0x0f;
83 }
84
desc26_get_dsm_cc_flag(const uint8_t * p_desc)85 static inline bool desc26_get_dsm_cc_flag(const uint8_t *p_desc)
86 {
87 return (p_desc[__ofs2 + 1] & 0x10) == 0x10;
88 }
89
desc26_set_dsm_cc_flag(uint8_t * p_desc,bool b_flag)90 static inline void desc26_set_dsm_cc_flag(uint8_t *p_desc, bool b_flag)
91 {
92 uint8_t ofs = __ofs2;
93 p_desc[ofs + 1] = (b_flag ? (p_desc[ofs + 1] | 0x10) : (p_desc[ofs + 1] &~ 0x10)) | 0x0f;
94 }
95
96
97
desc26_get_service_identification_record_length(const uint8_t * p_desc)98 static inline uint8_t desc26_get_service_identification_record_length(const uint8_t *p_desc)
99 {
100 return desc26_get_dsm_cc_flag(p_desc) ? p_desc[__ofs2 + 2] : 0;
101 }
102
desc26_get_service_identification_record_data(const uint8_t * p_desc)103 static inline const uint8_t *desc26_get_service_identification_record_data(const uint8_t *p_desc)
104 {
105 return desc26_get_dsm_cc_flag(p_desc) ? p_desc + __ofs2 + 3 : NULL;
106 }
107
desc26_get_service_identification_record(const uint8_t * p_desc,uint8_t * i_length)108 static inline const uint8_t *desc26_get_service_identification_record(const uint8_t *p_desc, uint8_t *i_length)
109 {
110 *i_length = desc26_get_service_identification_record_length(p_desc);
111 return desc26_get_service_identification_record_data(p_desc);
112 }
113
desc26_set_service_identification_record(uint8_t * p_desc,uint8_t i_length,uint8_t * p_data)114 static inline void desc26_set_service_identification_record(uint8_t *p_desc, uint8_t i_length, uint8_t *p_data)
115 {
116 if (desc26_get_dsm_cc_flag(p_desc)) {
117 uint8_t ofs = __ofs2;
118 p_desc[ofs + 2] = i_length;
119 memcpy(p_desc + ofs + 3, p_data, i_length);
120 }
121 }
122
123
124 #define __ofs3 \
125 (__ofs2 + 1 + \
126 (desc26_get_dsm_cc_flag(p_desc) \
127 ? 1 + desc26_get_service_identification_record_length(p_desc) \
128 : 0 \
129 ) + 1 \
130 )
131
desc26_get_decoder_config_length(const uint8_t * p_desc)132 static inline uint8_t desc26_get_decoder_config_length(const uint8_t *p_desc)
133 {
134 return (desc26_get_decoder_config_flags(p_desc) == 1) ? p_desc[__ofs3] : 0;
135 }
136
desc26_get_decoder_config_data(const uint8_t * p_desc)137 static inline const uint8_t *desc26_get_decoder_config_data(const uint8_t *p_desc)
138 {
139 return (desc26_get_decoder_config_flags(p_desc) == 1) ? p_desc + __ofs3 + 1 : NULL;
140 }
141
desc26_get_decoder_config(const uint8_t * p_desc,uint8_t * i_length)142 static inline const uint8_t *desc26_get_decoder_config(const uint8_t *p_desc, uint8_t *i_length)
143 {
144 *i_length = desc26_get_decoder_config_length(p_desc);
145 return desc26_get_decoder_config_data(p_desc);
146 }
147
desc26_set_decoder_config(uint8_t * p_desc,uint8_t i_length,uint8_t * p_data)148 static inline void desc26_set_decoder_config(uint8_t *p_desc, uint8_t i_length, uint8_t *p_data)
149 {
150 if (desc26_get_decoder_config_flags(p_desc) == 1) {
151 uint8_t ofs = __ofs3;
152 p_desc[ofs] = i_length;
153 memcpy(p_desc + ofs + 1, p_data, i_length);
154 }
155 }
156
157
desc26_get_dec_config_identification_record_length(const uint8_t * p_desc)158 static inline uint8_t desc26_get_dec_config_identification_record_length(const uint8_t *p_desc)
159 {
160 return (desc26_get_decoder_config_flags(p_desc) == 3) ? p_desc[__ofs3] : 0;
161 }
162
desc26_get_dec_config_identification_record_data(const uint8_t * p_desc)163 static inline const uint8_t *desc26_get_dec_config_identification_record_data(const uint8_t *p_desc)
164 {
165 return (desc26_get_decoder_config_flags(p_desc) == 3) ? p_desc + __ofs3 + 1 : NULL;
166 }
167
desc26_get_dec_config_identification_record(const uint8_t * p_desc,uint8_t * i_length)168 static inline const uint8_t *desc26_get_dec_config_identification_record(const uint8_t *p_desc, uint8_t *i_length)
169 {
170 *i_length = desc26_get_dec_config_identification_record_length(p_desc);
171 return desc26_get_dec_config_identification_record_data(p_desc);
172 }
173
desc26_set_dec_config_identification_record(uint8_t * p_desc,uint8_t i_length,uint8_t * p_data)174 static inline void desc26_set_dec_config_identification_record(uint8_t *p_desc, uint8_t i_length, uint8_t *p_data)
175 {
176 if (desc26_get_decoder_config_flags(p_desc) == 3) {
177 uint8_t ofs = __ofs3;
178 p_desc[ofs] = i_length;
179 memcpy(p_desc + ofs + 1, p_data, i_length);
180 }
181 }
182
183
desc26_get_decoder_config_metadata_service_id(const uint8_t * p_desc)184 static inline uint8_t desc26_get_decoder_config_metadata_service_id(const uint8_t *p_desc)
185 {
186 if (desc26_get_decoder_config_flags(p_desc) == 4)
187 return p_desc[__ofs3];
188 else
189 return 0;
190 }
191
desc26_set_decoder_config_metadata_service_id(uint8_t * p_desc,uint8_t i_service)192 static inline void desc26_set_decoder_config_metadata_service_id(uint8_t *p_desc, uint8_t i_service)
193 {
194 if (desc26_get_decoder_config_flags(p_desc) == 4)
195 p_desc[__ofs3] = i_service;
196 }
197
198 #undef __ofs1
199 #undef __ofs2
200 #undef __ofs3
201
desc26_calc_length(const uint8_t * p_desc)202 static inline int desc26_calc_length(const uint8_t *p_desc)
203 {
204 int i_length = DESC26_HEADER_SIZE - DESC_HEADER_SIZE;
205 uint8_t i_flags = desc26_get_decoder_config_flags(p_desc);
206
207 if (desc26_get_metadata_application_format(p_desc) == 0xffff)
208 i_length += 4;
209 if (desc26_get_metadata_format(p_desc) == 0xff)
210 i_length += 4;
211 if (desc26_get_dsm_cc_flag(p_desc))
212 i_length += 1 + desc26_get_service_identification_record_length(p_desc);
213 if (i_flags == 1)
214 i_length += 1 + desc26_get_decoder_config_length(p_desc);
215 if (i_flags == 3)
216 i_length += 1 + desc26_get_dec_config_identification_record_length(p_desc);
217 if (i_flags == 4)
218 i_length += 1;
219 return i_length;
220 }
221
desc26_validate(const uint8_t * p_desc)222 static inline bool desc26_validate(const uint8_t *p_desc)
223 {
224 return desc26_calc_length(p_desc) <= desc_get_length(p_desc);
225 }
226
desc26_set_length(uint8_t * p_desc)227 static inline void desc26_set_length(uint8_t *p_desc)
228 {
229 desc_set_length(p_desc, desc26_calc_length(p_desc));
230 }
231
desc26_print(const uint8_t * p_desc,f_print pf_print,void * opaque,print_type_t i_print_type)232 static inline void desc26_print(const uint8_t *p_desc, f_print pf_print,
233 void *opaque, print_type_t i_print_type)
234 {
235 uint8_t i, i_service_identification_record_length;
236 const uint8_t *p_service_identification_record = desc26_get_service_identification_record(p_desc, &i_service_identification_record_length);
237 char psz_service_identification_record[2 * 256 + 1];
238 const char *extra_str = "decoder_config";
239 const uint8_t *p_extra = NULL;
240 uint8_t i_extra_length = 0;
241 char psz_extra[2 * 256 + 1];
242
243 for (i = 0; i < i_service_identification_record_length; i++)
244 sprintf(psz_service_identification_record + 2 * i, "%02x", p_service_identification_record[i]);
245 psz_service_identification_record[2 * i] = '\0';
246
247 if (desc26_get_decoder_config_flags(p_desc) == 1) {
248 p_extra = desc26_get_decoder_config(p_desc, &i_extra_length);
249 }
250 if (desc26_get_decoder_config_flags(p_desc) == 3) {
251 extra_str = "dec_config_identification_record";
252 p_extra = desc26_get_dec_config_identification_record(p_desc, &i_extra_length);
253 }
254 for (i = 0; i < i_extra_length; i++)
255 sprintf(psz_extra + 2 * i, "%02x", p_extra[i]);
256 psz_extra[2 * i] = '\0';
257
258 switch (i_print_type) {
259 case PRINT_XML:
260 pf_print(opaque,
261 "<METADATA_DESC metadata_application_format=\"0x%04x\""
262 " metadata_application_format_identifier=\"0x%08x\""
263 " metadata_format=\"0x%02x\""
264 " metadata_format_identifier=\"0x%08x\""
265 " metadata_service_id=\"0x%02x\""
266
267 " dsm_cc_flag=\"%u\""
268 " service_identification_record_length=\"%u\""
269 " service_identification_record=\"%s\""
270
271 " decoder_config_flags=\"%u\""
272 " %s_length=\"%u\""
273 " %s_data=\"%s\""
274 " decoder_config_metadata_service_id=\"%u\"/>",
275 desc26_get_metadata_application_format(p_desc),
276 desc26_get_metadata_application_format_identifier(p_desc),
277 desc26_get_metadata_format(p_desc),
278 desc26_get_metadata_format_identifier(p_desc),
279 desc26_get_metadata_service_id(p_desc),
280 desc26_get_dsm_cc_flag(p_desc),
281
282 desc26_get_service_identification_record_length(p_desc),
283 psz_service_identification_record,
284
285 desc26_get_decoder_config_flags(p_desc),
286 extra_str, i_extra_length,
287 extra_str, psz_extra,
288 desc26_get_decoder_config_metadata_service_id(p_desc)
289 );
290 break;
291 default:
292 pf_print(opaque,
293 " - desc 26 metadata metadata_application_format=0x%04x"
294 " metadata_application_format_identifier=0x%08x"
295 " metadata_format=0x%02x"
296 " metadata_format_identifier=0x%08x"
297 " metadata_service_id=0x%02x"
298
299 " dsm_cc_flag=%u"
300 " service_identification_record_length=%u"
301 " service_identification_record=\"%s\""
302
303 " decoder_config_flags=%u"
304 " %s_length=%u"
305 " %s_data=\"%s\""
306 " decoder_config_metadata_service_id=%u",
307 desc26_get_metadata_application_format(p_desc),
308 desc26_get_metadata_application_format_identifier(p_desc),
309 desc26_get_metadata_format(p_desc),
310 desc26_get_metadata_format_identifier(p_desc),
311 desc26_get_metadata_service_id(p_desc),
312 desc26_get_dsm_cc_flag(p_desc),
313
314 desc26_get_service_identification_record_length(p_desc),
315 psz_service_identification_record,
316
317 desc26_get_decoder_config_flags(p_desc),
318 extra_str, i_extra_length,
319 extra_str, psz_extra,
320 desc26_get_decoder_config_metadata_service_id(p_desc)
321 );
322 }
323 }
324
325 #ifdef __cplusplus
326 }
327 #endif
328
329 #endif
330