1 /*****************************************************************************
2 * mpeg_ts.c : Transport Stream input module for vlc
3 *****************************************************************************
4 * Copyright (C) 2000-2001 VideoLAN
5 * $Id: ts.c,v 1.6 2002/09/26 22:40:24 massiot 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 *****************************************************************************/
33 #include <vlc/input.h>
37 #if defined MODULE_NAME_IS_ts_dvbpsi
38 # ifdef HAVE_DVBPSI_DR_H
39 # include <dvbpsi/dvbpsi.h>
40 # include <dvbpsi/descriptor.h>
41 # include <dvbpsi/pat.h>
42 # include <dvbpsi/pmt.h>
43 # include <dvbpsi/dr.h>
46 # include "descriptor.h"
47 # include "tables/pat.h"
48 # include "tables/pmt.h"
49 # include "descriptors/dr.h"
55 /*****************************************************************************
57 *****************************************************************************/
58 #define TS_READ_ONCE 200
60 /*****************************************************************************
62 *****************************************************************************/
69 /*****************************************************************************
71 *****************************************************************************/
72 static int Activate ( vlc_object_t * );
73 static void Deactivate ( vlc_object_t * );
74 static int Demux ( input_thread_t * );
76 #if defined MODULE_NAME_IS_ts
77 static void TSDemuxPSI ( input_thread_t *, data_packet_t *,
78 es_descriptor_t *, vlc_bool_t );
79 static void TSDecodePAT( input_thread_t *, es_descriptor_t *);
80 static void TSDecodePMT( input_thread_t *, es_descriptor_t *);
81 #define PSI_CALLBACK TSDemuxPSI
82 #elif defined MODULE_NAME_IS_ts_dvbpsi
83 static void TS_DVBPSI_DemuxPSI ( input_thread_t *, data_packet_t *,
84 es_descriptor_t *, vlc_bool_t );
85 static void TS_DVBPSI_HandlePAT ( input_thread_t *, dvbpsi_pat_t * );
86 static void TS_DVBPSI_HandlePMT ( input_thread_t *, dvbpsi_pmt_t * );
87 #define PSI_CALLBACK TS_DVBPSI_DemuxPSI
90 /*****************************************************************************
92 *****************************************************************************/
93 #define VLS_BACKWARDS_COMPAT_TEXT N_("compatibility with pre-0.4 VLS")
94 #define VLS_BACKWARDS_COMPAT_LONGTEXT N_( \
95 "The protocol for transmitting A/52 audio streams changed between VLC " \
96 "0.3.x and 0.4. By default VLC assumes you have the latest VLS. In case " \
97 "you're using an old version, select this option.")
100 #if defined MODULE_NAME_IS_ts
101 set_description( _("ISO 13818-1 MPEG Transport Stream input") );
102 set_capability( "demux", 160 );
103 add_shortcut( "ts" );
104 #elif defined MODULE_NAME_IS_ts_dvbpsi
105 set_description( _("ISO 13818-1 MPEG Transport Stream input (libdvbpsi)") );
106 set_capability( "demux", 170 );
107 add_shortcut( "ts_dvbpsi" );
109 add_bool( "vls-backwards-compat", 0, NULL,
110 VLS_BACKWARDS_COMPAT_TEXT, VLS_BACKWARDS_COMPAT_LONGTEXT );
111 set_callbacks( Activate, Deactivate );
114 /*****************************************************************************
115 * Activate: initialize TS structures
116 *****************************************************************************/
117 static int Activate( vlc_object_t * p_this )
119 input_thread_t * p_input = (input_thread_t *)p_this;
120 demux_sys_t * p_demux;
121 es_descriptor_t * p_pat_es;
122 es_ts_data_t * p_demux_data;
123 stream_ts_data_t * p_stream_data;
126 /* Set the demux function */
127 p_input->pf_demux = Demux;
129 /* Initialize access plug-in structures. */
130 if( p_input->i_mtu == 0 )
133 p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
136 /* Have a peep at the show. */
137 if( input_Peek( p_input, &p_peek, 1 ) < 1 )
139 msg_Err( p_input, "cannot peek()" );
143 if( *p_peek != TS_SYNC_CODE )
145 if( *p_input->psz_demux && !strncmp( p_input->psz_demux, "ts", 3 ) )
148 msg_Err( p_input, "this does not look like a TS stream, continuing" );
152 msg_Warn( p_input, "TS module discarded (no sync)" );
157 /* Adapt the bufsize for our only use. */
158 if( p_input->i_mtu != 0 )
160 /* Have minimum granularity to avoid bottlenecks at the input level. */
161 p_input->i_bufsize = (p_input->i_mtu / TS_PACKET_SIZE) * TS_PACKET_SIZE;
164 p_demux = p_input->p_demux_data = malloc( sizeof(demux_sys_t ) );
165 if( p_demux == NULL )
170 p_input->p_private = (void*)&p_demux->mpeg;
171 p_demux->p_module = module_Need( p_input, "mpeg-system", NULL );
172 if( p_demux->p_module == NULL )
174 free( p_input->p_demux_data );
178 vlc_mutex_lock( &p_input->stream.stream_lock );
180 if( input_InitStream( p_input, sizeof( stream_ts_data_t ) ) == -1 )
182 module_Unneed( p_input, p_demux->p_module );
183 free( p_input->p_demux_data );
187 p_stream_data = (stream_ts_data_t *)p_input->stream.p_demux_data;
188 p_stream_data->i_pat_version = PAT_UNINITIALIZED ;
190 #ifdef MODULE_NAME_IS_ts_dvbpsi
191 p_stream_data->p_pat_handle = (dvbpsi_handle *)
192 dvbpsi_AttachPAT( (dvbpsi_pat_callback) &TS_DVBPSI_HandlePAT, p_input );
194 if( p_stream_data->p_pat_handle == NULL )
196 msg_Err( p_input, "could not create PAT decoder" );
197 module_Unneed( p_input, p_demux->p_module );
198 free( p_input->p_demux_data );
203 /* We'll have to catch the PAT in order to continue
204 * Then the input will catch the PMT and then the others ES
205 * The PAT es is indepedent of any program. */
206 p_pat_es = input_AddES( p_input, NULL,
207 0x00, sizeof( es_ts_data_t ) );
208 p_demux_data = (es_ts_data_t *)p_pat_es->p_demux_data;
209 p_demux_data->b_psi = 1;
210 p_demux_data->i_psi_type = PSI_IS_PAT;
211 p_demux_data->p_psi_section = malloc(sizeof(psi_section_t));
212 p_demux_data->p_psi_section->b_is_complete = 1;
214 vlc_mutex_unlock( &p_input->stream.stream_lock );
219 /*****************************************************************************
220 * Deactivate: deinitialize TS structures
221 *****************************************************************************/
222 static void Deactivate( vlc_object_t * p_this )
224 input_thread_t * p_input = (input_thread_t *)p_this;
226 module_Unneed( p_input, p_input->p_demux_data->p_module );
227 free( p_input->p_demux_data );
230 /*****************************************************************************
231 * Demux: reads and demuxes data packets
232 *****************************************************************************
233 * Returns -1 in case of error, 0 in case of EOF, otherwise the number of
235 *****************************************************************************/
236 static int Demux( input_thread_t * p_input )
238 demux_sys_t * p_demux = p_input->p_demux_data;
239 int i_read_once = (p_input->i_mtu ?
240 p_input->i_bufsize / TS_PACKET_SIZE :
244 for( i = 0; i < i_read_once; i++ )
246 data_packet_t * p_data;
249 i_result = p_demux->mpeg.pf_read_ts( p_input, &p_data );
256 p_demux->mpeg.pf_demux_ts( p_input, p_data,
257 (psi_callback_t) &PSI_CALLBACK );
264 #if defined MODULE_NAME_IS_ts
266 * PSI demultiplexing and decoding without libdvbpsi
269 /*****************************************************************************
270 * DemuxPSI : makes up complete PSI data
271 *****************************************************************************/
272 static void TSDemuxPSI( input_thread_t * p_input, data_packet_t * p_data,
273 es_descriptor_t * p_es, vlc_bool_t b_unit_start )
275 es_ts_data_t * p_demux_data;
277 p_demux_data = (es_ts_data_t *)p_es->p_demux_data;
279 #define p_psi (p_demux_data->p_psi_section)
280 #define p (p_data->p_payload_start)
284 /* unit_start set to 1 -> presence of a pointer field
285 * (see ISO/IEC 13818 (2.4.4.2) which should be set to 0x00 */
286 if( (u8)p[0] != 0x00 )
289 "non-zero pointer field found, trying to continue" );
297 /* This is the begining of a new section */
299 if( ((u8)(p[1]) & 0xc0) != 0x80 )
301 msg_Warn( p_input, "invalid PSI packet" );
306 p_psi->i_section_length = ((p[1] & 0xF) << 8) | p[2];
307 p_psi->b_section_complete = 0;
308 p_psi->i_read_in_section = 0;
309 p_psi->i_section_number = (u8)p[6];
311 if( p_psi->b_is_complete || p_psi->i_section_number == 0 )
313 /* This is a new PSI packet */
314 p_psi->b_is_complete = 0;
316 p_psi->i_version_number = ( p[5] >> 1 ) & 0x1f;
317 p_psi->i_last_section_number = (u8)p[7];
319 /* We'll write at the begining of the buffer */
320 p_psi->p_current = p_psi->buffer;
324 if( p_psi->b_section_complete )
326 /* New Section of an already started PSI */
327 p_psi->b_section_complete = 0;
329 if( p_psi->i_version_number != (( p[5] >> 1 ) & 0x1f) )
332 "PSI version differs inside same PAT" );
335 if( p_psi->i_section_number + 1 != (u8)p[6] )
338 "PSI Section discontinuity, packet lost?" );
342 p_psi->i_section_number++;
346 msg_Warn( p_input, "got unexpected new PSI section" );
353 if( !p_psi->b_trash )
356 if( (p_data->p_payload_end - p) >=
357 ( p_psi->i_section_length - p_psi->i_read_in_section ) )
359 /* The end of the section is in this TS packet */
360 memcpy( p_psi->p_current, p,
361 (p_psi->i_section_length - p_psi->i_read_in_section) );
363 p_psi->b_section_complete = 1;
365 (p_psi->i_section_length - p_psi->i_read_in_section);
367 if( p_psi->i_section_number == p_psi->i_last_section_number )
369 /* This was the last section of PSI */
370 p_psi->b_is_complete = 1;
372 switch( p_demux_data->i_psi_type)
375 TSDecodePAT( p_input, p_es );
378 TSDecodePMT( p_input, p_es );
381 msg_Warn( p_input, "received unknown PSI in DemuxPSI" );
387 memcpy( p_psi->buffer, p, p_data->p_payload_end - p );
388 p_psi->i_read_in_section += p_data->p_payload_end - p;
390 p_psi->p_current += p_data->p_payload_end - p;
397 input_DeletePacket( p_input->p_method_data, p_data );
402 /*****************************************************************************
403 * DecodePAT : Decodes Programm association table and deal with it
404 *****************************************************************************/
405 static void TSDecodePAT( input_thread_t * p_input, es_descriptor_t * p_es )
407 stream_ts_data_t * p_stream_data;
408 es_ts_data_t * p_demux_data;
410 pgrm_descriptor_t * p_pgrm;
411 es_descriptor_t * p_current_es;
412 byte_t * p_current_data;
414 int i_section_length, i_program_id, i_pmt_pid;
415 int i_loop, i_current_section;
417 vlc_bool_t b_changed = 0;
419 p_demux_data = (es_ts_data_t *)p_es->p_demux_data;
420 p_stream_data = (stream_ts_data_t *)p_input->stream.p_demux_data;
422 #define p_psi (p_demux_data->p_psi_section)
424 /* Not so fast, Mike ! If the PAT version has changed, we first check
425 * that its content has really changed before doing anything */
426 if( p_stream_data->i_pat_version != p_psi->i_version_number )
428 int i_programs = p_input->stream.i_pgrm_number;
430 p_current_data = p_psi->buffer;
434 i_section_length = ((u32)(p_current_data[1] & 0xF) << 8) |
436 i_current_section = (u8)p_current_data[6];
439 ( i_loop < (i_section_length - 9) / 4 ) && !b_changed;
442 i_program_id = ( (u32)*(p_current_data + i_loop * 4 + 8) << 8 )
443 | *(p_current_data + i_loop * 4 + 9);
444 i_pmt_pid = ( ((u32)*(p_current_data + i_loop * 4 + 10) & 0x1F)
446 | *(p_current_data + i_loop * 4 + 11);
450 if( (p_pgrm = input_FindProgram( p_input, i_program_id ))
451 && (p_current_es = input_FindES( p_input, i_pmt_pid ))
452 && p_current_es->p_pgrm == p_pgrm
453 && p_current_es->i_id == i_pmt_pid
454 && ((es_ts_data_t *)p_current_es->p_demux_data)->b_psi
455 && ((es_ts_data_t *)p_current_es->p_demux_data)
456 ->i_psi_type == PSI_IS_PMT )
467 p_current_data += 3 + i_section_length;
469 } while( ( i_current_section < p_psi->i_last_section_number )
472 /* If we didn't find the expected amount of programs, the PAT has
473 * changed. Otherwise, it only changed if b_changed is already != 0 */
474 b_changed = b_changed || i_programs;
479 /* PAT has changed. We are going to delete all programs and
480 * create new ones. We chose not to only change what was needed
481 * as a PAT change may mean the stream is radically changing and
482 * this is a secure method to avoid crashes */
483 es_ts_data_t * p_es_demux;
484 pgrm_ts_data_t * p_pgrm_demux;
486 p_current_data = p_psi->buffer;
488 /* Delete all programs */
489 while( p_input->stream.i_pgrm_number )
491 input_DelProgram( p_input, p_input->stream.pp_programs[0] );
496 i_section_length = ((u32)(p_current_data[1] & 0xF) << 8) |
498 i_current_section = (u8)p_current_data[6];
500 for( i_loop = 0; i_loop < (i_section_length - 9) / 4 ; i_loop++ )
502 i_program_id = ( (u32)*(p_current_data + i_loop * 4 + 8) << 8 )
503 | *(p_current_data + i_loop * 4 + 9);
504 i_pmt_pid = ( ((u32)*(p_current_data + i_loop * 4 + 10) & 0x1F)
506 | *(p_current_data + i_loop * 4 + 11);
508 /* If program = 0, we're having info about NIT not PMT */
511 /* Add this program */
512 p_pgrm = input_AddProgram( p_input, i_program_id,
513 sizeof( pgrm_ts_data_t ) );
515 /* whatis the PID of the PMT of this program */
516 p_pgrm_demux = (pgrm_ts_data_t *)p_pgrm->p_demux_data;
517 p_pgrm_demux->i_pmt_version = PMT_UNINITIALIZED;
519 /* Add the PMT ES to this program */
520 p_current_es = input_AddES( p_input, p_pgrm,(u16)i_pmt_pid,
521 sizeof( es_ts_data_t) );
522 p_es_demux = (es_ts_data_t *)p_current_es->p_demux_data;
523 p_es_demux->b_psi = 1;
524 p_es_demux->i_psi_type = PSI_IS_PMT;
526 p_es_demux->p_psi_section =
527 malloc( sizeof( psi_section_t ) );
528 p_es_demux->p_psi_section->b_is_complete = 0;
532 p_current_data += 3 + i_section_length;
534 } while( i_current_section < p_psi->i_last_section_number );
536 /* Go to the beginning of the next section */
537 p_stream_data->i_pat_version = p_psi->i_version_number;
544 /*****************************************************************************
545 * DecodePMT : decode a given Program Stream Map
546 * ***************************************************************************
547 * When the PMT changes, it may mean a deep change in the stream, and it is
548 * careful to delete the ES and add them again. If the PMT doesn't change,
549 * there no need to do anything.
550 *****************************************************************************/
551 static void TSDecodePMT( input_thread_t * p_input, es_descriptor_t * p_es )
554 pgrm_ts_data_t * p_pgrm_data;
555 es_ts_data_t * p_demux_data;
556 vlc_bool_t b_vls_compat = config_GetInt( p_input, "vls-backwards-compat" );
558 p_demux_data = (es_ts_data_t *)p_es->p_demux_data;
559 p_pgrm_data = (pgrm_ts_data_t *)p_es->p_pgrm->p_demux_data;
561 #define p_psi (p_demux_data->p_psi_section)
563 if( p_psi->i_version_number != p_pgrm_data->i_pmt_version )
565 es_descriptor_t * p_new_es;
566 es_ts_data_t * p_es_demux;
567 byte_t * p_current_data, * p_current_section;
568 int i_section_length,i_current_section;
569 int i_prog_info_length, i_loop;
570 int i_es_info_length, i_pid, i_stream_type;
572 p_current_section = p_psi->buffer;
573 p_current_data = p_psi->buffer;
575 p_pgrm_data->i_pcr_pid = ( ((u32)*(p_current_section + 8) & 0x1F) << 8 ) |
576 *(p_current_section + 9);
579 /* Lock stream information */
580 vlc_mutex_lock( &p_input->stream.stream_lock );
582 /* Delete all ES in this program except the PSI. We start from the
583 * end because i_es_number gets decremented after each deletion. */
584 for( i_loop = p_es->p_pgrm->i_es_number ; i_loop ; )
587 p_es_demux = (es_ts_data_t *)
588 p_es->p_pgrm->pp_es[i_loop]->p_demux_data;
589 if ( ! p_es_demux->b_psi )
591 input_DelES( p_input, p_es->p_pgrm->pp_es[i_loop] );
595 /* Then add what we received in this PMT */
598 i_section_length = ( ((u32)*(p_current_data + 1) & 0xF) << 8 ) |
599 *(p_current_data + 2);
600 i_current_section = (u8)p_current_data[6];
601 i_prog_info_length = ( ((u32)*(p_current_data + 10) & 0xF) << 8 ) |
602 *(p_current_data + 11);
604 /* For the moment we ignore program descriptors */
605 p_current_data += 12 + i_prog_info_length;
607 /* The end of the section, before the CRC is at
608 * p_current_section + i_section_length -1 */
609 while( p_current_data < p_current_section + i_section_length -1 )
611 i_stream_type = (int)p_current_data[0];
612 i_pid = ( ((u32)*(p_current_data + 1) & 0x1F) << 8 ) |
613 *(p_current_data + 2);
614 i_es_info_length = ( ((u32)*(p_current_data + 3) & 0xF) << 8 ) |
615 *(p_current_data + 4);
617 /* Add this ES to the program */
618 p_new_es = input_AddES( p_input, p_es->p_pgrm,
619 (u16)i_pid, sizeof( es_ts_data_t ) );
621 /* Tell the interface what kind of stream it is and select
622 * the required ones */
624 switch( i_stream_type )
628 p_new_es->i_fourcc = VLC_FOURCC('m','p','g','v');
629 p_new_es->i_cat = VIDEO_ES;
633 p_new_es->i_fourcc = VLC_FOURCC('m','p','g','a');
634 p_new_es->i_cat = AUDIO_ES;
638 p_new_es->i_fourcc = VLC_FOURCC('a','5','2',' ');
640 p_new_es->i_fourcc = VLC_FOURCC('a','5','2','b');
641 p_new_es->i_stream_id = 0xBD;
642 p_new_es->i_cat = AUDIO_ES;
645 p_new_es->i_fourcc = VLC_FOURCC('l','p','c','m');
646 p_new_es->i_stream_id = 0xBD;
647 p_new_es->i_cat = AUDIO_ES;
651 p_new_es->i_fourcc = VLC_FOURCC('s','p','u',' ');
653 p_new_es->i_fourcc = VLC_FOURCC('s','p','u','b');
654 p_new_es->i_stream_id = 0xBD;
655 p_new_es->i_cat = SPU_ES;
658 p_new_es->i_fourcc = VLC_FOURCC('s','d','d','s');
659 p_new_es->i_stream_id = 0xBD;
660 p_new_es->i_cat = AUDIO_ES;
663 p_new_es->i_fourcc = VLC_FOURCC('d','t','s',' ');
664 p_new_es->i_stream_id = 0xBD;
665 p_new_es->i_cat = AUDIO_ES;
667 /* 'b' stands for 'buggy' */
669 p_new_es->i_fourcc = VLC_FOURCC('a','5','2','b');
670 p_new_es->i_stream_id = 0xBD;
671 p_new_es->i_cat = AUDIO_ES;
674 p_new_es->i_fourcc = VLC_FOURCC('l','p','c','b');
675 p_new_es->i_stream_id = 0xBD;
676 p_new_es->i_cat = AUDIO_ES;
679 p_new_es->i_fourcc = VLC_FOURCC('s','p','u','b');
680 p_new_es->i_stream_id = 0xBD;
681 p_new_es->i_cat = SPU_ES;
684 p_new_es->i_fourcc = 0;
685 p_new_es->i_cat = UNKNOWN_ES;
690 p_current_data += 5 + i_es_info_length;
693 /* Go to the beginning of the next section*/
694 p_current_data += 3 + i_section_length;
698 } while( i_current_section < p_psi->i_last_section_number );
700 p_pgrm_data->i_pmt_version = p_psi->i_version_number;
702 /* if no program is selected :*/
703 if( !p_input->stream.p_selected_program )
705 pgrm_descriptor_t * p_pgrm_to_select;
706 u16 i_id = (u16)config_GetInt( p_input, "program" );
708 if( i_id != 0 ) /* if user specified a program */
710 p_pgrm_to_select = input_FindProgram( p_input, i_id );
712 if( p_pgrm_to_select && p_pgrm_to_select == p_es->p_pgrm )
713 p_input->pf_set_program( p_input, p_pgrm_to_select );
716 p_input->pf_set_program( p_input, p_es->p_pgrm );
719 /* inform interface that stream has changed */
720 p_input->stream.b_changed = 1;
722 vlc_mutex_unlock( &p_input->stream.stream_lock );
728 #elif defined MODULE_NAME_IS_ts_dvbpsi
730 * PSI Decoding using libdvbcss
733 /*****************************************************************************
734 * DemuxPSI : send the PSI to the right libdvbpsi decoder
735 *****************************************************************************/
736 static void TS_DVBPSI_DemuxPSI( input_thread_t * p_input,
737 data_packet_t * p_data,
738 es_descriptor_t * p_es,
739 vlc_bool_t b_unit_start )
741 es_ts_data_t * p_es_demux_data;
742 pgrm_ts_data_t * p_pgrm_demux_data;
743 stream_ts_data_t * p_stream_demux_data;
745 p_es_demux_data = ( es_ts_data_t * ) p_es->p_demux_data;
746 p_stream_demux_data = ( stream_ts_data_t * ) p_input->stream.p_demux_data;
748 switch( p_es_demux_data->i_psi_type)
752 ( dvbpsi_handle ) p_stream_demux_data->p_pat_handle,
753 p_data->p_demux_start );
756 p_pgrm_demux_data = ( pgrm_ts_data_t * )p_es->p_pgrm->p_demux_data;
758 ( dvbpsi_handle ) p_pgrm_demux_data->p_pmt_handle,
759 p_data->p_demux_start );
762 msg_Warn( p_input, "received unknown PSI in DemuxPSI" );
765 input_DeletePacket( p_input->p_method_data, p_data );
768 /*****************************************************************************
769 * HandlePAT: will treat a PAT returned by dvbpsi
770 *****************************************************************************/
772 void TS_DVBPSI_HandlePAT( input_thread_t * p_input, dvbpsi_pat_t * p_new_pat )
774 dvbpsi_pat_program_t * p_pgrm;
775 pgrm_descriptor_t * p_new_pgrm;
776 pgrm_ts_data_t * p_pgrm_demux;
777 es_descriptor_t * p_current_es;
778 es_ts_data_t * p_es_demux;
779 stream_ts_data_t * p_stream_data;
781 vlc_mutex_lock( &p_input->stream.stream_lock );
783 p_stream_data = (stream_ts_data_t *)p_input->stream.p_demux_data;
785 if ( !p_new_pat->b_current_next ||
786 p_stream_data->i_pat_version == PAT_UNINITIALIZED )
788 /* Delete all programs */
789 while( p_input->stream.i_pgrm_number )
791 input_DelProgram( p_input, p_input->stream.pp_programs[0] );
794 /* treat the new programs list */
795 p_pgrm = p_new_pat->p_first_program;
799 /* If program = 0, we're having info about NIT not PMT */
800 if( p_pgrm->i_number )
802 /* Add this program */
803 p_new_pgrm = input_AddProgram( p_input, p_pgrm->i_number,
804 sizeof( pgrm_ts_data_t ) );
806 p_pgrm_demux = (pgrm_ts_data_t *)p_new_pgrm->p_demux_data;
807 p_pgrm_demux->i_pmt_version = PMT_UNINITIALIZED;
809 /* Add the PMT ES to this program */
810 p_current_es = input_AddES( p_input, p_new_pgrm,
812 sizeof( es_ts_data_t) );
813 p_es_demux = (es_ts_data_t *)p_current_es->p_demux_data;
814 p_es_demux->b_psi = 1;
815 p_es_demux->i_psi_type = PSI_IS_PMT;
817 p_es_demux->p_psi_section = malloc( sizeof( psi_section_t ) );
818 if ( p_es_demux->p_psi_section == NULL )
820 msg_Err( p_input, "out of memory" );
821 p_input->b_error = 1;
825 p_es_demux->p_psi_section->b_is_complete = 0;
827 /* Create a PMT decoder */
828 p_pgrm_demux->p_pmt_handle = (dvbpsi_handle *)
829 dvbpsi_AttachPMT( p_pgrm->i_number,
830 (dvbpsi_pmt_callback) &TS_DVBPSI_HandlePMT,
833 if( p_pgrm_demux->p_pmt_handle == NULL )
835 msg_Err( p_input, "could not create PMT decoder" );
836 p_input->b_error = 1;
841 p_pgrm = p_pgrm->p_next;
844 p_stream_data->i_pat_version = p_new_pat->i_version;
846 vlc_mutex_unlock( &p_input->stream.stream_lock );
849 /*****************************************************************************
850 * HandlePMT: will treat a PMT returned by dvbpsi
851 *****************************************************************************/
852 void TS_DVBPSI_HandlePMT( input_thread_t * p_input, dvbpsi_pmt_t * p_new_pmt )
854 dvbpsi_pmt_es_t * p_es;
855 pgrm_descriptor_t * p_pgrm;
856 es_descriptor_t * p_new_es;
857 pgrm_ts_data_t * p_pgrm_demux;
858 vlc_bool_t b_vls_compat = config_GetInt( p_input, "vls-backwards-compat" );
860 vlc_mutex_lock( &p_input->stream.stream_lock );
862 p_pgrm = input_FindProgram( p_input, p_new_pmt->i_program_number );
866 msg_Warn( p_input, "PMT of unreferenced program found" );
870 p_pgrm_demux = (pgrm_ts_data_t *)p_pgrm->p_demux_data;
871 p_pgrm_demux->i_pcr_pid = p_new_pmt->i_pcr_pid;
873 if( !p_new_pmt->b_current_next ||
874 p_pgrm_demux->i_pmt_version == PMT_UNINITIALIZED )
876 p_es = p_new_pmt->p_first_es;
880 p_new_es = input_AddES( p_input, p_pgrm,
881 (u16)p_es->i_pid, sizeof( es_ts_data_t ) );
882 if( p_new_es == NULL )
884 msg_Err( p_input, "could not add ES %d", p_es->i_pid );
885 p_input->b_error = 1;
889 switch( p_es->i_type )
893 p_new_es->i_fourcc = VLC_FOURCC('m','p','g','v');
894 p_new_es->i_cat = VIDEO_ES;
898 p_new_es->i_fourcc = VLC_FOURCC('m','p','g','a');
899 p_new_es->i_cat = AUDIO_ES;
903 p_new_es->i_fourcc = VLC_FOURCC('a','5','2',' ');
905 p_new_es->i_fourcc = VLC_FOURCC('a','5','2','b');
906 p_new_es->i_cat = AUDIO_ES;
907 p_new_es->i_stream_id = 0xBD;
911 p_new_es->i_fourcc = VLC_FOURCC('s','p','u',' ');
913 p_new_es->i_fourcc = VLC_FOURCC('s','p','u','b');
914 p_new_es->i_cat = SPU_ES;
915 p_new_es->i_stream_id = 0xBD;
918 p_new_es->i_fourcc = VLC_FOURCC('l','p','c','m');
919 p_new_es->i_cat = AUDIO_ES;
920 p_new_es->i_stream_id = 0xBD;
923 p_new_es->i_fourcc = VLC_FOURCC('s','d','d','s');
924 p_new_es->i_stream_id = 0xBD;
925 p_new_es->i_cat = AUDIO_ES;
928 p_new_es->i_fourcc = VLC_FOURCC('d','t','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('a','5','2','b');
934 p_new_es->i_cat = AUDIO_ES;
935 p_new_es->i_stream_id = 0xBD;
938 p_new_es->i_fourcc = VLC_FOURCC('s','p','u','b');
939 p_new_es->i_cat = SPU_ES;
940 p_new_es->i_stream_id = 0xBD;
943 p_new_es->i_fourcc = VLC_FOURCC('l','p','c','b');
944 p_new_es->i_cat = AUDIO_ES;
945 p_new_es->i_stream_id = 0xBD;
948 p_new_es->i_fourcc = 0;
949 p_new_es->i_cat = UNKNOWN_ES;
952 if( ( p_new_es->i_cat == AUDIO_ES )
953 || (p_new_es->i_cat == SPU_ES ) )
955 dvbpsi_descriptor_t *p_dr = p_es->p_first_descriptor;
956 while( p_dr && ( p_dr->i_tag != 0x0a ) )
960 dvbpsi_iso639_dr_t *p_decoded =
961 dvbpsi_DecodeISO639Dr( p_dr );
962 if( p_decoded->i_code_count > 0 )
964 const iso639_lang_t * p_iso;
965 p_iso = GetLang_2T((char*)p_decoded->i_iso_639_code);
968 if(p_iso->psz_native_name[0])
969 strcpy( p_new_es->psz_desc,
970 p_iso->psz_native_name );
972 strcpy( p_new_es->psz_desc,
973 p_iso->psz_eng_name );
977 strncpy( p_new_es->psz_desc,
978 p_decoded->i_iso_639_code, 3 );
982 switch( p_es->i_type )
986 strcat( p_new_es->psz_desc, " (mpeg)" );
990 strcat( p_new_es->psz_desc, " (lpcm)" );
994 strcat( p_new_es->psz_desc, " (A52)" );
1002 /* if no program is selected :*/
1003 if( !p_input->stream.p_selected_program )
1005 pgrm_descriptor_t * p_pgrm_to_select;
1006 u16 i_id = (u16)config_GetInt( p_input, "program" );
1008 if( i_id != 0 ) /* if user specified a program */
1010 p_pgrm_to_select = input_FindProgram( p_input, i_id );
1012 if( p_pgrm_to_select && p_pgrm_to_select == p_pgrm )
1013 p_input->pf_set_program( p_input, p_pgrm_to_select );
1016 p_input->pf_set_program( p_input, p_pgrm );
1018 /* if the pmt belongs to the currently selected program, we
1019 * reselect it to update its ES */
1020 else if( p_pgrm == p_input->stream.p_selected_program )
1022 p_input->pf_set_program( p_input, p_pgrm );
1025 p_pgrm_demux->i_pmt_version = p_new_pmt->i_version;
1026 p_input->stream.b_changed = 1;
1028 vlc_mutex_unlock( &p_input->stream.stream_lock );