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