File: | demux.c |
Location: | line 948, column 28 |
Description: | Call to 'malloc' has an allocation size of 0 bytes |
1 | /***************************************************************************** | |||
2 | * demux.c | |||
3 | ***************************************************************************** | |||
4 | * Copyright (C) 2004, 2008-2011 VideoLAN | |||
5 | * | |||
6 | * Authors: Christophe Massiot <massiot@via.ecp.fr> | |||
7 | * Andy Gatward <a.j.gatward@reading.ac.uk> | |||
8 | * Marian Ďurkovič <md@bts.sk> | |||
9 | * | |||
10 | * This program is free software; you can redistribute it and/or modify | |||
11 | * it under the terms of the GNU General Public License as published by | |||
12 | * the Free Software Foundation; either version 2 of the License, or | |||
13 | * (at your option) any later version. | |||
14 | * | |||
15 | * This program 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 | |||
18 | * GNU General Public License for more details. | |||
19 | * | |||
20 | * You should have received a copy of the GNU General Public License | |||
21 | * along with this program; if not, write to the Free Software | |||
22 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. | |||
23 | *****************************************************************************/ | |||
24 | ||||
25 | #include <stdlib.h> | |||
26 | #include <stdio.h> | |||
27 | #include <stdint.h> | |||
28 | #include <stdbool.h> | |||
29 | #include <stddef.h> | |||
30 | #include <string.h> | |||
31 | #include <stdarg.h> | |||
32 | #include <inttypes.h> | |||
33 | #include <sys/socket.h> | |||
34 | #include <netinet/in.h> | |||
35 | #include <arpa/inet.h> | |||
36 | ||||
37 | #include "dvblast.h" | |||
38 | #include "en50221.h" | |||
39 | ||||
40 | #ifdef HAVE_ICONV | |||
41 | #include <iconv.h> | |||
42 | #endif | |||
43 | ||||
44 | #include <bitstream/mpeg/ts.h> | |||
45 | #include <bitstream/mpeg/pes.h> | |||
46 | #include <bitstream/mpeg/psi.h> | |||
47 | #include <bitstream/dvb/si.h> | |||
48 | #include <bitstream/dvb/si_print.h> | |||
49 | #include <bitstream/mpeg/psi_print.h> | |||
50 | ||||
51 | extern bool_Bool b_enable_emm; | |||
52 | extern bool_Bool b_enable_ecm; | |||
53 | ||||
54 | /***************************************************************************** | |||
55 | * Local declarations | |||
56 | *****************************************************************************/ | |||
57 | #define MIN_SECTION_FRAGMENT8 PSI_HEADER_SIZE_SYNTAX18 | |||
58 | ||||
59 | typedef struct ts_pid_t | |||
60 | { | |||
61 | int i_refcount; | |||
62 | int i_psi_refcount; | |||
63 | bool_Bool b_pes; | |||
64 | int8_t i_last_cc; | |||
65 | int i_demux_fd; | |||
66 | /* b_emm is set to true when PID carries EMM packet | |||
67 | and should be outputed in all services */ | |||
68 | bool_Bool b_emm; | |||
69 | ||||
70 | /* PID info and stats */ | |||
71 | mtime_t i_bytes_ts; | |||
72 | unsigned long i_packets_passed; | |||
73 | ts_pid_info_t info; | |||
74 | ||||
75 | /* biTStream PSI section gathering */ | |||
76 | uint8_t *p_psi_buffer; | |||
77 | uint16_t i_psi_buffer_used; | |||
78 | ||||
79 | output_t **pp_outputs; | |||
80 | int i_nb_outputs; | |||
81 | } ts_pid_t; | |||
82 | ||||
83 | typedef struct sid_t | |||
84 | { | |||
85 | uint16_t i_sid, i_pmt_pid; | |||
86 | uint8_t *p_current_pmt; | |||
87 | } sid_t; | |||
88 | ||||
89 | ts_pid_t p_pids[MAX_PIDS8192]; | |||
90 | static sid_t **pp_sids = NULL((void*)0); | |||
91 | static int i_nb_sids = 0; | |||
92 | ||||
93 | static PSI_TABLE_DECLARE(pp_current_pat_sections)uint8_t *pp_current_pat_sections[256]; | |||
94 | static PSI_TABLE_DECLARE(pp_next_pat_sections)uint8_t *pp_next_pat_sections[256]; | |||
95 | static PSI_TABLE_DECLARE(pp_current_cat_sections)uint8_t *pp_current_cat_sections[256]; | |||
96 | static PSI_TABLE_DECLARE(pp_next_cat_sections)uint8_t *pp_next_cat_sections[256]; | |||
97 | static PSI_TABLE_DECLARE(pp_current_nit_sections)uint8_t *pp_current_nit_sections[256]; | |||
98 | static PSI_TABLE_DECLARE(pp_next_nit_sections)uint8_t *pp_next_nit_sections[256]; | |||
99 | static PSI_TABLE_DECLARE(pp_current_sdt_sections)uint8_t *pp_current_sdt_sections[256]; | |||
100 | static PSI_TABLE_DECLARE(pp_next_sdt_sections)uint8_t *pp_next_sdt_sections[256]; | |||
101 | static mtime_t i_last_dts = -1; | |||
102 | static int i_demux_fd; | |||
103 | static int i_nb_errors = 0; | |||
104 | static mtime_t i_last_error = 0; | |||
105 | static mtime_t i_last_reset = 0; | |||
106 | ||||
107 | #ifdef HAVE_ICONV | |||
108 | static iconv_t iconv_handle = (iconv_t)-1; | |||
109 | #endif | |||
110 | ||||
111 | /***************************************************************************** | |||
112 | * Local prototypes | |||
113 | *****************************************************************************/ | |||
114 | static void demux_Handle( block_t *p_ts ); | |||
115 | static void SetDTS( block_t *p_list ); | |||
116 | static void SetPID( uint16_t i_pid ); | |||
117 | static void SetPID_EMM( uint16_t i_pid ); | |||
118 | static void UnsetPID( uint16_t i_pid ); | |||
119 | static void StartPID( output_t *p_output, uint16_t i_pid ); | |||
120 | static void StopPID( output_t *p_output, uint16_t i_pid ); | |||
121 | static void SelectPID( uint16_t i_sid, uint16_t i_pid ); | |||
122 | static void UnselectPID( uint16_t i_sid, uint16_t i_pid ); | |||
123 | static void SelectPMT( uint16_t i_sid, uint16_t i_pid ); | |||
124 | static void UnselectPMT( uint16_t i_sid, uint16_t i_pid ); | |||
125 | static void GetPIDS( uint16_t **ppi_wanted_pids, int *pi_nb_wanted_pids, | |||
126 | uint16_t i_sid, | |||
127 | const uint16_t *pi_pids, int i_nb_pids ); | |||
128 | static bool_Bool SIDIsSelected( uint16_t i_sid ); | |||
129 | static bool_Bool PIDWouldBeSelected( uint8_t *p_es ); | |||
130 | static bool_Bool PMTNeedsDescrambling( uint8_t *p_pmt ); | |||
131 | static void FlushEIT( output_t *p_output, mtime_t i_dts ); | |||
132 | static void SendTDT( block_t *p_ts ); | |||
133 | static void SendEMM( block_t *p_ts ); | |||
134 | static void NewPAT( output_t *p_output ); | |||
135 | static void NewPMT( output_t *p_output ); | |||
136 | static void NewNIT( output_t *p_output ); | |||
137 | static void NewSDT( output_t *p_output ); | |||
138 | static void HandlePSIPacket( uint8_t *p_ts, mtime_t i_dts ); | |||
139 | static const char *get_pid_desc(uint16_t i_pid, uint16_t *i_sid); | |||
140 | ||||
141 | /* | |||
142 | * Remap an ES pid to a fixed value. | |||
143 | * Multiple streams of the same type use sequential pids | |||
144 | * Returns the new pid and updates the map tables | |||
145 | */ | |||
146 | static uint16_t map_es_pid(output_t * p_output, uint8_t *p_es, uint16_t i_pid) | |||
147 | { | |||
148 | uint16_t i_newpid = i_pid; | |||
149 | uint16_t i_stream_type = pmtn_get_streamtype(p_es); | |||
150 | ||||
151 | if ( !b_do_remap && !p_output->config.b_do_remap ) | |||
152 | return i_pid; | |||
153 | ||||
154 | msg_Dbg(NULL((void*)0), "REMAP: Found elementary stream type 0x%02x with original PID 0x%x (%u):", i_stream_type, i_pid, i_pid); | |||
155 | ||||
156 | switch ( i_stream_type ) | |||
157 | { | |||
158 | case 0x03: /* audio MPEG-1 */ | |||
159 | case 0x04: /* audio */ | |||
160 | case 0x0f: /* audio AAC ADTS */ | |||
161 | case 0x11: /* audio AAC LATM */ | |||
162 | case 0x81: /* ATSC AC-3 */ | |||
163 | case 0x87: /* ATSC Enhanced AC-3 */ | |||
164 | if ( b_do_remap ) | |||
165 | i_newpid = pi_newpids[I_APID]; | |||
166 | else | |||
167 | i_newpid = p_output->config.pi_confpids[I_APID]; | |||
168 | break; | |||
169 | case 0x01: /* video MPEG-1 */ | |||
170 | case 0x02: /* video */ | |||
171 | case 0x10: /* video MPEG-4 */ | |||
172 | case 0x1b: /* video H264 */ | |||
173 | if ( b_do_remap ) | |||
174 | i_newpid = pi_newpids[I_VPID]; | |||
175 | else | |||
176 | i_newpid = p_output->config.pi_confpids[I_VPID]; | |||
177 | break; | |||
178 | case 0x06: { /* PES Private Data - We must check the descriptors */ | |||
179 | /* By default, nothing identified */ | |||
180 | uint8_t SubStreamType = N_MAP_PIDS4; | |||
181 | uint16_t j = 0; | |||
182 | const uint8_t *p_desc; | |||
183 | /* Loop over the descriptors */ | |||
184 | while ( (p_desc = descs_get_desc( pmtn_get_descs( p_es ), j )) != NULL((void*)0) ) | |||
185 | { | |||
186 | /* Get the descriptor tag */ | |||
187 | uint8_t i_tag = desc_get_tag( p_desc ); | |||
188 | j++; | |||
189 | /* Check if the tag is: A/52, Enhanced A/52, DTS, AAC */ | |||
190 | if (i_tag == 0x6a || i_tag == 0x7a || i_tag == 0x7b || i_tag == 0x7c) | |||
191 | SubStreamType=I_APID; | |||
192 | /* Check if the tag is: VBI + teletext, teletext, dvbsub */ | |||
193 | if (i_tag == 0x46 || i_tag == 0x56 || i_tag == 0x59) | |||
194 | SubStreamType=I_SPUPID; | |||
195 | } | |||
196 | /* Audio found */ | |||
197 | if (SubStreamType==I_APID) { | |||
198 | msg_Dbg(NULL((void*)0), "REMAP: PES Private Data stream identified as [Audio]"); | |||
199 | if ( b_do_remap ) | |||
200 | i_newpid = pi_newpids[I_APID]; | |||
201 | else | |||
202 | i_newpid = p_output->config.pi_confpids[I_APID]; | |||
203 | } | |||
204 | /* Subtitle found */ | |||
205 | if (SubStreamType==I_SPUPID) { | |||
206 | msg_Dbg(NULL((void*)0), "REMAP: PES Private Data stream identified as [Subtitle]"); | |||
207 | if ( b_do_remap ) | |||
208 | i_newpid = pi_newpids[I_SPUPID]; | |||
209 | else | |||
210 | i_newpid = p_output->config.pi_confpids[I_SPUPID]; | |||
211 | } | |||
212 | break; | |||
213 | } | |||
214 | } | |||
215 | ||||
216 | if (!i_newpid) | |||
217 | return i_pid; | |||
218 | ||||
219 | /* Got the new base for the mapped pid. Find the next free one | |||
220 | we do this to ensure that multiple audios get unique pids */ | |||
221 | while (p_output->pi_freepids[i_newpid] != UNUSED_PID(8192 + 1)) | |||
222 | i_newpid++; | |||
223 | p_output->pi_freepids[i_newpid] = i_pid; /* Mark as in use */ | |||
224 | p_output->pi_newpids[i_pid] = i_newpid; /* Save the new pid */ | |||
225 | ||||
226 | msg_Dbg(NULL((void*)0), "REMAP: => Elementary stream is remapped to PID 0x%x (%u)", i_newpid, i_newpid); | |||
227 | ||||
228 | return i_newpid; | |||
229 | } | |||
230 | ||||
231 | /***************************************************************************** | |||
232 | * FindSID | |||
233 | *****************************************************************************/ | |||
234 | static inline sid_t *FindSID( uint16_t i_sid ) | |||
235 | { | |||
236 | int i; | |||
237 | ||||
238 | for ( i = 0; i < i_nb_sids; i++ ) | |||
239 | { | |||
240 | sid_t *p_sid = pp_sids[i]; | |||
241 | if ( p_sid->i_sid == i_sid ) | |||
242 | return p_sid; | |||
243 | } | |||
244 | return NULL((void*)0); | |||
245 | } | |||
246 | ||||
247 | /***************************************************************************** | |||
248 | * demux_Open | |||
249 | *****************************************************************************/ | |||
250 | void demux_Open( void ) | |||
251 | { | |||
252 | int i; | |||
253 | ||||
254 | memset( p_pids, 0, sizeof(p_pids) ); | |||
255 | ||||
256 | pf_Open(); | |||
257 | ||||
258 | for ( i = 0; i < MAX_PIDS8192; i++ ) | |||
259 | { | |||
260 | p_pids[i].i_last_cc = -1; | |||
261 | p_pids[i].i_demux_fd = -1; | |||
262 | psi_assemble_init( &p_pids[i].p_psi_buffer, | |||
263 | &p_pids[i].i_psi_buffer_used ); | |||
264 | } | |||
265 | ||||
266 | if ( b_budget_mode ) | |||
267 | i_demux_fd = pf_SetFilter(8192); | |||
268 | ||||
269 | psi_table_init( pp_current_pat_sections ); | |||
270 | psi_table_init( pp_next_pat_sections ); | |||
271 | SetPID(PAT_PID0x0); | |||
272 | p_pids[PAT_PID0x0].i_psi_refcount++; | |||
273 | ||||
274 | if ( b_enable_emm ) | |||
275 | { | |||
276 | psi_table_init( pp_current_cat_sections ); | |||
277 | psi_table_init( pp_next_cat_sections ); | |||
278 | SetPID_EMM(CAT_PID0x01); | |||
279 | p_pids[CAT_PID0x01].i_psi_refcount++; | |||
280 | } | |||
281 | ||||
282 | SetPID(NIT_PID0x10); | |||
283 | p_pids[NIT_PID0x10].i_psi_refcount++; | |||
284 | ||||
285 | psi_table_init( pp_current_sdt_sections ); | |||
286 | psi_table_init( pp_next_sdt_sections ); | |||
287 | SetPID(SDT_PID0x11); | |||
288 | p_pids[SDT_PID0x11].i_psi_refcount++; | |||
289 | ||||
290 | SetPID(EIT_PID0x12); | |||
291 | p_pids[EIT_PID0x12].i_psi_refcount++; | |||
292 | ||||
293 | SetPID(RST_PID0x13); | |||
294 | ||||
295 | SetPID(TDT_PID0x14); | |||
296 | } | |||
297 | ||||
298 | /***************************************************************************** | |||
299 | * demux_Close | |||
300 | *****************************************************************************/ | |||
301 | void demux_Close( void ) | |||
302 | { | |||
303 | int i; | |||
304 | ||||
305 | psi_table_free( pp_current_pat_sections ); | |||
306 | psi_table_free( pp_next_pat_sections ); | |||
307 | psi_table_free( pp_current_cat_sections ); | |||
308 | psi_table_free( pp_next_cat_sections ); | |||
309 | psi_table_free( pp_current_nit_sections ); | |||
310 | psi_table_free( pp_next_nit_sections ); | |||
311 | psi_table_free( pp_current_sdt_sections ); | |||
312 | psi_table_free( pp_next_sdt_sections ); | |||
313 | ||||
314 | for ( i = 0; i < MAX_PIDS8192; i++ ) | |||
315 | { | |||
316 | free( p_pids[i].p_psi_buffer ); | |||
317 | free( p_pids[i].pp_outputs ); | |||
318 | } | |||
319 | ||||
320 | for ( i = 0; i < i_nb_sids; i++ ) | |||
321 | { | |||
322 | sid_t *p_sid = pp_sids[i]; | |||
323 | free( p_sid->p_current_pmt ); | |||
324 | free( p_sid ); | |||
325 | } | |||
326 | free( pp_sids ); | |||
327 | ||||
328 | #ifdef HAVE_ICONV | |||
329 | if (iconv_handle != (iconv_t)-1) { | |||
330 | iconv_close(iconv_handle); | |||
331 | iconv_handle = (iconv_t)-1; | |||
332 | } | |||
333 | #endif | |||
334 | } | |||
335 | ||||
336 | /***************************************************************************** | |||
337 | * demux_Run | |||
338 | *****************************************************************************/ | |||
339 | void demux_Run( block_t *p_ts ) | |||
340 | { | |||
341 | SetDTS( p_ts ); | |||
342 | ||||
343 | while ( p_ts != NULL((void*)0) ) | |||
344 | { | |||
345 | block_t *p_next = p_ts->p_next; | |||
346 | p_ts->p_next = NULL((void*)0); | |||
347 | demux_Handle( p_ts ); | |||
348 | p_ts = p_next; | |||
349 | } | |||
350 | } | |||
351 | ||||
352 | /***************************************************************************** | |||
353 | * demux_Handle | |||
354 | *****************************************************************************/ | |||
355 | static void demux_Handle( block_t *p_ts ) | |||
356 | { | |||
357 | uint16_t i_pid = ts_get_pid( p_ts->p_ts ); | |||
358 | uint8_t i_cc = ts_get_cc( p_ts->p_ts ); | |||
359 | int i; | |||
360 | ||||
361 | if ( !ts_validate( p_ts->p_ts ) ) | |||
362 | { | |||
363 | msg_Warn( NULL((void*)0), "lost TS sync" ); | |||
364 | switch ( i_print_type ) | |||
365 | { | |||
366 | case PRINT_XML: | |||
367 | printf("<ERROR type=\"invalid_ts\"/>\n"); | |||
368 | break; | |||
369 | case PRINT_TEXT: | |||
370 | printf("lost TS sync\n"); | |||
371 | break; | |||
372 | default: | |||
373 | break; | |||
374 | } | |||
375 | ||||
376 | block_Delete( p_ts ); | |||
377 | return; | |||
378 | } | |||
379 | ||||
380 | if ( i_pid != PADDING_PID8191 ) | |||
381 | p_pids[i_pid].info.i_scrambling = ts_get_scrambling( p_ts->p_ts ); | |||
382 | ||||
383 | p_pids[i_pid].info.i_last_packet_ts = i_wallclock; | |||
384 | p_pids[i_pid].info.i_packets++; | |||
385 | ||||
386 | p_pids[i_pid].i_packets_passed++; | |||
387 | ||||
388 | /* Calculate bytes_per_sec */ | |||
389 | if ( i_wallclock > p_pids[i_pid].i_bytes_ts + 1000000 ) { | |||
390 | p_pids[i_pid].info.i_bytes_per_sec = p_pids[i_pid].i_packets_passed * TS_SIZE188; | |||
391 | p_pids[i_pid].i_packets_passed = 0; | |||
392 | p_pids[i_pid].i_bytes_ts = i_wallclock; | |||
393 | } | |||
394 | ||||
395 | if ( p_pids[i_pid].info.i_first_packet_ts == 0 ) | |||
396 | p_pids[i_pid].info.i_first_packet_ts = i_wallclock; | |||
397 | ||||
398 | if ( i_pid != PADDING_PID8191 && p_pids[i_pid].i_last_cc != -1 | |||
399 | && !ts_check_duplicate( i_cc, p_pids[i_pid].i_last_cc ) | |||
400 | && ts_check_discontinuity( i_cc, p_pids[i_pid].i_last_cc ) ) | |||
401 | { | |||
402 | unsigned int expected_cc = (p_pids[i_pid].i_last_cc + 1) & 0x0f; | |||
403 | uint16_t i_sid = 0; | |||
404 | const char *pid_desc = get_pid_desc(i_pid, &i_sid); | |||
405 | ||||
406 | p_pids[i_pid].info.i_cc_errors++; | |||
407 | ||||
408 | msg_Warn( NULL((void*)0), "TS discontinuity on pid %4hu expected_cc %2u got %2u (%s, sid %d)", | |||
409 | i_pid, expected_cc, i_cc, pid_desc, i_sid ); | |||
410 | ||||
411 | switch ( i_print_type ) | |||
412 | { | |||
413 | case PRINT_XML: | |||
414 | printf("<ERROR type=\"invalid_discontinuity\" pid=\"%hu\" expected_cc=\"%u\" got_cc=\"%u\" pid_carries=\"%s\" sid=\"%u\" />\n", | |||
415 | i_pid, expected_cc, i_cc, pid_desc, i_sid ); | |||
416 | break; | |||
417 | case PRINT_TEXT: | |||
418 | printf("TS discontinuity (PID=%hu) (expected_cc=%u) (got_cc=%u) (PID_carries=%s) (sid=%d)\n", | |||
419 | i_pid, expected_cc, i_cc, pid_desc, i_sid ); | |||
420 | break; | |||
421 | default: | |||
422 | break; | |||
423 | } | |||
424 | } | |||
425 | ||||
426 | if ( ts_get_transporterror( p_ts->p_ts ) ) | |||
427 | { | |||
428 | uint16_t i_sid = 0; | |||
429 | const char *pid_desc = get_pid_desc(i_pid, &i_sid); | |||
430 | ||||
431 | p_pids[i_pid].info.i_transport_errors++; | |||
432 | ||||
433 | msg_Warn( NULL((void*)0), "transport_error_indicator on pid %hu (%s, sid %u)", | |||
434 | i_pid, pid_desc, i_sid ); | |||
435 | switch ( i_print_type ) | |||
436 | { | |||
437 | case PRINT_XML: | |||
438 | printf("<ERROR type=\"transport_error\" pid=\"%hu\" pid_carries=\"%s\" sid=\"%u\" />\n", | |||
439 | i_pid, pid_desc, i_sid ); | |||
440 | break; | |||
441 | case PRINT_TEXT: | |||
442 | printf("transport_error_indicator (PID=%hu) (PID_carries=%s) (sid=%u)\n", | |||
443 | i_pid, pid_desc, i_sid ); | |||
444 | break; | |||
445 | default: | |||
446 | break; | |||
447 | } | |||
448 | ||||
449 | i_nb_errors++; | |||
450 | i_last_error = i_wallclock; | |||
451 | } | |||
452 | else if ( i_wallclock > i_last_error + WATCHDOG_WAIT10000000LL ) | |||
453 | i_nb_errors = 0; | |||
454 | ||||
455 | if ( i_nb_errors > MAX_ERRORS1000 ) | |||
456 | { | |||
457 | i_nb_errors = 0; | |||
458 | switch (i_print_type) { | |||
459 | case PRINT_XML: | |||
460 | printf("<EVENT type=\"reset\" cause=\"transport\" />\n"); | |||
461 | break; | |||
462 | default: | |||
463 | msg_Warn( NULL((void*)0), | |||
464 | "too many transport errors, tuning again" ); | |||
465 | } | |||
466 | pf_Reset(); | |||
467 | } | |||
468 | ||||
469 | if ( !ts_get_transporterror( p_ts->p_ts ) ) | |||
470 | { | |||
471 | /* PSI parsing */ | |||
472 | if ( i_pid == TDT_PID0x14 || i_pid == RST_PID0x13 ) | |||
473 | SendTDT( p_ts ); | |||
474 | else if ( p_pids[i_pid].i_psi_refcount ) | |||
475 | HandlePSIPacket( p_ts->p_ts, p_ts->i_dts ); | |||
476 | ||||
477 | if ( b_enable_emm && p_pids[i_pid].b_emm ) | |||
478 | SendEMM( p_ts ); | |||
479 | ||||
480 | /* PCR handling */ | |||
481 | if ( ts_has_adaptation( p_ts->p_ts ) | |||
482 | && ts_get_adaptation( p_ts->p_ts ) | |||
483 | && tsaf_has_pcr( p_ts->p_ts ) ) | |||
484 | { | |||
485 | mtime_t i_timestamp = tsaf_get_pcr( p_ts->p_ts ); | |||
486 | int j; | |||
487 | ||||
488 | for ( j = 0; j < i_nb_sids; j++ ) | |||
489 | { | |||
490 | sid_t *p_sid = pp_sids[j]; | |||
491 | if ( p_sid->i_sid && p_sid->p_current_pmt != NULL((void*)0) | |||
492 | && pmt_get_pcrpid( p_sid->p_current_pmt ) == i_pid ) | |||
493 | { | |||
494 | for ( i = 0; i < i_nb_outputs; i++ ) | |||
495 | { | |||
496 | output_t *p_output = pp_outputs[i]; | |||
497 | if ( p_output->config.i_sid == p_sid->i_sid ) | |||
498 | { | |||
499 | p_output->i_ref_timestamp = i_timestamp; | |||
500 | p_output->i_ref_wallclock = p_ts->i_dts; | |||
501 | } | |||
502 | } | |||
503 | } | |||
504 | } | |||
505 | } | |||
506 | } | |||
507 | ||||
508 | p_pids[i_pid].i_last_cc = i_cc; | |||
509 | ||||
510 | /* Output */ | |||
511 | for ( i = 0; i < p_pids[i_pid].i_nb_outputs; i++ ) | |||
512 | { | |||
513 | output_t *p_output = p_pids[i_pid].pp_outputs[i]; | |||
514 | if ( p_output != NULL((void*)0) ) | |||
515 | { | |||
516 | if ( i_ca_handle && (p_output->config.i_config & OUTPUT_WATCH0x01) && | |||
517 | ts_get_unitstart( p_ts->p_ts ) ) | |||
518 | { | |||
519 | uint8_t *p_payload; | |||
520 | ||||
521 | if ( ts_get_scrambling( p_ts->p_ts ) || | |||
522 | ( p_pids[i_pid].b_pes | |||
523 | && (p_payload = ts_payload( p_ts->p_ts )) + 3 | |||
524 | < p_ts->p_ts + TS_SIZE188 | |||
525 | && !pes_validate(p_payload) ) ) | |||
526 | { | |||
527 | if ( i_wallclock > | |||
528 | i_last_reset + WATCHDOG_REFRACTORY_PERIOD60000000LL ) | |||
529 | { | |||
530 | p_output->i_nb_errors++; | |||
531 | p_output->i_last_error = i_wallclock; | |||
532 | } | |||
533 | } | |||
534 | else if ( i_wallclock > p_output->i_last_error + WATCHDOG_WAIT10000000LL ) | |||
535 | p_output->i_nb_errors = 0; | |||
536 | ||||
537 | if ( p_output->i_nb_errors > MAX_ERRORS1000 ) | |||
538 | { | |||
539 | int j; | |||
540 | for ( j = 0; j < i_nb_outputs; j++ ) | |||
541 | pp_outputs[j]->i_nb_errors = 0; | |||
542 | ||||
543 | switch (i_print_type) { | |||
544 | case PRINT_XML: | |||
545 | printf("<EVENT type=\"reset\" cause=\"scrambling\" />\n"); | |||
546 | break; | |||
547 | default: | |||
548 | msg_Warn( NULL((void*)0), | |||
549 | "too many errors for stream %s, resetting", | |||
550 | p_output->config.psz_displayname ); | |||
551 | } | |||
552 | i_last_reset = i_wallclock; | |||
553 | en50221_Reset(); | |||
554 | } | |||
555 | } | |||
556 | ||||
557 | output_Put( p_output, p_ts ); | |||
558 | ||||
559 | if ( p_output->p_eit_ts_buffer != NULL((void*)0) | |||
560 | && p_ts->i_dts > p_output->p_eit_ts_buffer->i_dts | |||
561 | + MAX_EIT_RETENTION500000 ) | |||
562 | FlushEIT( p_output, p_ts->i_dts ); | |||
563 | } | |||
564 | } | |||
565 | ||||
566 | if ( output_dup.config.i_config & OUTPUT_VALID0x04 ) | |||
567 | output_Put( &output_dup, p_ts ); | |||
568 | ||||
569 | p_ts->i_refcount--; | |||
570 | if ( !p_ts->i_refcount ) | |||
571 | block_Delete( p_ts ); | |||
572 | } | |||
573 | ||||
574 | /***************************************************************************** | |||
575 | * demux_Change : called from main thread | |||
576 | *****************************************************************************/ | |||
577 | static int IsIn( uint16_t *pi_pids, int i_nb_pids, uint16_t i_pid ) | |||
578 | { | |||
579 | int i; | |||
580 | for ( i = 0; i < i_nb_pids; i++ ) | |||
581 | if ( i_pid == pi_pids[i] ) break; | |||
582 | return ( i != i_nb_pids ); | |||
583 | } | |||
584 | ||||
585 | void demux_Change( output_t *p_output, const output_config_t *p_config ) | |||
586 | { | |||
587 | uint16_t *pi_wanted_pids, *pi_current_pids; | |||
588 | int i_nb_wanted_pids, i_nb_current_pids; | |||
589 | ||||
590 | uint16_t i_old_sid = p_output->config.i_sid; | |||
591 | uint16_t i_sid = p_config->i_sid; | |||
592 | uint16_t *pi_old_pids = p_output->config.pi_pids; | |||
593 | uint16_t *pi_pids = p_config->pi_pids; | |||
594 | int i_old_nb_pids = p_output->config.i_nb_pids; | |||
595 | int i_nb_pids = p_config->i_nb_pids; | |||
596 | ||||
597 | bool_Bool b_sid_change = i_sid != i_old_sid; | |||
598 | bool_Bool b_pid_change = false0, b_tsid_change = false0; | |||
599 | bool_Bool b_dvb_change = !!((p_output->config.i_config ^ p_config->i_config) | |||
600 | & OUTPUT_DVB0x20); | |||
601 | bool_Bool b_service_name_change = | |||
602 | (!streq(p_output->config.psz_service_name, p_config->psz_service_name) || | |||
603 | !streq(p_output->config.psz_service_provider, p_config->psz_service_provider)); | |||
604 | bool_Bool b_remap_change = p_output->config.i_new_sid != p_config->i_new_sid || | |||
605 | p_output->config.b_do_remap != p_config->b_do_remap || | |||
606 | p_output->config.pi_confpids[I_PMTPID] != p_config->pi_confpids[I_PMTPID] || | |||
607 | p_output->config.pi_confpids[I_APID] != p_config->pi_confpids[I_APID] || | |||
608 | p_output->config.pi_confpids[I_VPID] != p_config->pi_confpids[I_VPID] || | |||
609 | p_output->config.pi_confpids[I_SPUPID] != p_config->pi_confpids[I_SPUPID]; | |||
610 | int i; | |||
611 | ||||
612 | p_output->config.i_config = p_config->i_config; | |||
613 | p_output->config.i_new_sid = p_config->i_new_sid; | |||
614 | p_output->config.b_do_remap = p_config->b_do_remap; | |||
615 | memcpy(p_output->config.pi_confpids, p_config->pi_confpids, | |||
616 | sizeof(uint16_t) * N_MAP_PIDS4); | |||
617 | ||||
618 | /* Change output settings related to service_name and service_provider . */ | |||
619 | free( p_output->config.psz_service_name ); | |||
620 | free( p_output->config.psz_service_provider ); | |||
621 | p_output->config.psz_service_name = xstrdup( p_config->psz_service_name ); | |||
622 | p_output->config.psz_service_provider = xstrdup( p_config->psz_service_provider ); | |||
623 | ||||
624 | if ( p_config->i_tsid != -1 && p_output->config.i_tsid != p_config->i_tsid ) | |||
625 | { | |||
626 | p_output->i_tsid = p_config->i_tsid; | |||
627 | b_tsid_change = true1; | |||
628 | } | |||
629 | if ( p_config->i_tsid == -1 && p_output->config.i_tsid != -1 ) | |||
630 | { | |||
631 | if ( psi_table_validate(pp_current_pat_sections) && !b_random_tsid ) | |||
632 | p_output->i_tsid = | |||
633 | psi_table_get_tableidext(pp_current_pat_sections)psi_get_tableidext(pp_current_pat_sections[0]); | |||
634 | else | |||
635 | p_output->i_tsid = rand() & 0xffff; | |||
636 | b_tsid_change = true1; | |||
637 | } | |||
638 | ||||
639 | if ( !b_sid_change && p_config->i_nb_pids == p_output->config.i_nb_pids && | |||
640 | (!p_config->i_nb_pids || | |||
641 | !memcmp( p_output->config.pi_pids, p_config->pi_pids, | |||
642 | p_config->i_nb_pids * sizeof(uint16_t) )) ) | |||
643 | goto out_change; | |||
644 | ||||
645 | GetPIDS( &pi_wanted_pids, &i_nb_wanted_pids, i_sid, pi_pids, i_nb_pids ); | |||
646 | GetPIDS( &pi_current_pids, &i_nb_current_pids, i_old_sid, pi_old_pids, | |||
647 | i_old_nb_pids ); | |||
648 | ||||
649 | if ( b_sid_change && i_old_sid ) | |||
650 | { | |||
651 | sid_t *p_old_sid = FindSID( i_old_sid ); | |||
652 | p_output->config.i_sid = p_config->i_sid; | |||
653 | ||||
654 | if ( p_old_sid != NULL((void*)0) ) | |||
655 | { | |||
656 | if ( i_sid != i_old_sid ) | |||
657 | UnselectPMT( i_old_sid, p_old_sid->i_pmt_pid ); | |||
658 | ||||
659 | if ( i_ca_handle && !SIDIsSelected( i_old_sid ) | |||
660 | && p_old_sid->p_current_pmt != NULL((void*)0) | |||
661 | && PMTNeedsDescrambling( p_old_sid->p_current_pmt ) ) | |||
662 | en50221_DeletePMT( p_old_sid->p_current_pmt ); | |||
663 | } | |||
664 | } | |||
665 | ||||
666 | for ( i = 0; i < i_nb_current_pids; i++ ) | |||
667 | { | |||
668 | if ( !IsIn( pi_wanted_pids, i_nb_wanted_pids, pi_current_pids[i] ) ) | |||
669 | { | |||
670 | StopPID( p_output, pi_current_pids[i] ); | |||
671 | b_pid_change = true1; | |||
672 | } | |||
673 | } | |||
674 | ||||
675 | if ( b_sid_change && i_ca_handle && i_old_sid && | |||
676 | SIDIsSelected( i_old_sid ) ) | |||
677 | { | |||
678 | sid_t *p_old_sid = FindSID( i_old_sid ); | |||
679 | if ( p_old_sid != NULL((void*)0) && p_old_sid->p_current_pmt != NULL((void*)0) | |||
680 | && PMTNeedsDescrambling( p_old_sid->p_current_pmt ) ) | |||
681 | en50221_UpdatePMT( p_old_sid->p_current_pmt ); | |||
682 | } | |||
683 | ||||
684 | for ( i = 0; i < i_nb_wanted_pids; i++ ) | |||
685 | { | |||
686 | if ( !IsIn( pi_current_pids, i_nb_current_pids, pi_wanted_pids[i] ) ) | |||
687 | { | |||
688 | StartPID( p_output, pi_wanted_pids[i] ); | |||
689 | b_pid_change = true1; | |||
690 | } | |||
691 | } | |||
692 | ||||
693 | free( pi_wanted_pids ); | |||
694 | free( pi_current_pids ); | |||
695 | ||||
696 | if ( b_sid_change && i_sid ) | |||
697 | { | |||
698 | sid_t *p_sid = FindSID( i_sid ); | |||
699 | p_output->config.i_sid = i_old_sid; | |||
700 | ||||
701 | if ( p_sid != NULL((void*)0) ) | |||
702 | { | |||
703 | if ( i_sid != i_old_sid ) | |||
704 | SelectPMT( i_sid, p_sid->i_pmt_pid ); | |||
705 | ||||
706 | if ( i_ca_handle && !SIDIsSelected( i_sid ) | |||
707 | && p_sid->p_current_pmt != NULL((void*)0) | |||
708 | && PMTNeedsDescrambling( p_sid->p_current_pmt ) ) | |||
709 | en50221_AddPMT( p_sid->p_current_pmt ); | |||
710 | } | |||
711 | } | |||
712 | ||||
713 | if ( i_ca_handle && i_sid && SIDIsSelected( i_sid ) ) | |||
714 | { | |||
715 | sid_t *p_sid = FindSID( i_sid ); | |||
716 | if ( p_sid != NULL((void*)0) && p_sid->p_current_pmt != NULL((void*)0) | |||
717 | && PMTNeedsDescrambling( p_sid->p_current_pmt ) ) | |||
718 | en50221_UpdatePMT( p_sid->p_current_pmt ); | |||
719 | } | |||
720 | ||||
721 | p_output->config.i_sid = i_sid; | |||
722 | free( p_output->config.pi_pids ); | |||
723 | p_output->config.pi_pids = malloc( sizeof(uint16_t) * i_nb_pids ); | |||
724 | memcpy( p_output->config.pi_pids, pi_pids, sizeof(uint16_t) * i_nb_pids ); | |||
725 | p_output->config.i_nb_pids = i_nb_pids; | |||
726 | ||||
727 | out_change: | |||
728 | if ( b_sid_change || b_remap_change ) | |||
729 | { | |||
730 | NewSDT( p_output ); | |||
731 | NewNIT( p_output ); | |||
732 | NewPAT( p_output ); | |||
733 | NewPMT( p_output ); | |||
734 | } | |||
735 | else | |||
736 | { | |||
737 | if ( b_tsid_change ) | |||
738 | { | |||
739 | NewSDT( p_output ); | |||
740 | NewNIT( p_output ); | |||
741 | NewPAT( p_output ); | |||
742 | } | |||
743 | else if ( b_dvb_change ) | |||
744 | { | |||
745 | NewNIT( p_output ); | |||
746 | NewPAT( p_output ); | |||
747 | } | |||
748 | ||||
749 | if ( b_pid_change ) | |||
750 | NewPMT( p_output ); | |||
751 | ||||
752 | if ( !b_sid_change && b_service_name_change ) | |||
753 | NewSDT( p_output ); | |||
754 | } | |||
755 | } | |||
756 | ||||
757 | /***************************************************************************** | |||
758 | * SetDTS | |||
759 | *****************************************************************************/ | |||
760 | static void SetDTS( block_t *p_list ) | |||
761 | { | |||
762 | int i_nb_ts = 0, i; | |||
763 | mtime_t i_duration; | |||
764 | block_t *p_ts = p_list; | |||
765 | ||||
766 | while ( p_ts != NULL((void*)0) ) | |||
767 | { | |||
768 | i_nb_ts++; | |||
769 | p_ts = p_ts->p_next; | |||
770 | } | |||
771 | ||||
772 | /* We suppose the stream is CBR, at least between two consecutive read(). | |||
773 | * This is especially true in budget mode */ | |||
774 | if ( i_last_dts == -1 ) | |||
775 | i_duration = 0; | |||
776 | else | |||
777 | i_duration = i_wallclock - i_last_dts; | |||
778 | ||||
779 | p_ts = p_list; | |||
780 | i = i_nb_ts - 1; | |||
781 | while ( p_ts != NULL((void*)0) ) | |||
782 | { | |||
783 | p_ts->i_dts = i_wallclock - i_duration * i / i_nb_ts; | |||
784 | i--; | |||
785 | p_ts = p_ts->p_next; | |||
786 | } | |||
787 | ||||
788 | i_last_dts = i_wallclock; | |||
789 | } | |||
790 | ||||
791 | /***************************************************************************** | |||
792 | * SetPID/UnsetPID | |||
793 | *****************************************************************************/ | |||
794 | static void SetPID( uint16_t i_pid ) | |||
795 | { | |||
796 | p_pids[i_pid].i_refcount++; | |||
797 | ||||
798 | if ( !b_budget_mode && p_pids[i_pid].i_refcount | |||
799 | && p_pids[i_pid].i_demux_fd == -1 ) | |||
800 | p_pids[i_pid].i_demux_fd = pf_SetFilter( i_pid ); | |||
801 | } | |||
802 | ||||
803 | static void SetPID_EMM( uint16_t i_pid ) | |||
804 | { | |||
805 | SetPID( i_pid ); | |||
806 | p_pids[i_pid].b_emm = true1; | |||
807 | } | |||
808 | ||||
809 | static void UnsetPID( uint16_t i_pid ) | |||
810 | { | |||
811 | p_pids[i_pid].i_refcount--; | |||
812 | ||||
813 | if ( !b_budget_mode && !p_pids[i_pid].i_refcount | |||
814 | && p_pids[i_pid].i_demux_fd != -1 ) | |||
815 | { | |||
816 | pf_UnsetFilter( p_pids[i_pid].i_demux_fd, i_pid ); | |||
817 | p_pids[i_pid].i_demux_fd = -1; | |||
818 | p_pids[i_pid].b_emm = false0; | |||
819 | } | |||
820 | } | |||
821 | ||||
822 | /***************************************************************************** | |||
823 | * StartPID/StopPID | |||
824 | *****************************************************************************/ | |||
825 | static void StartPID( output_t *p_output, uint16_t i_pid ) | |||
826 | { | |||
827 | int j; | |||
828 | ||||
829 | for ( j = 0; j < p_pids[i_pid].i_nb_outputs; j++ ) | |||
830 | if ( p_pids[i_pid].pp_outputs[j] == p_output ) | |||
831 | break; | |||
832 | ||||
833 | if ( j == p_pids[i_pid].i_nb_outputs ) | |||
834 | { | |||
835 | for ( j = 0; j < p_pids[i_pid].i_nb_outputs; j++ ) | |||
836 | if ( p_pids[i_pid].pp_outputs[j] == NULL((void*)0) ) | |||
837 | break; | |||
838 | ||||
839 | if ( j == p_pids[i_pid].i_nb_outputs ) | |||
840 | { | |||
841 | p_pids[i_pid].i_nb_outputs++; | |||
842 | p_pids[i_pid].pp_outputs = realloc( p_pids[i_pid].pp_outputs, | |||
843 | sizeof(output_t *) | |||
844 | * p_pids[i_pid].i_nb_outputs ); | |||
845 | } | |||
846 | ||||
847 | p_pids[i_pid].pp_outputs[j] = p_output; | |||
848 | SetPID( i_pid ); | |||
849 | } | |||
850 | } | |||
851 | ||||
852 | static void StopPID( output_t *p_output, uint16_t i_pid ) | |||
853 | { | |||
854 | int j; | |||
855 | ||||
856 | for ( j = 0; j < p_pids[i_pid].i_nb_outputs; j++ ) | |||
857 | { | |||
858 | if ( p_pids[i_pid].pp_outputs[j] != NULL((void*)0) ) | |||
859 | { | |||
860 | if ( p_pids[i_pid].pp_outputs[j] == p_output ) | |||
861 | break; | |||
862 | } | |||
863 | } | |||
864 | ||||
865 | if ( j != p_pids[i_pid].i_nb_outputs ) | |||
866 | { | |||
867 | p_pids[i_pid].pp_outputs[j] = NULL((void*)0); | |||
868 | UnsetPID( i_pid ); | |||
869 | } | |||
870 | } | |||
871 | ||||
872 | /***************************************************************************** | |||
873 | * SelectPID/UnselectPID | |||
874 | *****************************************************************************/ | |||
875 | static void SelectPID( uint16_t i_sid, uint16_t i_pid ) | |||
876 | { | |||
877 | int i; | |||
878 | ||||
879 | for ( i = 0; i < i_nb_outputs; i++ ) | |||
880 | if ( (pp_outputs[i]->config.i_config & OUTPUT_VALID0x04) | |||
881 | && pp_outputs[i]->config.i_sid == i_sid | |||
882 | && !pp_outputs[i]->config.i_nb_pids ) | |||
883 | StartPID( pp_outputs[i], i_pid ); | |||
884 | } | |||
885 | ||||
886 | static void UnselectPID( uint16_t i_sid, uint16_t i_pid ) | |||
887 | { | |||
888 | int i; | |||
889 | ||||
890 | for ( i = 0; i < i_nb_outputs; i++ ) | |||
891 | if ( (pp_outputs[i]->config.i_config & OUTPUT_VALID0x04) | |||
892 | && pp_outputs[i]->config.i_sid == i_sid | |||
893 | && !pp_outputs[i]->config.i_nb_pids ) | |||
894 | StopPID( pp_outputs[i], i_pid ); | |||
895 | } | |||
896 | ||||
897 | /***************************************************************************** | |||
898 | * SelectPMT/UnselectPMT | |||
899 | *****************************************************************************/ | |||
900 | static void SelectPMT( uint16_t i_sid, uint16_t i_pid ) | |||
901 | { | |||
902 | int i; | |||
903 | ||||
904 | p_pids[i_pid].i_psi_refcount++; | |||
905 | p_pids[i_pid].b_pes = false0; | |||
906 | ||||
907 | if ( b_select_pmts ) | |||
908 | SetPID( i_pid ); | |||
909 | else for ( i = 0; i < i_nb_outputs; i++ ) | |||
910 | if ( (pp_outputs[i]->config.i_config & OUTPUT_VALID0x04) | |||
911 | && pp_outputs[i]->config.i_sid == i_sid ) | |||
912 | SetPID( i_pid ); | |||
913 | } | |||
914 | ||||
915 | static void UnselectPMT( uint16_t i_sid, uint16_t i_pid ) | |||
916 | { | |||
917 | int i; | |||
918 | ||||
919 | p_pids[i_pid].i_psi_refcount--; | |||
920 | if ( !p_pids[i_pid].i_psi_refcount ) | |||
921 | psi_assemble_reset( &p_pids[i_pid].p_psi_buffer, | |||
922 | &p_pids[i_pid].i_psi_buffer_used ); | |||
923 | ||||
924 | if ( b_select_pmts ) | |||
925 | UnsetPID( i_pid ); | |||
926 | else for ( i = 0; i < i_nb_outputs; i++ ) | |||
927 | if ( (pp_outputs[i]->config.i_config & OUTPUT_VALID0x04) | |||
928 | && pp_outputs[i]->config.i_sid == i_sid ) | |||
929 | UnsetPID( i_pid ); | |||
930 | } | |||
931 | ||||
932 | /***************************************************************************** | |||
933 | * GetPIDS | |||
934 | *****************************************************************************/ | |||
935 | static void GetPIDS( uint16_t **ppi_wanted_pids, int *pi_nb_wanted_pids, | |||
936 | uint16_t i_sid, | |||
937 | const uint16_t *pi_pids, int i_nb_pids ) | |||
938 | { | |||
939 | sid_t *p_sid; | |||
940 | uint8_t *p_pmt; | |||
941 | uint16_t i_pmt_pid, i_pcr_pid; | |||
942 | uint8_t *p_es; | |||
943 | uint8_t j; | |||
944 | ||||
945 | if ( i_nb_pids || i_sid == 0 ) | |||
| ||||
946 | { | |||
947 | *pi_nb_wanted_pids = i_nb_pids; | |||
948 | *ppi_wanted_pids = malloc( sizeof(uint16_t) * i_nb_pids ); | |||
| ||||
949 | memcpy( *ppi_wanted_pids, pi_pids, sizeof(uint16_t) * i_nb_pids ); | |||
950 | return; | |||
951 | } | |||
952 | ||||
953 | *pi_nb_wanted_pids = 0; | |||
954 | *ppi_wanted_pids = NULL((void*)0); | |||
955 | ||||
956 | p_sid = FindSID( i_sid ); | |||
957 | if ( p_sid == NULL((void*)0) ) | |||
958 | return; | |||
959 | ||||
960 | p_pmt = p_sid->p_current_pmt; | |||
961 | i_pmt_pid = p_sid->i_pmt_pid; | |||
962 | if ( p_pmt == NULL((void*)0) ) { | |||
963 | msg_Dbg(NULL((void*)0), "no current PMT on sid %d\n", i_sid); | |||
964 | return; | |||
965 | } | |||
966 | ||||
967 | i_pcr_pid = pmt_get_pcrpid( p_pmt ); | |||
968 | j = 0; | |||
969 | while ( (p_es = pmt_get_es( p_pmt, j )) != NULL((void*)0) ) | |||
970 | { | |||
971 | j++; | |||
972 | if ( PIDWouldBeSelected( p_es ) ) | |||
973 | { | |||
974 | *ppi_wanted_pids = realloc( *ppi_wanted_pids, | |||
975 | (*pi_nb_wanted_pids + 1) * sizeof(uint16_t) ); | |||
976 | (*ppi_wanted_pids)[(*pi_nb_wanted_pids)++] = pmtn_get_pid( p_es ); | |||
977 | } | |||
978 | } | |||
979 | ||||
980 | if ( i_pcr_pid != PADDING_PID8191 && i_pcr_pid != i_pmt_pid | |||
981 | && !IsIn( *ppi_wanted_pids, *pi_nb_wanted_pids, i_pcr_pid ) ) | |||
982 | { | |||
983 | *ppi_wanted_pids = realloc( *ppi_wanted_pids, | |||
984 | (*pi_nb_wanted_pids + 1) * sizeof(uint16_t) ); | |||
985 | (*ppi_wanted_pids)[(*pi_nb_wanted_pids)++] = i_pcr_pid; | |||
986 | } | |||
987 | } | |||
988 | ||||
989 | /***************************************************************************** | |||
990 | * OutputPSISection | |||
991 | *****************************************************************************/ | |||
992 | static void OutputPSISection( output_t *p_output, uint8_t *p_section, | |||
993 | uint16_t i_pid, uint8_t *pi_cc, mtime_t i_dts, | |||
994 | block_t **pp_ts_buffer, | |||
995 | uint8_t *pi_ts_buffer_offset ) | |||
996 | { | |||
997 | uint16_t i_section_length = psi_get_length(p_section) + PSI_HEADER_SIZE3; | |||
998 | uint16_t i_section_offset = 0; | |||
999 | ||||
1000 | do | |||
1001 | { | |||
1002 | block_t *p_block; | |||
1003 | uint8_t *p; | |||
1004 | uint8_t i_ts_offset; | |||
1005 | bool_Bool b_append = (pp_ts_buffer != NULL((void*)0) && *pp_ts_buffer != NULL((void*)0)); | |||
1006 | ||||
1007 | if ( b_append ) | |||
1008 | { | |||
1009 | p_block = *pp_ts_buffer; | |||
1010 | i_ts_offset = *pi_ts_buffer_offset; | |||
1011 | } | |||
1012 | else | |||
1013 | { | |||
1014 | p_block = block_New(); | |||
1015 | p_block->i_dts = i_dts; | |||
1016 | i_ts_offset = 0; | |||
1017 | } | |||
1018 | p = p_block->p_ts; | |||
1019 | ||||
1020 | psi_split_section( p, &i_ts_offset, p_section, &i_section_offset ); | |||
1021 | ||||
1022 | if ( !b_append ) | |||
1023 | { | |||
1024 | ts_set_pid( p, i_pid ); | |||
1025 | ts_set_cc( p, *pi_cc ); | |||
1026 | (*pi_cc)++; | |||
1027 | *pi_cc &= 0xf; | |||
1028 | } | |||
1029 | ||||
1030 | if ( i_section_offset == i_section_length ) | |||
1031 | { | |||
1032 | if ( i_ts_offset < TS_SIZE188 - MIN_SECTION_FRAGMENT8 | |||
1033 | && pp_ts_buffer != NULL((void*)0) ) | |||
1034 | { | |||
1035 | *pp_ts_buffer = p_block; | |||
1036 | *pi_ts_buffer_offset = i_ts_offset; | |||
1037 | break; | |||
1038 | } | |||
1039 | else | |||
1040 | psi_split_end( p, &i_ts_offset ); | |||
1041 | } | |||
1042 | ||||
1043 | p_block->i_dts = i_dts; | |||
1044 | p_block->i_refcount--; | |||
1045 | output_Put( p_output, p_block ); | |||
1046 | if ( pp_ts_buffer != NULL((void*)0) ) | |||
1047 | { | |||
1048 | *pp_ts_buffer = NULL((void*)0); | |||
1049 | *pi_ts_buffer_offset = 0; | |||
1050 | } | |||
1051 | } | |||
1052 | while ( i_section_offset < i_section_length ); | |||
1053 | } | |||
1054 | ||||
1055 | /***************************************************************************** | |||
1056 | * SendPAT | |||
1057 | *****************************************************************************/ | |||
1058 | static void SendPAT( mtime_t i_dts ) | |||
1059 | { | |||
1060 | int i; | |||
1061 | ||||
1062 | for ( i = 0; i < i_nb_outputs; i++ ) | |||
1063 | { | |||
1064 | output_t *p_output = pp_outputs[i]; | |||
1065 | ||||
1066 | if ( !(p_output->config.i_config & OUTPUT_VALID0x04) ) | |||
1067 | continue; | |||
1068 | ||||
1069 | if ( p_output->p_pat_section == NULL((void*)0) && | |||
1070 | psi_table_validate(pp_current_pat_sections) ) | |||
1071 | { | |||
1072 | /* SID doesn't exist - build an empty PAT. */ | |||
1073 | uint8_t *p; | |||
1074 | p_output->i_pat_version++; | |||
1075 | ||||
1076 | p = p_output->p_pat_section = psi_allocate(); | |||
1077 | pat_init( p ); | |||
1078 | pat_set_length( p, 0 ); | |||
1079 | pat_set_tsidpsi_set_tableidext( p, p_output->i_tsid ); | |||
1080 | psi_set_version( p, p_output->i_pat_version ); | |||
1081 | psi_set_current( p ); | |||
1082 | psi_set_section( p, 0 ); | |||
1083 | psi_set_lastsection( p, 0 ); | |||
1084 | psi_set_crc( p_output->p_pat_section ); | |||
1085 | } | |||
1086 | ||||
1087 | ||||
1088 | if ( p_output->p_pat_section != NULL((void*)0) ) | |||
1089 | OutputPSISection( p_output, p_output->p_pat_section, PAT_PID0x0, | |||
1090 | &p_output->i_pat_cc, i_dts, NULL((void*)0), NULL((void*)0) ); | |||
1091 | } | |||
1092 | } | |||
1093 | ||||
1094 | /***************************************************************************** | |||
1095 | * SendPMT | |||
1096 | *****************************************************************************/ | |||
1097 | static void SendPMT( sid_t *p_sid, mtime_t i_dts ) | |||
1098 | { | |||
1099 | int i; | |||
1100 | int i_pmt_pid = p_sid->i_pmt_pid; | |||
1101 | ||||
1102 | if ( b_do_remap ) | |||
1103 | i_pmt_pid = pi_newpids[ I_PMTPID ]; | |||
1104 | ||||
1105 | for ( i = 0; i < i_nb_outputs; i++ ) | |||
1106 | { | |||
1107 | output_t *p_output = pp_outputs[i]; | |||
1108 | ||||
1109 | if ( (p_output->config.i_config & OUTPUT_VALID0x04) | |||
1110 | && p_output->config.i_sid == p_sid->i_sid | |||
1111 | && p_output->p_pmt_section != NULL((void*)0) ) | |||
1112 | { | |||
1113 | if ( p_output->config.b_do_remap && p_output->config.pi_confpids[I_PMTPID] ) | |||
1114 | i_pmt_pid = p_output->config.pi_confpids[I_PMTPID]; | |||
1115 | ||||
1116 | OutputPSISection( p_output, p_output->p_pmt_section, | |||
1117 | i_pmt_pid, &p_output->i_pmt_cc, i_dts, | |||
1118 | NULL((void*)0), NULL((void*)0) ); | |||
1119 | } | |||
1120 | } | |||
1121 | } | |||
1122 | ||||
1123 | /***************************************************************************** | |||
1124 | * SendNIT | |||
1125 | *****************************************************************************/ | |||
1126 | static void SendNIT( mtime_t i_dts ) | |||
1127 | { | |||
1128 | int i; | |||
1129 | ||||
1130 | for ( i = 0; i < i_nb_outputs; i++ ) | |||
1131 | { | |||
1132 | output_t *p_output = pp_outputs[i]; | |||
1133 | ||||
1134 | if ( (p_output->config.i_config & OUTPUT_VALID0x04) | |||
1135 | && (p_output->config.i_config & OUTPUT_DVB0x20) | |||
1136 | && p_output->p_nit_section != NULL((void*)0) ) | |||
1137 | OutputPSISection( p_output, p_output->p_nit_section, NIT_PID0x10, | |||
1138 | &p_output->i_nit_cc, i_dts, NULL((void*)0), NULL((void*)0) ); | |||
1139 | } | |||
1140 | } | |||
1141 | ||||
1142 | /***************************************************************************** | |||
1143 | * SendSDT | |||
1144 | *****************************************************************************/ | |||
1145 | static void SendSDT( mtime_t i_dts ) | |||
1146 | { | |||
1147 | int i; | |||
1148 | ||||
1149 | for ( i = 0; i < i_nb_outputs; i++ ) | |||
1150 | { | |||
1151 | output_t *p_output = pp_outputs[i]; | |||
1152 | ||||
1153 | if ( (p_output->config.i_config & OUTPUT_VALID0x04) | |||
1154 | && (p_output->config.i_config & OUTPUT_DVB0x20) | |||
1155 | && p_output->p_sdt_section != NULL((void*)0) ) | |||
1156 | OutputPSISection( p_output, p_output->p_sdt_section, SDT_PID0x11, | |||
1157 | &p_output->i_sdt_cc, i_dts, NULL((void*)0), NULL((void*)0) ); | |||
1158 | } | |||
1159 | } | |||
1160 | ||||
1161 | /***************************************************************************** | |||
1162 | * SendEIT | |||
1163 | *****************************************************************************/ | |||
1164 | static void SendEIT( sid_t *p_sid, mtime_t i_dts, uint8_t *p_eit ) | |||
1165 | { | |||
1166 | uint8_t i_table_id = psi_get_tableid( p_eit ); | |||
1167 | bool_Bool b_epg = i_table_id >= EIT_TABLE_ID_SCHED_ACTUAL_FIRST0x50 && | |||
1168 | i_table_id <= EIT_TABLE_ID_SCHED_ACTUAL_LAST0x5f; | |||
1169 | int i; | |||
1170 | ||||
1171 | for ( i = 0; i < i_nb_outputs; i++ ) | |||
1172 | { | |||
1173 | output_t *p_output = pp_outputs[i]; | |||
1174 | ||||
1175 | if ( (p_output->config.i_config & OUTPUT_VALID0x04) | |||
1176 | && (p_output->config.i_config & OUTPUT_DVB0x20) | |||
1177 | && (!b_epg || (p_output->config.i_config & OUTPUT_EPG0x40)) | |||
1178 | && p_output->config.i_sid == p_sid->i_sid ) | |||
1179 | { | |||
1180 | eit_set_tsid( p_eit, p_output->i_tsid ); | |||
1181 | ||||
1182 | if ( p_output->config.i_new_sid ) | |||
1183 | eit_set_sidpsi_set_tableidext( p_eit, p_output->config.i_new_sid ); | |||
1184 | else | |||
1185 | eit_set_sidpsi_set_tableidext( p_eit, p_output->config.i_sid ); | |||
1186 | ||||
1187 | psi_set_crc( p_eit ); | |||
1188 | ||||
1189 | OutputPSISection( p_output, p_eit, EIT_PID0x12, &p_output->i_eit_cc, | |||
1190 | i_dts, &p_output->p_eit_ts_buffer, | |||
1191 | &p_output->i_eit_ts_buffer_offset ); | |||
1192 | } | |||
1193 | } | |||
1194 | } | |||
1195 | ||||
1196 | /***************************************************************************** | |||
1197 | * FlushEIT | |||
1198 | *****************************************************************************/ | |||
1199 | static void FlushEIT( output_t *p_output, mtime_t i_dts ) | |||
1200 | { | |||
1201 | block_t *p_block = p_output->p_eit_ts_buffer; | |||
1202 | ||||
1203 | psi_split_end( p_block->p_ts, &p_output->i_eit_ts_buffer_offset ); | |||
1204 | p_block->i_dts = i_dts; | |||
1205 | p_block->i_refcount--; | |||
1206 | output_Put( p_output, p_block ); | |||
1207 | p_output->p_eit_ts_buffer = NULL((void*)0); | |||
1208 | p_output->i_eit_ts_buffer_offset = 0; | |||
1209 | } | |||
1210 | ||||
1211 | /***************************************************************************** | |||
1212 | * SendTDT | |||
1213 | *****************************************************************************/ | |||
1214 | static void SendTDT( block_t *p_ts ) | |||
1215 | { | |||
1216 | int i; | |||
1217 | ||||
1218 | for ( i = 0; i < i_nb_outputs; i++ ) | |||
1219 | { | |||
1220 | output_t *p_output = pp_outputs[i]; | |||
1221 | ||||
1222 | if ( (p_output->config.i_config & OUTPUT_VALID0x04) | |||
1223 | && (p_output->config.i_config & OUTPUT_DVB0x20) | |||
1224 | && p_output->p_sdt_section != NULL((void*)0) ) | |||
1225 | output_Put( p_output, p_ts ); | |||
1226 | } | |||
1227 | } | |||
1228 | /***************************************************************************** | |||
1229 | * SendEMM | |||
1230 | *****************************************************************************/ | |||
1231 | static void SendEMM( block_t *p_ts ) | |||
1232 | { | |||
1233 | int i; | |||
1234 | ||||
1235 | for ( i = 0; i < i_nb_outputs; i++ ) | |||
1236 | { | |||
1237 | output_t *p_output = pp_outputs[i]; | |||
1238 | ||||
1239 | if ( (p_output->config.i_config & OUTPUT_VALID0x04) ) | |||
1240 | output_Put( p_output, p_ts ); | |||
1241 | } | |||
1242 | } | |||
1243 | ||||
1244 | /***************************************************************************** | |||
1245 | * NewPAT | |||
1246 | *****************************************************************************/ | |||
1247 | static void NewPAT( output_t *p_output ) | |||
1248 | { | |||
1249 | const uint8_t *p_program; | |||
1250 | uint8_t *p; | |||
1251 | uint8_t k = 0; | |||
1252 | ||||
1253 | free( p_output->p_pat_section ); | |||
1254 | p_output->p_pat_section = NULL((void*)0); | |||
1255 | p_output->i_pat_version++; | |||
1256 | ||||
1257 | if ( !p_output->config.i_sid ) return; | |||
1258 | if ( !psi_table_validate(pp_current_pat_sections) ) return; | |||
1259 | ||||
1260 | p_program = pat_table_find_program( pp_current_pat_sections, | |||
1261 | p_output->config.i_sid ); | |||
1262 | if ( p_program == NULL((void*)0) ) return; | |||
1263 | ||||
1264 | p = p_output->p_pat_section = psi_allocate(); | |||
1265 | pat_init( p ); | |||
1266 | psi_set_length( p, PSI_MAX_SIZE1021 ); | |||
1267 | pat_set_tsidpsi_set_tableidext( p, p_output->i_tsid ); | |||
1268 | psi_set_version( p, p_output->i_pat_version ); | |||
1269 | psi_set_current( p ); | |||
1270 | psi_set_section( p, 0 ); | |||
1271 | psi_set_lastsection( p, 0 ); | |||
1272 | ||||
1273 | if ( p_output->config.i_config & OUTPUT_DVB0x20 ) | |||
1274 | { | |||
1275 | /* NIT */ | |||
1276 | p = pat_get_program( p_output->p_pat_section, k++ ); | |||
1277 | patn_init( p ); | |||
1278 | patn_set_program( p, 0 ); | |||
1279 | patn_set_pid( p, NIT_PID0x10 ); | |||
1280 | } | |||
1281 | ||||
1282 | p = pat_get_program( p_output->p_pat_section, k++ ); | |||
1283 | patn_init( p ); | |||
1284 | if ( p_output->config.i_new_sid ) | |||
1285 | { | |||
1286 | msg_Dbg( NULL((void*)0), "Mapping PAT SID %d to %d", p_output->config.i_sid, | |||
1287 | p_output->config.i_new_sid ); | |||
1288 | patn_set_program( p, p_output->config.i_new_sid ); | |||
1289 | } | |||
1290 | else | |||
1291 | patn_set_program( p, p_output->config.i_sid ); | |||
1292 | ||||
1293 | if ( b_do_remap ) | |||
1294 | { | |||
1295 | msg_Dbg( NULL((void*)0), "Mapping PMT PID %d to %d", patn_get_pid( p_program ), pi_newpids[I_PMTPID] ); | |||
1296 | patn_set_pid( p, pi_newpids[I_PMTPID]); | |||
1297 | } else if ( p_output->config.b_do_remap && p_output->config.pi_confpids[I_PMTPID] ) { | |||
1298 | msg_Dbg( NULL((void*)0), "Mapping PMT PID %d to %d", patn_get_pid( p_program ), p_output->config.pi_confpids[I_PMTPID] ); | |||
1299 | patn_set_pid( p, p_output->config.pi_confpids[I_PMTPID]); | |||
1300 | } else { | |||
1301 | patn_set_pid( p, patn_get_pid( p_program ) ); | |||
1302 | } | |||
1303 | ||||
1304 | p = pat_get_program( p_output->p_pat_section, k ); | |||
1305 | pat_set_length( p_output->p_pat_section, | |||
1306 | p - p_output->p_pat_section - PAT_HEADER_SIZE8 ); | |||
1307 | psi_set_crc( p_output->p_pat_section ); | |||
1308 | } | |||
1309 | ||||
1310 | /***************************************************************************** | |||
1311 | * NewPMT | |||
1312 | *****************************************************************************/ | |||
1313 | static void CopyDescriptors( uint8_t *p_descs, uint8_t *p_current_descs ) | |||
1314 | { | |||
1315 | uint8_t *p_desc; | |||
1316 | const uint8_t *p_current_desc; | |||
1317 | uint16_t j = 0, k = 0; | |||
1318 | ||||
1319 | descs_set_length( p_descs, DESCS_MAX_SIZE4095 ); | |||
1320 | ||||
1321 | while ( (p_current_desc = descs_get_desc( p_current_descs, j )) != NULL((void*)0) ) | |||
1322 | { | |||
1323 | uint8_t i_tag = desc_get_tag( p_current_desc ); | |||
1324 | ||||
1325 | j++; | |||
1326 | if ( !b_enable_ecm && i_tag == 0x9 ) continue; | |||
1327 | ||||
1328 | p_desc = descs_get_desc( p_descs, k ); | |||
1329 | if ( p_desc == NULL((void*)0) ) continue; /* This shouldn't happen */ | |||
1330 | k++; | |||
1331 | memcpy( p_desc, p_current_desc, | |||
1332 | DESC_HEADER_SIZE2 + desc_get_length( p_current_desc ) ); | |||
1333 | } | |||
1334 | ||||
1335 | p_desc = descs_get_desc( p_descs, k ); | |||
1336 | if ( p_desc == NULL((void*)0) ) | |||
1337 | /* This shouldn't happen if the incoming PMT is valid */ | |||
1338 | descs_set_length( p_descs, 0 ); | |||
1339 | else | |||
1340 | descs_set_length( p_descs, p_desc - p_descs - DESCS_HEADER_SIZE2 ); | |||
1341 | } | |||
1342 | ||||
1343 | static void NewPMT( output_t *p_output ) | |||
1344 | { | |||
1345 | sid_t *p_sid; | |||
1346 | uint8_t *p_current_pmt; | |||
1347 | uint8_t *p_es, *p_current_es; | |||
1348 | uint8_t *p; | |||
1349 | uint16_t j, k; | |||
1350 | uint16_t i_pcrpid; | |||
1351 | ||||
1352 | free( p_output->p_pmt_section ); | |||
1353 | p_output->p_pmt_section = NULL((void*)0); | |||
1354 | p_output->i_pmt_version++; | |||
1355 | ||||
1356 | if ( !p_output->config.i_sid ) return; | |||
1357 | ||||
1358 | p_sid = FindSID( p_output->config.i_sid ); | |||
1359 | if ( p_sid == NULL((void*)0) ) return; | |||
1360 | ||||
1361 | if ( p_sid->p_current_pmt == NULL((void*)0) ) return; | |||
1362 | p_current_pmt = p_sid->p_current_pmt; | |||
1363 | ||||
1364 | p = p_output->p_pmt_section = psi_allocate(); | |||
1365 | pmt_init( p ); | |||
1366 | psi_set_length( p, PSI_MAX_SIZE1021 ); | |||
1367 | if ( p_output->config.i_new_sid ) | |||
1368 | { | |||
1369 | msg_Dbg( NULL((void*)0), "Mapping PMT SID %d to %d", p_output->config.i_sid, | |||
1370 | p_output->config.i_new_sid ); | |||
1371 | pmt_set_programpsi_set_tableidext( p, p_output->config.i_new_sid ); | |||
1372 | } | |||
1373 | else | |||
1374 | pmt_set_programpsi_set_tableidext( p, p_output->config.i_sid ); | |||
1375 | psi_set_version( p, p_output->i_pmt_version ); | |||
1376 | psi_set_current( p ); | |||
1377 | pmt_set_desclength( p, 0 ); | |||
1378 | init_pid_mapping( p_output ); | |||
1379 | ||||
1380 | ||||
1381 | CopyDescriptors( pmt_get_descs( p ), pmt_get_descs( p_current_pmt ) ); | |||
1382 | ||||
1383 | j = 0; k = 0; | |||
1384 | while ( (p_current_es = pmt_get_es( p_current_pmt, j )) != NULL((void*)0) ) | |||
1385 | { | |||
1386 | uint16_t i_pid = pmtn_get_pid( p_current_es ); | |||
1387 | ||||
1388 | j++; | |||
1389 | if ( (p_output->config.i_nb_pids || !PIDWouldBeSelected( p_current_es )) | |||
1390 | && !IsIn( p_output->config.pi_pids, p_output->config.i_nb_pids, | |||
1391 | i_pid ) ) | |||
1392 | continue; | |||
1393 | ||||
1394 | p_es = pmt_get_es( p, k ); | |||
1395 | if ( p_es == NULL((void*)0) ) continue; /* This shouldn't happen */ | |||
1396 | k++; | |||
1397 | pmtn_init( p_es ); | |||
1398 | pmtn_set_streamtype( p_es, pmtn_get_streamtype( p_current_es ) ); | |||
1399 | pmtn_set_pid( p_es, map_es_pid(p_output, p_current_es, i_pid) ); | |||
1400 | pmtn_set_desclength( p_es, 0 ); | |||
1401 | ||||
1402 | CopyDescriptors( pmtn_get_descs( p_es ), | |||
1403 | pmtn_get_descs( p_current_es ) ); | |||
1404 | } | |||
1405 | ||||
1406 | /* Do the pcr pid after everything else as it may have been remapped */ | |||
1407 | i_pcrpid = pmt_get_pcrpid( p_current_pmt ); | |||
1408 | if ( p_output->pi_newpids[i_pcrpid] != UNUSED_PID(8192 + 1) ) { | |||
1409 | msg_Dbg( NULL((void*)0), "REMAP: The PCR PID was changed from 0x%x (%u) to 0x%x (%u)", | |||
1410 | i_pcrpid, i_pcrpid, p_output->pi_newpids[i_pcrpid], p_output->pi_newpids[i_pcrpid] ); | |||
1411 | i_pcrpid = p_output->pi_newpids[i_pcrpid]; | |||
1412 | } else { | |||
1413 | msg_Dbg( NULL((void*)0), "The PCR PID has kept its original value of 0x%x (%u)", i_pcrpid, i_pcrpid); | |||
1414 | } | |||
1415 | pmt_set_pcrpid( p, i_pcrpid ); | |||
1416 | p_es = pmt_get_es( p, k ); | |||
1417 | if ( p_es == NULL((void*)0) ) | |||
1418 | /* This shouldn't happen if the incoming PMT is valid */ | |||
1419 | pmt_set_length( p, 0 ); | |||
1420 | else | |||
1421 | pmt_set_length( p, p_es - p - PMT_HEADER_SIZE(8 + 4) ); | |||
1422 | psi_set_crc( p ); | |||
1423 | } | |||
1424 | ||||
1425 | /***************************************************************************** | |||
1426 | * NewNIT | |||
1427 | *****************************************************************************/ | |||
1428 | static void NewNIT( output_t *p_output ) | |||
1429 | { | |||
1430 | uint8_t *p_ts; | |||
1431 | uint8_t *p_header2; | |||
1432 | uint8_t *p; | |||
1433 | ||||
1434 | free( p_output->p_nit_section ); | |||
1435 | p_output->p_nit_section = NULL((void*)0); | |||
1436 | p_output->i_nit_version++; | |||
1437 | ||||
1438 | p = p_output->p_nit_section = psi_allocate(); | |||
1439 | nit_init( p, true1 ); | |||
1440 | nit_set_length( p, PSI_MAX_SIZE1021 ); | |||
1441 | nit_set_nidpsi_set_tableidext( p, i_network_id ); | |||
1442 | psi_set_version( p, p_output->i_nit_version ); | |||
1443 | psi_set_current( p ); | |||
1444 | psi_set_section( p, 0 ); | |||
1445 | psi_set_lastsection( p, 0 ); | |||
1446 | ||||
1447 | if ( p_network_name != NULL((void*)0) ) | |||
1448 | { | |||
1449 | uint8_t *p_descs; | |||
1450 | uint8_t *p_desc; | |||
1451 | nit_set_desclength( p, DESCS_MAX_SIZE4095 ); | |||
1452 | p_descs = nit_get_descs( p ); | |||
1453 | p_desc = descs_get_desc( p_descs, 0 ); | |||
1454 | desc40_init( p_desc ); | |||
1455 | desc40_set_networkname( p_desc, p_network_name, i_network_name_size ); | |||
1456 | p_desc = descs_get_desc( p_descs, 1 ); | |||
1457 | descs_set_length( p_descs, p_desc - p_descs - DESCS_HEADER_SIZE2 ); | |||
1458 | } | |||
1459 | else | |||
1460 | nit_set_desclength( p, 0 ); | |||
1461 | ||||
1462 | p_header2 = nit_get_header2( p ); | |||
1463 | nith_init( p_header2 ); | |||
1464 | nith_set_tslength( p_header2, NIT_TS_SIZE6 ); | |||
1465 | ||||
1466 | p_ts = nit_get_ts( p, 0 ); | |||
1467 | nitn_init( p_ts ); | |||
1468 | nitn_set_tsid( p_ts, p_output->i_tsid ); | |||
1469 | nitn_set_onid( p_ts, i_network_id ); | |||
1470 | nitn_set_desclength( p_ts, 0 ); | |||
1471 | ||||
1472 | p_ts = nit_get_ts( p, 1 ); | |||
1473 | if ( p_ts == NULL((void*)0) ) | |||
1474 | /* This shouldn't happen */ | |||
1475 | nit_set_length( p, 0 ); | |||
1476 | else | |||
1477 | nit_set_length( p, p_ts - p - NIT_HEADER_SIZE(8 + 2) ); | |||
1478 | psi_set_crc( p_output->p_nit_section ); | |||
1479 | } | |||
1480 | ||||
1481 | /***************************************************************************** | |||
1482 | * NewSDT | |||
1483 | *****************************************************************************/ | |||
1484 | static void NewSDT( output_t *p_output ) | |||
1485 | { | |||
1486 | uint8_t *p_service, *p_current_service; | |||
1487 | uint8_t *p; | |||
1488 | ||||
1489 | free( p_output->p_sdt_section ); | |||
1490 | p_output->p_sdt_section = NULL((void*)0); | |||
1491 | p_output->i_sdt_version++; | |||
1492 | ||||
1493 | if ( !p_output->config.i_sid ) return; | |||
1494 | if ( !psi_table_validate(pp_current_sdt_sections) ) return; | |||
1495 | ||||
1496 | p_current_service = sdt_table_find_service( pp_current_sdt_sections, | |||
1497 | p_output->config.i_sid ); | |||
1498 | ||||
1499 | if ( p_current_service == NULL((void*)0) ) | |||
1500 | { | |||
1501 | if ( p_output->p_pat_section != NULL((void*)0) && | |||
1502 | pat_get_program( p_output->p_pat_section, 0 ) == NULL((void*)0) ) | |||
1503 | { | |||
1504 | /* Empty PAT and no SDT anymore */ | |||
1505 | free( p_output->p_pat_section ); | |||
1506 | p_output->p_pat_section = NULL((void*)0); | |||
1507 | p_output->i_pat_version++; | |||
1508 | } | |||
1509 | return; | |||
1510 | } | |||
1511 | ||||
1512 | p = p_output->p_sdt_section = psi_allocate(); | |||
1513 | sdt_init( p, true1 ); | |||
1514 | sdt_set_length( p, PSI_MAX_SIZE1021 ); | |||
1515 | sdt_set_tsidpsi_set_tableidext( p, p_output->i_tsid ); | |||
1516 | psi_set_version( p, p_output->i_sdt_version ); | |||
1517 | psi_set_current( p ); | |||
1518 | psi_set_section( p, 0 ); | |||
1519 | psi_set_lastsection( p, 0 ); | |||
1520 | sdt_set_onid( p, | |||
1521 | sdt_get_onid( psi_table_get_section( pp_current_sdt_sections, 0 ) ) ); | |||
1522 | ||||
1523 | p_service = sdt_get_service( p, 0 ); | |||
1524 | sdtn_init( p_service ); | |||
1525 | if ( p_output->config.i_new_sid ) | |||
1526 | { | |||
1527 | msg_Dbg( NULL((void*)0), "Mapping SDT SID %d to %d", p_output->config.i_sid, | |||
1528 | p_output->config.i_new_sid ); | |||
1529 | sdtn_set_sid( p_service, p_output->config.i_new_sid ); | |||
1530 | } | |||
1531 | else | |||
1532 | sdtn_set_sid( p_service, p_output->config.i_sid ); | |||
1533 | ||||
1534 | if ( (p_output->config.i_config & OUTPUT_EPG0x40) == OUTPUT_EPG0x40 ) | |||
1535 | { | |||
1536 | sdtn_set_eitschedule(p_service); | |||
1537 | sdtn_set_eitpresent(p_service); | |||
1538 | } else { | |||
1539 | if ( sdtn_get_eitschedule(p_current_service) ) | |||
1540 | sdtn_set_eitschedule(p_service); | |||
1541 | if ( sdtn_get_eitpresent(p_current_service) ) | |||
1542 | sdtn_set_eitpresent(p_service); | |||
1543 | } | |||
1544 | ||||
1545 | sdtn_set_running( p_service, sdtn_get_running(p_current_service) ); | |||
1546 | /* Do not set free_ca */ | |||
1547 | sdtn_set_desclength( p_service, sdtn_get_desclength(p_current_service) ); | |||
1548 | ||||
1549 | char *p_new_provider = p_output->config.psz_service_provider; | |||
1550 | char *p_new_service = p_output->config.psz_service_name; | |||
1551 | ||||
1552 | if ( !p_new_provider && !p_new_service ) { | |||
1553 | /* Copy all descriptors unchanged */ | |||
1554 | memcpy( descs_get_desc( sdtn_get_descs(p_service), 0 ), | |||
1555 | descs_get_desc( sdtn_get_descs(p_current_service), 0 ), | |||
1556 | sdtn_get_desclength(p_current_service) ); | |||
1557 | } else { | |||
1558 | int j = 0, i_total_desc_len = 0; | |||
1559 | uint8_t *p_desc; | |||
1560 | uint8_t *p_new_desc = descs_get_desc( sdtn_get_descs(p_service), 0 ); | |||
1561 | while ( (p_desc = descs_get_desc( sdtn_get_descs( p_current_service ), j++ )) != NULL((void*)0) ) | |||
1562 | { | |||
1563 | /* Regenerate descriptor 48 (service name) */ | |||
1564 | if ( desc_get_tag( p_desc ) == 0x48 && desc48_validate( p_desc ) ) | |||
1565 | { | |||
1566 | uint8_t i_old_provider_len, i_old_service_len; | |||
1567 | uint8_t i_new_desc_len = 3; /* 1 byte - type, 1 byte provider_len, 1 byte service_len */ | |||
1568 | char *p_new_provider = p_output->config.psz_service_provider; | |||
1569 | char *p_new_service = p_output->config.psz_service_name; | |||
1570 | const uint8_t *p_old_provider = desc48_get_provider( p_desc, &i_old_provider_len ); | |||
1571 | const uint8_t *p_old_service = desc48_get_service( p_desc, &i_old_service_len ); | |||
1572 | ||||
1573 | desc48_init( p_new_desc ); | |||
1574 | desc48_set_type( p_new_desc, desc48_get_type( p_desc ) ); | |||
1575 | ||||
1576 | if ( p_new_provider ) { | |||
1577 | desc48_set_provider( p_new_desc, (uint8_t *)p_new_provider, strlen( p_new_provider ) ); | |||
1578 | i_new_desc_len += strlen( p_new_provider ); | |||
1579 | } else { | |||
1580 | desc48_set_provider( p_new_desc, p_old_provider, i_old_provider_len ); | |||
1581 | i_new_desc_len += i_old_provider_len; | |||
1582 | } | |||
1583 | ||||
1584 | if ( p_new_service ) { | |||
1585 | desc48_set_service( p_new_desc, (uint8_t *)p_new_service, strlen( p_new_service ) ); | |||
1586 | i_new_desc_len += strlen( p_new_service ); | |||
1587 | } else { | |||
1588 | desc48_set_service( p_new_desc, p_old_service, i_old_service_len ); | |||
1589 | i_new_desc_len += i_old_service_len; | |||
1590 | } | |||
1591 | desc_set_length( p_new_desc, i_new_desc_len ); | |||
1592 | i_total_desc_len += DESC_HEADER_SIZE2 + i_new_desc_len; | |||
1593 | p_new_desc += DESC_HEADER_SIZE2 + i_new_desc_len; | |||
1594 | } else { | |||
1595 | /* Copy single descriptor */ | |||
1596 | int i_desc_len = DESC_HEADER_SIZE2 + desc_get_length( p_desc ); | |||
1597 | memcpy( p_new_desc, p_desc, i_desc_len ); | |||
1598 | p_new_desc += i_desc_len; | |||
1599 | i_total_desc_len += i_desc_len; | |||
1600 | } | |||
1601 | } | |||
1602 | sdtn_set_desclength( p_service, i_total_desc_len ); | |||
1603 | } | |||
1604 | ||||
1605 | p_service = sdt_get_service( p, 1 ); | |||
1606 | if ( p_service == NULL((void*)0) ) | |||
1607 | /* This shouldn't happen if the incoming SDT is valid */ | |||
1608 | sdt_set_length( p, 0 ); | |||
1609 | else | |||
1610 | sdt_set_length( p, p_service - p - SDT_HEADER_SIZE(8 + 3) ); | |||
1611 | psi_set_crc( p_output->p_sdt_section ); | |||
1612 | } | |||
1613 | ||||
1614 | /***************************************************************************** | |||
1615 | * UpdatePAT/PMT/SDT | |||
1616 | *****************************************************************************/ | |||
1617 | #define DECLARE_UPDATE_FUNC( table )static void Updatetable( uint16_t i_sid ) { int i; for ( i = 0 ; i < i_nb_outputs; i++ ) if ( ( pp_outputs[i]->config. i_config & 0x04 ) && pp_outputs[i]->config.i_sid == i_sid ) Newtable( pp_outputs[i] ); } \ | |||
1618 | static void Update##table( uint16_t i_sid ) \ | |||
1619 | { \ | |||
1620 | int i; \ | |||
1621 | \ | |||
1622 | for ( i = 0; i < i_nb_outputs; i++ ) \ | |||
1623 | if ( ( pp_outputs[i]->config.i_config & OUTPUT_VALID0x04 ) \ | |||
1624 | && pp_outputs[i]->config.i_sid == i_sid ) \ | |||
1625 | New##table( pp_outputs[i] ); \ | |||
1626 | } | |||
1627 | ||||
1628 | DECLARE_UPDATE_FUNC(PAT)static void UpdatePAT( uint16_t i_sid ) { int i; for ( i = 0; i < i_nb_outputs; i++ ) if ( ( pp_outputs[i]->config.i_config & 0x04 ) && pp_outputs[i]->config.i_sid == i_sid ) NewPAT( pp_outputs[i] ); } | |||
1629 | DECLARE_UPDATE_FUNC(PMT)static void UpdatePMT( uint16_t i_sid ) { int i; for ( i = 0; i < i_nb_outputs; i++ ) if ( ( pp_outputs[i]->config.i_config & 0x04 ) && pp_outputs[i]->config.i_sid == i_sid ) NewPMT( pp_outputs[i] ); } | |||
1630 | DECLARE_UPDATE_FUNC(SDT)static void UpdateSDT( uint16_t i_sid ) { int i; for ( i = 0; i < i_nb_outputs; i++ ) if ( ( pp_outputs[i]->config.i_config & 0x04 ) && pp_outputs[i]->config.i_sid == i_sid ) NewSDT( pp_outputs[i] ); } | |||
1631 | ||||
1632 | /***************************************************************************** | |||
1633 | * UpdateTSID | |||
1634 | *****************************************************************************/ | |||
1635 | static void UpdateTSID(void) | |||
1636 | { | |||
1637 | uint16_t i_tsid = psi_table_get_tableidext(pp_current_pat_sections)psi_get_tableidext(pp_current_pat_sections[0]); | |||
1638 | int i; | |||
1639 | ||||
1640 | for ( i = 0; i < i_nb_outputs; i++ ) | |||
1641 | { | |||
1642 | output_t *p_output = pp_outputs[i]; | |||
1643 | ||||
1644 | if ( (p_output->config.i_config & OUTPUT_VALID0x04) | |||
1645 | && p_output->config.i_tsid == -1 && !b_random_tsid ) | |||
1646 | { | |||
1647 | p_output->i_tsid = i_tsid; | |||
1648 | NewNIT( p_output ); | |||
1649 | } | |||
1650 | } | |||
1651 | } | |||
1652 | ||||
1653 | /***************************************************************************** | |||
1654 | * SIDIsSelected | |||
1655 | *****************************************************************************/ | |||
1656 | static bool_Bool SIDIsSelected( uint16_t i_sid ) | |||
1657 | { | |||
1658 | int i; | |||
1659 | ||||
1660 | for ( i = 0; i < i_nb_outputs; i++ ) | |||
1661 | if ( (pp_outputs[i]->config.i_config & OUTPUT_VALID0x04) | |||
1662 | && pp_outputs[i]->config.i_sid == i_sid ) | |||
1663 | return true1; | |||
1664 | ||||
1665 | return false0; | |||
1666 | } | |||
1667 | ||||
1668 | /***************************************************************************** | |||
1669 | * demux_PIDIsSelected | |||
1670 | *****************************************************************************/ | |||
1671 | bool_Bool demux_PIDIsSelected( uint16_t i_pid ) | |||
1672 | { | |||
1673 | int i; | |||
1674 | ||||
1675 | for ( i = 0; i < p_pids[i_pid].i_nb_outputs; i++ ) | |||
1676 | if ( p_pids[i_pid].pp_outputs[i] != NULL((void*)0) ) | |||
1677 | return true1; | |||
1678 | ||||
1679 | return false0; | |||
1680 | } | |||
1681 | ||||
1682 | /***************************************************************************** | |||
1683 | * PIDWouldBeSelected | |||
1684 | *****************************************************************************/ | |||
1685 | static bool_Bool PIDWouldBeSelected( uint8_t *p_es ) | |||
1686 | { | |||
1687 | if ( b_any_type ) return true1; | |||
1688 | ||||
1689 | uint8_t i_type = pmtn_get_streamtype( p_es ); | |||
1690 | ||||
1691 | switch ( i_type ) | |||
1692 | { | |||
1693 | case 0x1: /* video MPEG-1 */ | |||
1694 | case 0x2: /* video */ | |||
1695 | case 0x3: /* audio MPEG-1 */ | |||
1696 | case 0x4: /* audio */ | |||
1697 | case 0xf: /* audio AAC ADTS */ | |||
1698 | case 0x10: /* video MPEG-4 */ | |||
1699 | case 0x11: /* audio AAC LATM */ | |||
1700 | case 0x1b: /* video H264 */ | |||
1701 | case 0x81: /* ATSC A/52 */ | |||
1702 | case 0x87: /* ATSC Enhanced A/52 */ | |||
1703 | return true1; | |||
1704 | break; | |||
1705 | ||||
1706 | case 0x6: | |||
1707 | { | |||
1708 | uint16_t j = 0; | |||
1709 | const uint8_t *p_desc; | |||
1710 | ||||
1711 | while ( (p_desc = descs_get_desc( pmtn_get_descs( p_es ), j )) != NULL((void*)0) ) | |||
1712 | { | |||
1713 | uint8_t i_tag = desc_get_tag( p_desc ); | |||
1714 | j++; | |||
1715 | ||||
1716 | if( i_tag == 0x46 /* VBI + teletext */ | |||
1717 | || i_tag == 0x56 /* teletext */ | |||
1718 | || i_tag == 0x59 /* dvbsub */ | |||
1719 | || i_tag == 0x6a /* A/52 */ | |||
1720 | || i_tag == 0x7a /* Enhanced A/52 */ | |||
1721 | || i_tag == 0x7b /* DCA */ | |||
1722 | || i_tag == 0x7c /* AAC */ ) | |||
1723 | return true1; | |||
1724 | } | |||
1725 | break; | |||
1726 | } | |||
1727 | ||||
1728 | default: | |||
1729 | break; | |||
1730 | } | |||
1731 | ||||
1732 | /* FIXME: also parse IOD */ | |||
1733 | return false0; | |||
1734 | } | |||
1735 | ||||
1736 | /***************************************************************************** | |||
1737 | * PIDCarriesPES | |||
1738 | *****************************************************************************/ | |||
1739 | static bool_Bool PIDCarriesPES( const uint8_t *p_es ) | |||
1740 | { | |||
1741 | uint8_t i_type = pmtn_get_streamtype( p_es ); | |||
1742 | ||||
1743 | switch ( i_type ) | |||
1744 | { | |||
1745 | case 0x1: /* video MPEG-1 */ | |||
1746 | case 0x2: /* video */ | |||
1747 | case 0x3: /* audio MPEG-1 */ | |||
1748 | case 0x4: /* audio */ | |||
1749 | case 0x6: /* private PES data */ | |||
1750 | case 0xf: /* audio AAC */ | |||
1751 | case 0x10: /* video MPEG-4 */ | |||
1752 | case 0x11: /* audio AAC LATM */ | |||
1753 | case 0x1b: /* video H264 */ | |||
1754 | case 0x81: /* ATSC A/52 */ | |||
1755 | case 0x87: /* ATSC Enhanced A/52 */ | |||
1756 | return true1; | |||
1757 | break; | |||
1758 | ||||
1759 | default: | |||
1760 | return false0; | |||
1761 | break; | |||
1762 | } | |||
1763 | } | |||
1764 | ||||
1765 | /***************************************************************************** | |||
1766 | * PMTNeedsDescrambling | |||
1767 | *****************************************************************************/ | |||
1768 | static bool_Bool PMTNeedsDescrambling( uint8_t *p_pmt ) | |||
1769 | { | |||
1770 | uint8_t i; | |||
1771 | uint16_t j; | |||
1772 | uint8_t *p_es; | |||
1773 | const uint8_t *p_desc; | |||
1774 | ||||
1775 | j = 0; | |||
1776 | while ( (p_desc = descs_get_desc( pmt_get_descs( p_pmt ), j )) != NULL((void*)0) ) | |||
1777 | { | |||
1778 | uint8_t i_tag = desc_get_tag( p_desc ); | |||
1779 | j++; | |||
1780 | ||||
1781 | if ( i_tag == 0x9 ) return true1; | |||
1782 | } | |||
1783 | ||||
1784 | i = 0; | |||
1785 | while ( (p_es = pmt_get_es( p_pmt, i )) != NULL((void*)0) ) | |||
1786 | { | |||
1787 | i++; | |||
1788 | j = 0; | |||
1789 | while ( (p_desc = descs_get_desc( pmtn_get_descs( p_es ), j )) != NULL((void*)0) ) | |||
1790 | { | |||
1791 | uint8_t i_tag = desc_get_tag( p_desc ); | |||
1792 | j++; | |||
1793 | ||||
1794 | if ( i_tag == 0x9 ) return true1; | |||
1795 | } | |||
1796 | } | |||
1797 | ||||
1798 | return false0; | |||
1799 | } | |||
1800 | ||||
1801 | /***************************************************************************** | |||
1802 | * demux_ResendCAPMTs | |||
1803 | *****************************************************************************/ | |||
1804 | void demux_ResendCAPMTs( void ) | |||
1805 | { | |||
1806 | int i; | |||
1807 | for ( i = 0; i < i_nb_sids; i++ ) | |||
1808 | if ( pp_sids[i]->p_current_pmt != NULL((void*)0) | |||
1809 | && SIDIsSelected( pp_sids[i]->i_sid ) | |||
1810 | && PMTNeedsDescrambling( pp_sids[i]->p_current_pmt ) ) | |||
1811 | en50221_AddPMT( pp_sids[i]->p_current_pmt ); | |||
1812 | } | |||
1813 | ||||
1814 | /* Find CA descriptor that have PID i_ca_pid */ | |||
1815 | static uint8_t *ca_desc_find( uint8_t *p_descl, uint16_t i_length, | |||
1816 | uint16_t i_ca_pid ) | |||
1817 | { | |||
1818 | int j = 0; | |||
1819 | uint8_t *p_desc; | |||
1820 | ||||
1821 | while ( (p_desc = descl_get_desc( p_descl, i_length, j++ )) != NULL((void*)0) ) { | |||
1822 | if ( desc_get_tag( p_desc ) != 0x09 || !desc09_validate( p_desc ) ) | |||
1823 | continue; | |||
1824 | if ( desc09_get_pid( p_desc ) == i_ca_pid ) | |||
1825 | return p_desc; | |||
1826 | } | |||
1827 | ||||
1828 | return NULL((void*)0); | |||
1829 | } | |||
1830 | ||||
1831 | /***************************************************************************** | |||
1832 | * DeleteProgram | |||
1833 | *****************************************************************************/ | |||
1834 | static void DeleteProgram( uint16_t i_sid, uint16_t i_pid ) | |||
1835 | { | |||
1836 | sid_t *p_sid; | |||
1837 | uint8_t *p_pmt; | |||
1838 | uint8_t *p_desc; | |||
1839 | ||||
1840 | UnselectPMT( i_sid, i_pid ); | |||
1841 | ||||
1842 | p_sid = FindSID( i_sid ); | |||
1843 | if ( p_sid == NULL((void*)0) ) return; | |||
1844 | ||||
1845 | p_pmt = p_sid->p_current_pmt; | |||
1846 | ||||
1847 | if ( p_pmt != NULL((void*)0) ) | |||
1848 | { | |||
1849 | uint16_t i_pcr_pid = pmt_get_pcrpid( p_pmt ); | |||
1850 | uint8_t *p_es; | |||
1851 | uint8_t j; | |||
1852 | ||||
1853 | if ( i_ca_handle && SIDIsSelected( i_sid ) | |||
1854 | && PMTNeedsDescrambling( p_pmt ) ) | |||
1855 | en50221_DeletePMT( p_pmt ); | |||
1856 | ||||
1857 | if ( i_pcr_pid != PADDING_PID8191 | |||
1858 | && i_pcr_pid != p_sid->i_pmt_pid ) | |||
1859 | UnselectPID( i_sid, i_pcr_pid ); | |||
1860 | ||||
1861 | if ( b_enable_ecm ) | |||
1862 | { | |||
1863 | j = 0; | |||
1864 | ||||
1865 | while ((p_desc = descs_get_desc( pmt_get_descs( p_pmt ), j++ )) != NULL((void*)0)) | |||
1866 | { | |||
1867 | if ( desc_get_tag( p_desc ) != 0x09 || | |||
1868 | !desc09_validate( p_desc ) ) | |||
1869 | continue; | |||
1870 | UnselectPID( i_sid, desc09_get_pid( p_desc ) ); | |||
1871 | } | |||
1872 | } | |||
1873 | ||||
1874 | j = 0; | |||
1875 | while ( (p_es = pmt_get_es( p_pmt, j )) != NULL((void*)0) ) | |||
1876 | { | |||
1877 | uint16_t i_pid = pmtn_get_pid( p_es ); | |||
1878 | j++; | |||
1879 | ||||
1880 | if ( PIDWouldBeSelected( p_es ) ) | |||
1881 | UnselectPID( i_sid, i_pid ); | |||
1882 | ||||
1883 | if ( b_enable_ecm ) | |||
1884 | { | |||
1885 | uint8_t k = 0; | |||
1886 | ||||
1887 | while ((p_desc = descs_get_desc( pmtn_get_descs( p_es ), k++ )) != NULL((void*)0)) | |||
1888 | { | |||
1889 | if ( desc_get_tag( p_desc ) != 0x09 || !desc09_validate( p_desc ) ) | |||
1890 | continue; | |||
1891 | UnselectPID( i_sid, desc09_get_pid( p_desc ) ); | |||
1892 | } | |||
1893 | } | |||
1894 | } | |||
1895 | ||||
1896 | free( p_pmt ); | |||
1897 | p_sid->p_current_pmt = NULL((void*)0); | |||
1898 | } | |||
1899 | p_sid->i_sid = 0; | |||
1900 | p_sid->i_pmt_pid = 0; | |||
1901 | } | |||
1902 | ||||
1903 | /***************************************************************************** | |||
1904 | * demux_Iconv | |||
1905 | ***************************************************************************** | |||
1906 | * This code is from biTStream's examples and is under the WTFPL (see | |||
1907 | * LICENSE.WTFPL). | |||
1908 | *****************************************************************************/ | |||
1909 | static char *iconv_append_null(const char *p_string, size_t i_length) | |||
1910 | { | |||
1911 | char *psz_string = malloc(i_length + 1); | |||
1912 | memcpy(psz_string, p_string, i_length); | |||
1913 | psz_string[i_length] = '\0'; | |||
1914 | return psz_string; | |||
1915 | } | |||
1916 | ||||
1917 | char *demux_Iconv(void *_unused, const char *psz_encoding, | |||
1918 | char *p_string, size_t i_length) | |||
1919 | { | |||
1920 | #ifdef HAVE_ICONV | |||
1921 | static const char *psz_current_encoding = ""; | |||
1922 | ||||
1923 | char *psz_string, *p; | |||
1924 | size_t i_out_length; | |||
1925 | ||||
1926 | if (!strcmp(psz_encoding, psz_native_charset)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (psz_encoding) && __builtin_constant_p (psz_native_charset ) && (__s1_len = strlen (psz_encoding), __s2_len = strlen (psz_native_charset), (!((size_t)(const void *)((psz_encoding ) + 1) - (size_t)(const void *)(psz_encoding) == 1) || __s1_len >= 4) && (!((size_t)(const void *)((psz_native_charset ) + 1) - (size_t)(const void *)(psz_native_charset) == 1) || __s2_len >= 4)) ? __builtin_strcmp (psz_encoding, psz_native_charset ) : (__builtin_constant_p (psz_encoding) && ((size_t) (const void *)((psz_encoding) + 1) - (size_t)(const void *)(psz_encoding ) == 1) && (__s1_len = strlen (psz_encoding), __s1_len < 4) ? (__builtin_constant_p (psz_native_charset) && ((size_t)(const void *)((psz_native_charset) + 1) - (size_t) (const void *)(psz_native_charset) == 1) ? __builtin_strcmp ( psz_encoding, psz_native_charset) : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (psz_native_charset ); int __result = (((const unsigned char *) (const char *) (psz_encoding ))[0] - __s2[0]); if (__s1_len > 0 && __result == 0 ) { __result = (((const unsigned char *) (const char *) (psz_encoding ))[1] - __s2[1]); if (__s1_len > 1 && __result == 0 ) { __result = (((const unsigned char *) (const char *) (psz_encoding ))[2] - __s2[2]); if (__s1_len > 2 && __result == 0 ) __result = (((const unsigned char *) (const char *) (psz_encoding ))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p ( psz_native_charset) && ((size_t)(const void *)((psz_native_charset ) + 1) - (size_t)(const void *)(psz_native_charset) == 1) && (__s2_len = strlen (psz_native_charset), __s2_len < 4) ? ( __builtin_constant_p (psz_encoding) && ((size_t)(const void *)((psz_encoding) + 1) - (size_t)(const void *)(psz_encoding ) == 1) ? __builtin_strcmp (psz_encoding, psz_native_charset) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (psz_encoding); int __result = (((const unsigned char *) (const char *) (psz_native_charset))[0] - __s2 [0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (psz_native_charset ))[1] - __s2[1]); if (__s2_len > 1 && __result == 0 ) { __result = (((const unsigned char *) (const char *) (psz_native_charset ))[2] - __s2[2]); if (__s2_len > 2 && __result == 0 ) __result = (((const unsigned char *) (const char *) (psz_native_charset ))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (psz_encoding , psz_native_charset)))); })) | |||
1927 | return iconv_append_null(p_string, i_length); | |||
1928 | ||||
1929 | if (iconv_handle != (iconv_t)-1 && | |||
1930 | strcmp(psz_encoding, psz_current_encoding)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (psz_encoding) && __builtin_constant_p (psz_current_encoding ) && (__s1_len = strlen (psz_encoding), __s2_len = strlen (psz_current_encoding), (!((size_t)(const void *)((psz_encoding ) + 1) - (size_t)(const void *)(psz_encoding) == 1) || __s1_len >= 4) && (!((size_t)(const void *)((psz_current_encoding ) + 1) - (size_t)(const void *)(psz_current_encoding) == 1) || __s2_len >= 4)) ? __builtin_strcmp (psz_encoding, psz_current_encoding ) : (__builtin_constant_p (psz_encoding) && ((size_t) (const void *)((psz_encoding) + 1) - (size_t)(const void *)(psz_encoding ) == 1) && (__s1_len = strlen (psz_encoding), __s1_len < 4) ? (__builtin_constant_p (psz_current_encoding) && ((size_t)(const void *)((psz_current_encoding) + 1) - (size_t )(const void *)(psz_current_encoding) == 1) ? __builtin_strcmp (psz_encoding, psz_current_encoding) : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (psz_current_encoding); int __result = (((const unsigned char *) (const char *) (psz_encoding))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (psz_encoding))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (psz_encoding))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (psz_encoding))[3] - __s2[3]); } } __result ; }))) : (__builtin_constant_p (psz_current_encoding) && ((size_t)(const void *)((psz_current_encoding) + 1) - (size_t )(const void *)(psz_current_encoding) == 1) && (__s2_len = strlen (psz_current_encoding), __s2_len < 4) ? (__builtin_constant_p (psz_encoding) && ((size_t)(const void *)((psz_encoding ) + 1) - (size_t)(const void *)(psz_encoding) == 1) ? __builtin_strcmp (psz_encoding, psz_current_encoding) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (psz_encoding); int __result = (((const unsigned char *) (const char *) (psz_current_encoding))[0] - __s2[0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (psz_current_encoding))[1] - __s2[1]); if ( __s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (psz_current_encoding))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (psz_current_encoding ))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (psz_encoding , psz_current_encoding)))); })) { | |||
1931 | iconv_close(iconv_handle); | |||
1932 | iconv_handle = (iconv_t)-1; | |||
1933 | } | |||
1934 | ||||
1935 | if (iconv_handle == (iconv_t)-1) | |||
1936 | iconv_handle = iconv_open(psz_native_charset, psz_encoding); | |||
1937 | if (iconv_handle == (iconv_t)-1) { | |||
1938 | msg_Warn(NULL((void*)0), "couldn't open converter from %s to %s (%m)", psz_encoding, | |||
1939 | psz_native_charset); | |||
1940 | return iconv_append_null(p_string, i_length); | |||
1941 | } | |||
1942 | ||||
1943 | /* converted strings can be up to six times larger */ | |||
1944 | i_out_length = i_length * 6; | |||
1945 | p = psz_string = malloc(i_out_length); | |||
1946 | if (iconv(iconv_handle, &p_string, &i_length, &p, &i_out_length) == -1) { | |||
1947 | msg_Warn(NULL((void*)0), "couldn't convert from %s to %s (%m)", psz_encoding, | |||
1948 | psz_native_charset); | |||
1949 | free(psz_string); | |||
1950 | return iconv_append_null(p_string, i_length); | |||
1951 | } | |||
1952 | if (i_length) | |||
1953 | msg_Warn(NULL((void*)0), "partial conversion from %s to %s", psz_encoding, | |||
1954 | psz_native_charset); | |||
1955 | ||||
1956 | *p = '\0'; | |||
1957 | return psz_string; | |||
1958 | #else | |||
1959 | return iconv_append_null(p_string, i_length); | |||
1960 | #endif | |||
1961 | } | |||
1962 | ||||
1963 | /***************************************************************************** | |||
1964 | * demux_Print | |||
1965 | ***************************************************************************** | |||
1966 | * This code is from biTStream's examples and is under the WTFPL (see | |||
1967 | * LICENSE.WTFPL). | |||
1968 | *****************************************************************************/ | |||
1969 | __attribute__ ((format(printf, 2, 3))) | |||
1970 | static void demux_Print(void *_unused, const char *psz_format, ...) | |||
1971 | { | |||
1972 | char psz_fmt[strlen(psz_format) + 2]; | |||
1973 | va_list args; | |||
1974 | va_start(args, psz_format)__builtin_va_start(args, psz_format); | |||
1975 | strcpy(psz_fmt, psz_format); | |||
1976 | if ( i_print_type != PRINT_XML ) | |||
1977 | strcat(psz_fmt, "\n"); | |||
1978 | vprintf(psz_fmt, args); | |||
1979 | va_end(args)__builtin_va_end(args); | |||
1980 | } | |||
1981 | ||||
1982 | /***************************************************************************** | |||
1983 | * HandlePAT | |||
1984 | *****************************************************************************/ | |||
1985 | static void HandlePAT( mtime_t i_dts ) | |||
1986 | { | |||
1987 | bool_Bool b_change = false0; | |||
1988 | PSI_TABLE_DECLARE( pp_old_pat_sections )uint8_t *pp_old_pat_sections[256]; | |||
1989 | uint8_t i_last_section = psi_table_get_lastsection( pp_next_pat_sections )psi_get_lastsection(pp_next_pat_sections[0]); | |||
1990 | uint8_t i; | |||
1991 | ||||
1992 | if ( psi_table_validate( pp_current_pat_sections ) && | |||
1993 | psi_table_compare( pp_current_pat_sections, pp_next_pat_sections ) ) | |||
1994 | { | |||
1995 | /* Identical PAT. Shortcut. */ | |||
1996 | psi_table_free( pp_next_pat_sections ); | |||
1997 | psi_table_init( pp_next_pat_sections ); | |||
1998 | goto out_pat; | |||
1999 | } | |||
2000 | ||||
2001 | if ( !pat_table_validate( pp_next_pat_sections ) ) | |||
2002 | { | |||
2003 | msg_Warn( NULL((void*)0), "invalid PAT received" ); | |||
2004 | switch (i_print_type) { | |||
2005 | case PRINT_XML: | |||
2006 | printf("<ERROR type=\"invalid_pat\"/>\n"); | |||
2007 | break; | |||
2008 | default: | |||
2009 | printf("invalid PAT received\n"); | |||
2010 | } | |||
2011 | psi_table_free( pp_next_pat_sections ); | |||
2012 | psi_table_init( pp_next_pat_sections ); | |||
2013 | goto out_pat; | |||
2014 | } | |||
2015 | ||||
2016 | /* Switch tables. */ | |||
2017 | psi_table_copy( pp_old_pat_sections, pp_current_pat_sections ); | |||
2018 | psi_table_copy( pp_current_pat_sections, pp_next_pat_sections ); | |||
2019 | psi_table_init( pp_next_pat_sections ); | |||
2020 | ||||
2021 | if ( !psi_table_validate( pp_old_pat_sections ) | |||
2022 | || psi_table_get_tableidext( pp_current_pat_sections )psi_get_tableidext(pp_current_pat_sections[0]) | |||
2023 | != psi_table_get_tableidext( pp_old_pat_sections )psi_get_tableidext(pp_old_pat_sections[0]) ) | |||
2024 | { | |||
2025 | b_change = true1; | |||
2026 | UpdateTSID(); | |||
2027 | /* This will trigger a universal reset of everything. */ | |||
2028 | } | |||
2029 | ||||
2030 | for ( i = 0; i <= i_last_section; i++ ) | |||
2031 | { | |||
2032 | uint8_t *p_section = | |||
2033 | psi_table_get_section( pp_current_pat_sections, i ); | |||
2034 | const uint8_t *p_program; | |||
2035 | int j = 0; | |||
2036 | ||||
2037 | while ( (p_program = pat_get_program( p_section, j )) != NULL((void*)0) ) | |||
2038 | { | |||
2039 | const uint8_t *p_old_program = NULL((void*)0); | |||
2040 | uint16_t i_sid = patn_get_program( p_program ); | |||
2041 | uint16_t i_pid = patn_get_pid( p_program ); | |||
2042 | j++; | |||
2043 | ||||
2044 | if ( i_sid == 0 ) | |||
2045 | { | |||
2046 | if ( i_pid != NIT_PID0x10 ) | |||
2047 | msg_Warn( NULL((void*)0), | |||
2048 | "NIT is carried on PID %hu which isn't DVB compliant", | |||
2049 | i_pid ); | |||
2050 | continue; /* NIT */ | |||
2051 | } | |||
2052 | ||||
2053 | if ( !psi_table_validate( pp_old_pat_sections ) | |||
2054 | || (p_old_program = pat_table_find_program( | |||
2055 | pp_old_pat_sections, i_sid )) == NULL((void*)0) | |||
2056 | || patn_get_pid( p_old_program ) != i_pid | |||
2057 | || b_change ) | |||
2058 | { | |||
2059 | sid_t *p_sid; | |||
2060 | ||||
2061 | if ( p_old_program != NULL((void*)0) ) | |||
2062 | DeleteProgram( i_sid, patn_get_pid( p_old_program ) ); | |||
2063 | ||||
2064 | SelectPMT( i_sid, i_pid ); | |||
2065 | ||||
2066 | p_sid = FindSID( 0 ); | |||
2067 | if ( p_sid == NULL((void*)0) ) | |||
2068 | { | |||
2069 | p_sid = malloc( sizeof(sid_t) ); | |||
2070 | p_sid->p_current_pmt = NULL((void*)0); | |||
2071 | i_nb_sids++; | |||
2072 | pp_sids = realloc( pp_sids, sizeof(sid_t *) * i_nb_sids ); | |||
2073 | pp_sids[i_nb_sids - 1] = p_sid; | |||
2074 | } | |||
2075 | ||||
2076 | p_sid->i_sid = i_sid; | |||
2077 | p_sid->i_pmt_pid = i_pid; | |||
2078 | ||||
2079 | UpdatePAT( i_sid ); | |||
2080 | } | |||
2081 | } | |||
2082 | } | |||
2083 | ||||
2084 | if ( psi_table_validate( pp_old_pat_sections ) ) | |||
2085 | { | |||
2086 | i_last_section = psi_table_get_lastsection( pp_old_pat_sections )psi_get_lastsection(pp_old_pat_sections[0]); | |||
2087 | for ( i = 0; i <= i_last_section; i++ ) | |||
2088 | { | |||
2089 | uint8_t *p_section = | |||
2090 | psi_table_get_section( pp_old_pat_sections, i ); | |||
2091 | const uint8_t *p_program; | |||
2092 | int j = 0; | |||
2093 | ||||
2094 | while ( (p_program = pat_get_program( p_section, j )) != NULL((void*)0) ) | |||
2095 | { | |||
2096 | uint16_t i_sid = patn_get_program( p_program ); | |||
2097 | uint16_t i_pid = patn_get_pid( p_program ); | |||
2098 | j++; | |||
2099 | ||||
2100 | if ( i_sid == 0 ) | |||
2101 | continue; /* NIT */ | |||
2102 | ||||
2103 | if ( pat_table_find_program( pp_current_pat_sections, i_sid ) | |||
2104 | == NULL((void*)0) ) | |||
2105 | { | |||
2106 | DeleteProgram( i_sid, i_pid ); | |||
2107 | UpdatePAT( i_sid ); | |||
2108 | } | |||
2109 | } | |||
2110 | } | |||
2111 | ||||
2112 | psi_table_free( pp_old_pat_sections ); | |||
2113 | } | |||
2114 | ||||
2115 | pat_table_print( pp_current_pat_sections, msg_Dbg, NULL((void*)0), PRINT_TEXT ); | |||
2116 | if ( b_print_enabled ) | |||
2117 | { | |||
2118 | pat_table_print( pp_current_pat_sections, demux_Print, NULL((void*)0), | |||
2119 | i_print_type ); | |||
2120 | if ( i_print_type == PRINT_XML ) | |||
2121 | printf("\n"); | |||
2122 | } | |||
2123 | ||||
2124 | out_pat: | |||
2125 | SendPAT( i_dts ); | |||
2126 | } | |||
2127 | ||||
2128 | /***************************************************************************** | |||
2129 | * HandlePATSection | |||
2130 | *****************************************************************************/ | |||
2131 | static void HandlePATSection( uint16_t i_pid, uint8_t *p_section, | |||
2132 | mtime_t i_dts ) | |||
2133 | { | |||
2134 | if ( i_pid != PAT_PID0x0 || !pat_validate( p_section ) ) | |||
2135 | { | |||
2136 | msg_Warn( NULL((void*)0), "invalid PAT section received on PID %hu", i_pid ); | |||
2137 | switch (i_print_type) { | |||
2138 | case PRINT_XML: | |||
2139 | printf("<ERROR type=\"invalid_pat_section\"/>\n"); | |||
2140 | break; | |||
2141 | default: | |||
2142 | printf("invalid PAT section received on PID %hu\n", i_pid); | |||
2143 | } | |||
2144 | free( p_section ); | |||
2145 | return; | |||
2146 | } | |||
2147 | ||||
2148 | if ( !psi_table_section( pp_next_pat_sections, p_section ) ) | |||
2149 | return; | |||
2150 | ||||
2151 | HandlePAT( i_dts ); | |||
2152 | } | |||
2153 | ||||
2154 | /***************************************************************************** | |||
2155 | * HandleCAT | |||
2156 | *****************************************************************************/ | |||
2157 | static void HandleCAT( mtime_t i_dts ) | |||
2158 | { | |||
2159 | PSI_TABLE_DECLARE( pp_old_cat_sections )uint8_t *pp_old_cat_sections[256]; | |||
2160 | uint8_t i_last_section = psi_table_get_lastsection( pp_next_cat_sections )psi_get_lastsection(pp_next_cat_sections[0]); | |||
2161 | uint8_t i_last_section2; | |||
2162 | uint8_t i, r; | |||
2163 | uint8_t *p_desc; | |||
2164 | int j, k; | |||
2165 | ||||
2166 | if ( psi_table_validate( pp_current_cat_sections ) && | |||
2167 | psi_table_compare( pp_current_cat_sections, pp_next_cat_sections ) ) | |||
2168 | { | |||
2169 | /* Identical CAT. Shortcut. */ | |||
2170 | psi_table_free( pp_next_cat_sections ); | |||
2171 | psi_table_init( pp_next_cat_sections ); | |||
2172 | goto out_cat; | |||
2173 | } | |||
2174 | ||||
2175 | if ( !cat_table_validate( pp_next_cat_sections ) ) | |||
2176 | { | |||
2177 | msg_Warn( NULL((void*)0), "invalid CAT received" ); | |||
2178 | switch (i_print_type) { | |||
2179 | case PRINT_XML: | |||
2180 | printf("<ERROR type=\"invalid_cat\"/>\n"); | |||
2181 | break; | |||
2182 | default: | |||
2183 | printf("invalid CAT received\n"); | |||
2184 | } | |||
2185 | psi_table_free( pp_next_cat_sections ); | |||
2186 | psi_table_init( pp_next_cat_sections ); | |||
2187 | goto out_cat; | |||
2188 | } | |||
2189 | ||||
2190 | /* Switch tables. */ | |||
2191 | psi_table_copy( pp_old_cat_sections, pp_current_cat_sections ); | |||
2192 | psi_table_copy( pp_current_cat_sections, pp_next_cat_sections ); | |||
2193 | psi_table_init( pp_next_cat_sections ); | |||
2194 | ||||
2195 | for ( i = 0; i <= i_last_section; i++ ) | |||
2196 | { | |||
2197 | uint8_t *p_section = psi_table_get_section( pp_current_cat_sections, i ); | |||
2198 | ||||
2199 | j = 0; | |||
2200 | while ( (p_desc = descl_get_desc( cat_get_descl(p_section), cat_get_desclength(p_section), j++ )) != NULL((void*)0) ) | |||
2201 | { | |||
2202 | if ( desc_get_tag( p_desc ) != 0x09 || !desc09_validate( p_desc ) ) | |||
2203 | continue; | |||
2204 | ||||
2205 | SetPID_EMM( desc09_get_pid( p_desc ) ); | |||
2206 | } | |||
2207 | } | |||
2208 | ||||
2209 | if ( psi_table_validate( pp_old_cat_sections ) ) | |||
2210 | { | |||
2211 | i_last_section = psi_table_get_lastsection( pp_old_cat_sections )psi_get_lastsection(pp_old_cat_sections[0]); | |||
2212 | for ( i = 0; i <= i_last_section; i++ ) | |||
2213 | { | |||
2214 | uint8_t *p_old_section = psi_table_get_section( pp_old_cat_sections, i ); | |||
2215 | j = 0; | |||
2216 | while ( (p_desc = descl_get_desc( cat_get_descl(p_old_section), cat_get_desclength(p_old_section), j++ )) != NULL((void*)0) ) | |||
2217 | { | |||
2218 | uint16_t emm_pid; | |||
2219 | int pid_found = 0; | |||
2220 | ||||
2221 | if ( desc_get_tag( p_desc ) != 0x09 || !desc09_validate( p_desc ) ) | |||
2222 | continue; | |||
2223 | ||||
2224 | emm_pid = desc09_get_pid( p_desc ); | |||
2225 | ||||
2226 | // Search in current sections if the pid exists | |||
2227 | i_last_section2 = psi_table_get_lastsection( pp_current_cat_sections )psi_get_lastsection(pp_current_cat_sections[0]); | |||
2228 | for ( r = 0; r <= i_last_section2; r++ ) | |||
2229 | { | |||
2230 | uint8_t *p_section = psi_table_get_section( pp_current_cat_sections, r ); | |||
2231 | ||||
2232 | k = 0; | |||
2233 | while ( (p_desc = descl_get_desc( cat_get_descl(p_section), cat_get_desclength(p_section), k++ )) != NULL((void*)0) ) | |||
2234 | { | |||
2235 | if ( desc_get_tag( p_desc ) != 0x09 || !desc09_validate( p_desc ) ) | |||
2236 | continue; | |||
2237 | if ( ca_desc_find( cat_get_descl(p_section), cat_get_desclength(p_section), emm_pid ) != NULL((void*)0) ) | |||
2238 | { | |||
2239 | pid_found = 1; | |||
2240 | break; | |||
2241 | } | |||
2242 | } | |||
2243 | } | |||
2244 | ||||
2245 | if ( !pid_found ) | |||
2246 | UnsetPID(emm_pid); | |||
2247 | } | |||
2248 | } | |||
2249 | ||||
2250 | psi_table_free( pp_old_cat_sections ); | |||
2251 | } | |||
2252 | ||||
2253 | cat_table_print( pp_current_cat_sections, msg_Dbg, NULL((void*)0), PRINT_TEXT ); | |||
2254 | if ( b_print_enabled ) | |||
2255 | { | |||
2256 | cat_table_print( pp_current_cat_sections, demux_Print, NULL((void*)0), | |||
2257 | i_print_type ); | |||
2258 | if ( i_print_type == PRINT_XML ) | |||
2259 | printf("\n"); | |||
2260 | } | |||
2261 | ||||
2262 | out_cat: | |||
2263 | return; | |||
2264 | } | |||
2265 | ||||
2266 | /***************************************************************************** | |||
2267 | * HandleCATSection | |||
2268 | *****************************************************************************/ | |||
2269 | static void HandleCATSection( uint16_t i_pid, uint8_t *p_section, | |||
2270 | mtime_t i_dts ) | |||
2271 | { | |||
2272 | if ( i_pid != CAT_PID0x01 || !cat_validate( p_section ) ) | |||
2273 | { | |||
2274 | msg_Warn( NULL((void*)0), "invalid CAT section received on PID %hu", i_pid ); | |||
2275 | switch (i_print_type) { | |||
2276 | case PRINT_XML: | |||
2277 | printf("<ERROR type=\"invalid_cat_section\"/>\n"); | |||
2278 | break; | |||
2279 | default: | |||
2280 | printf("invalid CAT section received on PID %hu\n", i_pid); | |||
2281 | } | |||
2282 | free( p_section ); | |||
2283 | return; | |||
2284 | } | |||
2285 | ||||
2286 | if ( !psi_table_section( pp_next_cat_sections, p_section ) ) | |||
2287 | return; | |||
2288 | ||||
2289 | HandleCAT( i_dts ); | |||
2290 | } | |||
2291 | ||||
2292 | static void mark_pmt_pids( uint8_t *p_pmt, uint8_t pid_map[], uint8_t marker ) | |||
2293 | { | |||
2294 | uint16_t j, k; | |||
2295 | uint8_t *p_es; | |||
2296 | uint8_t *p_desc; | |||
2297 | ||||
2298 | uint16_t i_pcr_pid = pmt_get_pcrpid( p_pmt ); | |||
2299 | ||||
2300 | if ( b_enable_ecm ) | |||
2301 | { | |||
2302 | j = 0; | |||
2303 | while ( (p_desc = descs_get_desc( pmt_get_descs( p_pmt ), j++ )) != NULL((void*)0) ) | |||
2304 | { | |||
2305 | if ( desc_get_tag( p_desc ) != 0x09 || !desc09_validate( p_desc ) ) | |||
2306 | continue; | |||
2307 | pid_map[ desc09_get_pid( p_desc ) ] |= marker; | |||
2308 | } | |||
2309 | } | |||
2310 | ||||
2311 | if ( i_pcr_pid != PADDING_PID8191 ) | |||
2312 | pid_map[ i_pcr_pid ] |= marker; | |||
2313 | ||||
2314 | j = 0; | |||
2315 | while ( (p_es = pmt_get_es( p_pmt, j )) != NULL((void*)0) ) | |||
2316 | { | |||
2317 | uint16_t i_pid = pmtn_get_pid( p_es ); | |||
2318 | j++; | |||
2319 | ||||
2320 | if ( PIDWouldBeSelected( p_es ) ) | |||
2321 | pid_map[ i_pid ] |= marker; | |||
2322 | ||||
2323 | p_pids[i_pid].b_pes = PIDCarriesPES( p_es ); | |||
2324 | ||||
2325 | if ( b_enable_ecm ) | |||
2326 | { | |||
2327 | k = 0; | |||
2328 | while ( (p_desc = descs_get_desc( pmtn_get_descs( p_es ), k++ )) != NULL((void*)0) ) | |||
2329 | { | |||
2330 | if ( desc_get_tag( p_desc ) != 0x09 || !desc09_validate( p_desc ) ) | |||
2331 | continue; | |||
2332 | pid_map[ desc09_get_pid( p_desc ) ] |= marker; | |||
2333 | } | |||
2334 | } | |||
2335 | } | |||
2336 | } | |||
2337 | ||||
2338 | /***************************************************************************** | |||
2339 | * HandlePMT | |||
2340 | *****************************************************************************/ | |||
2341 | static void HandlePMT( uint16_t i_pid, uint8_t *p_pmt, mtime_t i_dts ) | |||
2342 | { | |||
2343 | uint16_t i_sid = pmt_get_programpsi_get_tableidext( p_pmt ); | |||
2344 | sid_t *p_sid; | |||
2345 | bool_Bool b_needs_descrambling, b_needed_descrambling, b_is_selected; | |||
2346 | uint8_t pid_map[MAX_PIDS8192]; | |||
2347 | ||||
2348 | p_sid = FindSID( i_sid ); | |||
2349 | if ( p_sid == NULL((void*)0) ) | |||
2350 | { | |||
2351 | /* Unwanted SID (happens when the same PMT PID is used for several | |||
2352 | * programs). */ | |||
2353 | free( p_pmt ); | |||
2354 | return; | |||
2355 | } | |||
2356 | ||||
2357 | if ( i_pid != p_sid->i_pmt_pid ) | |||
2358 | { | |||
2359 | msg_Warn( NULL((void*)0), "invalid PMT section received on PID %hu", i_pid ); | |||
2360 | switch (i_print_type) { | |||
2361 | case PRINT_XML: | |||
2362 | printf("<ERROR type=\"ghost_pmt\" program=\"%hu\n pid=\"%hu\"/>\n", | |||
2363 | i_sid, i_pid); | |||
2364 | break; | |||
2365 | default: | |||
2366 | printf("ghost PMT for service %hu carried on PID %hu\n", i_sid, | |||
2367 | i_pid); | |||
2368 | } | |||
2369 | free( p_pmt ); | |||
2370 | return; | |||
2371 | } | |||
2372 | ||||
2373 | if ( p_sid->p_current_pmt != NULL((void*)0) && | |||
2374 | psi_compare( p_sid->p_current_pmt, p_pmt ) ) | |||
2375 | { | |||
2376 | /* Identical PMT. Shortcut. */ | |||
2377 | free( p_pmt ); | |||
2378 | goto out_pmt; | |||
2379 | } | |||
2380 | ||||
2381 | if ( !pmt_validate( p_pmt ) ) | |||
2382 | { | |||
2383 | msg_Warn( NULL((void*)0), "invalid PMT section received on PID %hu", i_pid ); | |||
2384 | switch (i_print_type) { | |||
2385 | case PRINT_XML: | |||
2386 | printf("<ERROR type=\"invalid_pmt_section\" pid=\"%hu\"/>\n", | |||
2387 | i_pid); | |||
2388 | break; | |||
2389 | default: | |||
2390 | printf("invalid PMT section received on PID %hu\n", i_pid); | |||
2391 | } | |||
2392 | free( p_pmt ); | |||
2393 | goto out_pmt; | |||
2394 | } | |||
2395 | ||||
2396 | memset( pid_map, 0, sizeof(pid_map) ); | |||
2397 | ||||
2398 | b_needs_descrambling = PMTNeedsDescrambling( p_pmt ); | |||
2399 | b_needed_descrambling = p_sid->p_current_pmt != NULL((void*)0) ? | |||
2400 | PMTNeedsDescrambling( p_sid->p_current_pmt ) : | |||
2401 | false0; | |||
2402 | b_is_selected = SIDIsSelected( i_sid ); | |||
2403 | ||||
2404 | if ( i_ca_handle && b_is_selected && | |||
2405 | !b_needs_descrambling && b_needed_descrambling ) | |||
2406 | en50221_DeletePMT( p_sid->p_current_pmt ); | |||
2407 | ||||
2408 | if ( p_sid->p_current_pmt != NULL((void*)0) ) | |||
2409 | { | |||
2410 | mark_pmt_pids( p_sid->p_current_pmt, pid_map, 0x02 ); | |||
2411 | free( p_sid->p_current_pmt ); | |||
2412 | } | |||
2413 | ||||
2414 | mark_pmt_pids( p_pmt, pid_map, 0x01 ); | |||
2415 | ||||
2416 | /* Start to stream PIDs */ | |||
2417 | int pid; | |||
2418 | for ( pid = 0; pid < MAX_PIDS8192; pid++ ) | |||
2419 | { | |||
2420 | /* The pid does not exist in the old PMT and in the new PMT. Ignore this pid. */ | |||
2421 | if ( !pid_map[ pid ] ) | |||
2422 | continue; | |||
2423 | ||||
2424 | switch ( pid_map[ pid ] & 0x03 ) { | |||
2425 | case 0x03: /* The pid exists in the old PMT and in the new PMT. The pid was already selected in case 0x01. */ | |||
2426 | continue; | |||
2427 | case 0x02: /* The pid does not exist in the new PMT but exists in the old PMT. Unselect it. */ | |||
2428 | UnselectPID( i_sid, pid ); | |||
2429 | break; | |||
2430 | case 0x01: /* The pid exists in new PMT. Select it. */ | |||
2431 | SelectPID( i_sid, pid ); | |||
2432 | break; | |||
2433 | } | |||
2434 | } | |||
2435 | ||||
2436 | p_sid->p_current_pmt = p_pmt; | |||
2437 | ||||
2438 | if ( i_ca_handle && b_is_selected ) | |||
2439 | { | |||
2440 | if ( b_needs_descrambling && !b_needed_descrambling ) | |||
2441 | en50221_AddPMT( p_pmt ); | |||
2442 | else if ( b_needs_descrambling && b_needed_descrambling ) | |||
2443 | en50221_UpdatePMT( p_pmt ); | |||
2444 | } | |||
2445 | ||||
2446 | UpdatePMT( i_sid ); | |||
2447 | ||||
2448 | pmt_print( p_pmt, msg_Dbg, NULL((void*)0), demux_Iconv, NULL((void*)0), PRINT_TEXT ); | |||
2449 | if ( b_print_enabled ) | |||
2450 | { | |||
2451 | pmt_print( p_pmt, demux_Print, NULL((void*)0), demux_Iconv, NULL((void*)0), | |||
2452 | i_print_type ); | |||
2453 | if ( i_print_type == PRINT_XML ) | |||
2454 | printf("\n"); | |||
2455 | } | |||
2456 | ||||
2457 | out_pmt: | |||
2458 | SendPMT( p_sid, i_dts ); | |||
2459 | } | |||
2460 | ||||
2461 | /***************************************************************************** | |||
2462 | * HandleNIT | |||
2463 | *****************************************************************************/ | |||
2464 | static void HandleNIT( mtime_t i_dts ) | |||
2465 | { | |||
2466 | if ( psi_table_validate( pp_current_nit_sections ) && | |||
2467 | psi_table_compare( pp_current_nit_sections, pp_next_nit_sections ) ) | |||
2468 | { | |||
2469 | /* Identical NIT. Shortcut. */ | |||
2470 | psi_table_free( pp_next_nit_sections ); | |||
2471 | psi_table_init( pp_next_nit_sections ); | |||
2472 | goto out_nit; | |||
2473 | } | |||
2474 | ||||
2475 | if ( !nit_table_validate( pp_next_nit_sections ) ) | |||
2476 | { | |||
2477 | msg_Warn( NULL((void*)0), "invalid NIT received" ); | |||
2478 | switch (i_print_type) { | |||
2479 | case PRINT_XML: | |||
2480 | printf("<ERROR type=\"invalid_nit\"/>\n"); | |||
2481 | break; | |||
2482 | default: | |||
2483 | printf("invalid NIT received\n"); | |||
2484 | } | |||
2485 | psi_table_free( pp_next_nit_sections ); | |||
2486 | psi_table_init( pp_next_nit_sections ); | |||
2487 | goto out_nit; | |||
2488 | } | |||
2489 | ||||
2490 | /* Switch tables. */ | |||
2491 | psi_table_free( pp_current_nit_sections ); | |||
2492 | psi_table_copy( pp_current_nit_sections, pp_next_nit_sections ); | |||
2493 | psi_table_init( pp_next_nit_sections ); | |||
2494 | ||||
2495 | nit_table_print( pp_current_nit_sections, msg_Dbg, NULL((void*)0), | |||
2496 | demux_Iconv, NULL((void*)0), PRINT_TEXT ); | |||
2497 | if ( b_print_enabled ) | |||
2498 | { | |||
2499 | nit_table_print( pp_current_nit_sections, demux_Print, NULL((void*)0), | |||
2500 | demux_Iconv, NULL((void*)0), i_print_type ); | |||
2501 | if ( i_print_type == PRINT_XML ) | |||
2502 | printf("\n"); | |||
2503 | } | |||
2504 | ||||
2505 | out_nit: | |||
2506 | ; | |||
2507 | } | |||
2508 | ||||
2509 | /***************************************************************************** | |||
2510 | * HandleNITSection | |||
2511 | *****************************************************************************/ | |||
2512 | static void HandleNITSection( uint16_t i_pid, uint8_t *p_section, | |||
2513 | mtime_t i_dts ) | |||
2514 | { | |||
2515 | if ( i_pid != NIT_PID0x10 || !nit_validate( p_section ) ) | |||
2516 | { | |||
2517 | msg_Warn( NULL((void*)0), "invalid NIT section received on PID %hu", i_pid ); | |||
2518 | switch (i_print_type) { | |||
2519 | case PRINT_XML: | |||
2520 | printf("<ERROR type=\"invalid_nit_section\" pid=\"%hu\"/>\n", | |||
2521 | i_pid); | |||
2522 | break; | |||
2523 | default: | |||
2524 | printf("invalid NIT section received on PID %hu\n", i_pid); | |||
2525 | } | |||
2526 | free( p_section ); | |||
2527 | return; | |||
2528 | } | |||
2529 | ||||
2530 | if ( psi_table_section( pp_next_nit_sections, p_section ) ) | |||
2531 | HandleNIT( i_dts ); | |||
2532 | ||||
2533 | /* This case is different because DVB specifies a minimum bitrate for | |||
2534 | * PID 0x10, even if we don't have any thing to send (for cheap | |||
2535 | * transport over network boundaries). */ | |||
2536 | SendNIT( i_dts ); | |||
2537 | } | |||
2538 | ||||
2539 | ||||
2540 | /***************************************************************************** | |||
2541 | * HandleSDT | |||
2542 | *****************************************************************************/ | |||
2543 | static void HandleSDT( mtime_t i_dts ) | |||
2544 | { | |||
2545 | PSI_TABLE_DECLARE( pp_old_sdt_sections )uint8_t *pp_old_sdt_sections[256]; | |||
2546 | uint8_t i_last_section = psi_table_get_lastsection( pp_next_sdt_sections )psi_get_lastsection(pp_next_sdt_sections[0]); | |||
2547 | uint8_t i; | |||
2548 | int j; | |||
2549 | ||||
2550 | if ( psi_table_validate( pp_current_sdt_sections ) && | |||
2551 | psi_table_compare( pp_current_sdt_sections, pp_next_sdt_sections ) ) | |||
2552 | { | |||
2553 | /* Identical SDT. Shortcut. */ | |||
2554 | psi_table_free( pp_next_sdt_sections ); | |||
2555 | psi_table_init( pp_next_sdt_sections ); | |||
2556 | goto out_sdt; | |||
2557 | } | |||
2558 | ||||
2559 | if ( !sdt_table_validate( pp_next_sdt_sections ) ) | |||
2560 | { | |||
2561 | msg_Warn( NULL((void*)0), "invalid SDT received" ); | |||
2562 | switch (i_print_type) { | |||
2563 | case PRINT_XML: | |||
2564 | printf("<ERROR type=\"invalid_sdt\"/>\n"); | |||
2565 | break; | |||
2566 | default: | |||
2567 | printf("invalid SDT received\n"); | |||
2568 | } | |||
2569 | psi_table_free( pp_next_sdt_sections ); | |||
2570 | psi_table_init( pp_next_sdt_sections ); | |||
2571 | goto out_sdt; | |||
2572 | } | |||
2573 | ||||
2574 | /* Switch tables. */ | |||
2575 | psi_table_copy( pp_old_sdt_sections, pp_current_sdt_sections ); | |||
2576 | psi_table_copy( pp_current_sdt_sections, pp_next_sdt_sections ); | |||
2577 | psi_table_init( pp_next_sdt_sections ); | |||
2578 | ||||
2579 | for ( i = 0; i <= i_last_section; i++ ) | |||
2580 | { | |||
2581 | uint8_t *p_section = | |||
2582 | psi_table_get_section( pp_current_sdt_sections, i ); | |||
2583 | uint8_t *p_service; | |||
2584 | j = 0; | |||
2585 | ||||
2586 | while ( (p_service = sdt_get_service( p_section, j )) != NULL((void*)0) ) | |||
2587 | { | |||
2588 | uint16_t i_sid = sdtn_get_sid( p_service ); | |||
2589 | j++; | |||
2590 | ||||
2591 | UpdateSDT( i_sid ); | |||
2592 | } | |||
2593 | } | |||
2594 | ||||
2595 | if ( psi_table_validate( pp_old_sdt_sections ) ) | |||
2596 | { | |||
2597 | i_last_section = psi_table_get_lastsection( pp_old_sdt_sections )psi_get_lastsection(pp_old_sdt_sections[0]); | |||
2598 | for ( i = 0; i <= i_last_section; i++ ) | |||
2599 | { | |||
2600 | uint8_t *p_section = | |||
2601 | psi_table_get_section( pp_old_sdt_sections, i ); | |||
2602 | const uint8_t *p_service; | |||
2603 | int j = 0; | |||
2604 | ||||
2605 | while ( (p_service = sdt_get_service( p_section, j )) != NULL((void*)0) ) | |||
2606 | { | |||
2607 | uint16_t i_sid = sdtn_get_sid( p_service ); | |||
2608 | j++; | |||
2609 | ||||
2610 | if ( sdt_table_find_service( pp_current_sdt_sections, i_sid ) | |||
2611 | == NULL((void*)0) ) | |||
2612 | UpdateSDT( i_sid ); | |||
2613 | } | |||
2614 | } | |||
2615 | ||||
2616 | psi_table_free( pp_old_sdt_sections ); | |||
2617 | } | |||
2618 | ||||
2619 | sdt_table_print( pp_current_sdt_sections, msg_Dbg, NULL((void*)0), | |||
2620 | demux_Iconv, NULL((void*)0), PRINT_TEXT ); | |||
2621 | if ( b_print_enabled ) | |||
2622 | { | |||
2623 | sdt_table_print( pp_current_sdt_sections, demux_Print, NULL((void*)0), | |||
2624 | demux_Iconv, NULL((void*)0), i_print_type ); | |||
2625 | if ( i_print_type == PRINT_XML ) | |||
2626 | printf("\n"); | |||
2627 | } | |||
2628 | ||||
2629 | out_sdt: | |||
2630 | SendSDT( i_dts ); | |||
2631 | } | |||
2632 | ||||
2633 | /***************************************************************************** | |||
2634 | * HandleSDTSection | |||
2635 | *****************************************************************************/ | |||
2636 | static void HandleSDTSection( uint16_t i_pid, uint8_t *p_section, | |||
2637 | mtime_t i_dts ) | |||
2638 | { | |||
2639 | if ( i_pid != SDT_PID0x11 || !sdt_validate( p_section ) ) | |||
2640 | { | |||
2641 | msg_Warn( NULL((void*)0), "invalid SDT section received on PID %hu", i_pid ); | |||
2642 | switch (i_print_type) { | |||
2643 | case PRINT_XML: | |||
2644 | printf("<ERROR type=\"invalid_sdt_section\" pid=\"%hu\"/>\n", | |||
2645 | i_pid); | |||
2646 | break; | |||
2647 | default: | |||
2648 | printf("invalid SDT section received on PID %hu\n", i_pid); | |||
2649 | } | |||
2650 | free( p_section ); | |||
2651 | return; | |||
2652 | } | |||
2653 | ||||
2654 | if ( !psi_table_section( pp_next_sdt_sections, p_section ) ) | |||
2655 | return; | |||
2656 | ||||
2657 | HandleSDT( i_dts ); | |||
2658 | } | |||
2659 | ||||
2660 | /***************************************************************************** | |||
2661 | * HandleEITSection | |||
2662 | *****************************************************************************/ | |||
2663 | static void HandleEIT( uint16_t i_pid, uint8_t *p_eit, mtime_t i_dts ) | |||
2664 | { | |||
2665 | uint16_t i_sid = eit_get_sidpsi_get_tableidext( p_eit ); | |||
2666 | sid_t *p_sid; | |||
2667 | ||||
2668 | p_sid = FindSID( i_sid ); | |||
2669 | if ( p_sid == NULL((void*)0) ) | |||
2670 | { | |||
2671 | /* Not a selected program. */ | |||
2672 | free( p_eit ); | |||
2673 | return; | |||
2674 | } | |||
2675 | ||||
2676 | if ( i_pid != EIT_PID0x12 || !eit_validate( p_eit ) ) | |||
2677 | { | |||
2678 | /* | |||
2679 | msg_Warn( NULL, "invalid EIT section received on PID %hu", i_pid ); | |||
2680 | switch (i_print_type) { | |||
2681 | case PRINT_XML: | |||
2682 | printf("<ERROR type=\"invalid_eit_section\" pid=\"%hu\"/>\n", | |||
2683 | i_pid); | |||
2684 | break; | |||
2685 | default: | |||
2686 | printf("invalid EIT section received on PID %hu\n", i_pid); | |||
2687 | } | |||
2688 | */ | |||
2689 | free( p_eit ); | |||
2690 | return; | |||
2691 | } | |||
2692 | ||||
2693 | SendEIT( p_sid, i_dts, p_eit ); | |||
2694 | free( p_eit ); | |||
2695 | } | |||
2696 | ||||
2697 | /***************************************************************************** | |||
2698 | * HandleSection | |||
2699 | *****************************************************************************/ | |||
2700 | static void HandleSection( uint16_t i_pid, uint8_t *p_section, mtime_t i_dts ) | |||
2701 | { | |||
2702 | uint8_t i_table_id = psi_get_tableid( p_section ); | |||
2703 | ||||
2704 | if ( !psi_validate( p_section ) ) | |||
2705 | { | |||
2706 | /* | |||
2707 | msg_Warn( NULL, "invalid section on PID %hu", i_pid ); | |||
2708 | switch (i_print_type) { | |||
2709 | case PRINT_XML: | |||
2710 | printf("<ERROR type=\"invalid_section\" pid=\"%hu\"/>\n", i_pid); | |||
2711 | break; | |||
2712 | default: | |||
2713 | printf("invalid section on PID %hu\n", i_pid); | |||
2714 | } | |||
2715 | */ | |||
2716 | free( p_section ); | |||
2717 | return; | |||
2718 | } | |||
2719 | ||||
2720 | if ( !psi_get_current( p_section ) ) | |||
2721 | { | |||
2722 | /* Ignore sections which are not in use yet. */ | |||
2723 | free( p_section ); | |||
2724 | return; | |||
2725 | } | |||
2726 | ||||
2727 | switch ( i_table_id ) | |||
2728 | { | |||
2729 | case PAT_TABLE_ID0x0: | |||
2730 | HandlePATSection( i_pid, p_section, i_dts ); | |||
2731 | break; | |||
2732 | ||||
2733 | case CAT_TABLE_ID0x01: | |||
2734 | if ( b_enable_emm ) | |||
2735 | HandleCATSection( i_pid, p_section, i_dts ); | |||
2736 | break; | |||
2737 | ||||
2738 | case PMT_TABLE_ID0x2: | |||
2739 | HandlePMT( i_pid, p_section, i_dts ); | |||
2740 | break; | |||
2741 | ||||
2742 | case NIT_TABLE_ID_ACTUAL0x40: | |||
2743 | HandleNITSection( i_pid, p_section, i_dts ); | |||
2744 | break; | |||
2745 | ||||
2746 | case SDT_TABLE_ID_ACTUAL0x42: | |||
2747 | HandleSDTSection( i_pid, p_section, i_dts ); | |||
2748 | break; | |||
2749 | ||||
2750 | default: | |||
2751 | if ( i_table_id == EIT_TABLE_ID_PF_ACTUAL0x4e || | |||
2752 | (i_table_id >= EIT_TABLE_ID_SCHED_ACTUAL_FIRST0x50 && | |||
2753 | i_table_id <= EIT_TABLE_ID_SCHED_ACTUAL_LAST0x5f) ) | |||
2754 | { | |||
2755 | HandleEIT( i_pid, p_section, i_dts ); | |||
2756 | break; | |||
2757 | } | |||
2758 | free( p_section ); | |||
2759 | break; | |||
2760 | } | |||
2761 | } | |||
2762 | ||||
2763 | /***************************************************************************** | |||
2764 | * HandlePSIPacket | |||
2765 | *****************************************************************************/ | |||
2766 | static void HandlePSIPacket( uint8_t *p_ts, mtime_t i_dts ) | |||
2767 | { | |||
2768 | uint16_t i_pid = ts_get_pid( p_ts ); | |||
2769 | ts_pid_t *p_pid = &p_pids[i_pid]; | |||
2770 | uint8_t i_cc = ts_get_cc( p_ts ); | |||
2771 | const uint8_t *p_payload; | |||
2772 | uint8_t i_length; | |||
2773 | ||||
2774 | if ( ts_check_duplicate( i_cc, p_pid->i_last_cc ) | |||
2775 | || !ts_has_payload( p_ts ) ) | |||
2776 | return; | |||
2777 | ||||
2778 | if ( p_pid->i_last_cc != -1 | |||
2779 | && ts_check_discontinuity( i_cc, p_pid->i_last_cc ) ) | |||
2780 | psi_assemble_reset( &p_pid->p_psi_buffer, &p_pid->i_psi_buffer_used ); | |||
2781 | ||||
2782 | p_payload = ts_section( p_ts ); | |||
2783 | i_length = p_ts + TS_SIZE188 - p_payload; | |||
2784 | ||||
2785 | if ( !psi_assemble_empty( &p_pid->p_psi_buffer, | |||
2786 | &p_pid->i_psi_buffer_used ) ) | |||
2787 | { | |||
2788 | uint8_t *p_section = psi_assemble_payload( &p_pid->p_psi_buffer, | |||
2789 | &p_pid->i_psi_buffer_used, | |||
2790 | &p_payload, &i_length ); | |||
2791 | if ( p_section != NULL((void*)0) ) | |||
2792 | HandleSection( i_pid, p_section, i_dts ); | |||
2793 | } | |||
2794 | ||||
2795 | p_payload = ts_next_section( p_ts ); | |||
2796 | i_length = p_ts + TS_SIZE188 - p_payload; | |||
2797 | ||||
2798 | while ( i_length ) | |||
2799 | { | |||
2800 | uint8_t *p_section = psi_assemble_payload( &p_pid->p_psi_buffer, | |||
2801 | &p_pid->i_psi_buffer_used, | |||
2802 | &p_payload, &i_length ); | |||
2803 | if ( p_section != NULL((void*)0) ) | |||
2804 | HandleSection( i_pid, p_section, i_dts ); | |||
2805 | } | |||
2806 | } | |||
2807 | ||||
2808 | /***************************************************************************** | |||
2809 | * PID info functions | |||
2810 | *****************************************************************************/ | |||
2811 | static const char *h222_stream_type_desc(uint8_t i_stream_type) { | |||
2812 | /* See ISO/IEC 13818-1 : 2000 (E) | Table 2-29 - Stream type assignments, Page 66 (48) */ | |||
2813 | if (i_stream_type == 0) | |||
2814 | return "Reserved stream"; | |||
2815 | switch (i_stream_type) { | |||
2816 | case 0x01: return "11172-2 video (MPEG-1)"; | |||
2817 | case 0x02: return "H.262/13818-2 video (MPEG-2) or 11172-2 constrained video"; | |||
2818 | case 0x03: return "11172-3 audio (MPEG-1)"; | |||
2819 | case 0x04: return "13818-3 audio (MPEG-2)"; | |||
2820 | case 0x05: return "H.222.0/13818-1 private sections"; | |||
2821 | case 0x06: return "H.222.0/13818-1 PES private data"; | |||
2822 | case 0x07: return "13522 MHEG"; | |||
2823 | case 0x08: return "H.222.0/13818-1 Annex A - DSM CC"; | |||
2824 | case 0x09: return "H.222.1"; | |||
2825 | case 0x0A: return "13818-6 type A"; | |||
2826 | case 0x0B: return "13818-6 type B"; | |||
2827 | case 0x0C: return "13818-6 type C"; | |||
2828 | case 0x0D: return "13818-6 type D"; | |||
2829 | case 0x0E: return "H.222.0/13818-1 auxiliary"; | |||
2830 | case 0x0F: return "13818-7 Audio with ADTS transport syntax"; | |||
2831 | case 0x10: return "14496-2 Visual (MPEG-4 part 2 video)"; | |||
2832 | case 0x11: return "14496-3 Audio with LATM transport syntax (14496-3/AMD 1)"; | |||
2833 | case 0x12: return "14496-1 SL-packetized or FlexMux stream in PES packets"; | |||
2834 | case 0x13: return "14496-1 SL-packetized or FlexMux stream in 14496 sections"; | |||
2835 | case 0x14: return "ISO/IEC 13818-6 Synchronized Download Protocol"; | |||
2836 | case 0x15: return "Metadata in PES packets"; | |||
2837 | case 0x16: return "Metadata in metadata_sections"; | |||
2838 | case 0x17: return "Metadata in 13818-6 Data Carousel"; | |||
2839 | case 0x18: return "Metadata in 13818-6 Object Carousel"; | |||
2840 | case 0x19: return "Metadata in 13818-6 Synchronized Download Protocol"; | |||
2841 | case 0x1A: return "13818-11 MPEG-2 IPMP stream"; | |||
2842 | case 0x1B: return "H.264/14496-10 video (MPEG-4/AVC)"; | |||
2843 | case 0x42: return "AVS Video"; | |||
2844 | case 0x7F: return "IPMP stream"; | |||
2845 | default : return "Unknown stream"; | |||
2846 | } | |||
2847 | } | |||
2848 | ||||
2849 | static const char *get_pid_desc(uint16_t i_pid, uint16_t *i_sid) { | |||
2850 | int i, j, k; | |||
2851 | uint8_t i_last_section; | |||
2852 | uint8_t *p_desc; | |||
2853 | uint16_t i_nit_pid = NIT_PID0x10, i_pcr_pid = 0; | |||
2854 | ||||
2855 | /* Simple cases */ | |||
2856 | switch (i_pid) | |||
2857 | { | |||
2858 | case 0x00: return "PAT"; | |||
2859 | case 0x01: return "CAT"; | |||
2860 | case 0x11: return "SDT"; | |||
2861 | case 0x12: return "EPG"; | |||
2862 | case 0x14: return "TDT/TOT"; | |||
2863 | } | |||
2864 | ||||
2865 | /* Detect NIT pid */ | |||
2866 | if ( psi_table_validate( pp_current_pat_sections ) ) | |||
2867 | { | |||
2868 | i_last_section = psi_table_get_lastsection( pp_current_pat_sections )psi_get_lastsection(pp_current_pat_sections[0]); | |||
2869 | for ( i = 0; i <= i_last_section; i++ ) | |||
2870 | { | |||
2871 | uint8_t *p_section = psi_table_get_section( pp_current_pat_sections, i ); | |||
2872 | uint8_t *p_program; | |||
2873 | ||||
2874 | j = 0; | |||
2875 | while ( (p_program = pat_get_program( p_section, j++ )) != NULL((void*)0) ) | |||
2876 | { | |||
2877 | /* Programs with PID == 0 are actually NIT */ | |||
2878 | if ( patn_get_program( p_program ) == 0 ) | |||
2879 | { | |||
2880 | i_nit_pid = patn_get_pid( p_program ); | |||
2881 | break; | |||
2882 | } | |||
2883 | } | |||
2884 | } | |||
2885 | } | |||
2886 | ||||
2887 | /* Detect EMM pids */ | |||
2888 | if ( b_enable_emm && psi_table_validate( pp_current_cat_sections ) ) | |||
2889 | { | |||
2890 | i_last_section = psi_table_get_lastsection( pp_current_cat_sections )psi_get_lastsection(pp_current_cat_sections[0]); | |||
2891 | for ( i = 0; i <= i_last_section; i++ ) | |||
2892 | { | |||
2893 | uint8_t *p_section = psi_table_get_section( pp_current_cat_sections, i ); | |||
2894 | ||||
2895 | j = 0; | |||
2896 | while ( (p_desc = descl_get_desc( cat_get_descl(p_section), cat_get_desclength(p_section), j++ )) != NULL((void*)0) ) | |||
2897 | { | |||
2898 | if ( desc_get_tag( p_desc ) != 0x09 || !desc09_validate( p_desc ) ) | |||
2899 | continue; | |||
2900 | ||||
2901 | if ( desc09_get_pid( p_desc ) == i_pid ) { | |||
2902 | return "EMM"; | |||
2903 | } | |||
2904 | } | |||
2905 | } | |||
2906 | } | |||
2907 | ||||
2908 | /* Detect streams in PMT */ | |||
2909 | for ( k = 0; k < i_nb_sids; k++ ) | |||
2910 | { | |||
2911 | sid_t *p_sid = pp_sids[k]; | |||
2912 | if ( p_sid->i_pmt_pid == i_pid ) | |||
2913 | { | |||
2914 | if ( i_sid ) | |||
2915 | *i_sid = p_sid->i_sid; | |||
2916 | return "PMT"; | |||
2917 | } | |||
2918 | ||||
2919 | if ( p_sid->i_sid && p_sid->p_current_pmt != NULL((void*)0) ) | |||
2920 | { | |||
2921 | uint8_t *p_current_pmt = p_sid->p_current_pmt; | |||
2922 | uint8_t *p_current_es; | |||
2923 | ||||
2924 | /* The PCR PID can be alone or PCR can be carried in some other PIDs (mostly video) | |||
2925 | so just remember the pid and if it is alone it will be reported as PCR, otherwise | |||
2926 | stream type of the PID will be reported */ | |||
2927 | if ( i_pid == pmt_get_pcrpid( p_current_pmt ) ) { | |||
2928 | if ( i_sid ) | |||
2929 | *i_sid = p_sid->i_sid; | |||
2930 | i_pcr_pid = pmt_get_pcrpid( p_current_pmt ); | |||
2931 | } | |||
2932 | ||||
2933 | /* Look for ECMs */ | |||
2934 | j = 0; | |||
2935 | while ((p_desc = descs_get_desc( pmt_get_descs( p_current_pmt ), j++ )) != NULL((void*)0)) | |||
2936 | { | |||
2937 | if ( desc_get_tag( p_desc ) != 0x09 || !desc09_validate( p_desc ) ) | |||
2938 | continue; | |||
2939 | ||||
2940 | if ( desc09_get_pid( p_desc ) == i_pid ) { | |||
2941 | if ( i_sid ) | |||
2942 | *i_sid = p_sid->i_sid; | |||
2943 | return "ECM"; | |||
2944 | } | |||
2945 | } | |||
2946 | ||||
2947 | /* Detect stream types */ | |||
2948 | j = 0; | |||
2949 | while ( (p_current_es = pmt_get_es( p_current_pmt, j++ )) != NULL((void*)0) ) | |||
2950 | { | |||
2951 | if ( pmtn_get_pid( p_current_es ) == i_pid ) | |||
2952 | { | |||
2953 | if ( i_sid ) | |||
2954 | *i_sid = p_sid->i_sid; | |||
2955 | return h222_stream_type_desc( pmtn_get_streamtype( p_current_es ) ); | |||
2956 | } | |||
2957 | } | |||
2958 | } | |||
2959 | } | |||
2960 | ||||
2961 | /* Are there any other PIDs? */ | |||
2962 | if (i_pid == i_nit_pid) | |||
2963 | return "NIT"; | |||
2964 | ||||
2965 | if (i_pid == i_pcr_pid) | |||
2966 | return "PCR"; | |||
2967 | ||||
2968 | return "..."; | |||
2969 | } | |||
2970 | ||||
2971 | /***************************************************************************** | |||
2972 | * Functions that return packed sections | |||
2973 | *****************************************************************************/ | |||
2974 | uint8_t *demux_get_current_packed_PAT( unsigned int *pi_pack_size ) { | |||
2975 | return psi_pack_sections( pp_current_pat_sections, pi_pack_size ); | |||
2976 | } | |||
2977 | ||||
2978 | uint8_t *demux_get_current_packed_CAT( unsigned int *pi_pack_size ) { | |||
2979 | return psi_pack_sections( pp_current_cat_sections, pi_pack_size ); | |||
2980 | } | |||
2981 | ||||
2982 | uint8_t *demux_get_current_packed_NIT( unsigned int *pi_pack_size ) { | |||
2983 | return psi_pack_sections( pp_current_nit_sections, pi_pack_size ); | |||
2984 | } | |||
2985 | ||||
2986 | uint8_t *demux_get_current_packed_SDT( unsigned int *pi_pack_size ) { | |||
2987 | return psi_pack_sections( pp_current_sdt_sections, pi_pack_size ); | |||
2988 | } | |||
2989 | ||||
2990 | uint8_t *demux_get_packed_PMT( uint16_t i_sid, unsigned int *pi_pack_size ) { | |||
2991 | sid_t *p_sid = FindSID( i_sid ); | |||
2992 | if ( p_sid != NULL((void*)0) && p_sid->p_current_pmt && pmt_validate( p_sid->p_current_pmt ) ) | |||
2993 | return psi_pack_section( p_sid->p_current_pmt, pi_pack_size ); | |||
2994 | return NULL((void*)0); | |||
2995 | } | |||
2996 | ||||
2997 | inline void demux_get_PID_info( uint16_t i_pid, uint8_t *p_data ) { | |||
2998 | ts_pid_info_t *p_info = (ts_pid_info_t *)p_data; | |||
2999 | *p_info = p_pids[i_pid].info; | |||
3000 | } | |||
3001 | ||||
3002 | inline void demux_get_PIDS_info( uint8_t *p_data ) { | |||
3003 | int i_pid; | |||
3004 | for (i_pid = 0; i_pid < MAX_PIDS8192; i_pid++ ) | |||
3005 | demux_get_PID_info( i_pid, p_data + ( i_pid * sizeof(ts_pid_info_t) ) ); | |||
3006 | } |