1 /*
2 * Copyright (c) 2011-2012 - Mauro Carvalho Chehab
3 * Copyright (c) 2012-2014 - Andre Roth <neolynx@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as published by
7 * the Free Software Foundation version 2.1 of the License.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 * Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
18 *
19 */
20
21 #include <libdvbv5/pmt.h>
22 #include <libdvbv5/descriptors.h>
23 #include <libdvbv5/dvb-fe.h>
24
25 #include <string.h> /* memcpy */
26
27 #if __GNUC__ >= 9
28 #pragma GCC diagnostic ignored "-Waddress-of-packed-member"
29 #endif
30
dvb_table_pmt_init(struct dvb_v5_fe_parms * parms,const uint8_t * buf,ssize_t buflen,struct dvb_table_pmt ** table)31 ssize_t dvb_table_pmt_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf,
32 ssize_t buflen, struct dvb_table_pmt **table)
33 {
34 const uint8_t *p = buf, *endbuf = buf + buflen;
35 struct dvb_table_pmt *pmt;
36 struct dvb_table_pmt_stream **head;
37 struct dvb_desc **head_desc;
38 size_t size;
39
40 size = offsetof(struct dvb_table_pmt, dvb_pmt_field_last);
41 if (p + size > endbuf) {
42 dvb_logerr("%s: short read %zd/%zd bytes", __func__,
43 endbuf - p, size);
44 return -1;
45 }
46
47 if (buf[0] != DVB_TABLE_PMT) {
48 dvb_logerr("%s: invalid marker 0x%02x, should be 0x%02x",
49 __func__, buf[0], DVB_TABLE_PMT);
50 return -2;
51 }
52
53 if (!*table) {
54 *table = calloc(sizeof(struct dvb_table_pmt), 1);
55 if (!*table) {
56 dvb_logerr("%s: out of memory", __func__);
57 return -3;
58 }
59 }
60 pmt = *table;
61 memcpy(pmt, p, size);
62 p += size;
63 dvb_table_header_init(&pmt->header);
64 bswap16(pmt->bitfield);
65 bswap16(pmt->bitfield2);
66
67 /* find end of current list */
68 head = &pmt->stream;
69 while (*head != NULL)
70 head = &(*head)->next;
71 head_desc = &pmt->descriptor;
72 while (*head_desc != NULL)
73 head_desc = &(*head_desc)->next;
74
75 size = pmt->header.section_length + 3 - DVB_CRC_SIZE; /* plus header, minus CRC */
76 if (buf + size > endbuf) {
77 dvb_logerr("%s: short read %zd/%zd bytes", __func__,
78 endbuf - buf, size);
79 return -4;
80 }
81 endbuf = buf + size;
82
83 /* parse the descriptors */
84 if (pmt->desc_length > 0 ) {
85 uint16_t desc_length = pmt->desc_length;
86 if (p + desc_length > endbuf) {
87 dvb_logwarn("%s: descriptors short read %d/%zd bytes", __func__,
88 desc_length, endbuf - p);
89 desc_length = endbuf - p;
90 }
91 if (dvb_desc_parse(parms, p, desc_length,
92 head_desc) != 0) {
93 return -4;
94 }
95 p += desc_length;
96 }
97
98 /* get the stream entries */
99 size = offsetof(struct dvb_table_pmt_stream, descriptor);
100 while (p + size <= endbuf) {
101 struct dvb_table_pmt_stream *stream;
102
103 stream = malloc(sizeof(struct dvb_table_pmt_stream));
104 if (!stream) {
105 dvb_logerr("%s: out of memory", __func__);
106 return -5;
107 }
108 memcpy(stream, p, size);
109 p += size;
110
111 bswap16(stream->bitfield);
112 bswap16(stream->bitfield2);
113 stream->descriptor = NULL;
114 stream->next = NULL;
115
116 *head = stream;
117 head = &(*head)->next;
118
119 /* parse the descriptors */
120 if (stream->desc_length > 0) {
121 uint16_t desc_length = stream->desc_length;
122 if (p + desc_length > endbuf) {
123 dvb_logwarn("%s: descriptors short read %zd/%d bytes", __func__,
124 endbuf - p, desc_length);
125 desc_length = endbuf - p;
126 }
127 if (dvb_desc_parse(parms, p, desc_length,
128 &stream->descriptor) != 0) {
129 return -6;
130 }
131 p += desc_length;
132 }
133 }
134 if (p < endbuf)
135 dvb_logwarn("%s: %zu spurious bytes at the end",
136 __func__, endbuf - p);
137
138 return p - buf;
139 }
140
dvb_table_pmt_free(struct dvb_table_pmt * pmt)141 void dvb_table_pmt_free(struct dvb_table_pmt *pmt)
142 {
143 struct dvb_table_pmt_stream *stream = pmt->stream;
144 while(stream) {
145 dvb_desc_free((struct dvb_desc **) &stream->descriptor);
146 struct dvb_table_pmt_stream *tmp = stream;
147 stream = stream->next;
148 free(tmp);
149 }
150 dvb_desc_free(&pmt->descriptor);
151 free(pmt);
152 }
153
dvb_table_pmt_print(struct dvb_v5_fe_parms * parms,const struct dvb_table_pmt * pmt)154 void dvb_table_pmt_print(struct dvb_v5_fe_parms *parms, const struct dvb_table_pmt *pmt)
155 {
156 dvb_loginfo("PMT");
157 dvb_table_header_print(parms, &pmt->header);
158 dvb_loginfo("|- pcr_pid %04x", pmt->pcr_pid);
159 dvb_loginfo("| reserved2 %d", pmt->reserved2);
160 dvb_loginfo("| descriptor length %d", pmt->desc_length);
161 dvb_loginfo("| zero3 %d", pmt->zero3);
162 dvb_loginfo("| reserved3 %d", pmt->reserved3);
163 dvb_desc_print(parms, pmt->descriptor);
164 dvb_loginfo("|\\");
165 const struct dvb_table_pmt_stream *stream = pmt->stream;
166 uint16_t streams = 0;
167 while(stream) {
168 dvb_loginfo("|- stream 0x%04x: %s (%x)", stream->elementary_pid,
169 pmt_stream_name[stream->type], stream->type);
170 dvb_loginfo("| descriptor length %d", stream->desc_length);
171 dvb_desc_print(parms, stream->descriptor);
172 stream = stream->next;
173 streams++;
174 }
175 dvb_loginfo("|_ %d streams", streams);
176 }
177
178 const char *pmt_stream_name[] = {
179 [0x00 ... 0x7f] = "Reserved",
180 [0x80 ... 0xff] = "User Private",
181
182 [stream_video] = "Video ISO/IEC 11172",
183 [stream_video_h262] = "Video ISO/IEC 13818-2",
184 [stream_audio] = "Audio ISO/IEC 11172",
185 [stream_audio_13818_3] = "Audio ISO/IEC 13818-3",
186 [stream_private_sections] = "ISO/IEC 13818-1 Private Sections",
187 [stream_private_data] = "ISO/IEC 13818-1 Private Data",
188 [stream_mheg] = "ISO/IEC 13522 MHEG",
189 [stream_h222] = "ISO/IEC 13818-1 Annex A DSM-CC",
190 [stream_h222_1] = "ITU-T Rec. H.222.1",
191 [stream_13818_6_A] = "ISO/IEC 13818-6 type A",
192 [stream_13818_6_B] = "ISO/IEC 13818-6 type B",
193 [stream_13818_6_C] = "ISO/IEC 13818-6 type C",
194 [stream_13818_6_D] = "ISO/IEC 13818-6 type D",
195 [stream_h222_aux] = "ISO/IEC 13818-1 auxiliary",
196 [stream_audio_adts] = "Audio ISO/IEC 13818-7 ADTS",
197 [stream_video_14496_2] = "Video ISO/IEC 14496-2",
198 [stream_audio_latm] = "Audio ISO/IEC 14496-3 LATM",
199 [stream_14496_1_pes] = "ISO/IEC 14496-1 PES",
200 [stream_14496_1_iso] = "ISO/IEC 14496-1 ISO",
201 [stream_download] = "ISO/IEC 13818-6 Synchronized Download Protocol",
202
203 [stream_video_h264] = "H264",
204 [stream_audio_14496_3] = "ISO/IEC 14496-3 Audio",
205 [stream_video_hevc] = "HEVC",
206 [stream_video_cavs] = "CAVS (Chinese AVS)",
207 [stream_video_moto] = "MPEG-2 MOTO video",
208 [stream_audio_a52] = "A52",
209 [stream_scte_27] = "SCTE-27 (sub)",
210 [stream_audio_sdds] = "SDDS",
211 [stream_audio_dts_hdmv] = "DTS",
212 [stream_audio_e_ac3] = "E-AC3, ATSC",
213 [stream_audio_dts] = "DTS",
214 [stream_audio_a52_vls] = "A52 vls",
215 [stream_spu_vls] = "DVD_SPU vls",
216 [stream_audio_sdds2] = "SDDS",
217 };
218
219