1 /*****************************************************************************
2  * rst.c: RST decoder/generator
3  *----------------------------------------------------------------------------
4  * Copyright (C) 2012 VideoLAN
5  * $Id:$
6  *
7  * Authors: Corno Roberto <corno.roberto@gmail.com>
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22  *
23  *----------------------------------------------------------------------------
24  *
25  *****************************************************************************/
26 
27 #include "config.h"
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <stdbool.h>
32 #include <string.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 "../descriptor.h"
46 #include "../demux.h"
47 
48 #include "rst.h"
49 #include "rst_private.h"
50 
51 /*****************************************************************************
52  * dvbpsi_rst_attach
53  *****************************************************************************
54  * Initialize a RST decoder and return a handle on it.
55  *****************************************************************************/
dvbpsi_rst_attach(dvbpsi_t * p_dvbpsi,dvbpsi_rst_callback pf_callback,void * p_cb_data)56 bool dvbpsi_rst_attach(dvbpsi_t *p_dvbpsi, dvbpsi_rst_callback pf_callback,
57                       void* p_cb_data)
58 {
59     assert(p_dvbpsi);
60     assert(p_dvbpsi->p_decoder == NULL);
61 
62     dvbpsi_rst_decoder_t* p_rst_decoder;
63     p_rst_decoder = (dvbpsi_rst_decoder_t*) dvbpsi_decoder_new(&dvbpsi_rst_sections_gather,
64                                                 1024, true, sizeof(dvbpsi_rst_decoder_t));
65     if (p_rst_decoder == NULL)
66         return false;
67 
68     /* RST decoder configuration */
69     p_rst_decoder->pf_rst_callback = pf_callback;
70     p_rst_decoder->p_cb_data = p_cb_data;
71     p_rst_decoder->p_building_rst = NULL;
72 
73     p_dvbpsi->p_decoder = DVBPSI_DECODER(p_rst_decoder);
74     return true;
75 }
76 
77 /*****************************************************************************
78  * dvbpsi_rst_detach
79  *****************************************************************************
80  * Close a RST decoder. The handle isn't valid any more.
81  *****************************************************************************/
dvbpsi_rst_detach(dvbpsi_t * p_dvbpsi)82 void dvbpsi_rst_detach(dvbpsi_t *p_dvbpsi)
83 {
84     assert(p_dvbpsi);
85     assert(p_dvbpsi->p_decoder);
86 
87     dvbpsi_rst_decoder_t* p_rst_decoder
88                         = (dvbpsi_rst_decoder_t*)p_dvbpsi->p_decoder;
89     if (p_rst_decoder->p_building_rst)
90         dvbpsi_rst_delete(p_rst_decoder->p_building_rst);
91     p_rst_decoder->p_building_rst = NULL;
92 
93     dvbpsi_decoder_delete(p_dvbpsi->p_decoder);
94     p_dvbpsi->p_decoder = NULL;
95 }
96 
97 /*****************************************************************************
98  * dvbpsi_rst_init
99  *****************************************************************************
100  * Initialize a pre-allocated dvbpsi_rst_t structure.
101  *****************************************************************************/
dvbpsi_rst_init(dvbpsi_rst_t * p_rst)102 void dvbpsi_rst_init(dvbpsi_rst_t* p_rst)
103 {
104     assert(p_rst);
105 
106     p_rst->p_first_event = NULL;
107 }
108 
109 /*****************************************************************************
110  * dvbpsi_rst_new
111  *****************************************************************************
112  * Allocate and Initialize a dvbpsi_rst_t structure.
113  *****************************************************************************/
dvbpsi_rst_new(void)114 dvbpsi_rst_t *dvbpsi_rst_new(void)
115 {
116     dvbpsi_rst_t *p_rst = (dvbpsi_rst_t*)malloc(sizeof(dvbpsi_rst_t));
117     if (p_rst != NULL)
118         dvbpsi_rst_init(p_rst);
119     return p_rst;
120 }
121 
122 /*****************************************************************************
123  * dvbpsi_rst_empty
124  *****************************************************************************
125  * Clean a dvbpsi_rst_t structure.
126  *****************************************************************************/
dvbpsi_rst_empty(dvbpsi_rst_t * p_rst)127 void dvbpsi_rst_empty(dvbpsi_rst_t* p_rst)
128 {
129 	dvbpsi_rst_event_t * p_rst_event = p_rst->p_first_event;
130 
131     while(p_rst_event != NULL)
132     {
133     	dvbpsi_rst_event_t* p_next = p_rst_event->p_next;
134 
135         free(p_rst_event);
136 
137         p_rst_event = p_next;
138     }
139 
140     p_rst->p_first_event = NULL;
141 }
142 
143 /*****************************************************************************
144  * dvbpsi_rst_delete
145  *****************************************************************************
146  * Clean a dvbpsi_rst_t structure.
147  *****************************************************************************/
dvbpsi_rst_delete(dvbpsi_rst_t * p_rst)148 void dvbpsi_rst_delete(dvbpsi_rst_t *p_rst)
149 {
150     if (p_rst)
151         dvbpsi_rst_empty(p_rst);
152     free(p_rst);
153 }
154 
155 /*****************************************************************************
156  * dvbpsi_rst_event_add
157  *****************************************************************************
158  * Add an event in the RST.
159  *****************************************************************************/
160 
dvbpsi_rst_event_add(dvbpsi_rst_t * p_rst,uint16_t i_ts_id,uint16_t i_orig_network_id,uint16_t i_service_id,uint16_t i_event_id,uint8_t i_running_status)161 dvbpsi_rst_event_t* dvbpsi_rst_event_add(dvbpsi_rst_t* p_rst,
162                                             uint16_t i_ts_id,
163                                             uint16_t i_orig_network_id,
164                                             uint16_t i_service_id,
165                                             uint16_t i_event_id,
166                                             uint8_t i_running_status)
167 {
168 	dvbpsi_rst_event_t* p_rst_event
169                         = (dvbpsi_rst_event_t*)malloc(sizeof(dvbpsi_rst_event_t));
170 
171     if (p_rst_event == NULL)
172         return NULL;
173 
174     p_rst_event->i_ts_id = i_ts_id;
175     p_rst_event->i_orig_network_id = i_orig_network_id;
176     p_rst_event->i_service_id = i_service_id;
177     p_rst_event->i_event_id = i_event_id;
178     p_rst_event->i_running_status = i_running_status;
179     p_rst_event->p_next = NULL;
180 
181     if (p_rst->p_first_event == NULL)
182     	p_rst->p_first_event = p_rst_event;
183     else
184     {
185     	dvbpsi_rst_event_t *p_last = p_rst->p_first_event;
186     	while (p_last->p_next != NULL)
187     		p_last = p_last->p_next;
188     	p_last->p_next = p_rst_event;
189     }
190 
191     return p_rst_event;
192 }
193 
194 /*****************************************************************************
195  * dvbpsi_rst_sections_generate
196  *****************************************************************************
197  * Generate RST sections based on the dvbpsi_rst_t structure.
198  *****************************************************************************/
dvbpsi_rst_sections_generate(dvbpsi_t * p_dvbpsi,dvbpsi_rst_t * p_rst)199 dvbpsi_psi_section_t* dvbpsi_rst_sections_generate(dvbpsi_t *p_dvbpsi, dvbpsi_rst_t* p_rst)
200 {
201     dvbpsi_psi_section_t* p_result = dvbpsi_NewPSISection(1024);
202     dvbpsi_psi_section_t* p_current = p_result;
203     dvbpsi_psi_section_t* p_prev;
204     dvbpsi_rst_event_t* p_event = p_rst->p_first_event;
205     int i_count = 0;
206 
207     if (p_current == NULL)
208     {
209         dvbpsi_error(p_dvbpsi, "RST encoder", "failed to allocate new PSI section");
210         return NULL;
211     }
212 
213     p_current->i_table_id = 0x71;
214     p_current->b_syntax_indicator = false;
215     p_current->b_private_indicator = false;
216     p_current->i_length = 3;                      /* header */
217     p_current->i_extension = 0;                   /* Not used in the RST */
218     p_current->i_version = 0;                     /* Not used in the RST */
219     p_current->b_current_next = true;             /* Not used in the RST */
220     p_current->i_number = 0;                      /* Not used in the RST */
221     p_current->p_payload_end += 3;                /* just after the header */
222     p_current->p_payload_start = p_current->p_payload_end;
223 
224     /* RST events */
225     while (p_event != NULL)
226     {
227         /* The section_length shall not exceed 1 021 so that the entire section has a maximum length of 1 024 bytes */
228         if((p_current->p_payload_end - p_current->p_data) < 1021)
229         {
230         	p_current->p_data[0+i_count] = (p_event->i_ts_id >> 8);
231         	p_current->p_data[1+i_count] = (p_event->i_ts_id & 0xFF);
232         	p_current->p_data[2+i_count] = (p_event->i_orig_network_id >> 8);
233         	p_current->p_data[3+i_count] = (p_event->i_orig_network_id & 0xFF);
234         	p_current->p_data[4+i_count] = (p_event->i_service_id >> 8);
235         	p_current->p_data[5+i_count] = (p_event->i_service_id & 0xFF);
236         	p_current->p_data[6+i_count] = (p_event->i_event_id >> 8);
237         	p_current->p_data[7+i_count] = (p_event->i_event_id & 0xFF);
238         	p_current->p_data[8+i_count] = 0xF8 + p_event->i_running_status;
239         	/* Increase length by event_length */
240         	p_current->i_length += 9;
241         	p_current->p_payload_end += 9;
242         }
243         p_event = p_event->p_next;
244         i_count++;
245     }
246 
247     /* Finalization */
248     p_prev = p_result;
249     while (p_prev != NULL)
250     {
251         p_prev->i_last_number = p_current->i_number;
252         dvbpsi_BuildPSISection(p_dvbpsi, p_prev);
253         p_prev = p_prev->p_next;
254     }
255     return p_result;
256 }
257 
258 /* */
dvbpsi_rst_reset(dvbpsi_rst_decoder_t * p_decoder,const bool b_force)259 static void dvbpsi_rst_reset(dvbpsi_rst_decoder_t* p_decoder, const bool b_force)
260 {
261     assert(p_decoder);
262 
263     dvbpsi_decoder_reset(DVBPSI_DECODER(p_decoder), b_force);
264 
265     /* Force redecoding */
266     if (b_force)
267     {
268         /* Free structures */
269         if (p_decoder->p_building_rst)
270             dvbpsi_rst_delete(p_decoder->p_building_rst);
271     }
272     p_decoder->p_building_rst = NULL;
273 }
274 
dvbpsi_rst_section_add(dvbpsi_t * p_dvbpsi,dvbpsi_rst_decoder_t * p_decoder,dvbpsi_psi_section_t * p_section)275 static bool dvbpsi_rst_section_add(dvbpsi_t *p_dvbpsi, dvbpsi_rst_decoder_t *p_decoder,
276                                  dvbpsi_psi_section_t* p_section)
277 {
278     assert(p_dvbpsi);
279     assert(p_decoder);
280     assert(p_section);
281 
282     /* Initialize the structures if it's the first section received */
283     if (p_decoder->p_building_rst == NULL)
284     {
285         p_decoder->p_building_rst = dvbpsi_rst_new();
286         if (p_decoder->p_building_rst == NULL)
287             return false;
288 
289         p_decoder->i_last_section_number = p_section->i_last_number;
290     }
291 
292     /* Add to linked list of sections */
293     if (dvbpsi_decoder_psi_section_add(DVBPSI_DECODER(p_decoder), p_section))
294         dvbpsi_debug(p_dvbpsi, "RST decoder", "overwrite section number %d",
295                      p_section->i_number);
296 
297     return true;
298 }
299 
300 /*****************************************************************************
301  * dvbpsi_rst_section_check
302  *****************************************************************************
303  * Check if RST section has the expected table_id and it the syntax indicator
304  * is set to 0 according to ETSI EN 300 468 §5.2.7.
305  *****************************************************************************/
dvbpsi_rst_section_check(dvbpsi_t * p_dvbpsi,dvbpsi_psi_section_t * p_section,const uint8_t table_id,const char * psz_table_name)306 static bool dvbpsi_rst_section_check(dvbpsi_t *p_dvbpsi, dvbpsi_psi_section_t *p_section,
307                             const uint8_t table_id, const char *psz_table_name)
308 {
309     assert(p_dvbpsi);
310     assert(p_section);
311 
312     if (p_section->i_table_id != table_id)
313     {
314         /* Invalid table_id value */
315         dvbpsi_error(p_dvbpsi, psz_table_name,
316                      "invalid section (table_id == 0x%02x expected 0x%02)",
317                      p_section->i_table_id, table_id);
318         goto error;
319     }
320 
321     if (p_section->b_syntax_indicator)
322     {
323         /* Invalid section_syntax_indicator */
324         dvbpsi_error(p_dvbpsi, psz_table_name,
325                      "invalid section (section_syntax_indicator != 0)");
326         goto error;
327     }
328 
329     dvbpsi_debug(p_dvbpsi, psz_table_name,
330                    "Table version %2d, " "i_extension %5d, "
331                    "section %3d up to %3d, " "current %1d",
332                    p_section->i_version, p_section->i_extension,
333                    p_section->i_number, p_section->i_last_number,
334                    p_section->b_current_next);
335     return true;
336 
337 error:
338     return false;
339 }
340 
341 /*****************************************************************************
342  * dvbpsi_rst_sections_gather
343  *****************************************************************************
344  * Callback for the PSI decoder.
345  *****************************************************************************/
dvbpsi_rst_sections_gather(dvbpsi_t * p_dvbpsi,dvbpsi_psi_section_t * p_section)346 void dvbpsi_rst_sections_gather(dvbpsi_t *p_dvbpsi,
347                               dvbpsi_psi_section_t* p_section)
348 {
349     assert(p_dvbpsi);
350     assert(p_dvbpsi->p_decoder);
351 
352     if (!dvbpsi_rst_section_check(p_dvbpsi, p_section, 0x71, "RST decoder"))
353     {
354         dvbpsi_DeletePSISections(p_section);
355         return;
356     }
357 
358     /* */
359     dvbpsi_rst_decoder_t* p_rst_decoder
360                           = (dvbpsi_rst_decoder_t*)p_dvbpsi->p_decoder;
361 
362     /* TS discontinuity check */
363     if (p_rst_decoder->b_discontinuity)
364     {
365     	dvbpsi_rst_reset(p_rst_decoder, true);
366         p_rst_decoder->b_discontinuity = false;
367     }
368 
369     /* Add section to RST */
370     if (!dvbpsi_rst_section_add(p_dvbpsi, p_rst_decoder, p_section))
371     {
372         dvbpsi_error(p_dvbpsi, "RST decoder", "failed decoding section %d",
373                      p_section->i_number);
374         dvbpsi_DeletePSISections(p_section);
375         return;
376     }
377 
378     /* Check if we have all the sections */
379     if (dvbpsi_decoder_psi_sections_completed(DVBPSI_DECODER(p_rst_decoder)))
380     {
381         assert(p_rst_decoder->pf_rst_callback);
382 
383         /* Save the current information */
384         p_rst_decoder->current_rst = *p_rst_decoder->p_building_rst;
385         p_rst_decoder->b_current_valid = true;
386         /* Decode the sections */
387         dvbpsi_rst_sections_decode(p_rst_decoder->p_building_rst,
388                                    p_rst_decoder->p_sections);
389         /* signal the new CAT */
390         p_rst_decoder->pf_rst_callback(p_rst_decoder->p_cb_data,
391                                        p_rst_decoder->p_building_rst);
392         /* Delete sectioins and Reinitialize the structures */
393         dvbpsi_rst_reset(p_rst_decoder, false);
394         assert(p_rst_decoder->p_sections == NULL);
395     }
396 }
397 
398 /*****************************************************************************
399  * dvbpsi_rst_sections_decode
400  *****************************************************************************
401  * RST decoder.
402  *****************************************************************************/
dvbpsi_rst_sections_decode(dvbpsi_rst_t * p_rst,dvbpsi_psi_section_t * p_section)403 void dvbpsi_rst_sections_decode(dvbpsi_rst_t* p_rst,
404                               dvbpsi_psi_section_t* p_section)
405 {
406     uint8_t* p_byte;
407 
408     while (p_section)
409     {
410         /* RST events */
411         p_byte = p_section->p_payload_start;
412         while (p_byte + 9 <= p_section->p_payload_end)
413         {
414             uint16_t i_transport_stream_id = (p_byte[0] << 8) + p_byte[1];
415             uint16_t i_original_network_id = (p_byte[2] << 8) + p_byte[3];
416             uint16_t i_service_id = (p_byte[4] << 8) + p_byte[5];
417             uint16_t i_event_id = (p_byte[6] << 8) + p_byte[7];
418             uint8_t i_running_status = (p_byte[8] & 0x07);
419 
420             dvbpsi_rst_event_add(p_rst, i_transport_stream_id, i_original_network_id, i_service_id, i_event_id, i_running_status);
421             p_byte += 9;
422         }
423         p_section = p_section->p_next;
424     }
425 }
426