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