1 /*****************************************************************************
2 * eit.c: EIT decoder/generator
3 *----------------------------------------------------------------------------
4 * Copyright (C) 2004-2011 VideoLAN
5 * $Id: eit.c 88 2004-02-24 14:31:18Z sam $
6 *
7 * Authors: Christophe Massiot <massiot@via.ecp.fr>
8 * Johan Bilien <jobi@via.ecp.fr>
9 * Jean-Paul Saman <jpsaman@videolan.org>
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 *----------------------------------------------------------------------------
26 *
27 *****************************************************************************/
28
29 #include "config.h"
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <stdbool.h>
34 #include <string.h>
35
36 #if defined(HAVE_INTTYPES_H)
37 #include <inttypes.h>
38 #elif defined(HAVE_STDINT_H)
39 #include <stdint.h>
40 #endif
41
42 #include <assert.h>
43
44 #include "../dvbpsi.h"
45 #include "../dvbpsi_private.h"
46 #include "../psi.h"
47 #include "../descriptor.h"
48 #include "../demux.h"
49 #include "eit.h"
50 #include "eit_private.h"
51
52 /*****************************************************************************
53 * dvbpsi_eit_attach
54 *****************************************************************************
55 * Initialize a EIT subtable decoder.
56 *****************************************************************************/
dvbpsi_eit_attach(dvbpsi_t * p_dvbpsi,uint8_t i_table_id,uint16_t i_extension,dvbpsi_eit_callback pf_callback,void * p_cb_data)57 bool dvbpsi_eit_attach(dvbpsi_t *p_dvbpsi, uint8_t i_table_id, uint16_t i_extension,
58 dvbpsi_eit_callback pf_callback, void* p_cb_data)
59 {
60 assert(p_dvbpsi);
61 assert(p_dvbpsi->p_decoder);
62
63 dvbpsi_demux_t* p_demux = (dvbpsi_demux_t*)p_dvbpsi->p_decoder;
64
65 if (dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension) != NULL)
66 {
67 dvbpsi_error(p_dvbpsi, "EIT decoder",
68 "Already a decoder for (table_id == 0x%02x,"
69 "extension == 0x%02x)",
70 i_table_id, i_extension);
71 return false;
72 }
73
74 dvbpsi_eit_decoder_t* p_eit_decoder;
75 p_eit_decoder = (dvbpsi_eit_decoder_t*) dvbpsi_decoder_new(NULL,
76 0, true, sizeof(dvbpsi_eit_decoder_t));
77 if (p_eit_decoder == NULL)
78 return false;
79
80 /* subtable decoder configuration */
81 dvbpsi_demux_subdec_t* p_subdec;
82 p_subdec = dvbpsi_NewDemuxSubDecoder(i_table_id, i_extension, dvbpsi_eit_detach,
83 dvbpsi_eit_sections_gather, DVBPSI_DECODER(p_eit_decoder));
84 if (p_subdec == NULL)
85 {
86 dvbpsi_decoder_delete(DVBPSI_DECODER(p_eit_decoder));
87 return false;
88 }
89
90 /* Attach the subtable decoder to the demux */
91 dvbpsi_AttachDemuxSubDecoder(p_demux, p_subdec);
92
93 /* EIT decoder information */
94 p_eit_decoder->pf_eit_callback = pf_callback;
95 p_eit_decoder->p_cb_data = p_cb_data;
96 p_eit_decoder->p_building_eit = NULL;
97
98 return true;
99 }
100
101 /*****************************************************************************
102 * dvbpsi_eit_detach
103 *****************************************************************************
104 * Close a EIT decoder.
105 *****************************************************************************/
dvbpsi_eit_detach(dvbpsi_t * p_dvbpsi,uint8_t i_table_id,uint16_t i_extension)106 void dvbpsi_eit_detach(dvbpsi_t *p_dvbpsi, uint8_t i_table_id,
107 uint16_t i_extension)
108 {
109 assert(p_dvbpsi);
110 assert(p_dvbpsi->p_decoder);
111
112 dvbpsi_demux_t *p_demux = (dvbpsi_demux_t *) p_dvbpsi->p_decoder;
113
114 dvbpsi_demux_subdec_t* p_subdec;
115 p_subdec = dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension);
116 if (p_subdec == NULL)
117 {
118 dvbpsi_error(p_dvbpsi, "EIT Decoder",
119 "No such EIT decoder (table_id == 0x%02x,"
120 "extension == 0x%02x)",
121 i_table_id, i_extension);
122 return;
123 }
124
125 dvbpsi_eit_decoder_t* p_eit_decoder;
126 p_eit_decoder = (dvbpsi_eit_decoder_t*)p_subdec->p_decoder;
127 if (p_eit_decoder->p_building_eit)
128 dvbpsi_eit_delete(p_eit_decoder->p_building_eit);
129 p_eit_decoder->p_building_eit = NULL;
130
131 dvbpsi_DetachDemuxSubDecoder(p_demux, p_subdec);
132 dvbpsi_DeleteDemuxSubDecoder(p_subdec);
133 }
134
135 /*****************************************************************************
136 * dvbpsi_eit_init
137 *****************************************************************************
138 * Initialize a pre-allocated dvbpsi_eit_t structure.
139 *****************************************************************************/
dvbpsi_eit_init(dvbpsi_eit_t * p_eit,uint8_t i_table_id,uint16_t i_extension,uint8_t i_version,bool b_current_next,uint16_t i_ts_id,uint16_t i_network_id,uint8_t i_segment_last_section_number,uint8_t i_last_table_id)140 void dvbpsi_eit_init(dvbpsi_eit_t* p_eit, uint8_t i_table_id, uint16_t i_extension,
141 uint8_t i_version, bool b_current_next, uint16_t i_ts_id,
142 uint16_t i_network_id, uint8_t i_segment_last_section_number,
143 uint8_t i_last_table_id)
144 {
145 p_eit->i_table_id = i_table_id;
146 p_eit->i_extension = i_extension;
147
148 p_eit->i_version = i_version;
149 p_eit->b_current_next = b_current_next;
150 p_eit->i_ts_id = i_ts_id;
151 p_eit->i_network_id = i_network_id;
152 p_eit->i_segment_last_section_number = i_segment_last_section_number;
153 p_eit->i_last_table_id = i_last_table_id;
154 p_eit->p_first_event = NULL;
155 }
156
157 /*****************************************************************************
158 * dvbpsi_eit_new
159 *****************************************************************************
160 * Allocate and Initialize a new dvbpsi_eit_t structure.
161 *****************************************************************************/
dvbpsi_eit_new(uint8_t i_table_id,uint16_t i_extension,uint8_t i_version,bool b_current_next,uint16_t i_ts_id,uint16_t i_network_id,uint8_t i_segment_last_section_number,uint8_t i_last_table_id)162 dvbpsi_eit_t* dvbpsi_eit_new(uint8_t i_table_id, uint16_t i_extension,
163 uint8_t i_version, bool b_current_next, uint16_t i_ts_id,
164 uint16_t i_network_id, uint8_t i_segment_last_section_number,
165 uint8_t i_last_table_id)
166 {
167 dvbpsi_eit_t *p_eit = (dvbpsi_eit_t*)malloc(sizeof(dvbpsi_eit_t));
168 if (p_eit != NULL)
169 dvbpsi_eit_init(p_eit, i_table_id, i_extension, i_version,
170 b_current_next, i_ts_id, i_network_id, i_segment_last_section_number,
171 i_last_table_id);
172 return p_eit;
173 }
174
175 /*****************************************************************************
176 * dvbpsi_eit_empty
177 *****************************************************************************
178 * Clean a dvbpsi_eit_t structure.
179 *****************************************************************************/
dvbpsi_eit_empty(dvbpsi_eit_t * p_eit)180 void dvbpsi_eit_empty(dvbpsi_eit_t* p_eit)
181 {
182 dvbpsi_eit_event_t* p_event = p_eit->p_first_event;
183
184 while(p_event != NULL)
185 {
186 dvbpsi_eit_event_t* p_tmp = p_event->p_next;
187 dvbpsi_DeleteDescriptors(p_event->p_first_descriptor);
188 free(p_event);
189 p_event = p_tmp;
190 }
191 p_eit->p_first_event = NULL;
192 }
193
194 /*****************************************************************************
195 * dvbpsi_eit_delete
196 *****************************************************************************
197 * Clean a dvbpsi_eit_t structure.
198 *****************************************************************************/
dvbpsi_eit_delete(dvbpsi_eit_t * p_eit)199 void dvbpsi_eit_delete(dvbpsi_eit_t* p_eit)
200 {
201 if (p_eit)
202 dvbpsi_eit_empty(p_eit);
203 free(p_eit);
204 }
205
206 /*****************************************************************************
207 * dvbpsi_eit_event_add
208 *****************************************************************************
209 * Add an event description at the end of the EIT.
210 *****************************************************************************/
dvbpsi_eit_event_add(dvbpsi_eit_t * p_eit,uint16_t i_event_id,uint64_t i_start_time,uint32_t i_duration,uint8_t i_running_status,bool b_free_ca,uint16_t i_event_descriptor_length)211 dvbpsi_eit_event_t* dvbpsi_eit_event_add(dvbpsi_eit_t* p_eit,
212 uint16_t i_event_id, uint64_t i_start_time, uint32_t i_duration,
213 uint8_t i_running_status, bool b_free_ca, uint16_t i_event_descriptor_length)
214 {
215 dvbpsi_eit_event_t* p_event;
216 p_event = (dvbpsi_eit_event_t*)calloc(1,sizeof(dvbpsi_eit_event_t));
217 if (p_event == NULL)
218 return NULL;
219
220 p_event->i_event_id = i_event_id;
221 p_event->i_start_time = i_start_time;
222 p_event->i_duration = i_duration;
223 p_event->i_running_status = i_running_status;
224 p_event->b_free_ca = b_free_ca;
225 p_event->b_nvod = ( (i_start_time & 0xFFFFF000) == 0xFFFFF000
226 && i_running_status == 0x0 );
227 p_event->p_next = NULL;
228 p_event->i_descriptors_length = i_event_descriptor_length;
229 p_event->p_first_descriptor = NULL;
230
231 if (p_eit->p_first_event == NULL)
232 p_eit->p_first_event = p_event;
233 else
234 {
235 dvbpsi_eit_event_t* p_last_event = p_eit->p_first_event;
236 while(p_last_event->p_next != NULL)
237 p_last_event = p_last_event->p_next;
238 p_last_event->p_next = p_event;
239 }
240 return p_event;
241 }
242
243 /*****************************************************************************
244 * dvbpsi_eit_nvod_event_add
245 *****************************************************************************
246 * Add an NVOD event description at the end of the EIT.
247 *****************************************************************************/
dvbpsi_eit_nvod_event_add(dvbpsi_eit_t * p_eit,uint16_t i_event_id,uint32_t i_duration,bool b_free_ca,uint16_t i_event_descriptor_length)248 dvbpsi_eit_event_t* dvbpsi_eit_nvod_event_add(dvbpsi_eit_t* p_eit,
249 uint16_t i_event_id, uint32_t i_duration, bool b_free_ca,
250 uint16_t i_event_descriptor_length)
251 {
252 return dvbpsi_eit_event_add(p_eit, i_event_id, 0xFFFFF000, i_duration,
253 0x0, b_free_ca, i_event_descriptor_length);
254 }
255
256 /*****************************************************************************
257 * dvbpsi_eit_event_descriptor_add
258 *****************************************************************************
259 * Add a descriptor in the EIT event description.
260 *****************************************************************************/
dvbpsi_eit_event_descriptor_add(dvbpsi_eit_event_t * p_event,uint8_t i_tag,uint8_t i_length,uint8_t * p_data)261 dvbpsi_descriptor_t* dvbpsi_eit_event_descriptor_add(dvbpsi_eit_event_t* p_event,
262 uint8_t i_tag, uint8_t i_length, uint8_t* p_data)
263 {
264 dvbpsi_descriptor_t* p_descriptor;
265 p_descriptor = dvbpsi_NewDescriptor(i_tag, i_length, p_data);
266 if (p_descriptor == NULL)
267 return NULL;
268
269 p_event->p_first_descriptor = dvbpsi_AddDescriptor(p_event->p_first_descriptor,
270 p_descriptor);
271 assert(p_event->p_first_descriptor);
272 if (p_event->p_first_descriptor == NULL)
273 return NULL;
274
275 return p_descriptor;
276 }
277
278 /* */
dvbpsi_ReInitEIT(dvbpsi_eit_decoder_t * p_decoder,const bool b_force)279 static void dvbpsi_ReInitEIT(dvbpsi_eit_decoder_t* p_decoder, const bool b_force)
280 {
281 assert(p_decoder);
282
283 dvbpsi_decoder_reset(DVBPSI_DECODER(p_decoder), b_force);
284
285 if (b_force)
286 {
287 /* Free structures */
288 if (p_decoder->p_building_eit)
289 dvbpsi_eit_delete(p_decoder->p_building_eit);
290 }
291 p_decoder->p_building_eit = NULL;
292 }
293
dvbpsi_CheckEIT(dvbpsi_t * p_dvbpsi,dvbpsi_eit_decoder_t * p_eit_decoder,dvbpsi_psi_section_t * p_section)294 static bool dvbpsi_CheckEIT(dvbpsi_t *p_dvbpsi, dvbpsi_eit_decoder_t *p_eit_decoder,
295 dvbpsi_psi_section_t *p_section)
296 {
297 bool b_reinit = false;
298 assert(p_dvbpsi);
299 assert(p_eit_decoder);
300
301 if (p_eit_decoder->p_building_eit->i_extension != p_section->i_extension)
302 {
303 /* service_id */
304 dvbpsi_error(p_dvbpsi, "EIT decoder",
305 "'service_id' differs"
306 " whereas no TS discontinuity has occurred");
307 b_reinit = true;
308 }
309 else if (p_eit_decoder->p_building_eit->i_version != p_section->i_version)
310 {
311 /* version_number */
312 dvbpsi_error(p_dvbpsi, "EIT decoder",
313 "'version_number' differs"
314 " whereas no discontinuity has occurred");
315 b_reinit = true;
316 }
317 else if (p_eit_decoder->i_last_section_number != p_section->i_last_number)
318 {
319 /* last_section_number */
320 dvbpsi_error(p_dvbpsi, "EIT decoder",
321 "'last_section_number' differs %2d / %2d "
322 " whereas no discontinuity has occurred",
323 p_eit_decoder->i_last_section_number, p_section->i_last_number);
324 b_reinit = true;
325 }
326
327 return b_reinit;
328 }
329
dvbpsi_IsCompleteEIT(dvbpsi_eit_decoder_t * p_eit_decoder,dvbpsi_psi_section_t * p_section)330 static bool dvbpsi_IsCompleteEIT(dvbpsi_eit_decoder_t* p_eit_decoder, dvbpsi_psi_section_t* p_section)
331 {
332 assert(p_eit_decoder);
333
334 bool b_complete = false;
335
336 /* As there may be gaps in the section_number fields (see below), we
337 * have to wait until we have received a section_number twice or
338 * until we have a received a section_number which is
339 * first_received_section_number - 1;
340 * if the first_received_section_number is 0, it's enough to wait
341 * until the last_section_number has been received;
342 * this is the only way to be sure that a complete table has been
343 * sent! */
344 if ((p_eit_decoder->i_first_received_section_number > 0 &&
345 (p_section->i_number == p_eit_decoder->i_first_received_section_number ||
346 p_section->i_number == p_eit_decoder->i_first_received_section_number - 1)) ||
347 (p_eit_decoder->i_first_received_section_number == 0 &&
348 p_section->i_number == p_eit_decoder->i_last_section_number))
349 {
350 dvbpsi_psi_section_t *p = p_eit_decoder->p_sections;
351 while (p)
352 {
353 if (p->i_number == p_eit_decoder->i_last_section_number)
354 {
355 b_complete = true;
356 break;
357 }
358
359 /* ETSI EN 300 468 V1.5.1 section 5.2.4 says that the EIT
360 * sections may be structured into a number of segments and
361 * that there may be a gap in the section_number between
362 * two segments (but not within a single segment); thus at
363 * the end of a segment (indicated by
364 * section_number == segment_last_section_number)
365 * we have to search for the beginning of the next segment) */
366 if (p->i_number == p->p_payload_start[4])
367 {
368 while (p->p_next &&
369 (p->p_next->i_number < p_eit_decoder->i_last_section_number))
370 {
371 p = p->p_next;
372 }
373 }
374
375 p = p->p_next;
376 }
377 }
378
379 return b_complete;
380 }
381
dvbpsi_AddSectionEIT(dvbpsi_t * p_dvbpsi,dvbpsi_eit_decoder_t * p_eit_decoder,dvbpsi_psi_section_t * p_section)382 static bool dvbpsi_AddSectionEIT(dvbpsi_t *p_dvbpsi, dvbpsi_eit_decoder_t *p_eit_decoder,
383 dvbpsi_psi_section_t* p_section)
384 {
385 assert(p_dvbpsi);
386 assert(p_eit_decoder);
387 assert(p_section);
388
389 /* Initialize the structures if it's the first section received */
390 if (!p_eit_decoder->p_building_eit)
391 {
392 p_eit_decoder->p_building_eit = dvbpsi_eit_new(
393 p_section->i_table_id,
394 p_section->i_extension,
395 p_section->i_version,
396 p_section->b_current_next,
397 ((uint16_t)(p_section->p_payload_start[0]) << 8)
398 | p_section->p_payload_start[1],
399 ((uint16_t)(p_section->p_payload_start[2]) << 8)
400 | p_section->p_payload_start[3],
401 p_section->p_payload_start[4],
402 p_section->p_payload_start[5]);
403
404 p_eit_decoder->i_last_section_number = p_section->i_last_number;
405 p_eit_decoder->i_first_received_section_number = p_section->i_number;
406
407 if (p_eit_decoder->p_building_eit == NULL)
408 return false;
409 }
410
411 /* Add to linked list of sections */
412 if (dvbpsi_decoder_psi_section_add(DVBPSI_DECODER(p_eit_decoder), p_section))
413 dvbpsi_debug(p_dvbpsi, "EIT decoder",
414 "overwrite section number %d", p_section->i_number);
415
416 return true;
417 }
418
419 /*****************************************************************************
420 * dvbpsi_eit_sections_gather
421 *****************************************************************************
422 * Callback for the subtable demultiplexor.
423 *****************************************************************************/
dvbpsi_eit_sections_gather(dvbpsi_t * p_dvbpsi,dvbpsi_decoder_t * p_private_decoder,dvbpsi_psi_section_t * p_section)424 void dvbpsi_eit_sections_gather(dvbpsi_t *p_dvbpsi, dvbpsi_decoder_t *p_private_decoder,
425 dvbpsi_psi_section_t *p_section)
426 {
427 assert(p_dvbpsi);
428 assert(p_dvbpsi->p_decoder);
429
430 const uint8_t i_table_id = (p_section->i_table_id >= 0x4e &&
431 p_section->i_table_id <= 0x6f) ?
432 p_section->i_table_id : 0x4e;
433
434 if (!dvbpsi_CheckPSISection(p_dvbpsi, p_section, i_table_id, "EIT decoder"))
435 {
436 dvbpsi_DeletePSISections(p_section);
437 return;
438 }
439
440 /* We have a valid EIT section */
441 dvbpsi_demux_t *p_demux = (dvbpsi_demux_t *) p_dvbpsi->p_decoder;
442 dvbpsi_eit_decoder_t* p_eit_decoder
443 = (dvbpsi_eit_decoder_t*)p_private_decoder;
444
445 /* TS discontinuity check */
446 if (p_demux->b_discontinuity)
447 {
448 dvbpsi_ReInitEIT(p_eit_decoder, true);
449 p_eit_decoder->b_discontinuity = false;
450 p_demux->b_discontinuity = false;
451 }
452 else
453 {
454 /* Perform a few sanity checks */
455 if (p_eit_decoder->p_building_eit)
456 {
457 if (dvbpsi_CheckEIT(p_dvbpsi, p_eit_decoder, p_section))
458 dvbpsi_ReInitEIT(p_eit_decoder, true);
459 }
460 else
461 {
462 if ( (p_eit_decoder->b_current_valid)
463 && (p_eit_decoder->current_eit.i_version == p_section->i_version)
464 && (p_eit_decoder->current_eit.b_current_next == p_section->b_current_next))
465 {
466 /* Don't decode since this version is already decoded */
467 dvbpsi_debug(p_dvbpsi, "EIT decoder",
468 "ignoring already decoded section %d",
469 p_section->i_number);
470 dvbpsi_DeletePSISections(p_section);
471 return;
472 }
473 }
474 }
475
476 bool b_complete = dvbpsi_IsCompleteEIT(p_eit_decoder, p_section);
477
478 /* Add section to EIT */
479 if (!dvbpsi_AddSectionEIT(p_dvbpsi, p_eit_decoder, p_section))
480 {
481 dvbpsi_error(p_dvbpsi, "EIT decoder", "failed decoding section %d",
482 p_section->i_number);
483 dvbpsi_DeletePSISections(p_section);
484 return;
485 }
486
487 /* Check if we have all the sections */
488 if (b_complete)
489 {
490 assert(p_eit_decoder->pf_eit_callback);
491
492 /* Save the current information */
493 p_eit_decoder->current_eit = *p_eit_decoder->p_building_eit;
494 p_eit_decoder->b_current_valid = true;
495
496 /* Decode the sections */
497 dvbpsi_eit_sections_decode(p_eit_decoder->p_building_eit,
498 p_eit_decoder->p_sections);
499
500 /* signal the new EIT */
501 p_eit_decoder->pf_eit_callback(p_eit_decoder->p_cb_data, p_eit_decoder->p_building_eit);
502
503 /* Delete sections and Reinitialize the structures */
504 dvbpsi_ReInitEIT(p_eit_decoder, false);
505 assert(p_eit_decoder->p_sections == NULL);
506 }
507 }
508
509 /*****************************************************************************
510 * dvbpsi_eit_sections_decode
511 *****************************************************************************
512 * EIT decoder.
513 *****************************************************************************/
dvbpsi_eit_sections_decode(dvbpsi_eit_t * p_eit,dvbpsi_psi_section_t * p_section)514 void dvbpsi_eit_sections_decode(dvbpsi_eit_t* p_eit,
515 dvbpsi_psi_section_t* p_section)
516 {
517 uint8_t* p_byte, *p_end;
518
519 while (p_section)
520 {
521 /* EIT Event Descriptions */
522 p_byte = p_section->p_payload_start + 6;
523 p_end = p_section->p_payload_end;
524
525 while (p_byte < p_end)
526 {
527 uint16_t i_event_id = ((uint16_t)(p_byte[0]) << 8) | p_byte[1];
528 uint64_t i_start_time = ((uint64_t)(p_byte[2]) << 32) |
529 ((uint64_t)(p_byte[3]) << 24) |
530 ((uint64_t)(p_byte[4]) << 16) |
531 ((uint64_t)(p_byte[5]) << 8) |
532 ((uint64_t)(p_byte[6]));
533 uint32_t i_duration = ((uint32_t)(p_byte[7]) << 16) |
534 ((uint32_t)(p_byte[8]) << 8) |
535 p_byte[9];
536 uint8_t i_running_status = (uint8_t)(p_byte[10]) >> 5;
537 bool b_free_ca = ((p_byte[10] & 0x10) == 0x10) ? true : false;
538 uint16_t i_ev_length = ((uint16_t)(p_byte[10] & 0xf) << 8) |
539 p_byte[11];
540 dvbpsi_eit_event_t *p_event = dvbpsi_eit_event_add(p_eit,
541 i_event_id, i_start_time, i_duration,
542 i_running_status, b_free_ca, i_ev_length);
543 if (!p_event)
544 break;
545
546 /* Event Descriptors */
547 p_byte += 12;
548 uint8_t *p_ev_end = p_byte + i_ev_length;
549 if (p_ev_end > p_section->p_payload_end)
550 p_ev_end = p_section->p_payload_end;
551 while (p_byte < p_ev_end)
552 {
553 uint8_t i_tag = p_byte[0];
554 uint8_t i_length = p_byte[1];
555 if (i_length + 2 <= p_ev_end - p_byte)
556 dvbpsi_eit_event_descriptor_add(p_event, i_tag, i_length, p_byte + 2);
557 p_byte += 2 + i_length;
558 }
559 }
560 p_section = p_section->p_next;
561 }
562 }
563
564 /*****************************************************************************
565 * NewEITSection
566 *****************************************************************************
567 * Helper function which allocates a initializes a new PSI section suitable
568 * for carrying EIT data.
569 *****************************************************************************/
NewEITSection(dvbpsi_eit_t * p_eit,int i_table_id,int i_section_number)570 static dvbpsi_psi_section_t* NewEITSection(dvbpsi_eit_t* p_eit, int i_table_id,
571 int i_section_number)
572 {
573 dvbpsi_psi_section_t *p_result = dvbpsi_NewPSISection(4094);
574
575 p_result->i_table_id = i_table_id;
576 p_result->b_syntax_indicator = 1;
577 p_result->b_private_indicator = 1;
578 p_result->i_length = 15; /* header: 11B + CRC32 */
579
580 p_result->i_extension = p_eit->i_extension;
581 p_result->i_version = p_eit->i_version;
582 p_result->b_current_next = p_eit->b_current_next;
583 p_result->i_number = i_section_number;
584
585 p_result->p_payload_end += 14;
586 p_result->p_payload_start = p_result->p_data + 8;
587
588 /* Transport Stream ID */
589 p_result->p_data[8] = p_eit->i_ts_id >> 8;
590 p_result->p_data[9] = p_eit->i_ts_id;
591
592 /* Original Network ID */
593 p_result->p_data[10] = p_eit->i_network_id >> 8;
594 p_result->p_data[11] = p_eit->i_network_id;
595
596 /* Segment last section number will be filled once we know how many
597 * sections we are going to need. */
598
599 /* Last Table ID */
600 p_result->p_data[13] = p_eit->i_last_table_id;
601
602 return p_result;
603 }
604
605 /*****************************************************************************
606 * EncodeEventHeaders
607 *****************************************************************************
608 * Helper function which encodes an EIT event header in a byte buffer.
609 *****************************************************************************/
EncodeEventHeaders(dvbpsi_eit_event_t * p_event,uint8_t * buf)610 static inline void EncodeEventHeaders(dvbpsi_eit_event_t *p_event, uint8_t *buf)
611 {
612 /* event_id */
613 buf[0] = p_event->i_event_id >> 8;
614 buf[1] = p_event->i_event_id;
615
616 /* start_time */
617 buf[2] = p_event->i_start_time >> 32;
618 buf[3] = p_event->i_start_time >> 24;
619 buf[4] = p_event->i_start_time >> 16;
620 buf[5] = p_event->i_start_time >> 8;
621 buf[6] = p_event->i_start_time;
622
623 /* duration */
624 buf[7] = p_event->i_duration >> 16;
625 buf[8] = p_event->i_duration >> 8;
626 buf[9] = p_event->i_duration;
627
628 /* running_status, free_CA_mode */
629 buf[10] = ((p_event->i_running_status & 0x7) << 5) |
630 ((p_event->b_free_ca & 0x1) << 4);
631
632 /* descriptors_loop_length is encoded later */
633 }
634
635 /*****************************************************************************
636 * dvbpsi_eit_sections_generate
637 *****************************************************************************
638 * Generate EIT sections based on the dvbpsi_eit_t structure.
639 *****************************************************************************/
dvbpsi_eit_sections_generate(dvbpsi_t * p_dvbpsi,dvbpsi_eit_t * p_eit,uint8_t i_table_id)640 dvbpsi_psi_section_t* dvbpsi_eit_sections_generate(dvbpsi_t *p_dvbpsi, dvbpsi_eit_t *p_eit,
641 uint8_t i_table_id)
642 {
643 dvbpsi_psi_section_t *p_result = NewEITSection (p_eit, i_table_id, 0);
644 dvbpsi_psi_section_t *p_current = p_result;
645 uint8_t i_last_section_number = 0;
646 dvbpsi_eit_event_t *p_event;
647
648 if (!p_current)
649 return NULL;
650
651 /* Encode events */
652 for (p_event = p_eit->p_first_event; p_event; p_event = p_event->p_next)
653 {
654 uint8_t *p_event_start = p_current->p_payload_end;
655 uint16_t i_event_length = 12;
656 dvbpsi_descriptor_t *p_descriptor;
657
658 /* Calculate the size of this event and allocate a new PSI section
659 * to contain it if necessary. */
660 for (p_descriptor = p_event->p_first_descriptor;
661 p_descriptor; p_descriptor = p_descriptor->p_next)
662 {
663 i_event_length += p_descriptor->i_length + 2;
664
665 if (p_event_start - p_current->p_data + i_event_length > 4090)
666 {
667 dvbpsi_psi_section_t *p_prev = p_current;
668
669 p_current = NewEITSection (p_eit, i_table_id, ++i_last_section_number);
670 p_event_start = p_current->p_payload_end;
671 p_prev->p_next = p_current;
672
673 break;
674 }
675 }
676
677 EncodeEventHeaders (p_event, p_event_start);
678
679 /* adjust section to indicate the header */
680 p_current->p_payload_end += 12;
681 p_current->i_length += 12;
682
683 /* encode event descriptors */
684 for (p_descriptor = p_event->p_first_descriptor; p_descriptor;
685 p_descriptor = p_descriptor->p_next)
686 {
687 /* check for overflows */
688 if ((p_current->p_payload_end - p_current->p_data) +
689 p_descriptor->i_length > 4090)
690 {
691 dvbpsi_error(p_dvbpsi, "EIT generator", "too many descriptors in event, "
692 "unable to carry all the descriptors");
693 break;
694 }
695
696 /* encode the descriptor */
697 p_current->p_payload_end[0] = p_descriptor->i_tag;
698 p_current->p_payload_end[1] = p_descriptor->i_length;
699 memcpy(p_current->p_payload_end + 2, p_descriptor->p_data, p_descriptor->i_length);
700
701 /* adjust section to reflect new encoded descriptor */
702 p_current->p_payload_end += p_descriptor->i_length + 2;
703 p_current->i_length += p_descriptor->i_length + 2;
704 }
705
706 /* now adjust the descriptors_loop_length */
707 i_event_length = p_current->p_payload_end - p_event_start - 12;
708 p_event_start[10] |= ((i_event_length >> 8) & 0x0f);
709 p_event_start[11] = i_event_length;
710 }
711
712 /* Finalization */
713 for (p_current = p_result; p_current; p_current = p_current->p_next)
714 {
715 /* Segment last section number */
716 p_current->p_data[12] = i_last_section_number;
717 p_current->i_last_number = i_last_section_number;
718
719 dvbpsi_BuildPSISection(p_dvbpsi, p_current);
720 }
721
722 return p_result;
723 }
724