1 /*****************************************************************************
2  * pat.c: PAT decoder/generator
3  *----------------------------------------------------------------------------
4  * Copyright (C) 2001-2012 VideoLAN
5  * $Id$
6  *
7  * Authors: Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr>
8  *          Jean-Paul Saman <jpsaman@videolan.org>
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
23  *
24  *----------------------------------------------------------------------------
25  *
26  *****************************************************************************/
27 
28 #include "config.h"
29 
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <stdbool.h>
33 
34 #if defined(HAVE_INTTYPES_H)
35 #include <inttypes.h>
36 #elif defined(HAVE_STDINT_H)
37 #include <stdint.h>
38 #endif
39 
40 #include <assert.h>
41 
42 #include "../dvbpsi.h"
43 #include "../dvbpsi_private.h"
44 #include "../psi.h"
45 #include "pat.h"
46 #include "pat_private.h"
47 
48 /*****************************************************************************
49  * dvbpsi_pat_attach
50  *****************************************************************************
51  * Initialize a PAT decoder and return a handle on it.
52  *****************************************************************************/
dvbpsi_pat_attach(dvbpsi_t * p_dvbpsi,dvbpsi_pat_callback pf_callback,void * p_cb_data)53 bool dvbpsi_pat_attach(dvbpsi_t *p_dvbpsi, dvbpsi_pat_callback pf_callback,
54                       void* p_cb_data)
55 {
56     assert(p_dvbpsi);
57     assert(p_dvbpsi->p_decoder == NULL);
58 
59     /* PSI decoder configuration and initial state */
60     dvbpsi_pat_decoder_t *p_pat_decoder;
61     p_pat_decoder = (dvbpsi_pat_decoder_t*) dvbpsi_decoder_new(&dvbpsi_pat_sections_gather,
62                                                 1024, true, sizeof(dvbpsi_pat_decoder_t));
63     if (p_pat_decoder == NULL)
64         return false;
65 
66     /* PAT decoder information */
67     p_pat_decoder->pf_pat_callback = pf_callback;
68     p_pat_decoder->p_cb_data = p_cb_data;
69     p_pat_decoder->p_building_pat = NULL;
70 
71     p_dvbpsi->p_decoder = DVBPSI_DECODER(p_pat_decoder);
72     return true;
73 }
74 
75 /*****************************************************************************
76  * dvbpsi_pat_detach
77  *****************************************************************************
78  * Close a PAT decoder. The handle isn't valid any more.
79  *****************************************************************************/
dvbpsi_pat_detach(dvbpsi_t * p_dvbpsi)80 void dvbpsi_pat_detach(dvbpsi_t *p_dvbpsi)
81 {
82     assert(p_dvbpsi);
83     assert(p_dvbpsi->p_decoder);
84 
85     dvbpsi_pat_decoder_t* p_pat_decoder = (dvbpsi_pat_decoder_t*)p_dvbpsi->p_decoder;
86     if (p_pat_decoder->p_building_pat)
87         dvbpsi_pat_delete(p_pat_decoder->p_building_pat);
88     p_pat_decoder->p_building_pat = NULL;
89 
90     dvbpsi_decoder_delete(p_dvbpsi->p_decoder);
91     p_dvbpsi->p_decoder = NULL;
92 }
93 
94 /*****************************************************************************
95  * dvbpsi_pat_init
96  *****************************************************************************
97  * Initialize a pre-allocated dvbpsi_pat_t structure.
98  *****************************************************************************/
dvbpsi_pat_init(dvbpsi_pat_t * p_pat,uint16_t i_ts_id,uint8_t i_version,bool b_current_next)99 void dvbpsi_pat_init(dvbpsi_pat_t* p_pat, uint16_t i_ts_id, uint8_t i_version,
100                     bool b_current_next)
101 {
102     assert(p_pat);
103 
104     p_pat->i_ts_id = i_ts_id;
105     p_pat->i_version = i_version;
106     p_pat->b_current_next = b_current_next;
107     p_pat->p_first_program = NULL;
108 }
109 
110 /*****************************************************************************
111  * dvbpsi_pat_new
112  *****************************************************************************
113  * Allocate and Initialize a newly allocated dvbpsi_pat_t structure.
114  *****************************************************************************/
dvbpsi_pat_new(uint16_t i_ts_id,uint8_t i_version,bool b_current_next)115 dvbpsi_pat_t *dvbpsi_pat_new(uint16_t i_ts_id, uint8_t i_version,
116                             bool b_current_next)
117 {
118     dvbpsi_pat_t *p_pat = (dvbpsi_pat_t*)malloc(sizeof(dvbpsi_pat_t));
119     if (p_pat)
120         dvbpsi_pat_init(p_pat, i_ts_id, i_version, b_current_next);
121     return p_pat;
122 }
123 
124 /*****************************************************************************
125  * dvbpsi_pat_empty
126  *****************************************************************************
127  * Clean a dvbpsi_pat_t structure.
128  *****************************************************************************/
dvbpsi_pat_empty(dvbpsi_pat_t * p_pat)129 void dvbpsi_pat_empty(dvbpsi_pat_t* p_pat)
130 {
131     dvbpsi_pat_program_t* p_program = p_pat->p_first_program;
132 
133     while(p_program != NULL)
134     {
135         dvbpsi_pat_program_t* p_tmp = p_program->p_next;
136         free(p_program);
137         p_program = p_tmp;
138     }
139     p_pat->p_first_program = NULL;
140 }
141 
142 /*****************************************************************************
143  * dvbpsi_pat_delete
144  *****************************************************************************
145  * Clean and Delete dvbpsi_pat_t structure.
146  *****************************************************************************/
dvbpsi_pat_delete(dvbpsi_pat_t * p_pat)147 void dvbpsi_pat_delete(dvbpsi_pat_t *p_pat)
148 {
149     if (p_pat)
150         dvbpsi_pat_empty(p_pat);
151     free(p_pat);
152 }
153 
154 /*****************************************************************************
155  * dvbpsi_pat_program_add
156  *****************************************************************************
157  * Add a program at the end of the PAT.
158  *****************************************************************************/
dvbpsi_pat_program_add(dvbpsi_pat_t * p_pat,uint16_t i_number,uint16_t i_pid)159 dvbpsi_pat_program_t* dvbpsi_pat_program_add(dvbpsi_pat_t* p_pat,
160                                              uint16_t i_number, uint16_t i_pid)
161 {
162     dvbpsi_pat_program_t* p_program;
163 
164     /* PID = 0 is invalid for programs
165      * FIXME: check for other fixed PIDs too. */
166     if (i_pid == 0)
167         return NULL;
168 
169     p_program = (dvbpsi_pat_program_t*) malloc(sizeof(dvbpsi_pat_program_t));
170     if (p_program == NULL)
171         return NULL;
172 
173     p_program->i_number = i_number;
174     p_program->i_pid = i_pid;
175     p_program->p_next = NULL;
176 
177     if (p_pat->p_first_program == NULL)
178         p_pat->p_first_program = p_program;
179     else
180     {
181         dvbpsi_pat_program_t* p_last_program = p_pat->p_first_program;
182         while (p_last_program->p_next != NULL)
183             p_last_program = p_last_program->p_next;
184         p_last_program->p_next = p_program;
185     }
186 
187     return p_program;
188 }
189 
190 /* */
dvbpsi_ReInitPAT(dvbpsi_pat_decoder_t * p_decoder,const bool b_force)191 static void dvbpsi_ReInitPAT(dvbpsi_pat_decoder_t* p_decoder, const bool b_force)
192 {
193     assert(p_decoder);
194 
195     dvbpsi_decoder_reset(DVBPSI_DECODER(p_decoder), b_force);
196 
197     /* Force redecoding */
198     if (b_force)
199     {
200         /* Free structures */
201         if (p_decoder->p_building_pat)
202             dvbpsi_pat_delete(p_decoder->p_building_pat);
203     }
204     p_decoder->p_building_pat = NULL;
205 }
206 
dvbpsi_CheckPAT(dvbpsi_t * p_dvbpsi,dvbpsi_psi_section_t * p_section)207 static bool dvbpsi_CheckPAT(dvbpsi_t *p_dvbpsi, dvbpsi_psi_section_t *p_section)
208 {
209     bool b_reinit = false;
210     assert(p_dvbpsi->p_decoder);
211 
212     dvbpsi_pat_decoder_t* p_pat_decoder;
213     p_pat_decoder = (dvbpsi_pat_decoder_t *)p_dvbpsi->p_decoder;
214 
215     /* Perform a few sanity checks */
216     if (p_pat_decoder->p_building_pat->i_ts_id != p_section->i_extension)
217     {
218         /* transport_stream_id */
219         dvbpsi_error(p_dvbpsi, "PAT decoder",
220                         "'transport_stream_id' differs"
221                         " whereas no TS discontinuity has occured");
222         b_reinit = true;
223     }
224     else if (p_pat_decoder->p_building_pat->i_version != p_section->i_version)
225     {
226         /* version_number */
227         dvbpsi_error(p_dvbpsi, "PAT decoder",
228                         "'version_number' differs"
229                         " whereas no discontinuity has occured");
230         b_reinit = true;
231     }
232     else if (p_pat_decoder->i_last_section_number != p_section->i_last_number)
233     {
234         /* last_section_number */
235         dvbpsi_error(p_dvbpsi, "PAT decoder",
236                         "'last_section_number' differs"
237                         " whereas no discontinuity has occured");
238         b_reinit = true;
239     }
240 
241     return b_reinit;
242 }
243 
dvbpsi_AddSectionPAT(dvbpsi_t * p_dvbpsi,dvbpsi_pat_decoder_t * p_pat_decoder,dvbpsi_psi_section_t * p_section)244 static bool dvbpsi_AddSectionPAT(dvbpsi_t *p_dvbpsi, dvbpsi_pat_decoder_t *p_pat_decoder,
245                                  dvbpsi_psi_section_t* p_section)
246 {
247     assert(p_dvbpsi);
248     assert(p_pat_decoder);
249     assert(p_section);
250 
251     /* Initialize the structures if it's the first section received */
252     if (p_pat_decoder->p_building_pat == NULL)
253     {
254         p_pat_decoder->p_building_pat = dvbpsi_pat_new(p_section->i_extension,
255                               p_section->i_version, p_section->b_current_next);
256         if (p_pat_decoder->p_building_pat == NULL)
257             return false;
258 
259         p_pat_decoder->i_last_section_number = p_section->i_last_number;
260     }
261 
262     /* Add to linked list of sections */
263     if (dvbpsi_decoder_psi_section_add(DVBPSI_DECODER(p_pat_decoder), p_section))
264         dvbpsi_debug(p_dvbpsi, "PAT decoder", "overwrite section number %d",
265                      p_section->i_number);
266     return true;
267 }
268 
269 /*****************************************************************************
270  * dvbpsi_pat_sections_gather
271  *****************************************************************************
272  * Callback for the PSI decoder.
273  *****************************************************************************/
dvbpsi_pat_sections_gather(dvbpsi_t * p_dvbpsi,dvbpsi_psi_section_t * p_section)274 void dvbpsi_pat_sections_gather(dvbpsi_t* p_dvbpsi, dvbpsi_psi_section_t* p_section)
275 {
276     dvbpsi_pat_decoder_t* p_pat_decoder;
277 
278     assert(p_dvbpsi);
279     assert(p_dvbpsi->p_decoder);
280 
281     if (!dvbpsi_CheckPSISection(p_dvbpsi, p_section, 0x00, "PAT decoder"))
282     {
283         dvbpsi_DeletePSISections(p_section);
284         return;
285     }
286 
287     /* Now we have a valid PAT section */
288     p_pat_decoder = (dvbpsi_pat_decoder_t *)p_dvbpsi->p_decoder;
289 
290     /* TS discontinuity check */
291     if (p_pat_decoder->b_discontinuity)
292     {
293         dvbpsi_ReInitPAT(p_pat_decoder, true);
294         p_pat_decoder->b_discontinuity = false;
295     }
296     else
297     {
298         if (p_pat_decoder->p_building_pat)
299         {
300             if (dvbpsi_CheckPAT(p_dvbpsi, p_section))
301                 dvbpsi_ReInitPAT(p_pat_decoder, true);
302         }
303         else
304         {
305             if(    (p_pat_decoder->b_current_valid)
306                 && (p_pat_decoder->current_pat.i_version == p_section->i_version)
307                 && (p_pat_decoder->current_pat.b_current_next ==
308                                                p_section->b_current_next))
309             {
310                 /* Don't decode since this version is already decoded */
311                 dvbpsi_debug(p_dvbpsi, "PAT decoder",
312                              "ignoring already decoded section %d",
313                              p_section->i_number);
314                 dvbpsi_DeletePSISections(p_section);
315                 return;
316             }
317         }
318     }
319 
320     /* Add section to PAT */
321     if (!dvbpsi_AddSectionPAT(p_dvbpsi, p_pat_decoder, p_section))
322     {
323         dvbpsi_error(p_dvbpsi, "PAT decoder", "failed decoding section %d",
324                      p_section->i_number);
325         dvbpsi_DeletePSISections(p_section);
326         return;
327     }
328 
329     /* Check if we have all the sections */
330     if (dvbpsi_decoder_psi_sections_completed(DVBPSI_DECODER(p_pat_decoder)))
331     {
332         assert(p_pat_decoder->pf_pat_callback);
333 
334         /* Save the current information */
335         p_pat_decoder->current_pat = *p_pat_decoder->p_building_pat;
336 
337         /* Decode the sections */
338         if (dvbpsi_pat_sections_decode(p_pat_decoder->p_building_pat,
339                                        p_pat_decoder->p_sections))
340             p_pat_decoder->b_current_valid = true;
341 
342         /* signal the new PAT */
343         if (p_pat_decoder->b_current_valid)
344             p_pat_decoder->pf_pat_callback(p_pat_decoder->p_cb_data,
345                                            p_pat_decoder->p_building_pat);
346 
347         /* Delete sectioins and Reinitialize the structures */
348         dvbpsi_ReInitPAT(p_pat_decoder, !p_pat_decoder->b_current_valid);
349         assert(p_pat_decoder->p_sections == NULL);
350     }
351 }
352 
353 /*****************************************************************************
354  * dvbpsi_DecodePATSection
355  *****************************************************************************
356  * Decode sections into a PAT table. The function returns 'true' on success,
357  * 'false' otherwise.
358  *****************************************************************************/
dvbpsi_pat_sections_decode(dvbpsi_pat_t * p_pat,dvbpsi_psi_section_t * p_section)359 bool dvbpsi_pat_sections_decode(dvbpsi_pat_t* p_pat, dvbpsi_psi_section_t* p_section)
360 {
361     bool b_valid = false;
362     while (p_section)
363     {
364         for (uint8_t *p_byte = p_section->p_payload_start;
365             p_byte < p_section->p_payload_end;
366             p_byte += 4)
367         {
368             uint16_t i_program_number = ((uint16_t)(p_byte[0]) << 8) | p_byte[1];
369             uint16_t i_pid = ((uint16_t)(p_byte[2] & 0x1f) << 8) | p_byte[3];
370             dvbpsi_pat_program_t* p_program = dvbpsi_pat_program_add(p_pat, i_program_number, i_pid);
371             if (p_program)
372                 b_valid = true;
373         }
374 
375         p_section = p_section->p_next;
376     }
377     return b_valid;
378 }
379 
380 /*****************************************************************************
381  * dvbpsi_pat_sections_generate
382  *****************************************************************************
383  * Generate PAT sections based on the dvbpsi_pat_t structure. The third
384  * argument is used to limit the number of program in each section (max: 253).
385  *****************************************************************************/
dvbpsi_pat_sections_generate(dvbpsi_t * p_dvbpsi,dvbpsi_pat_t * p_pat,int i_max_pps)386 dvbpsi_psi_section_t* dvbpsi_pat_sections_generate(dvbpsi_t *p_dvbpsi,
387                                             dvbpsi_pat_t* p_pat, int i_max_pps)
388 {
389     dvbpsi_psi_section_t* p_result = dvbpsi_NewPSISection(1024);
390     dvbpsi_psi_section_t* p_current = p_result;
391     dvbpsi_psi_section_t* p_prev;
392     dvbpsi_pat_program_t* p_program = p_pat->p_first_program;
393     int i_count = 0;
394 
395     if (p_current == NULL)
396     {
397         dvbpsi_error(p_dvbpsi, "PAT encoder", "failed to allocate new PSI section");
398         return NULL;
399     }
400 
401     /* A PAT section can carry up to 253 programs */
402     if((i_max_pps <= 0) || (i_max_pps > 253))
403         i_max_pps = 253;
404 
405     p_current->i_table_id = 0;
406     p_current->b_syntax_indicator = true;
407     p_current->b_private_indicator = false;
408     p_current->i_length = 9;                      /* header + CRC_32 */
409     p_current->i_extension = p_pat->i_ts_id;
410     p_current->i_version = p_pat->i_version;
411     p_current->b_current_next = p_pat->b_current_next;
412     p_current->i_number = 0;
413     p_current->p_payload_end += 8;                /* just after the header */
414     p_current->p_payload_start = p_current->p_payload_end;
415 
416     /* PAT programs */
417     while (p_program != NULL)
418     {
419         /* New section if needed */
420         if (++i_count > i_max_pps)
421         {
422             p_prev = p_current;
423             p_current = dvbpsi_NewPSISection(1024);
424             if (p_current ==  NULL)
425             {
426                 dvbpsi_error(p_dvbpsi, "PAT encoder", "failed to allocate new PSI section");
427                 goto error;
428             }
429             p_prev->p_next = p_current;
430             i_count = 1;
431 
432             p_current->i_table_id = 0;
433             p_current->b_syntax_indicator = true;
434             p_current->b_private_indicator = false;
435             p_current->i_length = 9;                  /* header + CRC_32 */
436             p_current->i_extension = p_pat->i_ts_id;
437             p_current->i_version = p_pat->i_version;
438             p_current->b_current_next = p_pat->b_current_next;
439             p_current->i_number = p_prev->i_number + 1;
440             p_current->p_payload_end += 8;            /* just after the header */
441             p_current->p_payload_start = p_current->p_payload_end;
442         }
443 
444         /* p_payload_end is where the program begins */
445         p_current->p_payload_end[0] = p_program->i_number >> 8;
446         p_current->p_payload_end[1] = p_program->i_number;
447         p_current->p_payload_end[2] = (p_program->i_pid >> 8) | 0xe0;
448         p_current->p_payload_end[3] = p_program->i_pid;
449 
450         /* Increase length by 4 */
451         p_current->p_payload_end += 4;
452         p_current->i_length += 4;
453 
454         p_program = p_program->p_next;
455     }
456 
457     /* Finalization */
458     p_prev = p_result;
459     while (p_prev != NULL)
460     {
461         p_prev->i_last_number = p_current->i_number;
462         dvbpsi_BuildPSISection(p_dvbpsi, p_prev);
463         p_prev = p_prev->p_next;
464     }
465 
466     return p_result;
467 
468 error:
469     /* Cleanup on error */
470     p_prev = p_result;
471     dvbpsi_DeletePSISections(p_prev);
472     return NULL;
473 }
474