1 /*****************************************************************************
2 * mpeg_ts.c : Transport Stream input module for vlc
3 *****************************************************************************
4 * Copyright (C) 2000-2001 VideoLAN
5 * $Id: ts.c,v 1.9 2002/11/20 13:37:36 sam Exp $
7 * Authors: Henri Fallon <henri@via.ecp.fr>
8 * Johan Bilien <jobi@via.ecp.fr>
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., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
32 # include <stdint.h> /* uint8_t */
36 #include <vlc/input.h>
40 #if defined MODULE_NAME_IS_ts_dvbpsi
41 # ifdef HAVE_DVBPSI_DR_H
42 # include <dvbpsi/dvbpsi.h>
43 # include <dvbpsi/descriptor.h>
44 # include <dvbpsi/pat.h>
45 # include <dvbpsi/pmt.h>
46 # include <dvbpsi/dr.h>
49 # include "descriptor.h"
50 # include "tables/pat.h"
51 # include "tables/pmt.h"
52 # include "descriptors/dr.h"
58 /*****************************************************************************
60 *****************************************************************************/
61 #define TS_READ_ONCE 200
63 /*****************************************************************************
65 *****************************************************************************/
72 /*****************************************************************************
74 *****************************************************************************/
75 static int Activate ( vlc_object_t * );
76 static void Deactivate ( vlc_object_t * );
77 static int Demux ( input_thread_t * );
79 #if defined MODULE_NAME_IS_ts
80 static void TSDemuxPSI ( input_thread_t *, data_packet_t *,
81 es_descriptor_t *, vlc_bool_t );
82 static void TSDecodePAT( input_thread_t *, es_descriptor_t *);
83 static void TSDecodePMT( input_thread_t *, es_descriptor_t *);
84 #define PSI_CALLBACK TSDemuxPSI
85 #elif defined MODULE_NAME_IS_ts_dvbpsi
86 static void TS_DVBPSI_DemuxPSI ( input_thread_t *, data_packet_t *,
87 es_descriptor_t *, vlc_bool_t );
88 static void TS_DVBPSI_HandlePAT ( input_thread_t *, dvbpsi_pat_t * );
89 static void TS_DVBPSI_HandlePMT ( input_thread_t *, dvbpsi_pmt_t * );
90 #define PSI_CALLBACK TS_DVBPSI_DemuxPSI
93 /*****************************************************************************
95 *****************************************************************************/
96 #define VLS_BACKWARDS_COMPAT_TEXT N_("compatibility with pre-0.4 VLS")
97 #define VLS_BACKWARDS_COMPAT_LONGTEXT N_( \
98 "The protocol for transmitting A/52 audio streams changed between VLC " \
99 "0.3.x and 0.4. By default VLC assumes you have the latest VLS. In case " \
100 "you're using an old version, select this option.")
103 #if defined MODULE_NAME_IS_ts
104 set_description( _("ISO 13818-1 MPEG Transport Stream input") );
105 set_capability( "demux", 160 );
106 add_shortcut( "ts" );
107 #elif defined MODULE_NAME_IS_ts_dvbpsi
108 set_description( _("ISO 13818-1 MPEG Transport Stream input (libdvbpsi)") );
109 set_capability( "demux", 170 );
110 add_shortcut( "ts_dvbpsi" );
112 add_bool( "vls-backwards-compat", 0, NULL,
113 VLS_BACKWARDS_COMPAT_TEXT, VLS_BACKWARDS_COMPAT_LONGTEXT );
114 set_callbacks( Activate, Deactivate );
117 /*****************************************************************************
118 * Activate: initialize TS structures
119 *****************************************************************************/
120 static int Activate( vlc_object_t * p_this )
122 input_thread_t * p_input = (input_thread_t *)p_this;
123 demux_sys_t * p_demux;
124 es_descriptor_t * p_pat_es;
125 es_ts_data_t * p_demux_data;
126 stream_ts_data_t * p_stream_data;
129 /* Set the demux function */
130 p_input->pf_demux = Demux;
132 /* Initialize access plug-in structures. */
133 if( p_input->i_mtu == 0 )
136 p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
139 /* Have a peep at the show. */
140 if( input_Peek( p_input, &p_peek, 1 ) < 1 )
142 msg_Err( p_input, "cannot peek()" );
146 if( *p_peek != TS_SYNC_CODE )
148 if( *p_input->psz_demux && !strncmp( p_input->psz_demux, "ts", 3 ) )
151 msg_Err( p_input, "this does not look like a TS stream, continuing" );
155 msg_Warn( p_input, "TS module discarded (no sync)" );
160 /* Adapt the bufsize for our only use. */
161 if( p_input->i_mtu != 0 )
163 /* Have minimum granularity to avoid bottlenecks at the input level. */
164 p_input->i_bufsize = (p_input->i_mtu / TS_PACKET_SIZE) * TS_PACKET_SIZE;
167 p_demux = p_input->p_demux_data = malloc( sizeof(demux_sys_t ) );
168 if( p_demux == NULL )
173 p_input->p_private = (void*)&p_demux->mpeg;
174 p_demux->p_module = module_Need( p_input, "mpeg-system", NULL );
175 if( p_demux->p_module == NULL )
177 free( p_input->p_demux_data );
181 vlc_mutex_lock( &p_input->stream.stream_lock );
183 if( input_InitStream( p_input, sizeof( stream_ts_data_t ) ) == -1 )
185 module_Unneed( p_input, p_demux->p_module );
186 free( p_input->p_demux_data );
190 p_stream_data = (stream_ts_data_t *)p_input->stream.p_demux_data;
191 p_stream_data->i_pat_version = PAT_UNINITIALIZED ;
193 #ifdef MODULE_NAME_IS_ts_dvbpsi
194 p_stream_data->p_pat_handle = (dvbpsi_handle *)
195 dvbpsi_AttachPAT( (dvbpsi_pat_callback) &TS_DVBPSI_HandlePAT, p_input );
197 if( p_stream_data->p_pat_handle == NULL )
199 msg_Err( p_input, "could not create PAT decoder" );
200 module_Unneed( p_input, p_demux->p_module );
201 free( p_input->p_demux_data );
206 /* We'll have to catch the PAT in order to continue
207 * Then the input will catch the PMT and then the others ES
208 * The PAT es is indepedent of any program. */
209 p_pat_es = input_AddES( p_input, NULL,
210 0x00, sizeof( es_ts_data_t ) );
211 p_demux_data = (es_ts_data_t *)p_pat_es->p_demux_data;
212 p_demux_data->b_psi = 1;
213 p_demux_data->i_psi_type = PSI_IS_PAT;
214 p_demux_data->p_psi_section = malloc(sizeof(psi_section_t));
215 p_demux_data->p_psi_section->b_is_complete = 1;
217 vlc_mutex_unlock( &p_input->stream.stream_lock );
222 /*****************************************************************************
223 * Deactivate: deinitialize TS structures
224 *****************************************************************************/
225 static void Deactivate( vlc_object_t * p_this )
227 input_thread_t * p_input = (input_thread_t *)p_this;
229 module_Unneed( p_input, p_input->p_demux_data->p_module );
230 free( p_input->p_demux_data );
233 /*****************************************************************************
234 * Demux: reads and demuxes data packets
235 *****************************************************************************
236 * Returns -1 in case of error, 0 in case of EOF, otherwise the number of
238 *****************************************************************************/
239 static int Demux( input_thread_t * p_input )
241 demux_sys_t * p_demux = p_input->p_demux_data;
242 int i_read_once = (p_input->i_mtu ?
243 p_input->i_bufsize / TS_PACKET_SIZE :
247 for( i = 0; i < i_read_once; i++ )
249 data_packet_t * p_data;
252 i_result = p_demux->mpeg.pf_read_ts( p_input, &p_data );
259 p_demux->mpeg.pf_demux_ts( p_input, p_data,
260 (psi_callback_t) &PSI_CALLBACK );
267 #if defined MODULE_NAME_IS_ts
269 * PSI demultiplexing and decoding without libdvbpsi
272 /*****************************************************************************
273 * DemuxPSI : makes up complete PSI data
274 *****************************************************************************/
275 static void TSDemuxPSI( input_thread_t * p_input, data_packet_t * p_data,
276 es_descriptor_t * p_es, vlc_bool_t b_unit_start )
278 es_ts_data_t * p_demux_data;
280 p_demux_data = (es_ts_data_t *)p_es->p_demux_data;
282 #define p_psi (p_demux_data->p_psi_section)
283 #define p (p_data->p_payload_start)
287 /* unit_start set to 1 -> presence of a pointer field
288 * (see ISO/IEC 13818 (2.4.4.2) which should be set to 0x00 */
289 if( (u8)p[0] != 0x00 )
292 "non-zero pointer field found, trying to continue" );
300 /* This is the begining of a new section */
302 if( ((u8)(p[1]) & 0xc0) != 0x80 )
304 msg_Warn( p_input, "invalid PSI packet" );
309 p_psi->i_section_length = ((p[1] & 0xF) << 8) | p[2];
310 p_psi->b_section_complete = 0;
311 p_psi->i_read_in_section = 0;
312 p_psi->i_section_number = (u8)p[6];
314 if( p_psi->b_is_complete || p_psi->i_section_number == 0 )
316 /* This is a new PSI packet */
317 p_psi->b_is_complete = 0;
319 p_psi->i_version_number = ( p[5] >> 1 ) & 0x1f;
320 p_psi->i_last_section_number = (u8)p[7];
322 /* We'll write at the begining of the buffer */
323 p_psi->p_current = p_psi->buffer;
327 if( p_psi->b_section_complete )
329 /* New Section of an already started PSI */
330 p_psi->b_section_complete = 0;
332 if( p_psi->i_version_number != (( p[5] >> 1 ) & 0x1f) )
335 "PSI version differs inside same PAT" );
338 if( p_psi->i_section_number + 1 != (u8)p[6] )
341 "PSI Section discontinuity, packet lost?" );
345 p_psi->i_section_number++;
349 msg_Warn( p_input, "got unexpected new PSI section" );
356 if( !p_psi->b_trash )
359 if( (p_data->p_payload_end - p) >=
360 ( p_psi->i_section_length - p_psi->i_read_in_section ) )
362 /* The end of the section is in this TS packet */
363 memcpy( p_psi->p_current, p,
364 (p_psi->i_section_length - p_psi->i_read_in_section) );
366 p_psi->b_section_complete = 1;
368 (p_psi->i_section_length - p_psi->i_read_in_section);
370 if( p_psi->i_section_number == p_psi->i_last_section_number )
372 /* This was the last section of PSI */
373 p_psi->b_is_complete = 1;
375 switch( p_demux_data->i_psi_type)
378 TSDecodePAT( p_input, p_es );
381 TSDecodePMT( p_input, p_es );
384 msg_Warn( p_input, "received unknown PSI in DemuxPSI" );
390 memcpy( p_psi->buffer, p, p_data->p_payload_end - p );
391 p_psi->i_read_in_section += p_data->p_payload_end - p;
393 p_psi->p_current += p_data->p_payload_end - p;
400 input_DeletePacket( p_input->p_method_data, p_data );
405 /*****************************************************************************
406 * DecodePAT : Decodes Programm association table and deal with it
407 *****************************************************************************/
408 static void TSDecodePAT( input_thread_t * p_input, es_descriptor_t * p_es )
410 stream_ts_data_t * p_stream_data;
411 es_ts_data_t * p_demux_data;
413 pgrm_descriptor_t * p_pgrm;
414 es_descriptor_t * p_current_es;
415 byte_t * p_current_data;
417 int i_section_length, i_program_id, i_pmt_pid;
418 int i_loop, i_current_section;
420 vlc_bool_t b_changed = 0;
422 p_demux_data = (es_ts_data_t *)p_es->p_demux_data;
423 p_stream_data = (stream_ts_data_t *)p_input->stream.p_demux_data;
425 #define p_psi (p_demux_data->p_psi_section)
427 /* Not so fast, Mike ! If the PAT version has changed, we first check
428 * that its content has really changed before doing anything */
429 if( p_stream_data->i_pat_version != p_psi->i_version_number )
431 int i_programs = p_input->stream.i_pgrm_number;
433 p_current_data = p_psi->buffer;
437 i_section_length = ((u32)(p_current_data[1] & 0xF) << 8) |
439 i_current_section = (u8)p_current_data[6];
442 ( i_loop < (i_section_length - 9) / 4 ) && !b_changed;
445 i_program_id = ( (u32)*(p_current_data + i_loop * 4 + 8) << 8 )
446 | *(p_current_data + i_loop * 4 + 9);
447 i_pmt_pid = ( ((u32)*(p_current_data + i_loop * 4 + 10) & 0x1F)
449 | *(p_current_data + i_loop * 4 + 11);
453 if( (p_pgrm = input_FindProgram( p_input, i_program_id ))
454 && (p_current_es = input_FindES( p_input, i_pmt_pid ))
455 && p_current_es->p_pgrm == p_pgrm
456 && p_current_es->i_id == i_pmt_pid
457 && ((es_ts_data_t *)p_current_es->p_demux_data)->b_psi
458 && ((es_ts_data_t *)p_current_es->p_demux_data)
459 ->i_psi_type == PSI_IS_PMT )
470 p_current_data += 3 + i_section_length;
472 } while( ( i_current_section < p_psi->i_last_section_number )
475 /* If we didn't find the expected amount of programs, the PAT has
476 * changed. Otherwise, it only changed if b_changed is already != 0 */
477 b_changed = b_changed || i_programs;
482 /* PAT has changed. We are going to delete all programs and
483 * create new ones. We chose not to only change what was needed
484 * as a PAT change may mean the stream is radically changing and
485 * this is a secure method to avoid crashes */
486 es_ts_data_t * p_es_demux;
487 pgrm_ts_data_t * p_pgrm_demux;
489 p_current_data = p_psi->buffer;
491 /* Delete all programs */
492 while( p_input->stream.i_pgrm_number )
494 input_DelProgram( p_input, p_input->stream.pp_programs[0] );
499 i_section_length = ((u32)(p_current_data[1] & 0xF) << 8) |
501 i_current_section = (u8)p_current_data[6];
503 for( i_loop = 0; i_loop < (i_section_length - 9) / 4 ; i_loop++ )
505 i_program_id = ( (u32)*(p_current_data + i_loop * 4 + 8) << 8 )
506 | *(p_current_data + i_loop * 4 + 9);
507 i_pmt_pid = ( ((u32)*(p_current_data + i_loop * 4 + 10) & 0x1F)
509 | *(p_current_data + i_loop * 4 + 11);
511 /* If program = 0, we're having info about NIT not PMT */
514 /* Add this program */
515 p_pgrm = input_AddProgram( p_input, i_program_id,
516 sizeof( pgrm_ts_data_t ) );
518 /* whatis the PID of the PMT of this program */
519 p_pgrm_demux = (pgrm_ts_data_t *)p_pgrm->p_demux_data;
520 p_pgrm_demux->i_pmt_version = PMT_UNINITIALIZED;
522 /* Add the PMT ES to this program */
523 p_current_es = input_AddES( p_input, p_pgrm,(u16)i_pmt_pid,
524 sizeof( es_ts_data_t) );
525 p_es_demux = (es_ts_data_t *)p_current_es->p_demux_data;
526 p_es_demux->b_psi = 1;
527 p_es_demux->i_psi_type = PSI_IS_PMT;
529 p_es_demux->p_psi_section =
530 malloc( sizeof( psi_section_t ) );
531 p_es_demux->p_psi_section->b_is_complete = 0;
535 p_current_data += 3 + i_section_length;
537 } while( i_current_section < p_psi->i_last_section_number );
539 /* Go to the beginning of the next section */
540 p_stream_data->i_pat_version = p_psi->i_version_number;
547 /*****************************************************************************
548 * DecodePMT : decode a given Program Stream Map
549 * ***************************************************************************
550 * When the PMT changes, it may mean a deep change in the stream, and it is
551 * careful to delete the ES and add them again. If the PMT doesn't change,
552 * there no need to do anything.
553 *****************************************************************************/
554 static void TSDecodePMT( input_thread_t * p_input, es_descriptor_t * p_es )
557 pgrm_ts_data_t * p_pgrm_data;
558 es_ts_data_t * p_demux_data;
559 vlc_bool_t b_vls_compat = config_GetInt( p_input, "vls-backwards-compat" );
561 p_demux_data = (es_ts_data_t *)p_es->p_demux_data;
562 p_pgrm_data = (pgrm_ts_data_t *)p_es->p_pgrm->p_demux_data;
564 #define p_psi (p_demux_data->p_psi_section)
566 if( p_psi->i_version_number != p_pgrm_data->i_pmt_version )
568 es_descriptor_t * p_new_es;
569 es_ts_data_t * p_es_demux;
570 byte_t * p_current_data, * p_current_section;
571 int i_section_length,i_current_section;
572 int i_prog_info_length, i_loop;
573 int i_es_info_length, i_pid, i_stream_type;
575 p_current_section = p_psi->buffer;
576 p_current_data = p_psi->buffer;
578 p_pgrm_data->i_pcr_pid = ( ((u32)*(p_current_section + 8) & 0x1F) << 8 ) |
579 *(p_current_section + 9);
582 /* Lock stream information */
583 vlc_mutex_lock( &p_input->stream.stream_lock );
585 /* Delete all ES in this program except the PSI. We start from the
586 * end because i_es_number gets decremented after each deletion. */
587 for( i_loop = p_es->p_pgrm->i_es_number ; i_loop ; )
590 p_es_demux = (es_ts_data_t *)
591 p_es->p_pgrm->pp_es[i_loop]->p_demux_data;
592 if ( ! p_es_demux->b_psi )
594 input_DelES( p_input, p_es->p_pgrm->pp_es[i_loop] );
598 /* Then add what we received in this PMT */
601 i_section_length = ( ((u32)*(p_current_data + 1) & 0xF) << 8 ) |
602 *(p_current_data + 2);
603 i_current_section = (u8)p_current_data[6];
604 i_prog_info_length = ( ((u32)*(p_current_data + 10) & 0xF) << 8 ) |
605 *(p_current_data + 11);
607 /* For the moment we ignore program descriptors */
608 p_current_data += 12 + i_prog_info_length;
610 /* The end of the section, before the CRC is at
611 * p_current_section + i_section_length -1 */
612 while( p_current_data < p_current_section + i_section_length -1 )
614 i_stream_type = (int)p_current_data[0];
615 i_pid = ( ((u32)*(p_current_data + 1) & 0x1F) << 8 ) |
616 *(p_current_data + 2);
617 i_es_info_length = ( ((u32)*(p_current_data + 3) & 0xF) << 8 ) |
618 *(p_current_data + 4);
620 /* Add this ES to the program */
621 p_new_es = input_AddES( p_input, p_es->p_pgrm,
622 (u16)i_pid, sizeof( es_ts_data_t ) );
624 /* Tell the interface what kind of stream it is and select
625 * the required ones */
627 switch( i_stream_type )
631 p_new_es->i_fourcc = VLC_FOURCC('m','p','g','v');
632 p_new_es->i_cat = VIDEO_ES;
636 p_new_es->i_fourcc = VLC_FOURCC('m','p','g','a');
637 p_new_es->i_cat = AUDIO_ES;
640 case A52DVB_AUDIO_ES:
642 p_new_es->i_fourcc = VLC_FOURCC('a','5','2',' ');
644 p_new_es->i_fourcc = VLC_FOURCC('a','5','2','b');
645 p_new_es->i_stream_id = 0xBD;
646 p_new_es->i_cat = AUDIO_ES;
649 p_new_es->i_fourcc = VLC_FOURCC('l','p','c','m');
650 p_new_es->i_stream_id = 0xBD;
651 p_new_es->i_cat = AUDIO_ES;
655 p_new_es->i_fourcc = VLC_FOURCC('s','p','u',' ');
657 p_new_es->i_fourcc = VLC_FOURCC('s','p','u','b');
658 p_new_es->i_stream_id = 0xBD;
659 p_new_es->i_cat = SPU_ES;
662 p_new_es->i_fourcc = VLC_FOURCC('s','d','d','s');
663 p_new_es->i_stream_id = 0xBD;
664 p_new_es->i_cat = AUDIO_ES;
667 p_new_es->i_fourcc = VLC_FOURCC('d','t','s',' ');
668 p_new_es->i_stream_id = 0xBD;
669 p_new_es->i_cat = AUDIO_ES;
671 /* 'b' stands for 'buggy' */
673 p_new_es->i_fourcc = VLC_FOURCC('a','5','2','b');
674 p_new_es->i_stream_id = 0xBD;
675 p_new_es->i_cat = AUDIO_ES;
678 p_new_es->i_fourcc = VLC_FOURCC('l','p','c','b');
679 p_new_es->i_stream_id = 0xBD;
680 p_new_es->i_cat = AUDIO_ES;
683 p_new_es->i_fourcc = VLC_FOURCC('s','p','u','b');
684 p_new_es->i_stream_id = 0xBD;
685 p_new_es->i_cat = SPU_ES;
688 p_new_es->i_fourcc = 0;
689 p_new_es->i_cat = UNKNOWN_ES;
694 p_current_data += 5 + i_es_info_length;
697 /* Go to the beginning of the next section*/
698 p_current_data += 3 + i_section_length;
702 } while( i_current_section < p_psi->i_last_section_number );
704 p_pgrm_data->i_pmt_version = p_psi->i_version_number;
706 /* if no program is selected :*/
707 if( !p_input->stream.p_selected_program )
709 pgrm_descriptor_t * p_pgrm_to_select;
710 u16 i_id = (u16)config_GetInt( p_input, "program" );
712 if( i_id != 0 ) /* if user specified a program */
714 p_pgrm_to_select = input_FindProgram( p_input, i_id );
716 if( p_pgrm_to_select && p_pgrm_to_select == p_es->p_pgrm )
717 p_input->pf_set_program( p_input, p_pgrm_to_select );
720 p_input->pf_set_program( p_input, p_es->p_pgrm );
723 /* inform interface that stream has changed */
724 p_input->stream.b_changed = 1;
726 vlc_mutex_unlock( &p_input->stream.stream_lock );
732 #elif defined MODULE_NAME_IS_ts_dvbpsi
734 * PSI Decoding using libdvbcss
737 /*****************************************************************************
738 * DemuxPSI : send the PSI to the right libdvbpsi decoder
739 *****************************************************************************/
740 static void TS_DVBPSI_DemuxPSI( input_thread_t * p_input,
741 data_packet_t * p_data,
742 es_descriptor_t * p_es,
743 vlc_bool_t b_unit_start )
745 es_ts_data_t * p_es_demux_data;
746 pgrm_ts_data_t * p_pgrm_demux_data;
747 stream_ts_data_t * p_stream_demux_data;
749 p_es_demux_data = ( es_ts_data_t * ) p_es->p_demux_data;
750 p_stream_demux_data = ( stream_ts_data_t * ) p_input->stream.p_demux_data;
752 switch( p_es_demux_data->i_psi_type)
756 ( dvbpsi_handle ) p_stream_demux_data->p_pat_handle,
757 p_data->p_demux_start );
760 p_pgrm_demux_data = ( pgrm_ts_data_t * )p_es->p_pgrm->p_demux_data;
762 ( dvbpsi_handle ) p_pgrm_demux_data->p_pmt_handle,
763 p_data->p_demux_start );
766 msg_Warn( p_input, "received unknown PSI in DemuxPSI" );
769 input_DeletePacket( p_input->p_method_data, p_data );
772 /*****************************************************************************
773 * HandlePAT: will treat a PAT returned by dvbpsi
774 *****************************************************************************/
776 void TS_DVBPSI_HandlePAT( input_thread_t * p_input, dvbpsi_pat_t * p_new_pat )
778 dvbpsi_pat_program_t * p_pgrm;
779 pgrm_descriptor_t * p_new_pgrm;
780 pgrm_ts_data_t * p_pgrm_demux;
781 es_descriptor_t * p_current_es;
782 es_ts_data_t * p_es_demux;
783 stream_ts_data_t * p_stream_data;
785 vlc_mutex_lock( &p_input->stream.stream_lock );
787 p_stream_data = (stream_ts_data_t *)p_input->stream.p_demux_data;
789 if ( !p_new_pat->b_current_next ||
790 p_stream_data->i_pat_version == PAT_UNINITIALIZED )
792 /* Delete all programs */
793 while( p_input->stream.i_pgrm_number )
795 input_DelProgram( p_input, p_input->stream.pp_programs[0] );
798 /* treat the new programs list */
799 p_pgrm = p_new_pat->p_first_program;
803 /* If program = 0, we're having info about NIT not PMT */
804 if( p_pgrm->i_number )
806 /* Add this program */
807 p_new_pgrm = input_AddProgram( p_input, p_pgrm->i_number,
808 sizeof( pgrm_ts_data_t ) );
810 p_pgrm_demux = (pgrm_ts_data_t *)p_new_pgrm->p_demux_data;
811 p_pgrm_demux->i_pmt_version = PMT_UNINITIALIZED;
813 /* Add the PMT ES to this program */
814 p_current_es = input_AddES( p_input, p_new_pgrm,
816 sizeof( es_ts_data_t) );
817 p_es_demux = (es_ts_data_t *)p_current_es->p_demux_data;
818 p_es_demux->b_psi = 1;
819 p_es_demux->i_psi_type = PSI_IS_PMT;
821 p_es_demux->p_psi_section = malloc( sizeof( psi_section_t ) );
822 if ( p_es_demux->p_psi_section == NULL )
824 msg_Err( p_input, "out of memory" );
825 p_input->b_error = 1;
829 p_es_demux->p_psi_section->b_is_complete = 0;
831 /* Create a PMT decoder */
832 p_pgrm_demux->p_pmt_handle = (dvbpsi_handle *)
833 dvbpsi_AttachPMT( p_pgrm->i_number,
834 (dvbpsi_pmt_callback) &TS_DVBPSI_HandlePMT,
837 if( p_pgrm_demux->p_pmt_handle == NULL )
839 msg_Err( p_input, "could not create PMT decoder" );
840 p_input->b_error = 1;
845 p_pgrm = p_pgrm->p_next;
848 p_stream_data->i_pat_version = p_new_pat->i_version;
850 vlc_mutex_unlock( &p_input->stream.stream_lock );
853 /*****************************************************************************
854 * HandlePMT: will treat a PMT returned by dvbpsi
855 *****************************************************************************/
856 void TS_DVBPSI_HandlePMT( input_thread_t * p_input, dvbpsi_pmt_t * p_new_pmt )
858 dvbpsi_pmt_es_t * p_es;
859 pgrm_descriptor_t * p_pgrm;
860 es_descriptor_t * p_new_es;
861 pgrm_ts_data_t * p_pgrm_demux;
862 vlc_bool_t b_vls_compat = config_GetInt( p_input, "vls-backwards-compat" );
864 vlc_mutex_lock( &p_input->stream.stream_lock );
866 p_pgrm = input_FindProgram( p_input, p_new_pmt->i_program_number );
870 msg_Warn( p_input, "PMT of unreferenced program found" );
874 p_pgrm_demux = (pgrm_ts_data_t *)p_pgrm->p_demux_data;
875 p_pgrm_demux->i_pcr_pid = p_new_pmt->i_pcr_pid;
877 if( !p_new_pmt->b_current_next ||
878 p_pgrm_demux->i_pmt_version == PMT_UNINITIALIZED )
880 p_es = p_new_pmt->p_first_es;
884 p_new_es = input_AddES( p_input, p_pgrm,
885 (u16)p_es->i_pid, sizeof( es_ts_data_t ) );
886 if( p_new_es == NULL )
888 msg_Err( p_input, "could not add ES %d", p_es->i_pid );
889 p_input->b_error = 1;
893 switch( p_es->i_type )
897 p_new_es->i_fourcc = VLC_FOURCC('m','p','g','v');
898 p_new_es->i_cat = VIDEO_ES;
902 p_new_es->i_fourcc = VLC_FOURCC('m','p','g','a');
903 p_new_es->i_cat = AUDIO_ES;
906 case A52DVB_AUDIO_ES:
908 p_new_es->i_fourcc = VLC_FOURCC('a','5','2',' ');
910 p_new_es->i_fourcc = VLC_FOURCC('a','5','2','b');
911 p_new_es->i_cat = AUDIO_ES;
912 p_new_es->i_stream_id = 0xBD;
916 p_new_es->i_fourcc = VLC_FOURCC('s','p','u',' ');
918 p_new_es->i_fourcc = VLC_FOURCC('s','p','u','b');
919 p_new_es->i_cat = SPU_ES;
920 p_new_es->i_stream_id = 0xBD;
923 p_new_es->i_fourcc = VLC_FOURCC('l','p','c','m');
924 p_new_es->i_cat = AUDIO_ES;
925 p_new_es->i_stream_id = 0xBD;
928 p_new_es->i_fourcc = VLC_FOURCC('s','d','d','s');
929 p_new_es->i_stream_id = 0xBD;
930 p_new_es->i_cat = AUDIO_ES;
933 p_new_es->i_fourcc = VLC_FOURCC('d','t','s',' ');
934 p_new_es->i_stream_id = 0xBD;
935 p_new_es->i_cat = AUDIO_ES;
938 p_new_es->i_fourcc = VLC_FOURCC('a','5','2','b');
939 p_new_es->i_cat = AUDIO_ES;
940 p_new_es->i_stream_id = 0xBD;
943 p_new_es->i_fourcc = VLC_FOURCC('s','p','u','b');
944 p_new_es->i_cat = SPU_ES;
945 p_new_es->i_stream_id = 0xBD;
948 p_new_es->i_fourcc = VLC_FOURCC('l','p','c','b');
949 p_new_es->i_cat = AUDIO_ES;
950 p_new_es->i_stream_id = 0xBD;
953 p_new_es->i_fourcc = 0;
954 p_new_es->i_cat = UNKNOWN_ES;
957 if( ( p_new_es->i_cat == AUDIO_ES )
958 || (p_new_es->i_cat == SPU_ES ) )
960 dvbpsi_descriptor_t *p_dr = p_es->p_first_descriptor;
961 while( p_dr && ( p_dr->i_tag != 0x0a ) )
965 dvbpsi_iso639_dr_t *p_decoded =
966 dvbpsi_DecodeISO639Dr( p_dr );
967 if( p_decoded->i_code_count > 0 )
969 const iso639_lang_t * p_iso;
970 p_iso = GetLang_2T((char*)p_decoded->i_iso_639_code);
973 if(p_iso->psz_native_name[0])
974 strcpy( p_new_es->psz_desc,
975 p_iso->psz_native_name );
977 strcpy( p_new_es->psz_desc,
978 p_iso->psz_eng_name );
982 strncpy( p_new_es->psz_desc,
983 p_decoded->i_iso_639_code, 3 );
987 switch( p_es->i_type )
991 strcat( p_new_es->psz_desc, " (mpeg)" );
995 strcat( p_new_es->psz_desc, " (lpcm)" );
998 case A52DVB_AUDIO_ES:
1000 strcat( p_new_es->psz_desc, " (A52)" );
1005 p_es = p_es->p_next;
1008 /* if no program is selected :*/
1009 if( !p_input->stream.p_selected_program )
1011 pgrm_descriptor_t * p_pgrm_to_select;
1012 u16 i_id = (u16)config_GetInt( p_input, "program" );
1014 if( i_id != 0 ) /* if user specified a program */
1016 p_pgrm_to_select = input_FindProgram( p_input, i_id );
1018 if( p_pgrm_to_select && p_pgrm_to_select == p_pgrm )
1019 p_input->pf_set_program( p_input, p_pgrm_to_select );
1022 p_input->pf_set_program( p_input, p_pgrm );
1024 /* if the pmt belongs to the currently selected program, we
1025 * reselect it to update its ES */
1026 else if( p_pgrm == p_input->stream.p_selected_program )
1028 p_input->pf_set_program( p_input, p_pgrm );
1031 p_pgrm_demux->i_pmt_version = p_new_pmt->i_version;
1032 p_input->stream.b_changed = 1;
1034 vlc_mutex_unlock( &p_input->stream.stream_lock );