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