]> git.sesse.net Git - vlc/blob - plugins/mpeg_system/mpeg_ts.c
* ./configure.in, ./plugins/mpeg_system/mpeg_ts.c: fixed libdvbpsi handling.
[vlc] / plugins / mpeg_system / mpeg_ts.c
1 /*****************************************************************************
2  * mpeg_ts.c : Transport Stream input module for vlc
3  *****************************************************************************
4  * Copyright (C) 2000-2001 VideoLAN
5  * $Id: mpeg_ts.c,v 1.13.2.1 2002/06/03 23:14:49 sam Exp $
6  *
7  * Authors: Henri Fallon <henri@via.ecp.fr>
8  *          Johan Bilien <jobi@via.ecp.fr>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  * 
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include <stdlib.h>
29 #include <string.h>
30 #include <errno.h>
31
32 #include <videolan/vlc.h>
33
34 #include "stream_control.h"
35 #include "input_ext-intf.h"
36 #include "input_ext-dec.h"
37 #include "input_ext-plugins.h"
38
39 #include "iso_lang.h"
40
41 #if defined MODULE_NAME_IS_mpeg_ts_dvbpsi
42 #   ifdef HAVE_DVBPSI_DR_H
43 #       include <dvbpsi/dvbpsi.h>
44 #       include <dvbpsi/descriptor.h>
45 #       include <dvbpsi/pat.h>
46 #       include <dvbpsi/pmt.h>
47 #       include <dvbpsi/dr.h>
48 #   else
49 #       include "dvbpsi.h"
50 #       include "descriptor.h"
51 #       include "tables/pat.h"
52 #       include "tables/pmt.h"
53 #       include "descriptors/dr.h"
54 #   endif
55 #endif
56
57 /*****************************************************************************
58  * Constants
59  *****************************************************************************/
60 #define TS_READ_ONCE 200
61
62 /*****************************************************************************
63  * Local prototypes
64  *****************************************************************************/
65 static void input_getfunctions( function_list_t * p_function_list );
66 static int  TSInit      ( struct input_thread_s * );
67 static void TSEnd       ( struct input_thread_s * );
68 static int  TSDemux     ( struct input_thread_s * );
69
70 #if defined MODULE_NAME_IS_mpeg_ts
71 static void TSDemuxPSI  ( struct input_thread_s *, struct data_packet_s *,
72                           struct es_descriptor_s *, boolean_t );
73 static void TSDecodePAT( input_thread_t *, es_descriptor_t *);
74 static void TSDecodePMT( input_thread_t *, es_descriptor_t *);
75 #define PSI_CALLBACK TSDemuxPSI
76 #elif defined MODULE_NAME_IS_mpeg_ts_dvbpsi
77 static void TS_DVBPSI_DemuxPSI  
78                         ( struct input_thread_s *, struct data_packet_s *,
79                           struct es_descriptor_s *, boolean_t );
80 static void TS_DVBPSI_HandlePAT
81                         ( struct input_thread_s *, dvbpsi_pat_t * );
82 static void TS_DVBPSI_HandlePMT
83                         ( struct input_thread_s *, dvbpsi_pmt_t * );
84 #define PSI_CALLBACK TS_DVBPSI_DemuxPSI
85 #endif
86
87 /*****************************************************************************
88  * Build configuration tree.
89  *****************************************************************************/
90 MODULE_CONFIG_START
91 MODULE_CONFIG_STOP
92
93 MODULE_INIT_START
94 #if defined MODULE_NAME_IS_mpeg_ts
95     SET_DESCRIPTION( _("ISO 13818-1 MPEG Transport Stream input") )
96     ADD_CAPABILITY( DEMUX, 160 )
97     ADD_SHORTCUT( "ts" )
98 #elif defined MODULE_NAME_IS_mpeg_ts_dvbpsi
99     SET_DESCRIPTION( _("ISO 13818-1 MPEG Transport Stream input (libdvbpsi)") )
100     ADD_CAPABILITY( DEMUX, 170 )
101     ADD_SHORTCUT( "ts_dvbpsi" )
102 #endif
103 MODULE_INIT_STOP
104
105 MODULE_ACTIVATE_START
106     input_getfunctions( &p_module->p_functions->demux );
107 MODULE_ACTIVATE_STOP
108
109 MODULE_DEACTIVATE_START
110 MODULE_DEACTIVATE_STOP
111
112 /*****************************************************************************
113  * Functions exported as capabilities. They are declared as static so that
114  * we don't pollute the namespace too much.
115  *****************************************************************************/
116 static void input_getfunctions( function_list_t * p_function_list )
117 {
118 #define input p_function_list->functions.demux
119     input.pf_init             = TSInit;
120     input.pf_end              = TSEnd;
121     input.pf_demux            = TSDemux;
122     input.pf_rewind           = NULL;
123 #undef input
124 }
125
126 /*****************************************************************************
127  * TSInit: initializes TS structures
128  *****************************************************************************/
129 static int TSInit( input_thread_t * p_input )
130 {
131     es_descriptor_t     * p_pat_es;
132     es_ts_data_t        * p_demux_data;
133     stream_ts_data_t    * p_stream_data;
134     byte_t              * p_peek;
135
136     /* Initialize access plug-in structures. */
137     if( p_input->i_mtu == 0 )
138     {
139         /* Improve speed. */
140         p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
141     }
142
143     /* Have a peep at the show. */
144     if( input_Peek( p_input, &p_peek, 1 ) < 1 )
145     {
146         intf_ErrMsg( "input error: cannot peek() (mpeg_ts)" );
147         return( -1 );
148     }
149
150     if( *p_peek != TS_SYNC_CODE )
151     {
152         if( *p_input->psz_demux && !strncmp( p_input->psz_demux, "ts", 3 ) )
153         {
154             /* User forced */
155             intf_ErrMsg( "input error: this doesn't look like a TS stream, continuing" );
156         }
157         else
158         {
159             intf_WarnMsg( 2, "input: TS plug-in discarded (no sync)" );
160             return( -1 );
161         }
162     }
163
164     /* Adapt the bufsize for our only use. */
165     if( p_input->i_mtu != 0 )
166     {
167         /* Have minimum granularity to avoid bottlenecks at the input level. */
168         p_input->i_bufsize = (p_input->i_mtu / TS_PACKET_SIZE) * TS_PACKET_SIZE;
169     }
170
171     vlc_mutex_lock( &p_input->stream.stream_lock );
172
173     if( input_InitStream( p_input, sizeof( stream_ts_data_t ) ) == -1 )
174     {
175         return( -1 );
176     }
177     
178     p_stream_data = (stream_ts_data_t *)p_input->stream.p_demux_data;
179     p_stream_data->i_pat_version = PAT_UNINITIALIZED ;
180
181 #ifdef MODULE_NAME_IS_mpeg_ts_dvbpsi
182     p_stream_data->p_pat_handle = (dvbpsi_handle *)
183       dvbpsi_AttachPAT( (dvbpsi_pat_callback) &TS_DVBPSI_HandlePAT, p_input ); 
184
185     if( p_stream_data->p_pat_handle == NULL )
186     {
187         intf_ErrMsg( "input: ts: could not create PAT decoder" );
188         return( -1 );
189     }
190 #endif
191     
192     /* We'll have to catch the PAT in order to continue
193      * Then the input will catch the PMT and then the others ES
194      * The PAT es is indepedent of any program. */
195     p_pat_es = input_AddES( p_input, NULL,
196                             0x00, sizeof( es_ts_data_t ) );
197     p_demux_data = (es_ts_data_t *)p_pat_es->p_demux_data;
198     p_demux_data->b_psi = 1;
199     p_demux_data->i_psi_type = PSI_IS_PAT;
200     p_demux_data->p_psi_section = malloc(sizeof(psi_section_t));
201     p_demux_data->p_psi_section->b_is_complete = 1;
202
203     vlc_mutex_unlock( &p_input->stream.stream_lock );
204     
205     return( 0 );
206 }
207
208 /*****************************************************************************
209  * TSEnd: frees unused data
210  *****************************************************************************/
211 static void TSEnd( input_thread_t * p_input )
212 {
213 }
214
215 /*****************************************************************************
216  * TSDemux: reads and demuxes data packets
217  *****************************************************************************
218  * Returns -1 in case of error, 0 in case of EOF, otherwise the number of
219  * packets.
220  *****************************************************************************/
221 static int TSDemux( input_thread_t * p_input )
222 {
223     int             i_read_once = (p_input->i_mtu ?
224                                    p_input->i_bufsize / TS_PACKET_SIZE :
225                                    TS_READ_ONCE);
226     int             i;
227
228     for( i = 0; i < i_read_once; i++ )
229     {
230         data_packet_t *     p_data;
231         ssize_t             i_result;
232
233         i_result = input_ReadTS( p_input, &p_data );
234
235         if( i_result <= 0 )
236         {
237             return( i_result );
238         }
239
240         input_DemuxTS( p_input, p_data, (psi_callback_t) &PSI_CALLBACK );
241     }
242
243     return( i_read_once );
244 }
245
246
247 #if defined MODULE_NAME_IS_mpeg_ts
248 /*
249  * PSI demultiplexing and decoding without libdvbpsi
250  */
251
252 /*****************************************************************************
253  * DemuxPSI : makes up complete PSI data
254  *****************************************************************************/
255 static void TSDemuxPSI( input_thread_t * p_input, data_packet_t * p_data, 
256         es_descriptor_t * p_es, boolean_t b_unit_start )
257 {
258     es_ts_data_t  * p_demux_data;
259     
260     p_demux_data = (es_ts_data_t *)p_es->p_demux_data;
261
262 #define p_psi (p_demux_data->p_psi_section)
263 #define p (p_data->p_payload_start)
264
265     if( b_unit_start )
266     {
267         /* unit_start set to 1 -> presence of a pointer field
268          * (see ISO/IEC 13818 (2.4.4.2) which should be set to 0x00 */
269         if( (u8)p[0] != 0x00 )
270         {
271             intf_WarnMsg( 2, "input: non zero pointer field found, "
272                              "trying to continue" );
273             p+=(u8)p[0];
274         }
275         else
276         {
277             p++;
278         }
279
280         /* This is the begining of a new section */
281
282         if( ((u8)(p[1]) & 0xc0) != 0x80 ) 
283         {
284             intf_WarnMsg( 2, "input: invalid PSI packet" );
285             p_psi->b_trash = 1;
286         }
287         else 
288         {
289             p_psi->i_section_length = ((p[1] & 0xF) << 8) | p[2];
290             p_psi->b_section_complete = 0;
291             p_psi->i_read_in_section = 0;
292             p_psi->i_section_number = (u8)p[6];
293
294             if( p_psi->b_is_complete || p_psi->i_section_number == 0 )
295             {
296                 /* This is a new PSI packet */
297                 p_psi->b_is_complete = 0;
298                 p_psi->b_trash = 0;
299                 p_psi->i_version_number = ( p[5] >> 1 ) & 0x1f;
300                 p_psi->i_last_section_number = (u8)p[7];
301
302                 /* We'll write at the begining of the buffer */
303                 p_psi->p_current = p_psi->buffer;
304             }
305             else
306             {
307                 if( p_psi->b_section_complete )
308                 {
309                     /* New Section of an already started PSI */
310                     p_psi->b_section_complete = 0;
311                     
312                     if( p_psi->i_version_number != (( p[5] >> 1 ) & 0x1f) )
313                     {
314                         intf_WarnMsg( 2, "input: PSI version differs "
315                                          "inside same PAT" );
316                         p_psi->b_trash = 1;
317                     }
318                     if( p_psi->i_section_number + 1 != (u8)p[6] )
319                     {
320                         intf_WarnMsg( 2, "input: PSI Section discontinuity, "
321                                          "packet lost ?" );
322                         p_psi->b_trash = 1;
323                     }
324                     else
325                         p_psi->i_section_number++;
326                 }
327                 else
328                 {
329                     intf_WarnMsg( 2, "input: got unexpected new PSI section" );
330                     p_psi->b_trash = 1;
331                 }
332             }
333         }
334     } /* b_unit_start */
335     
336     if( !p_psi->b_trash )
337     {
338         /* read */
339         if( (p_data->p_payload_end - p) >=
340             ( p_psi->i_section_length - p_psi->i_read_in_section ) )
341         {
342             /* The end of the section is in this TS packet */
343             memcpy( p_psi->p_current, p, 
344             (p_psi->i_section_length - p_psi->i_read_in_section) );
345     
346             p_psi->b_section_complete = 1;
347             p_psi->p_current += 
348                 (p_psi->i_section_length - p_psi->i_read_in_section);
349                         
350             if( p_psi->i_section_number == p_psi->i_last_section_number )
351             {
352                 /* This was the last section of PSI */
353                 p_psi->b_is_complete = 1;
354
355                 switch( p_demux_data->i_psi_type)
356                 {
357                 case PSI_IS_PAT:
358                     TSDecodePAT( p_input, p_es );
359                     break;
360                 case PSI_IS_PMT:
361                     TSDecodePMT( p_input, p_es );
362                     break;
363                 default:
364                     intf_WarnMsg(2, "Received unknown PSI in DemuxPSI");
365                 }
366             }
367         }
368         else
369         {
370             memcpy( p_psi->buffer, p, p_data->p_payload_end - p );
371             p_psi->i_read_in_section += p_data->p_payload_end - p;
372
373             p_psi->p_current += p_data->p_payload_end - p;
374         }
375     }
376
377 #undef p_psi    
378 #undef p
379    
380     input_DeletePacket( p_input->p_method_data, p_data );
381     
382     return ;
383 }
384
385 /*****************************************************************************
386  * DecodePAT : Decodes Programm association table and deal with it
387  *****************************************************************************/
388 static void TSDecodePAT( input_thread_t * p_input, es_descriptor_t * p_es )
389 {
390     stream_ts_data_t  * p_stream_data;
391     es_ts_data_t      * p_demux_data;
392
393     pgrm_descriptor_t * p_pgrm;
394     es_descriptor_t   * p_current_es;
395     byte_t            * p_current_data;           
396
397     int                 i_section_length, i_program_id, i_pmt_pid;
398     int                 i_loop, i_current_section;
399
400     boolean_t           b_changed = 0;
401
402     p_demux_data = (es_ts_data_t *)p_es->p_demux_data;
403     p_stream_data = (stream_ts_data_t *)p_input->stream.p_demux_data;
404     
405 #define p_psi (p_demux_data->p_psi_section)
406
407     /* Not so fast, Mike ! If the PAT version has changed, we first check
408      * that its content has really changed before doing anything */
409     if( p_stream_data->i_pat_version != p_psi->i_version_number )
410     {
411         int i_programs = p_input->stream.i_pgrm_number;
412
413         p_current_data = p_psi->buffer;
414
415         do
416         {
417             i_section_length = ((u32)(p_current_data[1] & 0xF) << 8) |
418                                  p_current_data[2];
419             i_current_section = (u8)p_current_data[6];
420     
421             for( i_loop = 0;
422                  ( i_loop < (i_section_length - 9) / 4 ) && !b_changed;
423                  i_loop++ )
424             {
425                 i_program_id = ( (u32)*(p_current_data + i_loop * 4 + 8) << 8 )
426                                  | *(p_current_data + i_loop * 4 + 9);
427                 i_pmt_pid = ( ((u32)*(p_current_data + i_loop * 4 + 10) & 0x1F)
428                                     << 8 )
429                                | *(p_current_data + i_loop * 4 + 11);
430
431                 if( i_program_id )
432                 {
433                     if( (p_pgrm = input_FindProgram( p_input, i_program_id ))
434                         && (p_current_es = input_FindES( p_input, i_pmt_pid ))
435                         && p_current_es->p_pgrm == p_pgrm
436                         && p_current_es->i_id == i_pmt_pid
437                         && ((es_ts_data_t *)p_current_es->p_demux_data)->b_psi
438                         && ((es_ts_data_t *)p_current_es->p_demux_data)
439                             ->i_psi_type == PSI_IS_PMT )
440                     {
441                         i_programs--;
442                     }
443                     else
444                     {
445                         b_changed = 1;
446                     }
447                 }
448             }
449             
450             p_current_data += 3 + i_section_length;
451
452         } while( ( i_current_section < p_psi->i_last_section_number )
453                   && !b_changed );
454
455         /* If we didn't find the expected amount of programs, the PAT has
456          * changed. Otherwise, it only changed if b_changed is already != 0 */
457         b_changed = b_changed || i_programs;
458     }
459
460     if( b_changed )
461     {
462         /* PAT has changed. We are going to delete all programs and 
463          * create new ones. We chose not to only change what was needed
464          * as a PAT change may mean the stream is radically changing and
465          * this is a secure method to avoid crashes */
466         es_ts_data_t      * p_es_demux;
467         pgrm_ts_data_t    * p_pgrm_demux;
468         
469         p_current_data = p_psi->buffer;
470
471         /* Delete all programs */
472         while( p_input->stream.i_pgrm_number )
473         {
474             input_DelProgram( p_input, p_input->stream.pp_programs[0] );
475         }
476         
477         do
478         {
479             i_section_length = ((u32)(p_current_data[1] & 0xF) << 8) |
480                                  p_current_data[2];
481             i_current_section = (u8)p_current_data[6];
482     
483             for( i_loop = 0; i_loop < (i_section_length - 9) / 4 ; i_loop++ )
484             {
485                 i_program_id = ( (u32)*(p_current_data + i_loop * 4 + 8) << 8 )
486                                  | *(p_current_data + i_loop * 4 + 9);
487                 i_pmt_pid = ( ((u32)*(p_current_data + i_loop * 4 + 10) & 0x1F)
488                                     << 8 )
489                                | *(p_current_data + i_loop * 4 + 11);
490     
491                 /* If program = 0, we're having info about NIT not PMT */
492                 if( i_program_id )
493                 {
494                     /* Add this program */
495                     p_pgrm = input_AddProgram( p_input, i_program_id, 
496                                                sizeof( pgrm_ts_data_t ) );
497                    
498                     /* whatis the PID of the PMT of this program */
499                     p_pgrm_demux = (pgrm_ts_data_t *)p_pgrm->p_demux_data;
500                     p_pgrm_demux->i_pmt_version = PMT_UNINITIALIZED;
501     
502                     /* Add the PMT ES to this program */
503                     p_current_es = input_AddES( p_input, p_pgrm,(u16)i_pmt_pid,
504                                         sizeof( es_ts_data_t) );
505                     p_es_demux = (es_ts_data_t *)p_current_es->p_demux_data;
506                     p_es_demux->b_psi = 1;
507                     p_es_demux->i_psi_type = PSI_IS_PMT;
508                     
509                     p_es_demux->p_psi_section = 
510                                             malloc( sizeof( psi_section_t ) );
511                     p_es_demux->p_psi_section->b_is_complete = 0;
512                 }
513             }
514             
515             p_current_data += 3 + i_section_length;
516
517         } while( i_current_section < p_psi->i_last_section_number );
518
519         /* Go to the beginning of the next section */
520         p_stream_data->i_pat_version = p_psi->i_version_number;
521
522     }
523 #undef p_psi
524
525 }
526
527 /*****************************************************************************
528  * DecodePMT : decode a given Program Stream Map
529  * ***************************************************************************
530  * When the PMT changes, it may mean a deep change in the stream, and it is
531  * careful to delete the ES and add them again. If the PMT doesn't change,
532  * there no need to do anything.
533  *****************************************************************************/
534 static void TSDecodePMT( input_thread_t * p_input, es_descriptor_t * p_es )
535 {
536
537     pgrm_ts_data_t            * p_pgrm_data;
538     es_ts_data_t              * p_demux_data;
539
540     p_demux_data = (es_ts_data_t *)p_es->p_demux_data;
541     p_pgrm_data = (pgrm_ts_data_t *)p_es->p_pgrm->p_demux_data;
542     
543 #define p_psi (p_demux_data->p_psi_section)
544
545     if( p_psi->i_version_number != p_pgrm_data->i_pmt_version ) 
546     {
547         es_descriptor_t   * p_new_es;  
548         es_ts_data_t      * p_es_demux;
549         byte_t            * p_current_data, * p_current_section;
550         int                 i_section_length,i_current_section;
551         int                 i_prog_info_length, i_loop;
552         int                 i_es_info_length, i_pid, i_stream_type;
553         
554         p_current_section = p_psi->buffer;
555         p_current_data = p_psi->buffer;
556
557         p_pgrm_data->i_pcr_pid = ( ((u32)*(p_current_section + 8) & 0x1F) << 8 ) |
558                                     *(p_current_section + 9);
559
560
561         /* Lock stream information */
562         vlc_mutex_lock( &p_input->stream.stream_lock );
563
564         /* Delete all ES in this program  except the PSI. We start from the
565          * end because i_es_number gets decremented after each deletion. */
566         for( i_loop = p_es->p_pgrm->i_es_number ; i_loop ; )
567         {
568             i_loop--;
569             p_es_demux = (es_ts_data_t *)
570                          p_es->p_pgrm->pp_es[i_loop]->p_demux_data;
571             if ( ! p_es_demux->b_psi )
572             {
573                 input_DelES( p_input, p_es->p_pgrm->pp_es[i_loop] );
574             }
575         }
576
577         /* Then add what we received in this PMT */
578         do
579         {
580             i_section_length = ( ((u32)*(p_current_data + 1) & 0xF) << 8 ) |
581                                   *(p_current_data + 2);
582             i_current_section = (u8)p_current_data[6];
583             i_prog_info_length = ( ((u32)*(p_current_data + 10) & 0xF) << 8 ) |
584                                     *(p_current_data + 11);
585
586             /* For the moment we ignore program descriptors */
587             p_current_data += 12 + i_prog_info_length;
588     
589             /* The end of the section, before the CRC is at 
590              * p_current_section + i_section_length -1 */
591             while( p_current_data < p_current_section + i_section_length -1 )
592             {
593                 i_stream_type = (int)p_current_data[0];
594                 i_pid = ( ((u32)*(p_current_data + 1) & 0x1F) << 8 ) |
595                            *(p_current_data + 2);
596                 i_es_info_length = ( ((u32)*(p_current_data + 3) & 0xF) << 8 ) |
597                                       *(p_current_data + 4);
598                 
599                 /* Add this ES to the program */
600                 p_new_es = input_AddES( p_input, p_es->p_pgrm, 
601                                         (u16)i_pid, sizeof( es_ts_data_t ) );
602
603                 /* Tell the decoders what kind of stream it is */
604                 p_new_es->i_type = i_stream_type;
605
606                 /* Tell the interface what kind of stream it is and select 
607                  * the required ones */
608                 {
609                     switch( i_stream_type )
610                     {
611                         case MPEG1_VIDEO_ES:
612                         case MPEG2_VIDEO_ES:
613                             p_new_es->i_cat = VIDEO_ES;
614                             break;
615                         case MPEG1_AUDIO_ES:
616                         case MPEG2_AUDIO_ES:
617                             p_new_es->i_cat = AUDIO_ES;
618                             break;
619                         case LPCM_AUDIO_ES :
620                         case AC3_AUDIO_ES :
621                             p_new_es->i_stream_id = 0xBD;
622                             p_new_es->i_cat = AUDIO_ES;
623                             break;
624                         /* Not sure this one is fully specification-compliant */
625                         case DVD_SPU_ES :
626                             p_new_es->i_stream_id = 0xBD;
627                             p_new_es->i_cat = SPU_ES;
628                             break;
629                         default :
630                             p_new_es->i_cat = UNKNOWN_ES;
631                             break;
632                     }
633                 }
634                 
635                 p_current_data += 5 + i_es_info_length;
636             }
637
638             /* Go to the beginning of the next section*/
639             p_current_data += 3 + i_section_length;
640            
641             p_current_section++;
642             
643         } while( i_current_section < p_psi->i_last_section_number );
644
645         p_pgrm_data->i_pmt_version = p_psi->i_version_number;
646
647         /* if no program is selected :*/
648         if( !p_input->stream.p_selected_program )
649         {
650             pgrm_descriptor_t *     p_pgrm_to_select;
651             u16 i_id = (u16)config_GetIntVariable( "program" );
652
653             if( i_id != 0 ) /* if user specified a program */
654             {
655                 p_pgrm_to_select = input_FindProgram( p_input, i_id );
656
657                 if( p_pgrm_to_select && p_pgrm_to_select == p_es->p_pgrm )
658                     p_input->pf_set_program( p_input, p_pgrm_to_select );
659             }
660             else
661                     p_input->pf_set_program( p_input, p_es->p_pgrm );
662         }
663         
664         /* inform interface that stream has changed */
665         p_input->stream.b_changed = 1;
666         /*  Remove lock */
667         vlc_mutex_unlock( &p_input->stream.stream_lock );
668     }
669     
670 #undef p_psi
671 }
672
673 #elif defined MODULE_NAME_IS_mpeg_ts_dvbpsi
674 /*
675  * PSI Decoding using libdvbcss 
676  */
677
678 /*****************************************************************************
679  * DemuxPSI : send the PSI to the right libdvbpsi decoder
680  *****************************************************************************/
681 static void TS_DVBPSI_DemuxPSI( input_thread_t  * p_input, 
682                                 data_packet_t   * p_data, 
683                                 es_descriptor_t * p_es, 
684                                 boolean_t         b_unit_start )
685 {
686     es_ts_data_t        * p_es_demux_data;
687     pgrm_ts_data_t      * p_pgrm_demux_data;
688     stream_ts_data_t    * p_stream_demux_data;
689
690     p_es_demux_data = ( es_ts_data_t * ) p_es->p_demux_data;
691     p_stream_demux_data = ( stream_ts_data_t * ) p_input->stream.p_demux_data;
692
693     switch( p_es_demux_data->i_psi_type)
694     {
695         case PSI_IS_PAT:
696             dvbpsi_PushPacket( 
697                     ( dvbpsi_handle ) p_stream_demux_data->p_pat_handle,
698                     p_data->p_demux_start );
699             break;
700         case PSI_IS_PMT:
701             p_pgrm_demux_data = ( pgrm_ts_data_t * )p_es->p_pgrm->p_demux_data;
702             dvbpsi_PushPacket( 
703                     ( dvbpsi_handle ) p_pgrm_demux_data->p_pmt_handle,
704                     p_data->p_demux_start );
705             break;
706         default:
707             intf_WarnMsg( 2, "Received unknown PSI in DemuxPSI" );
708     }
709     
710     input_DeletePacket( p_input->p_method_data, p_data );
711 }
712
713 /*****************************************************************************
714  * HandlePAT: will treat a PAT returned by dvbpsi
715  *****************************************************************************/
716
717 void TS_DVBPSI_HandlePAT( input_thread_t * p_input, dvbpsi_pat_t * p_new_pat )
718 {
719     dvbpsi_pat_program_t *      p_pgrm;
720     pgrm_descriptor_t *         p_new_pgrm;
721     pgrm_ts_data_t *            p_pgrm_demux;
722     es_descriptor_t *           p_current_es;
723     es_ts_data_t *              p_es_demux;
724     stream_ts_data_t *          p_stream_data;
725
726     vlc_mutex_lock( &p_input->stream.stream_lock );
727     
728     p_stream_data = (stream_ts_data_t *)p_input->stream.p_demux_data;
729     
730     if ( !p_new_pat->b_current_next || 
731             p_stream_data->i_pat_version == PAT_UNINITIALIZED  )
732     {
733         /* Delete all programs */
734         while( p_input->stream.i_pgrm_number )
735         {
736             input_DelProgram( p_input, p_input->stream.pp_programs[0] );
737         }
738     
739         /* treat the new programs list */
740         p_pgrm = p_new_pat->p_first_program;
741         
742         while( p_pgrm )
743         {
744             /* If program = 0, we're having info about NIT not PMT */
745             if( p_pgrm->i_number )
746             {
747                 /* Add this program */
748                 p_new_pgrm = input_AddProgram( p_input, p_pgrm->i_number, 
749                                             sizeof( pgrm_ts_data_t ) );
750
751                 p_pgrm_demux = (pgrm_ts_data_t *)p_new_pgrm->p_demux_data;
752                 p_pgrm_demux->i_pmt_version = PMT_UNINITIALIZED;
753         
754                 /* Add the PMT ES to this program */
755                 p_current_es = input_AddES( p_input, p_new_pgrm,
756                                             (u16) p_pgrm->i_pid,
757                                             sizeof( es_ts_data_t) );
758                 p_es_demux = (es_ts_data_t *)p_current_es->p_demux_data;
759                 p_es_demux->b_psi = 1;
760                 p_es_demux->i_psi_type = PSI_IS_PMT;
761                         
762                 p_es_demux->p_psi_section = malloc( sizeof( psi_section_t ) );
763                 if ( p_es_demux->p_psi_section == NULL )
764                 {
765                     intf_ErrMsg( "input: ts: could not malloc pmt section" );
766                     p_input->b_error = 1;
767                     return;
768                 }
769             
770                 p_es_demux->p_psi_section->b_is_complete = 0;
771                 
772                 /* Create a PMT decoder */
773                 p_pgrm_demux->p_pmt_handle = (dvbpsi_handle *)
774                     dvbpsi_AttachPMT( p_pgrm->i_number,
775                             (dvbpsi_pmt_callback) &TS_DVBPSI_HandlePMT, 
776                             p_input );
777
778                 if( p_pgrm_demux->p_pmt_handle == NULL )
779                 {
780                     intf_ErrMsg( "input: ts: could not create PMT decoder" );
781                     p_input->b_error = 1;
782                     return;
783                 }
784
785             }
786             p_pgrm = p_pgrm->p_next; 
787         }
788         
789         p_stream_data->i_pat_version = p_new_pat->i_version;
790     }
791     vlc_mutex_unlock( &p_input->stream.stream_lock );
792 }
793
794 /*****************************************************************************
795  * HandlePMT: will treat a PMT returned by dvbpsi
796  *****************************************************************************/
797 void TS_DVBPSI_HandlePMT( input_thread_t * p_input, dvbpsi_pmt_t * p_new_pmt )
798 {
799     dvbpsi_pmt_es_t *       p_es;
800     pgrm_descriptor_t *     p_pgrm;
801     es_descriptor_t *       p_new_es;
802     pgrm_ts_data_t *        p_pgrm_demux;
803    
804     vlc_mutex_lock( &p_input->stream.stream_lock );
805     
806     p_pgrm = input_FindProgram( p_input, p_new_pmt->i_program_number );
807
808     if( p_pgrm == NULL )
809     {
810         intf_WarnMsg( 2, "input: ts: PMT of unreferenced program found" );
811         return;
812     }
813
814     p_pgrm_demux = (pgrm_ts_data_t *)p_pgrm->p_demux_data;
815     p_pgrm_demux->i_pcr_pid = p_new_pmt->i_pcr_pid;
816
817     if( !p_new_pmt->b_current_next || 
818             p_pgrm_demux->i_pmt_version == PMT_UNINITIALIZED )
819     {
820         p_es = p_new_pmt->p_first_es;
821         while( p_es )
822         {
823             /* Add this ES */
824             p_new_es = input_AddES( p_input, p_pgrm, 
825                             (u16)p_es->i_pid, sizeof( es_ts_data_t ) );
826             if( p_new_es == NULL )
827             {
828                 intf_ErrMsg( "input: ts: Could not add ES %d", p_es->i_pid );
829                 p_input->b_error = 1;
830                 return;
831             }
832
833             p_new_es->i_type = p_es->i_type;
834             switch( p_es->i_type )
835             {
836                 case MPEG1_VIDEO_ES:
837                 case MPEG2_VIDEO_ES:
838                     p_new_es->i_cat = VIDEO_ES;
839                     break;
840                 case MPEG1_AUDIO_ES:
841                 case MPEG2_AUDIO_ES:
842                     p_new_es->i_cat = AUDIO_ES;
843                     break;
844                 case LPCM_AUDIO_ES:
845                 case AC3_AUDIO_ES:
846                     p_new_es->i_cat = AUDIO_ES;
847                     p_new_es->i_stream_id = 0xBD;
848                     break;
849                 case DVD_SPU_ES:
850                     p_new_es->i_cat = SPU_ES;
851                     p_new_es->i_stream_id = 0xBD;
852                     break;
853                 default:
854                     p_new_es->i_cat = UNKNOWN_ES;
855             }
856
857             if(    ( p_new_es->i_cat == AUDIO_ES )
858                 || (p_new_es->i_cat == SPU_ES ) )
859             {
860                 dvbpsi_descriptor_t *p_dr = p_es->p_first_descriptor;
861                 while( p_dr && ( p_dr->i_tag != 0x0a ) )
862                     p_dr = p_dr->p_next;
863                 if( p_dr )
864                 {
865                     dvbpsi_iso639_dr_t *p_decoded =
866                                                 dvbpsi_DecodeISO639Dr( p_dr );
867                     if( p_decoded->i_code_count > 0 )
868                     {
869                         const iso639_lang_t * p_iso;
870                         p_iso = GetLang_2T(p_decoded->i_iso_639_code);
871                         if(p_iso)
872                         {
873                             if(p_iso->psz_native_name[0])
874                                 strcpy( p_new_es->psz_desc,
875                                         p_iso->psz_native_name );
876                             else
877                                 strcpy( p_new_es->psz_desc,
878                                         p_iso->psz_eng_name );
879                         }
880                         else
881                         {
882                             strncpy( p_new_es->psz_desc,
883                                      p_decoded->i_iso_639_code, 3 );
884                         }
885                     }
886                 }
887                 switch( p_es->i_type )
888                 {
889                     case MPEG1_AUDIO_ES:
890                     case MPEG2_AUDIO_ES:
891                         strcat( p_new_es->psz_desc, " (mpeg)" );
892                         break;
893                     case LPCM_AUDIO_ES:
894                         strcat( p_new_es->psz_desc, " (lpcm)" );
895                         break;
896                     case AC3_AUDIO_ES:
897                         strcat( p_new_es->psz_desc, " (ac3)" );
898                         break;
899                 }
900             }
901
902             p_es = p_es->p_next;
903         }
904         
905         /* if no program is selected :*/
906         if( !p_input->stream.p_selected_program )
907         {
908             pgrm_descriptor_t *     p_pgrm_to_select;
909             u16 i_id = (u16)config_GetIntVariable( "program" );
910
911             if( i_id != 0 ) /* if user specified a program */
912             {
913                 p_pgrm_to_select = input_FindProgram( p_input, i_id );
914
915                 if( p_pgrm_to_select && p_pgrm_to_select == p_pgrm )
916                     p_input->pf_set_program( p_input, p_pgrm_to_select );
917             }
918             else
919                     p_input->pf_set_program( p_input, p_pgrm );
920         }
921         /* if the pmt belongs to the currently selected program, we
922          * reselect it to update its ES */
923         else if( p_pgrm == p_input->stream.p_selected_program )
924         {
925             p_input->pf_set_program( p_input, p_pgrm );
926         }
927         
928         p_pgrm_demux->i_pmt_version = p_new_pmt->i_version;
929         p_input->stream.b_changed = 1;
930     }
931     vlc_mutex_unlock( &p_input->stream.stream_lock );
932 }
933 #endif