rewrite core to use libev event loop
[dvblast.git] / demux.c
blobbc874fdf23cd6549ec7aee5bc026efef0a2b9b4f
1 /*****************************************************************************
2 * demux.c
3 *****************************************************************************
4 * Copyright (C) 2004, 2008-2011, 2015 VideoLAN
6 * Authors: Christophe Massiot <massiot@via.ecp.fr>
7 * Andy Gatward <a.j.gatward@reading.ac.uk>
8 * Marian Ďurkovič <md@bts.sk>
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.
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.
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 *****************************************************************************/
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>
37 #include "dvblast.h"
38 #include "en50221.h"
39 #include "mrtg-cnt.h"
41 #ifdef HAVE_ICONV
42 #include <iconv.h>
43 #endif
45 #include <bitstream/mpeg/ts.h>
46 #include <bitstream/mpeg/pes.h>
47 #include <bitstream/mpeg/psi.h>
48 #include <bitstream/dvb/si.h>
49 #include <bitstream/dvb/si_print.h>
50 #include <bitstream/mpeg/psi_print.h>
52 /*****************************************************************************
53 * Local declarations
54 *****************************************************************************/
55 #define MIN_SECTION_FRAGMENT PSI_HEADER_SIZE_SYNTAX1
57 typedef struct ts_pid_t
59 int i_refcount;
60 int i_psi_refcount;
61 bool b_pes;
62 int8_t i_last_cc;
63 int i_demux_fd;
64 /* b_emm is set to true when PID carries EMM packet
65 and should be outputed in all services */
66 bool b_emm;
68 /* PID info and stats */
69 mtime_t i_bytes_ts;
70 unsigned long i_packets_passed;
71 ts_pid_info_t info;
73 /* biTStream PSI section gathering */
74 uint8_t *p_psi_buffer;
75 uint16_t i_psi_buffer_used;
77 output_t **pp_outputs;
78 int i_nb_outputs;
79 } ts_pid_t;
81 typedef struct sid_t
83 uint16_t i_sid, i_pmt_pid;
84 uint8_t *p_current_pmt;
85 } sid_t;
87 mtime_t i_wallclock = 0;
89 static ts_pid_t p_pids[MAX_PIDS];
90 static sid_t **pp_sids = NULL;
91 static int i_nb_sids = 0;
93 static PSI_TABLE_DECLARE(pp_current_pat_sections);
94 static PSI_TABLE_DECLARE(pp_next_pat_sections);
95 static PSI_TABLE_DECLARE(pp_current_cat_sections);
96 static PSI_TABLE_DECLARE(pp_next_cat_sections);
97 static PSI_TABLE_DECLARE(pp_current_nit_sections);
98 static PSI_TABLE_DECLARE(pp_next_nit_sections);
99 static PSI_TABLE_DECLARE(pp_current_sdt_sections);
100 static PSI_TABLE_DECLARE(pp_next_sdt_sections);
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;
107 #ifdef HAVE_ICONV
108 static iconv_t iconv_handle = (iconv_t)-1;
109 #endif
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 SIDIsSelected( uint16_t i_sid );
129 static bool PIDWouldBeSelected( uint8_t *p_es );
130 static 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);
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
146 static uint16_t map_es_pid(output_t * p_output, uint8_t *p_es, uint16_t i_pid)
148 uint16_t i_newpid = i_pid;
149 uint16_t i_stream_type = pmtn_get_streamtype(p_es);
151 if ( !b_do_remap && !p_output->config.b_do_remap )
152 return i_pid;
154 msg_Dbg(NULL, "REMAP: Found elementary stream type 0x%02x with original PID 0x%x (%u):", i_stream_type, i_pid, i_pid);
156 switch ( i_stream_type )
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_PIDS;
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 )
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;
196 /* Audio found */
197 if (SubStreamType==I_APID) {
198 msg_Dbg(NULL, "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];
204 /* Subtitle found */
205 if (SubStreamType==I_SPUPID) {
206 msg_Dbg(NULL, "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];
212 break;
216 if (!i_newpid)
217 return i_pid;
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)
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 */
226 msg_Dbg(NULL, "REMAP: => Elementary stream is remapped to PID 0x%x (%u)", i_newpid, i_newpid);
228 return i_newpid;
231 /*****************************************************************************
232 * FindSID
233 *****************************************************************************/
234 static inline sid_t *FindSID( uint16_t i_sid )
236 int i;
238 for ( i = 0; i < i_nb_sids; i++ )
240 sid_t *p_sid = pp_sids[i];
241 if ( p_sid->i_sid == i_sid )
242 return p_sid;
244 return NULL;
247 /*****************************************************************************
248 * demux_Open
249 *****************************************************************************/
250 void demux_Open( void )
252 int i;
254 memset( p_pids, 0, sizeof(p_pids) );
256 pf_Open();
258 for ( i = 0; i < MAX_PIDS; i++ )
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 );
266 if ( b_budget_mode )
267 i_demux_fd = pf_SetFilter(8192);
269 psi_table_init( pp_current_pat_sections );
270 psi_table_init( pp_next_pat_sections );
271 SetPID(PAT_PID);
272 p_pids[PAT_PID].i_psi_refcount++;
274 if ( b_enable_emm )
276 psi_table_init( pp_current_cat_sections );
277 psi_table_init( pp_next_cat_sections );
278 SetPID_EMM(CAT_PID);
279 p_pids[CAT_PID].i_psi_refcount++;
282 SetPID(NIT_PID);
283 p_pids[NIT_PID].i_psi_refcount++;
285 psi_table_init( pp_current_sdt_sections );
286 psi_table_init( pp_next_sdt_sections );
287 SetPID(SDT_PID);
288 p_pids[SDT_PID].i_psi_refcount++;
290 SetPID(EIT_PID);
291 p_pids[EIT_PID].i_psi_refcount++;
293 SetPID(RST_PID);
295 SetPID(TDT_PID);
298 /*****************************************************************************
299 * demux_Close
300 *****************************************************************************/
301 void demux_Close( void )
303 int i;
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 );
314 for ( i = 0; i < MAX_PIDS; i++ )
316 free( p_pids[i].p_psi_buffer );
317 free( p_pids[i].pp_outputs );
320 for ( i = 0; i < i_nb_sids; i++ )
322 sid_t *p_sid = pp_sids[i];
323 free( p_sid->p_current_pmt );
324 free( p_sid );
326 free( pp_sids );
328 #ifdef HAVE_ICONV
329 if (iconv_handle != (iconv_t)-1) {
330 iconv_close(iconv_handle);
331 iconv_handle = (iconv_t)-1;
333 #endif
336 /*****************************************************************************
337 * demux_Run
338 *****************************************************************************/
339 void demux_Run( block_t *p_ts )
341 i_wallclock = mdate();
342 mrtgAnalyse( p_ts );
343 SetDTS( p_ts );
345 while ( p_ts != NULL )
347 block_t *p_next = p_ts->p_next;
348 p_ts->p_next = NULL;
349 demux_Handle( p_ts );
350 p_ts = p_next;
354 /*****************************************************************************
355 * demux_Handle
356 *****************************************************************************/
357 static void demux_Handle( block_t *p_ts )
359 uint16_t i_pid = ts_get_pid( p_ts->p_ts );
360 uint8_t i_cc = ts_get_cc( p_ts->p_ts );
361 int i;
363 if ( !ts_validate( p_ts->p_ts ) )
365 msg_Warn( NULL, "lost TS sync" );
366 block_Delete( p_ts );
367 return;
370 if ( i_pid != PADDING_PID )
371 p_pids[i_pid].info.i_scrambling = ts_get_scrambling( p_ts->p_ts );
373 p_pids[i_pid].info.i_last_packet_ts = i_wallclock;
374 p_pids[i_pid].info.i_packets++;
376 p_pids[i_pid].i_packets_passed++;
378 /* Calculate bytes_per_sec */
379 if ( i_wallclock > p_pids[i_pid].i_bytes_ts + 1000000 ) {
380 p_pids[i_pid].info.i_bytes_per_sec = p_pids[i_pid].i_packets_passed * TS_SIZE;
381 p_pids[i_pid].i_packets_passed = 0;
382 p_pids[i_pid].i_bytes_ts = i_wallclock;
385 if ( p_pids[i_pid].info.i_first_packet_ts == 0 )
386 p_pids[i_pid].info.i_first_packet_ts = i_wallclock;
388 if ( i_pid != PADDING_PID && p_pids[i_pid].i_last_cc != -1
389 && !ts_check_duplicate( i_cc, p_pids[i_pid].i_last_cc )
390 && ts_check_discontinuity( i_cc, p_pids[i_pid].i_last_cc ) )
392 unsigned int expected_cc = (p_pids[i_pid].i_last_cc + 1) & 0x0f;
393 uint16_t i_sid = 0;
394 const char *pid_desc = get_pid_desc(i_pid, &i_sid);
396 p_pids[i_pid].info.i_cc_errors++;
398 msg_Warn( NULL, "TS discontinuity on pid %4hu expected_cc %2u got %2u (%s, sid %d)",
399 i_pid, expected_cc, i_cc, pid_desc, i_sid );
402 if ( ts_get_transporterror( p_ts->p_ts ) )
404 uint16_t i_sid = 0;
405 const char *pid_desc = get_pid_desc(i_pid, &i_sid);
407 p_pids[i_pid].info.i_transport_errors++;
409 msg_Warn( NULL, "transport_error_indicator on pid %hu (%s, sid %u)",
410 i_pid, pid_desc, i_sid );
412 i_nb_errors++;
413 i_last_error = i_wallclock;
415 else if ( i_wallclock > i_last_error + WATCHDOG_WAIT )
416 i_nb_errors = 0;
418 if ( i_nb_errors > MAX_ERRORS )
420 i_nb_errors = 0;
421 msg_Warn( NULL,
422 "too many transport errors, tuning again" );
423 switch (i_print_type) {
424 case PRINT_XML:
425 fprintf(print_fh, "<EVENT type=\"reset\" cause=\"transport\" />\n");
426 break;
427 case PRINT_TEXT:
428 fprintf(print_fh, "reset cause: transport\n");
429 break;
430 default:
431 break;
433 pf_Reset();
436 if ( !ts_get_transporterror( p_ts->p_ts ) )
438 /* PSI parsing */
439 if ( i_pid == TDT_PID || i_pid == RST_PID )
440 SendTDT( p_ts );
441 else if ( p_pids[i_pid].i_psi_refcount )
442 HandlePSIPacket( p_ts->p_ts, p_ts->i_dts );
444 if ( b_enable_emm && p_pids[i_pid].b_emm )
445 SendEMM( p_ts );
448 p_pids[i_pid].i_last_cc = i_cc;
450 /* Output */
451 for ( i = 0; i < p_pids[i_pid].i_nb_outputs; i++ )
453 output_t *p_output = p_pids[i_pid].pp_outputs[i];
454 if ( p_output != NULL )
456 if ( i_ca_handle && (p_output->config.i_config & OUTPUT_WATCH) &&
457 ts_get_unitstart( p_ts->p_ts ) )
459 uint8_t *p_payload;
461 if ( ts_get_scrambling( p_ts->p_ts ) ||
462 ( p_pids[i_pid].b_pes
463 && (p_payload = ts_payload( p_ts->p_ts )) + 3
464 < p_ts->p_ts + TS_SIZE
465 && !pes_validate(p_payload) ) )
467 if ( i_wallclock >
468 i_last_reset + WATCHDOG_REFRACTORY_PERIOD )
470 p_output->i_nb_errors++;
471 p_output->i_last_error = i_wallclock;
474 else if ( i_wallclock > p_output->i_last_error + WATCHDOG_WAIT )
475 p_output->i_nb_errors = 0;
477 if ( p_output->i_nb_errors > MAX_ERRORS )
479 int j;
480 for ( j = 0; j < i_nb_outputs; j++ )
481 pp_outputs[j]->i_nb_errors = 0;
483 msg_Warn( NULL,
484 "too many errors for stream %s, resetting",
485 p_output->config.psz_displayname );
487 switch (i_print_type) {
488 case PRINT_XML:
489 fprintf(print_fh, "<EVENT type=\"reset\" cause=\"scrambling\" />\n");
490 break;
491 case PRINT_TEXT:
492 fprintf(print_fh, "reset cause: scrambling");
493 break;
494 default:
495 break;
497 i_last_reset = i_wallclock;
498 en50221_Reset();
502 output_Put( p_output, p_ts );
504 if ( p_output->p_eit_ts_buffer != NULL
505 && p_ts->i_dts > p_output->p_eit_ts_buffer->i_dts
506 + MAX_EIT_RETENTION )
507 FlushEIT( p_output, p_ts->i_dts );
511 if ( output_dup.config.i_config & OUTPUT_VALID )
512 output_Put( &output_dup, p_ts );
514 p_ts->i_refcount--;
515 if ( !p_ts->i_refcount )
516 block_Delete( p_ts );
519 /*****************************************************************************
520 * demux_Change : called from main thread
521 *****************************************************************************/
522 static int IsIn( uint16_t *pi_pids, int i_nb_pids, uint16_t i_pid )
524 int i;
525 for ( i = 0; i < i_nb_pids; i++ )
526 if ( i_pid == pi_pids[i] ) break;
527 return ( i != i_nb_pids );
530 void demux_Change( output_t *p_output, const output_config_t *p_config )
532 uint16_t *pi_wanted_pids, *pi_current_pids;
533 int i_nb_wanted_pids, i_nb_current_pids;
535 uint16_t i_old_sid = p_output->config.i_sid;
536 uint16_t i_sid = p_config->i_sid;
537 uint16_t *pi_old_pids = p_output->config.pi_pids;
538 uint16_t *pi_pids = p_config->pi_pids;
539 int i_old_nb_pids = p_output->config.i_nb_pids;
540 int i_nb_pids = p_config->i_nb_pids;
542 bool b_sid_change = i_sid != i_old_sid;
543 bool b_pid_change = false, b_tsid_change = false;
544 bool b_dvb_change = !!((p_output->config.i_config ^ p_config->i_config)
545 & OUTPUT_DVB);
546 bool b_service_name_change =
547 (!streq(p_output->config.psz_service_name, p_config->psz_service_name) ||
548 !streq(p_output->config.psz_service_provider, p_config->psz_service_provider));
549 bool b_remap_change = p_output->config.i_new_sid != p_config->i_new_sid ||
550 p_output->config.b_do_remap != p_config->b_do_remap ||
551 p_output->config.pi_confpids[I_PMTPID] != p_config->pi_confpids[I_PMTPID] ||
552 p_output->config.pi_confpids[I_APID] != p_config->pi_confpids[I_APID] ||
553 p_output->config.pi_confpids[I_VPID] != p_config->pi_confpids[I_VPID] ||
554 p_output->config.pi_confpids[I_SPUPID] != p_config->pi_confpids[I_SPUPID];
555 int i;
557 p_output->config.i_config = p_config->i_config;
558 p_output->config.i_new_sid = p_config->i_new_sid;
559 p_output->config.b_do_remap = p_config->b_do_remap;
560 memcpy(p_output->config.pi_confpids, p_config->pi_confpids,
561 sizeof(uint16_t) * N_MAP_PIDS);
563 /* Change output settings related to service_name and service_provider . */
564 free( p_output->config.psz_service_name );
565 free( p_output->config.psz_service_provider );
566 p_output->config.psz_service_name = xstrdup( p_config->psz_service_name );
567 p_output->config.psz_service_provider = xstrdup( p_config->psz_service_provider );
569 if ( p_config->i_tsid != -1 && p_output->config.i_tsid != p_config->i_tsid )
571 p_output->i_tsid = p_config->i_tsid;
572 b_tsid_change = true;
574 if ( p_config->i_tsid == -1 && p_output->config.i_tsid != -1 )
576 if ( psi_table_validate(pp_current_pat_sections) && !b_random_tsid )
577 p_output->i_tsid =
578 psi_table_get_tableidext(pp_current_pat_sections);
579 else
580 p_output->i_tsid = rand() & 0xffff;
581 b_tsid_change = true;
584 if ( !b_sid_change && p_config->i_nb_pids == p_output->config.i_nb_pids &&
585 (!p_config->i_nb_pids ||
586 !memcmp( p_output->config.pi_pids, p_config->pi_pids,
587 p_config->i_nb_pids * sizeof(uint16_t) )) )
588 goto out_change;
590 GetPIDS( &pi_wanted_pids, &i_nb_wanted_pids, i_sid, pi_pids, i_nb_pids );
591 GetPIDS( &pi_current_pids, &i_nb_current_pids, i_old_sid, pi_old_pids,
592 i_old_nb_pids );
594 if ( b_sid_change && i_old_sid )
596 sid_t *p_old_sid = FindSID( i_old_sid );
597 p_output->config.i_sid = p_config->i_sid;
599 if ( p_old_sid != NULL )
601 if ( i_sid != i_old_sid )
602 UnselectPMT( i_old_sid, p_old_sid->i_pmt_pid );
604 if ( i_ca_handle && !SIDIsSelected( i_old_sid )
605 && p_old_sid->p_current_pmt != NULL
606 && PMTNeedsDescrambling( p_old_sid->p_current_pmt ) )
607 en50221_DeletePMT( p_old_sid->p_current_pmt );
611 for ( i = 0; i < i_nb_current_pids; i++ )
613 if ( !IsIn( pi_wanted_pids, i_nb_wanted_pids, pi_current_pids[i] ) )
615 StopPID( p_output, pi_current_pids[i] );
616 b_pid_change = true;
620 if ( b_sid_change && i_ca_handle && i_old_sid &&
621 SIDIsSelected( i_old_sid ) )
623 sid_t *p_old_sid = FindSID( i_old_sid );
624 if ( p_old_sid != NULL && p_old_sid->p_current_pmt != NULL
625 && PMTNeedsDescrambling( p_old_sid->p_current_pmt ) )
626 en50221_UpdatePMT( p_old_sid->p_current_pmt );
629 for ( i = 0; i < i_nb_wanted_pids; i++ )
631 if ( !IsIn( pi_current_pids, i_nb_current_pids, pi_wanted_pids[i] ) )
633 StartPID( p_output, pi_wanted_pids[i] );
634 b_pid_change = true;
638 free( pi_wanted_pids );
639 free( pi_current_pids );
641 if ( b_sid_change && i_sid )
643 sid_t *p_sid = FindSID( i_sid );
644 p_output->config.i_sid = i_old_sid;
646 if ( p_sid != NULL )
648 if ( i_sid != i_old_sid )
649 SelectPMT( i_sid, p_sid->i_pmt_pid );
651 if ( i_ca_handle && !SIDIsSelected( i_sid )
652 && p_sid->p_current_pmt != NULL
653 && PMTNeedsDescrambling( p_sid->p_current_pmt ) )
654 en50221_AddPMT( p_sid->p_current_pmt );
658 if ( i_ca_handle && i_sid && SIDIsSelected( i_sid ) )
660 sid_t *p_sid = FindSID( i_sid );
661 if ( p_sid != NULL && p_sid->p_current_pmt != NULL
662 && PMTNeedsDescrambling( p_sid->p_current_pmt ) )
663 en50221_UpdatePMT( p_sid->p_current_pmt );
666 p_output->config.i_sid = i_sid;
667 free( p_output->config.pi_pids );
668 p_output->config.pi_pids = malloc( sizeof(uint16_t) * i_nb_pids );
669 memcpy( p_output->config.pi_pids, pi_pids, sizeof(uint16_t) * i_nb_pids );
670 p_output->config.i_nb_pids = i_nb_pids;
672 out_change:
673 if ( b_sid_change || b_remap_change )
675 NewSDT( p_output );
676 NewNIT( p_output );
677 NewPAT( p_output );
678 NewPMT( p_output );
680 else
682 if ( b_tsid_change )
684 NewSDT( p_output );
685 NewNIT( p_output );
686 NewPAT( p_output );
688 else if ( b_dvb_change )
690 NewNIT( p_output );
691 NewPAT( p_output );
694 if ( b_pid_change )
695 NewPMT( p_output );
697 if ( !b_sid_change && b_service_name_change )
698 NewSDT( p_output );
702 /*****************************************************************************
703 * SetDTS
704 *****************************************************************************/
705 static void SetDTS( block_t *p_list )
707 int i_nb_ts = 0, i;
708 mtime_t i_duration;
709 block_t *p_ts = p_list;
711 while ( p_ts != NULL )
713 i_nb_ts++;
714 p_ts = p_ts->p_next;
717 /* We suppose the stream is CBR, at least between two consecutive read().
718 * This is especially true in budget mode */
719 if ( i_last_dts == -1 )
720 i_duration = 0;
721 else
722 i_duration = i_wallclock - i_last_dts;
724 p_ts = p_list;
725 i = i_nb_ts - 1;
726 while ( p_ts != NULL )
728 p_ts->i_dts = i_wallclock - i_duration * i / i_nb_ts;
729 i--;
730 p_ts = p_ts->p_next;
733 i_last_dts = i_wallclock;
736 /*****************************************************************************
737 * SetPID/UnsetPID
738 *****************************************************************************/
739 static void SetPID( uint16_t i_pid )
741 p_pids[i_pid].i_refcount++;
743 if ( !b_budget_mode && p_pids[i_pid].i_refcount
744 && p_pids[i_pid].i_demux_fd == -1 )
745 p_pids[i_pid].i_demux_fd = pf_SetFilter( i_pid );
748 static void SetPID_EMM( uint16_t i_pid )
750 SetPID( i_pid );
751 p_pids[i_pid].b_emm = true;
754 static void UnsetPID( uint16_t i_pid )
756 p_pids[i_pid].i_refcount--;
758 if ( !b_budget_mode && !p_pids[i_pid].i_refcount
759 && p_pids[i_pid].i_demux_fd != -1 )
761 pf_UnsetFilter( p_pids[i_pid].i_demux_fd, i_pid );
762 p_pids[i_pid].i_demux_fd = -1;
763 p_pids[i_pid].b_emm = false;
767 /*****************************************************************************
768 * StartPID/StopPID
769 *****************************************************************************/
770 static void StartPID( output_t *p_output, uint16_t i_pid )
772 int j;
774 for ( j = 0; j < p_pids[i_pid].i_nb_outputs; j++ )
775 if ( p_pids[i_pid].pp_outputs[j] == p_output )
776 break;
778 if ( j == p_pids[i_pid].i_nb_outputs )
780 for ( j = 0; j < p_pids[i_pid].i_nb_outputs; j++ )
781 if ( p_pids[i_pid].pp_outputs[j] == NULL )
782 break;
784 if ( j == p_pids[i_pid].i_nb_outputs )
786 p_pids[i_pid].i_nb_outputs++;
787 p_pids[i_pid].pp_outputs = realloc( p_pids[i_pid].pp_outputs,
788 sizeof(output_t *)
789 * p_pids[i_pid].i_nb_outputs );
792 p_pids[i_pid].pp_outputs[j] = p_output;
793 SetPID( i_pid );
797 static void StopPID( output_t *p_output, uint16_t i_pid )
799 int j;
801 for ( j = 0; j < p_pids[i_pid].i_nb_outputs; j++ )
803 if ( p_pids[i_pid].pp_outputs[j] != NULL )
805 if ( p_pids[i_pid].pp_outputs[j] == p_output )
806 break;
810 if ( j != p_pids[i_pid].i_nb_outputs )
812 p_pids[i_pid].pp_outputs[j] = NULL;
813 UnsetPID( i_pid );
817 /*****************************************************************************
818 * SelectPID/UnselectPID
819 *****************************************************************************/
820 static void SelectPID( uint16_t i_sid, uint16_t i_pid )
822 int i;
824 for ( i = 0; i < i_nb_outputs; i++ )
825 if ( (pp_outputs[i]->config.i_config & OUTPUT_VALID)
826 && pp_outputs[i]->config.i_sid == i_sid
827 && !pp_outputs[i]->config.i_nb_pids )
828 StartPID( pp_outputs[i], i_pid );
831 static void UnselectPID( uint16_t i_sid, uint16_t i_pid )
833 int i;
835 for ( i = 0; i < i_nb_outputs; i++ )
836 if ( (pp_outputs[i]->config.i_config & OUTPUT_VALID)
837 && pp_outputs[i]->config.i_sid == i_sid
838 && !pp_outputs[i]->config.i_nb_pids )
839 StopPID( pp_outputs[i], i_pid );
842 /*****************************************************************************
843 * SelectPMT/UnselectPMT
844 *****************************************************************************/
845 static void SelectPMT( uint16_t i_sid, uint16_t i_pid )
847 int i;
849 p_pids[i_pid].i_psi_refcount++;
850 p_pids[i_pid].b_pes = false;
852 if ( b_select_pmts )
853 SetPID( i_pid );
854 else for ( i = 0; i < i_nb_outputs; i++ )
855 if ( (pp_outputs[i]->config.i_config & OUTPUT_VALID)
856 && pp_outputs[i]->config.i_sid == i_sid )
857 SetPID( i_pid );
860 static void UnselectPMT( uint16_t i_sid, uint16_t i_pid )
862 int i;
864 p_pids[i_pid].i_psi_refcount--;
865 if ( !p_pids[i_pid].i_psi_refcount )
866 psi_assemble_reset( &p_pids[i_pid].p_psi_buffer,
867 &p_pids[i_pid].i_psi_buffer_used );
869 if ( b_select_pmts )
870 UnsetPID( i_pid );
871 else for ( i = 0; i < i_nb_outputs; i++ )
872 if ( (pp_outputs[i]->config.i_config & OUTPUT_VALID)
873 && pp_outputs[i]->config.i_sid == i_sid )
874 UnsetPID( i_pid );
877 /*****************************************************************************
878 * GetPIDS
879 *****************************************************************************/
880 static void GetPIDS( uint16_t **ppi_wanted_pids, int *pi_nb_wanted_pids,
881 uint16_t i_sid,
882 const uint16_t *pi_pids, int i_nb_pids )
884 sid_t *p_sid;
885 uint8_t *p_pmt;
886 uint16_t i_pmt_pid, i_pcr_pid;
887 uint8_t *p_es;
888 uint8_t j;
890 if ( i_nb_pids || i_sid == 0 )
892 *pi_nb_wanted_pids = i_nb_pids;
893 *ppi_wanted_pids = malloc( sizeof(uint16_t) * i_nb_pids );
894 memcpy( *ppi_wanted_pids, pi_pids, sizeof(uint16_t) * i_nb_pids );
895 return;
898 *pi_nb_wanted_pids = 0;
899 *ppi_wanted_pids = NULL;
901 p_sid = FindSID( i_sid );
902 if ( p_sid == NULL )
903 return;
905 p_pmt = p_sid->p_current_pmt;
906 i_pmt_pid = p_sid->i_pmt_pid;
907 if ( p_pmt == NULL ) {
908 msg_Dbg(NULL, "no current PMT on sid %d\n", i_sid);
909 return;
912 i_pcr_pid = pmt_get_pcrpid( p_pmt );
913 j = 0;
914 while ( (p_es = pmt_get_es( p_pmt, j )) != NULL )
916 j++;
917 if ( PIDWouldBeSelected( p_es ) )
919 *ppi_wanted_pids = realloc( *ppi_wanted_pids,
920 (*pi_nb_wanted_pids + 1) * sizeof(uint16_t) );
921 (*ppi_wanted_pids)[(*pi_nb_wanted_pids)++] = pmtn_get_pid( p_es );
925 if ( i_pcr_pid != PADDING_PID && i_pcr_pid != i_pmt_pid
926 && !IsIn( *ppi_wanted_pids, *pi_nb_wanted_pids, i_pcr_pid ) )
928 *ppi_wanted_pids = realloc( *ppi_wanted_pids,
929 (*pi_nb_wanted_pids + 1) * sizeof(uint16_t) );
930 (*ppi_wanted_pids)[(*pi_nb_wanted_pids)++] = i_pcr_pid;
934 /*****************************************************************************
935 * OutputPSISection
936 *****************************************************************************/
937 static void OutputPSISection( output_t *p_output, uint8_t *p_section,
938 uint16_t i_pid, uint8_t *pi_cc, mtime_t i_dts,
939 block_t **pp_ts_buffer,
940 uint8_t *pi_ts_buffer_offset )
942 uint16_t i_section_length = psi_get_length(p_section) + PSI_HEADER_SIZE;
943 uint16_t i_section_offset = 0;
947 block_t *p_block;
948 uint8_t *p;
949 uint8_t i_ts_offset;
950 bool b_append = (pp_ts_buffer != NULL && *pp_ts_buffer != NULL);
952 if ( b_append )
954 p_block = *pp_ts_buffer;
955 i_ts_offset = *pi_ts_buffer_offset;
957 else
959 p_block = block_New();
960 p_block->i_dts = i_dts;
961 i_ts_offset = 0;
963 p = p_block->p_ts;
965 psi_split_section( p, &i_ts_offset, p_section, &i_section_offset );
967 if ( !b_append )
969 ts_set_pid( p, i_pid );
970 ts_set_cc( p, *pi_cc );
971 (*pi_cc)++;
972 *pi_cc &= 0xf;
975 if ( i_section_offset == i_section_length )
977 if ( i_ts_offset < TS_SIZE - MIN_SECTION_FRAGMENT
978 && pp_ts_buffer != NULL )
980 *pp_ts_buffer = p_block;
981 *pi_ts_buffer_offset = i_ts_offset;
982 break;
984 else
985 psi_split_end( p, &i_ts_offset );
988 p_block->i_dts = i_dts;
989 p_block->i_refcount--;
990 output_Put( p_output, p_block );
991 if ( pp_ts_buffer != NULL )
993 *pp_ts_buffer = NULL;
994 *pi_ts_buffer_offset = 0;
997 while ( i_section_offset < i_section_length );
1000 /*****************************************************************************
1001 * SendPAT
1002 *****************************************************************************/
1003 static void SendPAT( mtime_t i_dts )
1005 int i;
1007 for ( i = 0; i < i_nb_outputs; i++ )
1009 output_t *p_output = pp_outputs[i];
1011 if ( !(p_output->config.i_config & OUTPUT_VALID) )
1012 continue;
1014 if ( p_output->p_pat_section == NULL &&
1015 psi_table_validate(pp_current_pat_sections) )
1017 /* SID doesn't exist - build an empty PAT. */
1018 uint8_t *p;
1019 p_output->i_pat_version++;
1021 p = p_output->p_pat_section = psi_allocate();
1022 pat_init( p );
1023 pat_set_length( p, 0 );
1024 pat_set_tsid( p, p_output->i_tsid );
1025 psi_set_version( p, p_output->i_pat_version );
1026 psi_set_current( p );
1027 psi_set_section( p, 0 );
1028 psi_set_lastsection( p, 0 );
1029 psi_set_crc( p_output->p_pat_section );
1033 if ( p_output->p_pat_section != NULL )
1034 OutputPSISection( p_output, p_output->p_pat_section, PAT_PID,
1035 &p_output->i_pat_cc, i_dts, NULL, NULL );
1039 /*****************************************************************************
1040 * SendPMT
1041 *****************************************************************************/
1042 static void SendPMT( sid_t *p_sid, mtime_t i_dts )
1044 int i;
1045 int i_pmt_pid = p_sid->i_pmt_pid;
1047 if ( b_do_remap )
1048 i_pmt_pid = pi_newpids[ I_PMTPID ];
1050 for ( i = 0; i < i_nb_outputs; i++ )
1052 output_t *p_output = pp_outputs[i];
1054 if ( (p_output->config.i_config & OUTPUT_VALID)
1055 && p_output->config.i_sid == p_sid->i_sid
1056 && p_output->p_pmt_section != NULL )
1058 if ( p_output->config.b_do_remap && p_output->config.pi_confpids[I_PMTPID] )
1059 i_pmt_pid = p_output->config.pi_confpids[I_PMTPID];
1061 OutputPSISection( p_output, p_output->p_pmt_section,
1062 i_pmt_pid, &p_output->i_pmt_cc, i_dts,
1063 NULL, NULL );
1068 /*****************************************************************************
1069 * SendNIT
1070 *****************************************************************************/
1071 static void SendNIT( mtime_t i_dts )
1073 int i;
1075 for ( i = 0; i < i_nb_outputs; i++ )
1077 output_t *p_output = pp_outputs[i];
1079 if ( (p_output->config.i_config & OUTPUT_VALID)
1080 && (p_output->config.i_config & OUTPUT_DVB)
1081 && p_output->p_nit_section != NULL )
1082 OutputPSISection( p_output, p_output->p_nit_section, NIT_PID,
1083 &p_output->i_nit_cc, i_dts, NULL, NULL );
1087 /*****************************************************************************
1088 * SendSDT
1089 *****************************************************************************/
1090 static void SendSDT( mtime_t i_dts )
1092 int i;
1094 for ( i = 0; i < i_nb_outputs; i++ )
1096 output_t *p_output = pp_outputs[i];
1098 if ( (p_output->config.i_config & OUTPUT_VALID)
1099 && (p_output->config.i_config & OUTPUT_DVB)
1100 && p_output->p_sdt_section != NULL )
1101 OutputPSISection( p_output, p_output->p_sdt_section, SDT_PID,
1102 &p_output->i_sdt_cc, i_dts, NULL, NULL );
1106 /*****************************************************************************
1107 * SendEIT
1108 *****************************************************************************/
1109 static void SendEIT( sid_t *p_sid, mtime_t i_dts, uint8_t *p_eit )
1111 uint8_t i_table_id = psi_get_tableid( p_eit );
1112 bool b_epg = i_table_id >= EIT_TABLE_ID_SCHED_ACTUAL_FIRST &&
1113 i_table_id <= EIT_TABLE_ID_SCHED_ACTUAL_LAST;
1114 int i;
1116 for ( i = 0; i < i_nb_outputs; i++ )
1118 output_t *p_output = pp_outputs[i];
1120 if ( (p_output->config.i_config & OUTPUT_VALID)
1121 && (p_output->config.i_config & OUTPUT_DVB)
1122 && (!b_epg || (p_output->config.i_config & OUTPUT_EPG))
1123 && p_output->config.i_sid == p_sid->i_sid )
1125 eit_set_tsid( p_eit, p_output->i_tsid );
1127 if ( p_output->config.i_new_sid )
1128 eit_set_sid( p_eit, p_output->config.i_new_sid );
1129 else
1130 eit_set_sid( p_eit, p_output->config.i_sid );
1132 psi_set_crc( p_eit );
1134 OutputPSISection( p_output, p_eit, EIT_PID, &p_output->i_eit_cc,
1135 i_dts, &p_output->p_eit_ts_buffer,
1136 &p_output->i_eit_ts_buffer_offset );
1141 /*****************************************************************************
1142 * FlushEIT
1143 *****************************************************************************/
1144 static void FlushEIT( output_t *p_output, mtime_t i_dts )
1146 block_t *p_block = p_output->p_eit_ts_buffer;
1148 psi_split_end( p_block->p_ts, &p_output->i_eit_ts_buffer_offset );
1149 p_block->i_dts = i_dts;
1150 p_block->i_refcount--;
1151 output_Put( p_output, p_block );
1152 p_output->p_eit_ts_buffer = NULL;
1153 p_output->i_eit_ts_buffer_offset = 0;
1156 /*****************************************************************************
1157 * SendTDT
1158 *****************************************************************************/
1159 static void SendTDT( block_t *p_ts )
1161 int i;
1163 for ( i = 0; i < i_nb_outputs; i++ )
1165 output_t *p_output = pp_outputs[i];
1167 if ( (p_output->config.i_config & OUTPUT_VALID)
1168 && (p_output->config.i_config & OUTPUT_DVB)
1169 && p_output->p_sdt_section != NULL )
1170 output_Put( p_output, p_ts );
1173 /*****************************************************************************
1174 * SendEMM
1175 *****************************************************************************/
1176 static void SendEMM( block_t *p_ts )
1178 int i;
1180 for ( i = 0; i < i_nb_outputs; i++ )
1182 output_t *p_output = pp_outputs[i];
1184 if ( (p_output->config.i_config & OUTPUT_VALID) )
1185 output_Put( p_output, p_ts );
1189 /*****************************************************************************
1190 * NewPAT
1191 *****************************************************************************/
1192 static void NewPAT( output_t *p_output )
1194 const uint8_t *p_program;
1195 uint8_t *p;
1196 uint8_t k = 0;
1198 free( p_output->p_pat_section );
1199 p_output->p_pat_section = NULL;
1200 p_output->i_pat_version++;
1202 if ( !p_output->config.i_sid ) return;
1203 if ( !psi_table_validate(pp_current_pat_sections) ) return;
1205 p_program = pat_table_find_program( pp_current_pat_sections,
1206 p_output->config.i_sid );
1207 if ( p_program == NULL ) return;
1209 p = p_output->p_pat_section = psi_allocate();
1210 pat_init( p );
1211 psi_set_length( p, PSI_MAX_SIZE );
1212 pat_set_tsid( p, p_output->i_tsid );
1213 psi_set_version( p, p_output->i_pat_version );
1214 psi_set_current( p );
1215 psi_set_section( p, 0 );
1216 psi_set_lastsection( p, 0 );
1218 if ( p_output->config.i_config & OUTPUT_DVB )
1220 /* NIT */
1221 p = pat_get_program( p_output->p_pat_section, k++ );
1222 patn_init( p );
1223 patn_set_program( p, 0 );
1224 patn_set_pid( p, NIT_PID );
1227 p = pat_get_program( p_output->p_pat_section, k++ );
1228 patn_init( p );
1229 if ( p_output->config.i_new_sid )
1231 msg_Dbg( NULL, "Mapping PAT SID %d to %d", p_output->config.i_sid,
1232 p_output->config.i_new_sid );
1233 patn_set_program( p, p_output->config.i_new_sid );
1235 else
1236 patn_set_program( p, p_output->config.i_sid );
1238 if ( b_do_remap )
1240 msg_Dbg( NULL, "Mapping PMT PID %d to %d", patn_get_pid( p_program ), pi_newpids[I_PMTPID] );
1241 patn_set_pid( p, pi_newpids[I_PMTPID]);
1242 } else if ( p_output->config.b_do_remap && p_output->config.pi_confpids[I_PMTPID] ) {
1243 msg_Dbg( NULL, "Mapping PMT PID %d to %d", patn_get_pid( p_program ), p_output->config.pi_confpids[I_PMTPID] );
1244 patn_set_pid( p, p_output->config.pi_confpids[I_PMTPID]);
1245 } else {
1246 patn_set_pid( p, patn_get_pid( p_program ) );
1249 p = pat_get_program( p_output->p_pat_section, k );
1250 pat_set_length( p_output->p_pat_section,
1251 p - p_output->p_pat_section - PAT_HEADER_SIZE );
1252 psi_set_crc( p_output->p_pat_section );
1255 /*****************************************************************************
1256 * NewPMT
1257 *****************************************************************************/
1258 static void CopyDescriptors( uint8_t *p_descs, uint8_t *p_current_descs )
1260 uint8_t *p_desc;
1261 const uint8_t *p_current_desc;
1262 uint16_t j = 0, k = 0;
1264 descs_set_length( p_descs, DESCS_MAX_SIZE );
1266 while ( (p_current_desc = descs_get_desc( p_current_descs, j )) != NULL )
1268 uint8_t i_tag = desc_get_tag( p_current_desc );
1270 j++;
1271 if ( !b_enable_ecm && i_tag == 0x9 ) continue;
1273 p_desc = descs_get_desc( p_descs, k );
1274 if ( p_desc == NULL ) continue; /* This shouldn't happen */
1275 k++;
1276 memcpy( p_desc, p_current_desc,
1277 DESC_HEADER_SIZE + desc_get_length( p_current_desc ) );
1280 p_desc = descs_get_desc( p_descs, k );
1281 if ( p_desc == NULL )
1282 /* This shouldn't happen if the incoming PMT is valid */
1283 descs_set_length( p_descs, 0 );
1284 else
1285 descs_set_length( p_descs, p_desc - p_descs - DESCS_HEADER_SIZE );
1288 static void NewPMT( output_t *p_output )
1290 sid_t *p_sid;
1291 uint8_t *p_current_pmt;
1292 uint8_t *p_es, *p_current_es;
1293 uint8_t *p;
1294 uint16_t j, k;
1295 uint16_t i_pcrpid;
1297 free( p_output->p_pmt_section );
1298 p_output->p_pmt_section = NULL;
1299 p_output->i_pmt_version++;
1301 if ( !p_output->config.i_sid ) return;
1303 p_sid = FindSID( p_output->config.i_sid );
1304 if ( p_sid == NULL ) return;
1306 if ( p_sid->p_current_pmt == NULL ) return;
1307 p_current_pmt = p_sid->p_current_pmt;
1309 p = p_output->p_pmt_section = psi_allocate();
1310 pmt_init( p );
1311 psi_set_length( p, PSI_MAX_SIZE );
1312 if ( p_output->config.i_new_sid )
1314 msg_Dbg( NULL, "Mapping PMT SID %d to %d", p_output->config.i_sid,
1315 p_output->config.i_new_sid );
1316 pmt_set_program( p, p_output->config.i_new_sid );
1318 else
1319 pmt_set_program( p, p_output->config.i_sid );
1320 psi_set_version( p, p_output->i_pmt_version );
1321 psi_set_current( p );
1322 pmt_set_desclength( p, 0 );
1323 init_pid_mapping( p_output );
1326 CopyDescriptors( pmt_get_descs( p ), pmt_get_descs( p_current_pmt ) );
1328 j = 0; k = 0;
1329 while ( (p_current_es = pmt_get_es( p_current_pmt, j )) != NULL )
1331 uint16_t i_pid = pmtn_get_pid( p_current_es );
1333 j++;
1334 if ( (p_output->config.i_nb_pids || !PIDWouldBeSelected( p_current_es ))
1335 && !IsIn( p_output->config.pi_pids, p_output->config.i_nb_pids,
1336 i_pid ) )
1337 continue;
1339 p_es = pmt_get_es( p, k );
1340 if ( p_es == NULL ) continue; /* This shouldn't happen */
1341 k++;
1342 pmtn_init( p_es );
1343 pmtn_set_streamtype( p_es, pmtn_get_streamtype( p_current_es ) );
1344 pmtn_set_pid( p_es, map_es_pid(p_output, p_current_es, i_pid) );
1345 pmtn_set_desclength( p_es, 0 );
1347 CopyDescriptors( pmtn_get_descs( p_es ),
1348 pmtn_get_descs( p_current_es ) );
1351 /* Do the pcr pid after everything else as it may have been remapped */
1352 i_pcrpid = pmt_get_pcrpid( p_current_pmt );
1353 if ( p_output->pi_newpids[i_pcrpid] != UNUSED_PID ) {
1354 msg_Dbg( NULL, "REMAP: The PCR PID was changed from 0x%x (%u) to 0x%x (%u)",
1355 i_pcrpid, i_pcrpid, p_output->pi_newpids[i_pcrpid], p_output->pi_newpids[i_pcrpid] );
1356 i_pcrpid = p_output->pi_newpids[i_pcrpid];
1357 } else {
1358 msg_Dbg( NULL, "The PCR PID has kept its original value of 0x%x (%u)", i_pcrpid, i_pcrpid);
1360 pmt_set_pcrpid( p, i_pcrpid );
1361 p_es = pmt_get_es( p, k );
1362 if ( p_es == NULL )
1363 /* This shouldn't happen if the incoming PMT is valid */
1364 pmt_set_length( p, 0 );
1365 else
1366 pmt_set_length( p, p_es - p - PMT_HEADER_SIZE );
1367 psi_set_crc( p );
1370 /*****************************************************************************
1371 * NewNIT
1372 *****************************************************************************/
1373 static void NewNIT( output_t *p_output )
1375 uint8_t *p_ts;
1376 uint8_t *p_header2;
1377 uint8_t *p;
1379 free( p_output->p_nit_section );
1380 p_output->p_nit_section = NULL;
1381 p_output->i_nit_version++;
1383 p = p_output->p_nit_section = psi_allocate();
1384 nit_init( p, true );
1385 nit_set_length( p, PSI_MAX_SIZE );
1386 nit_set_nid( p, i_network_id );
1387 psi_set_version( p, p_output->i_nit_version );
1388 psi_set_current( p );
1389 psi_set_section( p, 0 );
1390 psi_set_lastsection( p, 0 );
1392 if ( p_network_name != NULL )
1394 uint8_t *p_descs;
1395 uint8_t *p_desc;
1396 nit_set_desclength( p, DESCS_MAX_SIZE );
1397 p_descs = nit_get_descs( p );
1398 p_desc = descs_get_desc( p_descs, 0 );
1399 desc40_init( p_desc );
1400 desc40_set_networkname( p_desc, p_network_name, i_network_name_size );
1401 p_desc = descs_get_desc( p_descs, 1 );
1402 descs_set_length( p_descs, p_desc - p_descs - DESCS_HEADER_SIZE );
1404 else
1405 nit_set_desclength( p, 0 );
1407 p_header2 = nit_get_header2( p );
1408 nith_init( p_header2 );
1409 nith_set_tslength( p_header2, NIT_TS_SIZE );
1411 p_ts = nit_get_ts( p, 0 );
1412 nitn_init( p_ts );
1413 nitn_set_tsid( p_ts, p_output->i_tsid );
1414 nitn_set_onid( p_ts, i_network_id );
1415 nitn_set_desclength( p_ts, 0 );
1417 p_ts = nit_get_ts( p, 1 );
1418 if ( p_ts == NULL )
1419 /* This shouldn't happen */
1420 nit_set_length( p, 0 );
1421 else
1422 nit_set_length( p, p_ts - p - NIT_HEADER_SIZE );
1423 psi_set_crc( p_output->p_nit_section );
1426 /*****************************************************************************
1427 * NewSDT
1428 *****************************************************************************/
1429 static void NewSDT( output_t *p_output )
1431 uint8_t *p_service, *p_current_service;
1432 uint8_t *p;
1434 free( p_output->p_sdt_section );
1435 p_output->p_sdt_section = NULL;
1436 p_output->i_sdt_version++;
1438 if ( !p_output->config.i_sid ) return;
1439 if ( !psi_table_validate(pp_current_sdt_sections) ) return;
1441 p_current_service = sdt_table_find_service( pp_current_sdt_sections,
1442 p_output->config.i_sid );
1444 if ( p_current_service == NULL )
1446 if ( p_output->p_pat_section != NULL &&
1447 pat_get_program( p_output->p_pat_section, 0 ) == NULL )
1449 /* Empty PAT and no SDT anymore */
1450 free( p_output->p_pat_section );
1451 p_output->p_pat_section = NULL;
1452 p_output->i_pat_version++;
1454 return;
1457 p = p_output->p_sdt_section = psi_allocate();
1458 sdt_init( p, true );
1459 sdt_set_length( p, PSI_MAX_SIZE );
1460 sdt_set_tsid( p, p_output->i_tsid );
1461 psi_set_version( p, p_output->i_sdt_version );
1462 psi_set_current( p );
1463 psi_set_section( p, 0 );
1464 psi_set_lastsection( p, 0 );
1465 sdt_set_onid( p,
1466 sdt_get_onid( psi_table_get_section( pp_current_sdt_sections, 0 ) ) );
1468 p_service = sdt_get_service( p, 0 );
1469 sdtn_init( p_service );
1470 if ( p_output->config.i_new_sid )
1472 msg_Dbg( NULL, "Mapping SDT SID %d to %d", p_output->config.i_sid,
1473 p_output->config.i_new_sid );
1474 sdtn_set_sid( p_service, p_output->config.i_new_sid );
1476 else
1477 sdtn_set_sid( p_service, p_output->config.i_sid );
1479 if ( (p_output->config.i_config & OUTPUT_EPG) == OUTPUT_EPG )
1481 sdtn_set_eitschedule(p_service);
1482 sdtn_set_eitpresent(p_service);
1483 } else {
1484 if ( sdtn_get_eitschedule(p_current_service) )
1485 sdtn_set_eitschedule(p_service);
1486 if ( sdtn_get_eitpresent(p_current_service) )
1487 sdtn_set_eitpresent(p_service);
1490 sdtn_set_running( p_service, sdtn_get_running(p_current_service) );
1491 /* Do not set free_ca */
1492 sdtn_set_desclength( p_service, sdtn_get_desclength(p_current_service) );
1494 char *p_new_provider = p_output->config.psz_service_provider;
1495 char *p_new_service = p_output->config.psz_service_name;
1497 if ( !p_new_provider && !p_new_service ) {
1498 /* Copy all descriptors unchanged */
1499 memcpy( descs_get_desc( sdtn_get_descs(p_service), 0 ),
1500 descs_get_desc( sdtn_get_descs(p_current_service), 0 ),
1501 sdtn_get_desclength(p_current_service) );
1502 } else {
1503 int j = 0, i_total_desc_len = 0;
1504 uint8_t *p_desc;
1505 uint8_t *p_new_desc = descs_get_desc( sdtn_get_descs(p_service), 0 );
1506 while ( (p_desc = descs_get_desc( sdtn_get_descs( p_current_service ), j++ )) != NULL )
1508 /* Regenerate descriptor 48 (service name) */
1509 if ( desc_get_tag( p_desc ) == 0x48 && desc48_validate( p_desc ) )
1511 uint8_t i_old_provider_len, i_old_service_len;
1512 uint8_t i_new_desc_len = 3; /* 1 byte - type, 1 byte provider_len, 1 byte service_len */
1513 char *p_new_provider = p_output->config.psz_service_provider;
1514 char *p_new_service = p_output->config.psz_service_name;
1515 const uint8_t *p_old_provider = desc48_get_provider( p_desc, &i_old_provider_len );
1516 const uint8_t *p_old_service = desc48_get_service( p_desc, &i_old_service_len );
1518 desc48_init( p_new_desc );
1519 desc48_set_type( p_new_desc, desc48_get_type( p_desc ) );
1521 if ( p_new_provider ) {
1522 desc48_set_provider( p_new_desc, (uint8_t *)p_new_provider, strlen( p_new_provider ) );
1523 i_new_desc_len += strlen( p_new_provider );
1524 } else {
1525 desc48_set_provider( p_new_desc, p_old_provider, i_old_provider_len );
1526 i_new_desc_len += i_old_provider_len;
1529 if ( p_new_service ) {
1530 desc48_set_service( p_new_desc, (uint8_t *)p_new_service, strlen( p_new_service ) );
1531 i_new_desc_len += strlen( p_new_service );
1532 } else {
1533 desc48_set_service( p_new_desc, p_old_service, i_old_service_len );
1534 i_new_desc_len += i_old_service_len;
1536 desc_set_length( p_new_desc, i_new_desc_len );
1537 i_total_desc_len += DESC_HEADER_SIZE + i_new_desc_len;
1538 p_new_desc += DESC_HEADER_SIZE + i_new_desc_len;
1539 } else {
1540 /* Copy single descriptor */
1541 int i_desc_len = DESC_HEADER_SIZE + desc_get_length( p_desc );
1542 memcpy( p_new_desc, p_desc, i_desc_len );
1543 p_new_desc += i_desc_len;
1544 i_total_desc_len += i_desc_len;
1547 sdtn_set_desclength( p_service, i_total_desc_len );
1550 p_service = sdt_get_service( p, 1 );
1551 if ( p_service == NULL )
1552 /* This shouldn't happen if the incoming SDT is valid */
1553 sdt_set_length( p, 0 );
1554 else
1555 sdt_set_length( p, p_service - p - SDT_HEADER_SIZE );
1556 psi_set_crc( p_output->p_sdt_section );
1559 /*****************************************************************************
1560 * UpdatePAT/PMT/SDT
1561 *****************************************************************************/
1562 #define DECLARE_UPDATE_FUNC( table ) \
1563 static void Update##table( uint16_t i_sid ) \
1565 int i; \
1567 for ( i = 0; i < i_nb_outputs; i++ ) \
1568 if ( ( pp_outputs[i]->config.i_config & OUTPUT_VALID ) \
1569 && pp_outputs[i]->config.i_sid == i_sid ) \
1570 New##table( pp_outputs[i] ); \
1573 DECLARE_UPDATE_FUNC(PAT)
1574 DECLARE_UPDATE_FUNC(PMT)
1575 DECLARE_UPDATE_FUNC(SDT)
1577 /*****************************************************************************
1578 * UpdateTSID
1579 *****************************************************************************/
1580 static void UpdateTSID(void)
1582 uint16_t i_tsid = psi_table_get_tableidext(pp_current_pat_sections);
1583 int i;
1585 for ( i = 0; i < i_nb_outputs; i++ )
1587 output_t *p_output = pp_outputs[i];
1589 if ( (p_output->config.i_config & OUTPUT_VALID)
1590 && p_output->config.i_tsid == -1 && !b_random_tsid )
1592 p_output->i_tsid = i_tsid;
1593 NewNIT( p_output );
1598 /*****************************************************************************
1599 * SIDIsSelected
1600 *****************************************************************************/
1601 static bool SIDIsSelected( uint16_t i_sid )
1603 int i;
1605 for ( i = 0; i < i_nb_outputs; i++ )
1606 if ( (pp_outputs[i]->config.i_config & OUTPUT_VALID)
1607 && pp_outputs[i]->config.i_sid == i_sid )
1608 return true;
1610 return false;
1613 /*****************************************************************************
1614 * demux_PIDIsSelected
1615 *****************************************************************************/
1616 bool demux_PIDIsSelected( uint16_t i_pid )
1618 int i;
1620 for ( i = 0; i < p_pids[i_pid].i_nb_outputs; i++ )
1621 if ( p_pids[i_pid].pp_outputs[i] != NULL )
1622 return true;
1624 return false;
1627 /*****************************************************************************
1628 * PIDWouldBeSelected
1629 *****************************************************************************/
1630 static bool PIDWouldBeSelected( uint8_t *p_es )
1632 if ( b_any_type ) return true;
1634 uint8_t i_type = pmtn_get_streamtype( p_es );
1636 switch ( i_type )
1638 case 0x1: /* video MPEG-1 */
1639 case 0x2: /* video */
1640 case 0x3: /* audio MPEG-1 */
1641 case 0x4: /* audio */
1642 case 0xf: /* audio AAC ADTS */
1643 case 0x10: /* video MPEG-4 */
1644 case 0x11: /* audio AAC LATM */
1645 case 0x1b: /* video H264 */
1646 case 0x81: /* ATSC A/52 */
1647 case 0x87: /* ATSC Enhanced A/52 */
1648 return true;
1649 break;
1651 case 0x6:
1653 uint16_t j = 0;
1654 const uint8_t *p_desc;
1656 while ( (p_desc = descs_get_desc( pmtn_get_descs( p_es ), j )) != NULL )
1658 uint8_t i_tag = desc_get_tag( p_desc );
1659 j++;
1661 if( i_tag == 0x46 /* VBI + teletext */
1662 || i_tag == 0x56 /* teletext */
1663 || i_tag == 0x59 /* dvbsub */
1664 || i_tag == 0x6a /* A/52 */
1665 || i_tag == 0x7a /* Enhanced A/52 */
1666 || i_tag == 0x7b /* DCA */
1667 || i_tag == 0x7c /* AAC */ )
1668 return true;
1670 break;
1673 default:
1674 break;
1677 /* FIXME: also parse IOD */
1678 return false;
1681 /*****************************************************************************
1682 * PIDCarriesPES
1683 *****************************************************************************/
1684 static bool PIDCarriesPES( const uint8_t *p_es )
1686 uint8_t i_type = pmtn_get_streamtype( p_es );
1688 switch ( i_type )
1690 case 0x1: /* video MPEG-1 */
1691 case 0x2: /* video */
1692 case 0x3: /* audio MPEG-1 */
1693 case 0x4: /* audio */
1694 case 0x6: /* private PES data */
1695 case 0xf: /* audio AAC */
1696 case 0x10: /* video MPEG-4 */
1697 case 0x11: /* audio AAC LATM */
1698 case 0x1b: /* video H264 */
1699 case 0x81: /* ATSC A/52 */
1700 case 0x87: /* ATSC Enhanced A/52 */
1701 return true;
1702 break;
1704 default:
1705 return false;
1706 break;
1710 /*****************************************************************************
1711 * PMTNeedsDescrambling
1712 *****************************************************************************/
1713 static bool PMTNeedsDescrambling( uint8_t *p_pmt )
1715 uint8_t i;
1716 uint16_t j;
1717 uint8_t *p_es;
1718 const uint8_t *p_desc;
1720 j = 0;
1721 while ( (p_desc = descs_get_desc( pmt_get_descs( p_pmt ), j )) != NULL )
1723 uint8_t i_tag = desc_get_tag( p_desc );
1724 j++;
1726 if ( i_tag == 0x9 ) return true;
1729 i = 0;
1730 while ( (p_es = pmt_get_es( p_pmt, i )) != NULL )
1732 i++;
1733 j = 0;
1734 while ( (p_desc = descs_get_desc( pmtn_get_descs( p_es ), j )) != NULL )
1736 uint8_t i_tag = desc_get_tag( p_desc );
1737 j++;
1739 if ( i_tag == 0x9 ) return true;
1743 return false;
1746 /*****************************************************************************
1747 * demux_ResendCAPMTs
1748 *****************************************************************************/
1749 void demux_ResendCAPMTs( void )
1751 int i;
1752 for ( i = 0; i < i_nb_sids; i++ )
1753 if ( pp_sids[i]->p_current_pmt != NULL
1754 && SIDIsSelected( pp_sids[i]->i_sid )
1755 && PMTNeedsDescrambling( pp_sids[i]->p_current_pmt ) )
1756 en50221_AddPMT( pp_sids[i]->p_current_pmt );
1759 /* Find CA descriptor that have PID i_ca_pid */
1760 static uint8_t *ca_desc_find( uint8_t *p_descl, uint16_t i_length,
1761 uint16_t i_ca_pid )
1763 int j = 0;
1764 uint8_t *p_desc;
1766 while ( (p_desc = descl_get_desc( p_descl, i_length, j++ )) != NULL ) {
1767 if ( desc_get_tag( p_desc ) != 0x09 || !desc09_validate( p_desc ) )
1768 continue;
1769 if ( desc09_get_pid( p_desc ) == i_ca_pid )
1770 return p_desc;
1773 return NULL;
1776 /*****************************************************************************
1777 * DeleteProgram
1778 *****************************************************************************/
1779 static void DeleteProgram( uint16_t i_sid, uint16_t i_pid )
1781 sid_t *p_sid;
1782 uint8_t *p_pmt;
1783 uint8_t *p_desc;
1785 UnselectPMT( i_sid, i_pid );
1787 p_sid = FindSID( i_sid );
1788 if ( p_sid == NULL ) return;
1790 p_pmt = p_sid->p_current_pmt;
1792 if ( p_pmt != NULL )
1794 uint16_t i_pcr_pid = pmt_get_pcrpid( p_pmt );
1795 uint8_t *p_es;
1796 uint8_t j;
1798 if ( i_ca_handle && SIDIsSelected( i_sid )
1799 && PMTNeedsDescrambling( p_pmt ) )
1800 en50221_DeletePMT( p_pmt );
1802 if ( i_pcr_pid != PADDING_PID
1803 && i_pcr_pid != p_sid->i_pmt_pid )
1804 UnselectPID( i_sid, i_pcr_pid );
1806 if ( b_enable_ecm )
1808 j = 0;
1810 while ((p_desc = descs_get_desc( pmt_get_descs( p_pmt ), j++ )) != NULL)
1812 if ( desc_get_tag( p_desc ) != 0x09 ||
1813 !desc09_validate( p_desc ) )
1814 continue;
1815 UnselectPID( i_sid, desc09_get_pid( p_desc ) );
1819 j = 0;
1820 while ( (p_es = pmt_get_es( p_pmt, j )) != NULL )
1822 uint16_t i_pid = pmtn_get_pid( p_es );
1823 j++;
1825 if ( PIDWouldBeSelected( p_es ) )
1826 UnselectPID( i_sid, i_pid );
1828 if ( b_enable_ecm )
1830 uint8_t k = 0;
1832 while ((p_desc = descs_get_desc( pmtn_get_descs( p_es ), k++ )) != NULL)
1834 if ( desc_get_tag( p_desc ) != 0x09 || !desc09_validate( p_desc ) )
1835 continue;
1836 UnselectPID( i_sid, desc09_get_pid( p_desc ) );
1841 free( p_pmt );
1842 p_sid->p_current_pmt = NULL;
1844 p_sid->i_sid = 0;
1845 p_sid->i_pmt_pid = 0;
1848 /*****************************************************************************
1849 * demux_Iconv
1850 *****************************************************************************
1851 * This code is from biTStream's examples and is under the WTFPL (see
1852 * LICENSE.WTFPL).
1853 *****************************************************************************/
1854 static char *iconv_append_null(const char *p_string, size_t i_length)
1856 char *psz_string = malloc(i_length + 1);
1857 memcpy(psz_string, p_string, i_length);
1858 psz_string[i_length] = '\0';
1859 return psz_string;
1862 char *demux_Iconv(void *_unused, const char *psz_encoding,
1863 char *p_string, size_t i_length)
1865 #ifdef HAVE_ICONV
1866 static const char *psz_current_encoding = "";
1868 char *psz_string, *p;
1869 size_t i_out_length;
1871 if (!strcmp(psz_encoding, psz_native_charset))
1872 return iconv_append_null(p_string, i_length);
1874 if (iconv_handle != (iconv_t)-1 &&
1875 strcmp(psz_encoding, psz_current_encoding)) {
1876 iconv_close(iconv_handle);
1877 iconv_handle = (iconv_t)-1;
1880 if (iconv_handle == (iconv_t)-1)
1881 iconv_handle = iconv_open(psz_native_charset, psz_encoding);
1882 if (iconv_handle == (iconv_t)-1) {
1883 msg_Warn(NULL, "couldn't open converter from %s to %s (%m)", psz_encoding,
1884 psz_native_charset);
1885 return iconv_append_null(p_string, i_length);
1887 psz_current_encoding = psz_encoding;
1889 /* converted strings can be up to six times larger */
1890 i_out_length = i_length * 6;
1891 p = psz_string = malloc(i_out_length);
1892 if (iconv(iconv_handle, &p_string, &i_length, &p, &i_out_length) == -1) {
1893 msg_Warn(NULL, "couldn't convert from %s to %s (%m)", psz_encoding,
1894 psz_native_charset);
1895 free(psz_string);
1896 return iconv_append_null(p_string, i_length);
1898 if (i_length)
1899 msg_Warn(NULL, "partial conversion from %s to %s", psz_encoding,
1900 psz_native_charset);
1902 *p = '\0';
1903 return psz_string;
1904 #else
1905 return iconv_append_null(p_string, i_length);
1906 #endif
1909 /*****************************************************************************
1910 * demux_Print
1911 *****************************************************************************
1912 * This code is from biTStream's examples and is under the WTFPL (see
1913 * LICENSE.WTFPL).
1914 *****************************************************************************/
1915 __attribute__ ((format(printf, 2, 3)))
1916 static void demux_Print(void *_unused, const char *psz_format, ...)
1918 char psz_fmt[strlen(psz_format) + 2];
1919 va_list args;
1920 va_start(args, psz_format);
1921 strcpy(psz_fmt, psz_format);
1922 if ( i_print_type != PRINT_XML )
1923 strcat(psz_fmt, "\n");
1924 vprintf(psz_fmt, args);
1925 va_end(args);
1928 /*****************************************************************************
1929 * HandlePAT
1930 *****************************************************************************/
1931 static void HandlePAT( mtime_t i_dts )
1933 bool b_change = false;
1934 PSI_TABLE_DECLARE( pp_old_pat_sections );
1935 uint8_t i_last_section = psi_table_get_lastsection( pp_next_pat_sections );
1936 uint8_t i;
1938 if ( psi_table_validate( pp_current_pat_sections ) &&
1939 psi_table_compare( pp_current_pat_sections, pp_next_pat_sections ) )
1941 /* Identical PAT. Shortcut. */
1942 psi_table_free( pp_next_pat_sections );
1943 psi_table_init( pp_next_pat_sections );
1944 goto out_pat;
1947 if ( !pat_table_validate( pp_next_pat_sections ) )
1949 msg_Warn( NULL, "invalid PAT received" );
1950 switch (i_print_type) {
1951 case PRINT_XML:
1952 fprintf(print_fh, "<ERROR type=\"invalid_pat\"/>\n");
1953 break;
1954 case PRINT_TEXT:
1955 fprintf(print_fh, "error type: invalid_pat\n");
1956 break;
1957 default:
1958 break;
1960 psi_table_free( pp_next_pat_sections );
1961 psi_table_init( pp_next_pat_sections );
1962 goto out_pat;
1965 /* Switch tables. */
1966 psi_table_copy( pp_old_pat_sections, pp_current_pat_sections );
1967 psi_table_copy( pp_current_pat_sections, pp_next_pat_sections );
1968 psi_table_init( pp_next_pat_sections );
1970 if ( !psi_table_validate( pp_old_pat_sections )
1971 || psi_table_get_tableidext( pp_current_pat_sections )
1972 != psi_table_get_tableidext( pp_old_pat_sections ) )
1974 b_change = true;
1975 UpdateTSID();
1976 /* This will trigger a universal reset of everything. */
1979 for ( i = 0; i <= i_last_section; i++ )
1981 uint8_t *p_section =
1982 psi_table_get_section( pp_current_pat_sections, i );
1983 const uint8_t *p_program;
1984 int j = 0;
1986 while ( (p_program = pat_get_program( p_section, j )) != NULL )
1988 const uint8_t *p_old_program = NULL;
1989 uint16_t i_sid = patn_get_program( p_program );
1990 uint16_t i_pid = patn_get_pid( p_program );
1991 j++;
1993 if ( i_sid == 0 )
1995 if ( i_pid != NIT_PID )
1996 msg_Warn( NULL,
1997 "NIT is carried on PID %hu which isn't DVB compliant",
1998 i_pid );
1999 continue; /* NIT */
2002 if ( !psi_table_validate( pp_old_pat_sections )
2003 || (p_old_program = pat_table_find_program(
2004 pp_old_pat_sections, i_sid )) == NULL
2005 || patn_get_pid( p_old_program ) != i_pid
2006 || b_change )
2008 sid_t *p_sid;
2010 if ( p_old_program != NULL )
2011 DeleteProgram( i_sid, patn_get_pid( p_old_program ) );
2013 SelectPMT( i_sid, i_pid );
2015 p_sid = FindSID( 0 );
2016 if ( p_sid == NULL )
2018 p_sid = malloc( sizeof(sid_t) );
2019 p_sid->p_current_pmt = NULL;
2020 i_nb_sids++;
2021 pp_sids = realloc( pp_sids, sizeof(sid_t *) * i_nb_sids );
2022 pp_sids[i_nb_sids - 1] = p_sid;
2025 p_sid->i_sid = i_sid;
2026 p_sid->i_pmt_pid = i_pid;
2028 UpdatePAT( i_sid );
2033 if ( psi_table_validate( pp_old_pat_sections ) )
2035 i_last_section = psi_table_get_lastsection( pp_old_pat_sections );
2036 for ( i = 0; i <= i_last_section; i++ )
2038 uint8_t *p_section =
2039 psi_table_get_section( pp_old_pat_sections, i );
2040 const uint8_t *p_program;
2041 int j = 0;
2043 while ( (p_program = pat_get_program( p_section, j )) != NULL )
2045 uint16_t i_sid = patn_get_program( p_program );
2046 uint16_t i_pid = patn_get_pid( p_program );
2047 j++;
2049 if ( i_sid == 0 )
2050 continue; /* NIT */
2052 if ( pat_table_find_program( pp_current_pat_sections, i_sid )
2053 == NULL )
2055 DeleteProgram( i_sid, i_pid );
2056 UpdatePAT( i_sid );
2061 psi_table_free( pp_old_pat_sections );
2064 pat_table_print( pp_current_pat_sections, msg_Dbg, NULL, PRINT_TEXT );
2065 if ( b_print_enabled )
2067 pat_table_print( pp_current_pat_sections, demux_Print, NULL,
2068 i_print_type );
2069 if ( i_print_type == PRINT_XML )
2070 fprintf(print_fh, "\n");
2073 out_pat:
2074 SendPAT( i_dts );
2077 /*****************************************************************************
2078 * HandlePATSection
2079 *****************************************************************************/
2080 static void HandlePATSection( uint16_t i_pid, uint8_t *p_section,
2081 mtime_t i_dts )
2083 if ( i_pid != PAT_PID || !pat_validate( p_section ) )
2085 msg_Warn( NULL, "invalid PAT section received on PID %hu", i_pid );
2086 switch (i_print_type) {
2087 case PRINT_XML:
2088 fprintf(print_fh, "<ERROR type=\"invalid_pat_section\"/>\n");
2089 break;
2090 case PRINT_TEXT:
2091 fprintf(print_fh, "error type: invalid_pat_section\n");
2092 break;
2093 default:
2094 break;
2096 free( p_section );
2097 return;
2100 if ( !psi_table_section( pp_next_pat_sections, p_section ) )
2101 return;
2103 HandlePAT( i_dts );
2106 /*****************************************************************************
2107 * HandleCAT
2108 *****************************************************************************/
2109 static void HandleCAT( mtime_t i_dts )
2111 PSI_TABLE_DECLARE( pp_old_cat_sections );
2112 uint8_t i_last_section = psi_table_get_lastsection( pp_next_cat_sections );
2113 uint8_t i_last_section2;
2114 uint8_t i, r;
2115 uint8_t *p_desc;
2116 int j, k;
2118 if ( psi_table_validate( pp_current_cat_sections ) &&
2119 psi_table_compare( pp_current_cat_sections, pp_next_cat_sections ) )
2121 /* Identical CAT. Shortcut. */
2122 psi_table_free( pp_next_cat_sections );
2123 psi_table_init( pp_next_cat_sections );
2124 goto out_cat;
2127 if ( !cat_table_validate( pp_next_cat_sections ) )
2129 msg_Warn( NULL, "invalid CAT received" );
2130 switch (i_print_type) {
2131 case PRINT_XML:
2132 fprintf(print_fh, "<ERROR type=\"invalid_cat\"/>\n");
2133 break;
2134 case PRINT_TEXT:
2135 fprintf(print_fh, "error type: invalid_cat\n");
2136 break;
2137 default:
2138 break;
2140 psi_table_free( pp_next_cat_sections );
2141 psi_table_init( pp_next_cat_sections );
2142 goto out_cat;
2145 /* Switch tables. */
2146 psi_table_copy( pp_old_cat_sections, pp_current_cat_sections );
2147 psi_table_copy( pp_current_cat_sections, pp_next_cat_sections );
2148 psi_table_init( pp_next_cat_sections );
2150 for ( i = 0; i <= i_last_section; i++ )
2152 uint8_t *p_section = psi_table_get_section( pp_current_cat_sections, i );
2154 j = 0;
2155 while ( (p_desc = descl_get_desc( cat_get_descl(p_section), cat_get_desclength(p_section), j++ )) != NULL )
2157 if ( desc_get_tag( p_desc ) != 0x09 || !desc09_validate( p_desc ) )
2158 continue;
2160 SetPID_EMM( desc09_get_pid( p_desc ) );
2164 if ( psi_table_validate( pp_old_cat_sections ) )
2166 i_last_section = psi_table_get_lastsection( pp_old_cat_sections );
2167 for ( i = 0; i <= i_last_section; i++ )
2169 uint8_t *p_old_section = psi_table_get_section( pp_old_cat_sections, i );
2170 j = 0;
2171 while ( (p_desc = descl_get_desc( cat_get_descl(p_old_section), cat_get_desclength(p_old_section), j++ )) != NULL )
2173 uint16_t emm_pid;
2174 int pid_found = 0;
2176 if ( desc_get_tag( p_desc ) != 0x09 || !desc09_validate( p_desc ) )
2177 continue;
2179 emm_pid = desc09_get_pid( p_desc );
2181 // Search in current sections if the pid exists
2182 i_last_section2 = psi_table_get_lastsection( pp_current_cat_sections );
2183 for ( r = 0; r <= i_last_section2; r++ )
2185 uint8_t *p_section = psi_table_get_section( pp_current_cat_sections, r );
2187 k = 0;
2188 while ( (p_desc = descl_get_desc( cat_get_descl(p_section), cat_get_desclength(p_section), k++ )) != NULL )
2190 if ( desc_get_tag( p_desc ) != 0x09 || !desc09_validate( p_desc ) )
2191 continue;
2192 if ( ca_desc_find( cat_get_descl(p_section), cat_get_desclength(p_section), emm_pid ) != NULL )
2194 pid_found = 1;
2195 break;
2200 if ( !pid_found )
2201 UnsetPID(emm_pid);
2205 psi_table_free( pp_old_cat_sections );
2208 cat_table_print( pp_current_cat_sections, msg_Dbg, NULL, PRINT_TEXT );
2209 if ( b_print_enabled )
2211 cat_table_print( pp_current_cat_sections, demux_Print, NULL,
2212 i_print_type );
2213 if ( i_print_type == PRINT_XML )
2214 fprintf(print_fh, "\n");
2217 out_cat:
2218 return;
2221 /*****************************************************************************
2222 * HandleCATSection
2223 *****************************************************************************/
2224 static void HandleCATSection( uint16_t i_pid, uint8_t *p_section,
2225 mtime_t i_dts )
2227 if ( i_pid != CAT_PID || !cat_validate( p_section ) )
2229 msg_Warn( NULL, "invalid CAT section received on PID %hu", i_pid );
2230 switch (i_print_type) {
2231 case PRINT_XML:
2232 fprintf(print_fh, "<ERROR type=\"invalid_cat_section\"/>\n");
2233 break;
2234 case PRINT_TEXT:
2235 fprintf(print_fh, "error type: invalid_cat_section\n");
2236 break;
2237 default:
2238 break;
2240 free( p_section );
2241 return;
2244 if ( !psi_table_section( pp_next_cat_sections, p_section ) )
2245 return;
2247 HandleCAT( i_dts );
2250 static void mark_pmt_pids( uint8_t *p_pmt, uint8_t pid_map[], uint8_t marker )
2252 uint16_t j, k;
2253 uint8_t *p_es;
2254 uint8_t *p_desc;
2256 uint16_t i_pcr_pid = pmt_get_pcrpid( p_pmt );
2258 if ( b_enable_ecm )
2260 j = 0;
2261 while ( (p_desc = descs_get_desc( pmt_get_descs( p_pmt ), j++ )) != NULL )
2263 if ( desc_get_tag( p_desc ) != 0x09 || !desc09_validate( p_desc ) )
2264 continue;
2265 pid_map[ desc09_get_pid( p_desc ) ] |= marker;
2269 if ( i_pcr_pid != PADDING_PID )
2270 pid_map[ i_pcr_pid ] |= marker;
2272 j = 0;
2273 while ( (p_es = pmt_get_es( p_pmt, j )) != NULL )
2275 uint16_t i_pid = pmtn_get_pid( p_es );
2276 j++;
2278 if ( PIDWouldBeSelected( p_es ) )
2279 pid_map[ i_pid ] |= marker;
2281 p_pids[i_pid].b_pes = PIDCarriesPES( p_es );
2283 if ( b_enable_ecm )
2285 k = 0;
2286 while ( (p_desc = descs_get_desc( pmtn_get_descs( p_es ), k++ )) != NULL )
2288 if ( desc_get_tag( p_desc ) != 0x09 || !desc09_validate( p_desc ) )
2289 continue;
2290 pid_map[ desc09_get_pid( p_desc ) ] |= marker;
2296 /*****************************************************************************
2297 * HandlePMT
2298 *****************************************************************************/
2299 static void HandlePMT( uint16_t i_pid, uint8_t *p_pmt, mtime_t i_dts )
2301 uint16_t i_sid = pmt_get_program( p_pmt );
2302 sid_t *p_sid;
2303 bool b_needs_descrambling, b_needed_descrambling, b_is_selected;
2304 uint8_t pid_map[MAX_PIDS];
2306 p_sid = FindSID( i_sid );
2307 if ( p_sid == NULL )
2309 /* Unwanted SID (happens when the same PMT PID is used for several
2310 * programs). */
2311 free( p_pmt );
2312 return;
2315 if ( i_pid != p_sid->i_pmt_pid )
2317 msg_Warn( NULL, "invalid PMT section received on PID %hu", i_pid );
2318 switch (i_print_type) {
2319 case PRINT_XML:
2320 fprintf(print_fh, "<ERROR type=\"ghost_pmt\" program=\"%hu\n pid=\"%hu\"/>\n",
2321 i_sid, i_pid);
2322 break;
2323 case PRINT_TEXT:
2324 fprintf(print_fh, "error type: ghost_pmt program: %hu pid: %hu\n",
2325 i_sid, i_pid);
2326 break;
2327 default:
2328 break;
2330 free( p_pmt );
2331 return;
2334 if ( p_sid->p_current_pmt != NULL &&
2335 psi_compare( p_sid->p_current_pmt, p_pmt ) )
2337 /* Identical PMT. Shortcut. */
2338 free( p_pmt );
2339 goto out_pmt;
2342 if ( !pmt_validate( p_pmt ) )
2344 msg_Warn( NULL, "invalid PMT section received on PID %hu", i_pid );
2345 switch (i_print_type) {
2346 case PRINT_XML:
2347 fprintf(print_fh, "<ERROR type=\"invalid_pmt_section\" pid=\"%hu\"/>\n",
2348 i_pid);
2349 break;
2350 case PRINT_TEXT:
2351 fprintf(print_fh, "error type: invalid_pmt_section pid: %hu\n",
2352 i_pid);
2353 break;
2354 default:
2355 break;
2357 free( p_pmt );
2358 goto out_pmt;
2361 memset( pid_map, 0, sizeof(pid_map) );
2363 b_needs_descrambling = PMTNeedsDescrambling( p_pmt );
2364 b_needed_descrambling = p_sid->p_current_pmt != NULL ?
2365 PMTNeedsDescrambling( p_sid->p_current_pmt ) :
2366 false;
2367 b_is_selected = SIDIsSelected( i_sid );
2369 if ( i_ca_handle && b_is_selected &&
2370 !b_needs_descrambling && b_needed_descrambling )
2371 en50221_DeletePMT( p_sid->p_current_pmt );
2373 if ( p_sid->p_current_pmt != NULL )
2375 mark_pmt_pids( p_sid->p_current_pmt, pid_map, 0x02 );
2376 free( p_sid->p_current_pmt );
2379 mark_pmt_pids( p_pmt, pid_map, 0x01 );
2381 /* Start to stream PIDs */
2382 int pid;
2383 for ( pid = 0; pid < MAX_PIDS; pid++ )
2385 /* The pid does not exist in the old PMT and in the new PMT. Ignore this pid. */
2386 if ( !pid_map[ pid ] )
2387 continue;
2389 switch ( pid_map[ pid ] & 0x03 ) {
2390 case 0x03: /* The pid exists in the old PMT and in the new PMT. The pid was already selected in case 0x01. */
2391 continue;
2392 case 0x02: /* The pid does not exist in the new PMT but exists in the old PMT. Unselect it. */
2393 UnselectPID( i_sid, pid );
2394 break;
2395 case 0x01: /* The pid exists in new PMT. Select it. */
2396 SelectPID( i_sid, pid );
2397 break;
2401 p_sid->p_current_pmt = p_pmt;
2403 if ( i_ca_handle && b_is_selected )
2405 if ( b_needs_descrambling && !b_needed_descrambling )
2406 en50221_AddPMT( p_pmt );
2407 else if ( b_needs_descrambling && b_needed_descrambling )
2408 en50221_UpdatePMT( p_pmt );
2411 UpdatePMT( i_sid );
2413 pmt_print( p_pmt, msg_Dbg, NULL, demux_Iconv, NULL, PRINT_TEXT );
2414 if ( b_print_enabled )
2416 pmt_print( p_pmt, demux_Print, NULL, demux_Iconv, NULL,
2417 i_print_type );
2418 if ( i_print_type == PRINT_XML )
2419 fprintf(print_fh, "\n");
2422 out_pmt:
2423 SendPMT( p_sid, i_dts );
2426 /*****************************************************************************
2427 * HandleNIT
2428 *****************************************************************************/
2429 static void HandleNIT( mtime_t i_dts )
2431 if ( psi_table_validate( pp_current_nit_sections ) &&
2432 psi_table_compare( pp_current_nit_sections, pp_next_nit_sections ) )
2434 /* Identical NIT. Shortcut. */
2435 psi_table_free( pp_next_nit_sections );
2436 psi_table_init( pp_next_nit_sections );
2437 goto out_nit;
2440 if ( !nit_table_validate( pp_next_nit_sections ) )
2442 msg_Warn( NULL, "invalid NIT received" );
2443 switch (i_print_type) {
2444 case PRINT_XML:
2445 fprintf(print_fh, "<ERROR type=\"invalid_nit\"/>\n");
2446 break;
2447 case PRINT_TEXT:
2448 fprintf(print_fh, "error type: invalid_nit\n");
2449 break;
2450 default:
2451 break;
2453 psi_table_free( pp_next_nit_sections );
2454 psi_table_init( pp_next_nit_sections );
2455 goto out_nit;
2458 /* Switch tables. */
2459 psi_table_free( pp_current_nit_sections );
2460 psi_table_copy( pp_current_nit_sections, pp_next_nit_sections );
2461 psi_table_init( pp_next_nit_sections );
2463 nit_table_print( pp_current_nit_sections, msg_Dbg, NULL,
2464 demux_Iconv, NULL, PRINT_TEXT );
2465 if ( b_print_enabled )
2467 nit_table_print( pp_current_nit_sections, demux_Print, NULL,
2468 demux_Iconv, NULL, i_print_type );
2469 if ( i_print_type == PRINT_XML )
2470 fprintf(print_fh, "\n");
2473 out_nit:
2477 /*****************************************************************************
2478 * HandleNITSection
2479 *****************************************************************************/
2480 static void HandleNITSection( uint16_t i_pid, uint8_t *p_section,
2481 mtime_t i_dts )
2483 if ( i_pid != NIT_PID || !nit_validate( p_section ) )
2485 msg_Warn( NULL, "invalid NIT section received on PID %hu", i_pid );
2486 switch (i_print_type) {
2487 case PRINT_XML:
2488 fprintf(print_fh, "<ERROR type=\"invalid_nit_section\" pid=\"%hu\"/>\n",
2489 i_pid);
2490 break;
2491 case PRINT_TEXT:
2492 fprintf(print_fh, "error type: invalid_nit_section pid: %hu\n",
2493 i_pid);
2494 break;
2495 default:
2496 break;
2498 free( p_section );
2499 return;
2502 if ( psi_table_section( pp_next_nit_sections, p_section ) )
2503 HandleNIT( i_dts );
2505 /* This case is different because DVB specifies a minimum bitrate for
2506 * PID 0x10, even if we don't have any thing to send (for cheap
2507 * transport over network boundaries). */
2508 SendNIT( i_dts );
2512 /*****************************************************************************
2513 * HandleSDT
2514 *****************************************************************************/
2515 static void HandleSDT( mtime_t i_dts )
2517 PSI_TABLE_DECLARE( pp_old_sdt_sections );
2518 uint8_t i_last_section = psi_table_get_lastsection( pp_next_sdt_sections );
2519 uint8_t i;
2520 int j;
2522 if ( psi_table_validate( pp_current_sdt_sections ) &&
2523 psi_table_compare( pp_current_sdt_sections, pp_next_sdt_sections ) )
2525 /* Identical SDT. Shortcut. */
2526 psi_table_free( pp_next_sdt_sections );
2527 psi_table_init( pp_next_sdt_sections );
2528 goto out_sdt;
2531 if ( !sdt_table_validate( pp_next_sdt_sections ) )
2533 msg_Warn( NULL, "invalid SDT received" );
2534 switch (i_print_type) {
2535 case PRINT_XML:
2536 fprintf(print_fh, "<ERROR type=\"invalid_sdt\"/>\n");
2537 break;
2538 case PRINT_TEXT:
2539 fprintf(print_fh, "error type: invalid_sdt\n");
2540 break;
2541 default:
2542 break;
2544 psi_table_free( pp_next_sdt_sections );
2545 psi_table_init( pp_next_sdt_sections );
2546 goto out_sdt;
2549 /* Switch tables. */
2550 psi_table_copy( pp_old_sdt_sections, pp_current_sdt_sections );
2551 psi_table_copy( pp_current_sdt_sections, pp_next_sdt_sections );
2552 psi_table_init( pp_next_sdt_sections );
2554 for ( i = 0; i <= i_last_section; i++ )
2556 uint8_t *p_section =
2557 psi_table_get_section( pp_current_sdt_sections, i );
2558 uint8_t *p_service;
2559 j = 0;
2561 while ( (p_service = sdt_get_service( p_section, j )) != NULL )
2563 uint16_t i_sid = sdtn_get_sid( p_service );
2564 j++;
2566 UpdateSDT( i_sid );
2570 if ( psi_table_validate( pp_old_sdt_sections ) )
2572 i_last_section = psi_table_get_lastsection( pp_old_sdt_sections );
2573 for ( i = 0; i <= i_last_section; i++ )
2575 uint8_t *p_section =
2576 psi_table_get_section( pp_old_sdt_sections, i );
2577 const uint8_t *p_service;
2578 int j = 0;
2580 while ( (p_service = sdt_get_service( p_section, j )) != NULL )
2582 uint16_t i_sid = sdtn_get_sid( p_service );
2583 j++;
2585 if ( sdt_table_find_service( pp_current_sdt_sections, i_sid )
2586 == NULL )
2587 UpdateSDT( i_sid );
2591 psi_table_free( pp_old_sdt_sections );
2594 sdt_table_print( pp_current_sdt_sections, msg_Dbg, NULL,
2595 demux_Iconv, NULL, PRINT_TEXT );
2596 if ( b_print_enabled )
2598 sdt_table_print( pp_current_sdt_sections, demux_Print, NULL,
2599 demux_Iconv, NULL, i_print_type );
2600 if ( i_print_type == PRINT_XML )
2601 fprintf(print_fh, "\n");
2604 out_sdt:
2605 SendSDT( i_dts );
2608 /*****************************************************************************
2609 * HandleSDTSection
2610 *****************************************************************************/
2611 static void HandleSDTSection( uint16_t i_pid, uint8_t *p_section,
2612 mtime_t i_dts )
2614 if ( i_pid != SDT_PID || !sdt_validate( p_section ) )
2616 msg_Warn( NULL, "invalid SDT section received on PID %hu", i_pid );
2617 switch (i_print_type) {
2618 case PRINT_XML:
2619 fprintf(print_fh, "<ERROR type=\"invalid_sdt_section\" pid=\"%hu\"/>\n",
2620 i_pid);
2621 break;
2622 case PRINT_TEXT:
2623 fprintf(print_fh, "error type: invalid_sdt_section pid: %hu\n",
2624 i_pid);
2625 break;
2626 default:
2627 break;
2629 free( p_section );
2630 return;
2633 if ( !psi_table_section( pp_next_sdt_sections, p_section ) )
2634 return;
2636 HandleSDT( i_dts );
2639 /*****************************************************************************
2640 * HandleEITSection
2641 *****************************************************************************/
2642 static void HandleEIT( uint16_t i_pid, uint8_t *p_eit, mtime_t i_dts )
2644 uint16_t i_sid = eit_get_sid( p_eit );
2645 sid_t *p_sid;
2647 p_sid = FindSID( i_sid );
2648 if ( p_sid == NULL )
2650 /* Not a selected program. */
2651 free( p_eit );
2652 return;
2655 if ( i_pid != EIT_PID || !eit_validate( p_eit ) )
2657 msg_Warn( NULL, "invalid EIT section received on PID %hu", i_pid );
2658 switch (i_print_type) {
2659 case PRINT_XML:
2660 fprintf(print_fh, "<ERROR type=\"invalid_eit_section\" pid=\"%hu\"/>\n",
2661 i_pid);
2662 break;
2663 case PRINT_TEXT:
2664 fprintf(print_fh, "error type: invalid_eit_section pid: %hu\n",
2665 i_pid);
2666 break;
2667 default:
2668 break;
2670 free( p_eit );
2671 return;
2674 SendEIT( p_sid, i_dts, p_eit );
2675 free( p_eit );
2678 /*****************************************************************************
2679 * HandleSection
2680 *****************************************************************************/
2681 static void HandleSection( uint16_t i_pid, uint8_t *p_section, mtime_t i_dts )
2683 uint8_t i_table_id = psi_get_tableid( p_section );
2685 if ( !psi_validate( p_section ) )
2687 msg_Warn( NULL, "invalid section on PID %hu", i_pid );
2688 switch (i_print_type) {
2689 case PRINT_XML:
2690 fprintf(print_fh, "<ERROR type=\"invalid_section\" pid=\"%hu\"/>\n", i_pid);
2691 break;
2692 case PRINT_TEXT:
2693 fprintf(print_fh, "error type: invalid_section pid: %hu\n", i_pid);
2694 break;
2695 default:
2696 break;
2698 free( p_section );
2699 return;
2702 if ( !psi_get_current( p_section ) )
2704 /* Ignore sections which are not in use yet. */
2705 free( p_section );
2706 return;
2709 switch ( i_table_id )
2711 case PAT_TABLE_ID:
2712 HandlePATSection( i_pid, p_section, i_dts );
2713 break;
2715 case CAT_TABLE_ID:
2716 if ( b_enable_emm )
2717 HandleCATSection( i_pid, p_section, i_dts );
2718 break;
2720 case PMT_TABLE_ID:
2721 HandlePMT( i_pid, p_section, i_dts );
2722 break;
2724 case NIT_TABLE_ID_ACTUAL:
2725 HandleNITSection( i_pid, p_section, i_dts );
2726 break;
2728 case SDT_TABLE_ID_ACTUAL:
2729 HandleSDTSection( i_pid, p_section, i_dts );
2730 break;
2732 default:
2733 if ( i_table_id == EIT_TABLE_ID_PF_ACTUAL ||
2734 (i_table_id >= EIT_TABLE_ID_SCHED_ACTUAL_FIRST &&
2735 i_table_id <= EIT_TABLE_ID_SCHED_ACTUAL_LAST) )
2737 HandleEIT( i_pid, p_section, i_dts );
2738 break;
2740 free( p_section );
2741 break;
2745 /*****************************************************************************
2746 * HandlePSIPacket
2747 *****************************************************************************/
2748 static void HandlePSIPacket( uint8_t *p_ts, mtime_t i_dts )
2750 uint16_t i_pid = ts_get_pid( p_ts );
2751 ts_pid_t *p_pid = &p_pids[i_pid];
2752 uint8_t i_cc = ts_get_cc( p_ts );
2753 const uint8_t *p_payload;
2754 uint8_t i_length;
2756 if ( ts_check_duplicate( i_cc, p_pid->i_last_cc )
2757 || !ts_has_payload( p_ts ) )
2758 return;
2760 if ( p_pid->i_last_cc != -1
2761 && ts_check_discontinuity( i_cc, p_pid->i_last_cc ) )
2762 psi_assemble_reset( &p_pid->p_psi_buffer, &p_pid->i_psi_buffer_used );
2764 p_payload = ts_section( p_ts );
2765 i_length = p_ts + TS_SIZE - p_payload;
2767 if ( !psi_assemble_empty( &p_pid->p_psi_buffer,
2768 &p_pid->i_psi_buffer_used ) )
2770 uint8_t *p_section = psi_assemble_payload( &p_pid->p_psi_buffer,
2771 &p_pid->i_psi_buffer_used,
2772 &p_payload, &i_length );
2773 if ( p_section != NULL )
2774 HandleSection( i_pid, p_section, i_dts );
2777 p_payload = ts_next_section( p_ts );
2778 i_length = p_ts + TS_SIZE - p_payload;
2780 while ( i_length )
2782 uint8_t *p_section = psi_assemble_payload( &p_pid->p_psi_buffer,
2783 &p_pid->i_psi_buffer_used,
2784 &p_payload, &i_length );
2785 if ( p_section != NULL )
2786 HandleSection( i_pid, p_section, i_dts );
2790 /*****************************************************************************
2791 * PID info functions
2792 *****************************************************************************/
2793 static const char *h222_stream_type_desc(uint8_t i_stream_type) {
2794 /* See ISO/IEC 13818-1 : 2000 (E) | Table 2-29 - Stream type assignments, Page 66 (48) */
2795 if (i_stream_type == 0)
2796 return "Reserved stream";
2797 switch (i_stream_type) {
2798 case 0x01: return "11172-2 video (MPEG-1)";
2799 case 0x02: return "H.262/13818-2 video (MPEG-2) or 11172-2 constrained video";
2800 case 0x03: return "11172-3 audio (MPEG-1)";
2801 case 0x04: return "13818-3 audio (MPEG-2)";
2802 case 0x05: return "H.222.0/13818-1 private sections";
2803 case 0x06: return "H.222.0/13818-1 PES private data";
2804 case 0x07: return "13522 MHEG";
2805 case 0x08: return "H.222.0/13818-1 Annex A - DSM CC";
2806 case 0x09: return "H.222.1";
2807 case 0x0A: return "13818-6 type A";
2808 case 0x0B: return "13818-6 type B";
2809 case 0x0C: return "13818-6 type C";
2810 case 0x0D: return "13818-6 type D";
2811 case 0x0E: return "H.222.0/13818-1 auxiliary";
2812 case 0x0F: return "13818-7 Audio with ADTS transport syntax";
2813 case 0x10: return "14496-2 Visual (MPEG-4 part 2 video)";
2814 case 0x11: return "14496-3 Audio with LATM transport syntax (14496-3/AMD 1)";
2815 case 0x12: return "14496-1 SL-packetized or FlexMux stream in PES packets";
2816 case 0x13: return "14496-1 SL-packetized or FlexMux stream in 14496 sections";
2817 case 0x14: return "ISO/IEC 13818-6 Synchronized Download Protocol";
2818 case 0x15: return "Metadata in PES packets";
2819 case 0x16: return "Metadata in metadata_sections";
2820 case 0x17: return "Metadata in 13818-6 Data Carousel";
2821 case 0x18: return "Metadata in 13818-6 Object Carousel";
2822 case 0x19: return "Metadata in 13818-6 Synchronized Download Protocol";
2823 case 0x1A: return "13818-11 MPEG-2 IPMP stream";
2824 case 0x1B: return "H.264/14496-10 video (MPEG-4/AVC)";
2825 case 0x42: return "AVS Video";
2826 case 0x7F: return "IPMP stream";
2827 default : return "Unknown stream";
2831 static const char *get_pid_desc(uint16_t i_pid, uint16_t *i_sid) {
2832 int i, j, k;
2833 uint8_t i_last_section;
2834 uint8_t *p_desc;
2835 uint16_t i_nit_pid = NIT_PID, i_pcr_pid = 0;
2837 /* Simple cases */
2838 switch (i_pid)
2840 case 0x00: return "PAT";
2841 case 0x01: return "CAT";
2842 case 0x11: return "SDT";
2843 case 0x12: return "EPG";
2844 case 0x14: return "TDT/TOT";
2847 /* Detect NIT pid */
2848 if ( psi_table_validate( pp_current_pat_sections ) )
2850 i_last_section = psi_table_get_lastsection( pp_current_pat_sections );
2851 for ( i = 0; i <= i_last_section; i++ )
2853 uint8_t *p_section = psi_table_get_section( pp_current_pat_sections, i );
2854 uint8_t *p_program;
2856 j = 0;
2857 while ( (p_program = pat_get_program( p_section, j++ )) != NULL )
2859 /* Programs with PID == 0 are actually NIT */
2860 if ( patn_get_program( p_program ) == 0 )
2862 i_nit_pid = patn_get_pid( p_program );
2863 break;
2869 /* Detect EMM pids */
2870 if ( b_enable_emm && psi_table_validate( pp_current_cat_sections ) )
2872 i_last_section = psi_table_get_lastsection( pp_current_cat_sections );
2873 for ( i = 0; i <= i_last_section; i++ )
2875 uint8_t *p_section = psi_table_get_section( pp_current_cat_sections, i );
2877 j = 0;
2878 while ( (p_desc = descl_get_desc( cat_get_descl(p_section), cat_get_desclength(p_section), j++ )) != NULL )
2880 if ( desc_get_tag( p_desc ) != 0x09 || !desc09_validate( p_desc ) )
2881 continue;
2883 if ( desc09_get_pid( p_desc ) == i_pid ) {
2884 return "EMM";
2890 /* Detect streams in PMT */
2891 for ( k = 0; k < i_nb_sids; k++ )
2893 sid_t *p_sid = pp_sids[k];
2894 if ( p_sid->i_pmt_pid == i_pid )
2896 if ( i_sid )
2897 *i_sid = p_sid->i_sid;
2898 return "PMT";
2901 if ( p_sid->i_sid && p_sid->p_current_pmt != NULL )
2903 uint8_t *p_current_pmt = p_sid->p_current_pmt;
2904 uint8_t *p_current_es;
2906 /* The PCR PID can be alone or PCR can be carried in some other PIDs (mostly video)
2907 so just remember the pid and if it is alone it will be reported as PCR, otherwise
2908 stream type of the PID will be reported */
2909 if ( i_pid == pmt_get_pcrpid( p_current_pmt ) ) {
2910 if ( i_sid )
2911 *i_sid = p_sid->i_sid;
2912 i_pcr_pid = pmt_get_pcrpid( p_current_pmt );
2915 /* Look for ECMs */
2916 j = 0;
2917 while ((p_desc = descs_get_desc( pmt_get_descs( p_current_pmt ), j++ )) != NULL)
2919 if ( desc_get_tag( p_desc ) != 0x09 || !desc09_validate( p_desc ) )
2920 continue;
2922 if ( desc09_get_pid( p_desc ) == i_pid ) {
2923 if ( i_sid )
2924 *i_sid = p_sid->i_sid;
2925 return "ECM";
2929 /* Detect stream types */
2930 j = 0;
2931 while ( (p_current_es = pmt_get_es( p_current_pmt, j++ )) != NULL )
2933 if ( pmtn_get_pid( p_current_es ) == i_pid )
2935 if ( i_sid )
2936 *i_sid = p_sid->i_sid;
2937 return h222_stream_type_desc( pmtn_get_streamtype( p_current_es ) );
2943 /* Are there any other PIDs? */
2944 if (i_pid == i_nit_pid)
2945 return "NIT";
2947 if (i_pid == i_pcr_pid)
2948 return "PCR";
2950 return "...";
2953 /*****************************************************************************
2954 * Functions that return packed sections
2955 *****************************************************************************/
2956 uint8_t *demux_get_current_packed_PAT( unsigned int *pi_pack_size ) {
2957 return psi_pack_sections( pp_current_pat_sections, pi_pack_size );
2960 uint8_t *demux_get_current_packed_CAT( unsigned int *pi_pack_size ) {
2961 return psi_pack_sections( pp_current_cat_sections, pi_pack_size );
2964 uint8_t *demux_get_current_packed_NIT( unsigned int *pi_pack_size ) {
2965 return psi_pack_sections( pp_current_nit_sections, pi_pack_size );
2968 uint8_t *demux_get_current_packed_SDT( unsigned int *pi_pack_size ) {
2969 return psi_pack_sections( pp_current_sdt_sections, pi_pack_size );
2972 uint8_t *demux_get_packed_PMT( uint16_t i_sid, unsigned int *pi_pack_size ) {
2973 sid_t *p_sid = FindSID( i_sid );
2974 if ( p_sid != NULL && p_sid->p_current_pmt && pmt_validate( p_sid->p_current_pmt ) )
2975 return psi_pack_section( p_sid->p_current_pmt, pi_pack_size );
2976 return NULL;
2979 inline void demux_get_PID_info( uint16_t i_pid, uint8_t *p_data ) {
2980 ts_pid_info_t *p_info = (ts_pid_info_t *)p_data;
2981 *p_info = p_pids[i_pid].info;
2984 inline void demux_get_PIDS_info( uint8_t *p_data ) {
2985 int i_pid;
2986 for (i_pid = 0; i_pid < MAX_PIDS; i_pid++ )
2987 demux_get_PID_info( i_pid, p_data + ( i_pid * sizeof(ts_pid_info_t) ) );