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