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