1 /*****************************************************************************
2  * desc_4d.h: ETSI EN 300 468 Descriptor 0x4d: Short event 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  *  - ETSI EN 300 468 V1.11.1 (2010-04) (SI in DVB systems)
31  */
32 
33 #ifndef __BITSTREAM_DVB_DESC_4D_H__
34 #define __BITSTREAM_DVB_DESC_4D_H__
35 
36 #include <bitstream/common.h>
37 #include <bitstream/mpeg/psi/descriptors.h>
38 #include <bitstream/dvb/si/numbers.h>
39 #include <bitstream/dvb/si/strings.h>
40 
41 #ifdef __cplusplus
42 extern "C"
43 {
44 #endif
45 
46 /*****************************************************************************
47  * Descriptor 0x4d: Short event descriptor
48  *****************************************************************************/
49 #define DESC4D_HEADER_SIZE      (DESC_HEADER_SIZE + 3)
50 
desc4d_init(uint8_t * p_desc)51 static inline void desc4d_init(uint8_t *p_desc)
52 {
53     desc_set_tag(p_desc, 0x4d);
54 }
55 
desc4d_get_lang(const uint8_t * p_desc)56 static inline const uint8_t *desc4d_get_lang(const uint8_t *p_desc)
57 {
58     return p_desc + DESC_HEADER_SIZE;
59 }
60 
desc4d_set_lang(uint8_t * p_desc,const uint8_t p_lang[3])61 static inline void desc4d_set_lang(uint8_t *p_desc, const uint8_t p_lang[3])
62 {
63     p_desc[2] = p_lang[0];
64     p_desc[3] = p_lang[1];
65     p_desc[4] = p_lang[2];
66 }
67 
desc4d_get_event_name(const uint8_t * p_desc,uint8_t * pi_length)68 static inline const uint8_t *desc4d_get_event_name(const uint8_t *p_desc,
69                                                  uint8_t *pi_length)
70 {
71     const uint8_t *p = p_desc + DESC4D_HEADER_SIZE;
72     *pi_length = p[0];
73     return p + 1;
74 }
75 
desc4d_set_event_name(uint8_t * p_desc,const uint8_t * p_event_name,uint8_t i_length)76 static inline void desc4d_set_event_name(uint8_t *p_desc,
77                                        const uint8_t *p_event_name,
78                                        uint8_t i_length)
79 {
80     uint8_t *p = p_desc + DESC4D_HEADER_SIZE;
81     p[0] = i_length;
82     memcpy(p + 1, p_event_name, i_length);
83 }
84 
desc4d_get_text(const uint8_t * p_desc,uint8_t * pi_length)85 static inline uint8_t *desc4d_get_text(const uint8_t *p_desc,
86                                           uint8_t *pi_length)
87 {
88     const uint8_t *p = (uint8_t *)p_desc + DESC4D_HEADER_SIZE + 1 + p_desc[5];
89     *pi_length = p[0];
90     return (uint8_t *)p + 1;
91 }
92 
desc4d_set_text(uint8_t * p_desc,const uint8_t * p_text,uint8_t i_length)93 static inline void desc4d_set_text(uint8_t *p_desc,
94                                    const uint8_t *p_text,
95                                    uint8_t i_length)
96 {
97     uint8_t *p = p_desc + DESC4D_HEADER_SIZE + 1 + p_desc[5];
98     p[0] = i_length;
99     memcpy(p + 1, p_text, i_length);
100 }
101 
desc4d_set_length(uint8_t * p_desc)102 static inline void desc4d_set_length(uint8_t *p_desc)
103 {
104     uint8_t i_event_name_len, i_text_len;
105     desc4d_get_event_name(p_desc, &i_event_name_len);
106     desc4d_get_text(p_desc, &i_text_len);
107     desc_set_length(p_desc, DESC4D_HEADER_SIZE - DESC_HEADER_SIZE
108                             + 1 + i_event_name_len
109                             + 1 + i_text_len);
110 }
111 
desc4d_validate(const uint8_t * p_desc)112 static inline bool desc4d_validate(const uint8_t *p_desc)
113 {
114     uint8_t i_length = desc_get_length(p_desc);
115     const uint8_t *p = p_desc + DESC4D_HEADER_SIZE;
116 
117     p += *p + 1;
118     if (DESC4D_HEADER_SIZE + 2 > i_length + DESC_HEADER_SIZE ||
119         p + 1 - p_desc > i_length + DESC_HEADER_SIZE)
120         return false;
121 
122     p += *p + 1;
123     if (p - p_desc > i_length + DESC_HEADER_SIZE)
124         return false;
125 
126     return true;
127 }
128 
desc4d_print(const uint8_t * p_desc,f_print pf_print,void * print_opaque,f_iconv pf_iconv,void * iconv_opaque,print_type_t i_print_type)129 static inline void desc4d_print(const uint8_t *p_desc,
130                                 f_print pf_print, void *print_opaque,
131                                 f_iconv pf_iconv, void *iconv_opaque,
132                                 print_type_t i_print_type)
133 {
134     uint8_t i_event_name_length, i_text_length;
135     const uint8_t *p_event_name = desc4d_get_event_name(p_desc, &i_event_name_length);
136     const uint8_t *p_text = desc4d_get_text(p_desc, &i_text_length);
137     char *psz_event_name = dvb_string_get(p_event_name, i_event_name_length,
138                                         pf_iconv, iconv_opaque);
139     char *psz_text = dvb_string_get(p_text, i_text_length,
140                                        pf_iconv, iconv_opaque);
141     switch (i_print_type) {
142     case PRINT_XML:
143         psz_event_name = dvb_string_xml_escape(psz_event_name);
144         psz_text = dvb_string_xml_escape(psz_text);
145         pf_print(print_opaque,
146                  "<SHORT_EVENT_DESC lang=\"%3.3s\" event_name=\"%s\" text=\"%s\"/>",
147                  (char *)desc4d_get_lang(p_desc), psz_event_name, psz_text);
148         break;
149     default:
150         pf_print(print_opaque,
151                  "    - desc 4d short_event lang=%3.3s event_name=\"%s\" text=\"%s\"",
152                  (char *)desc4d_get_lang(p_desc), psz_event_name, psz_text);
153     }
154     free(psz_event_name);
155     free(psz_text);
156 }
157 
158 #ifdef __cplusplus
159 }
160 #endif
161 
162 #endif
163