748f0ebbe98c79a8eaf9ad24da4f1aecfd4d8772
[vlc.git] / modules / demux / mpeg / ts.c
1 /*****************************************************************************
2  * mpeg_ts.c : Transport Stream input module for vlc
3  *****************************************************************************
4  * Copyright (C) 2000-2001 VideoLAN
5  * $Id: ts.c,v 1.5 2002/09/23 23:05:58 massiot 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 <vlc/vlc.h>
33 #include <vlc/input.h>
34
35 #include "iso_lang.h"
36
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>
44 #   else
45 #       include "dvbpsi.h"
46 #       include "descriptor.h"
47 #       include "tables/pat.h"
48 #       include "tables/pmt.h"
49 #       include "descriptors/dr.h"
50 #   endif
51 #endif
52
53 #include "system.h"
54
55 /*****************************************************************************
56  * Constants
57  *****************************************************************************/
58 #define TS_READ_ONCE 200
59
60 /*****************************************************************************
61  * Private structure
62  *****************************************************************************/
63 struct demux_sys_t
64 {
65     module_t *   p_module;
66     mpeg_demux_t mpeg;
67 };
68
69 /*****************************************************************************
70  * Local prototypes
71  *****************************************************************************/
72 static int  Activate   ( vlc_object_t * );
73 static void Deactivate ( vlc_object_t * );
74 static int  Demux      ( input_thread_t * );
75
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
88 #endif
89
90 /*****************************************************************************
91  * Module descriptor
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.")
98
99 vlc_module_begin();
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" );
108 #endif
109     add_bool( "vls-backwards-compat", 0, NULL,
110               VLS_BACKWARDS_COMPAT_TEXT, VLS_BACKWARDS_COMPAT_LONGTEXT );
111     set_callbacks( Activate, Deactivate );
112 vlc_module_end();
113
114 /*****************************************************************************
115  * Activate: initialize TS structures
116  *****************************************************************************/
117 static int Activate( vlc_object_t * p_this )
118 {
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;
124     byte_t *            p_peek;
125
126     /* Set the demux function */
127     p_input->pf_demux = Demux;
128
129     /* Initialize access plug-in structures. */
130     if( p_input->i_mtu == 0 )
131     {
132         /* Improve speed. */
133         p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
134     }
135
136     /* Have a peep at the show. */
137     if( input_Peek( p_input, &p_peek, 1 ) < 1 )
138     {
139         msg_Err( p_input, "cannot peek()" );
140         return -1;
141     }
142
143     if( *p_peek != TS_SYNC_CODE )
144     {
145         if( *p_input->psz_demux && !strncmp( p_input->psz_demux, "ts", 3 ) )
146         {
147             /* User forced */
148             msg_Err( p_input, "this does not look like a TS stream, continuing" );
149         }
150         else
151         {
152             msg_Warn( p_input, "TS module discarded (no sync)" );
153             return -1;
154         }
155     }
156
157     /* Adapt the bufsize for our only use. */
158     if( p_input->i_mtu != 0 )
159     {
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;
162     }
163
164     p_demux = p_input->p_demux_data = malloc( sizeof(demux_sys_t ) );
165     if( p_demux == NULL )
166     {
167         return -1;
168     }
169
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 )
173     {
174         free( p_input->p_demux_data );
175         return -1;
176     }
177
178     vlc_mutex_lock( &p_input->stream.stream_lock );
179
180     if( input_InitStream( p_input, sizeof( stream_ts_data_t ) ) == -1 )
181     {
182         module_Unneed( p_input, p_demux->p_module );
183         free( p_input->p_demux_data );
184         return -1;
185     }
186
187     p_stream_data = (stream_ts_data_t *)p_input->stream.p_demux_data;
188     p_stream_data->i_pat_version = PAT_UNINITIALIZED ;
189
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 ); 
193
194     if( p_stream_data->p_pat_handle == NULL )
195     {
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 );
199         return -1;
200     }
201 #endif
202     
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;
213
214     vlc_mutex_unlock( &p_input->stream.stream_lock );
215     
216     return 0;
217 }
218
219 /*****************************************************************************
220  * Deactivate: deinitialize TS structures
221  *****************************************************************************/
222 static void Deactivate( vlc_object_t * p_this )
223 {
224     input_thread_t *    p_input = (input_thread_t *)p_this;
225
226     module_Unneed( p_input, p_input->p_demux_data->p_module );
227     free( p_input->p_demux_data );
228 }
229
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
234  * packets.
235  *****************************************************************************/
236 static int Demux( input_thread_t * p_input )
237 {
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 :
241                                    TS_READ_ONCE);
242     int             i;
243
244     for( i = 0; i < i_read_once; i++ )
245     {
246         data_packet_t *     p_data;
247         ssize_t             i_result;
248
249         i_result = p_demux->mpeg.pf_read_ts( p_input, &p_data );
250
251         if( i_result <= 0 )
252         {
253             return i_result;
254         }
255
256         p_demux->mpeg.pf_demux_ts( p_input, p_data,
257                                    (psi_callback_t) &PSI_CALLBACK );
258     }
259
260     return i_read_once;
261 }
262
263
264 #if defined MODULE_NAME_IS_ts
265 /*
266  * PSI demultiplexing and decoding without libdvbpsi
267  */
268
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 )
274 {
275     es_ts_data_t  * p_demux_data;
276     
277     p_demux_data = (es_ts_data_t *)p_es->p_demux_data;
278
279 #define p_psi (p_demux_data->p_psi_section)
280 #define p (p_data->p_payload_start)
281
282     if( b_unit_start )
283     {
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 )
287         {
288             msg_Warn( p_input,
289                       "non-zero pointer field found, trying to continue" );
290             p+=(u8)p[0];
291         }
292         else
293         {
294             p++;
295         }
296
297         /* This is the begining of a new section */
298
299         if( ((u8)(p[1]) & 0xc0) != 0x80 ) 
300         {
301             msg_Warn( p_input, "invalid PSI packet" );
302             p_psi->b_trash = 1;
303         }
304         else 
305         {
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];
310
311             if( p_psi->b_is_complete || p_psi->i_section_number == 0 )
312             {
313                 /* This is a new PSI packet */
314                 p_psi->b_is_complete = 0;
315                 p_psi->b_trash = 0;
316                 p_psi->i_version_number = ( p[5] >> 1 ) & 0x1f;
317                 p_psi->i_last_section_number = (u8)p[7];
318
319                 /* We'll write at the begining of the buffer */
320                 p_psi->p_current = p_psi->buffer;
321             }
322             else
323             {
324                 if( p_psi->b_section_complete )
325                 {
326                     /* New Section of an already started PSI */
327                     p_psi->b_section_complete = 0;
328                     
329                     if( p_psi->i_version_number != (( p[5] >> 1 ) & 0x1f) )
330                     {
331                         msg_Warn( p_input,
332                                   "PSI version differs inside same PAT" );
333                         p_psi->b_trash = 1;
334                     }
335                     if( p_psi->i_section_number + 1 != (u8)p[6] )
336                     {
337                         msg_Warn( p_input,
338                                   "PSI Section discontinuity, packet lost?" );
339                         p_psi->b_trash = 1;
340                     }
341                     else
342                         p_psi->i_section_number++;
343                 }
344                 else
345                 {
346                     msg_Warn( p_input, "got unexpected new PSI section" );
347                     p_psi->b_trash = 1;
348                 }
349             }
350         }
351     } /* b_unit_start */
352     
353     if( !p_psi->b_trash )
354     {
355         /* read */
356         if( (p_data->p_payload_end - p) >=
357             ( p_psi->i_section_length - p_psi->i_read_in_section ) )
358         {
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) );
362     
363             p_psi->b_section_complete = 1;
364             p_psi->p_current += 
365                 (p_psi->i_section_length - p_psi->i_read_in_section);
366                         
367             if( p_psi->i_section_number == p_psi->i_last_section_number )
368             {
369                 /* This was the last section of PSI */
370                 p_psi->b_is_complete = 1;
371
372                 switch( p_demux_data->i_psi_type)
373                 {
374                 case PSI_IS_PAT:
375                     TSDecodePAT( p_input, p_es );
376                     break;
377                 case PSI_IS_PMT:
378                     TSDecodePMT( p_input, p_es );
379                     break;
380                 default:
381                     msg_Warn( p_input, "received unknown PSI in DemuxPSI" );
382                 }
383             }
384         }
385         else
386         {
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;
389
390             p_psi->p_current += p_data->p_payload_end - p;
391         }
392     }
393
394 #undef p_psi    
395 #undef p
396    
397     input_DeletePacket( p_input->p_method_data, p_data );
398     
399     return ;
400 }
401
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 )
406 {
407     stream_ts_data_t  * p_stream_data;
408     es_ts_data_t      * p_demux_data;
409
410     pgrm_descriptor_t * p_pgrm;
411     es_descriptor_t   * p_current_es;
412     byte_t            * p_current_data;           
413
414     int                 i_section_length, i_program_id, i_pmt_pid;
415     int                 i_loop, i_current_section;
416
417     vlc_bool_t          b_changed = 0;
418
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;
421     
422 #define p_psi (p_demux_data->p_psi_section)
423
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 )
427     {
428         int i_programs = p_input->stream.i_pgrm_number;
429
430         p_current_data = p_psi->buffer;
431
432         do
433         {
434             i_section_length = ((u32)(p_current_data[1] & 0xF) << 8) |
435                                  p_current_data[2];
436             i_current_section = (u8)p_current_data[6];
437     
438             for( i_loop = 0;
439                  ( i_loop < (i_section_length - 9) / 4 ) && !b_changed;
440                  i_loop++ )
441             {
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)
445                                     << 8 )
446                                | *(p_current_data + i_loop * 4 + 11);
447
448                 if( i_program_id )
449                 {
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 )
457                     {
458                         i_programs--;
459                     }
460                     else
461                     {
462                         b_changed = 1;
463                     }
464                 }
465             }
466             
467             p_current_data += 3 + i_section_length;
468
469         } while( ( i_current_section < p_psi->i_last_section_number )
470                   && !b_changed );
471
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;
475     }
476
477     if( b_changed )
478     {
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;
485         
486         p_current_data = p_psi->buffer;
487
488         /* Delete all programs */
489         while( p_input->stream.i_pgrm_number )
490         {
491             input_DelProgram( p_input, p_input->stream.pp_programs[0] );
492         }
493         
494         do
495         {
496             i_section_length = ((u32)(p_current_data[1] & 0xF) << 8) |
497                                  p_current_data[2];
498             i_current_section = (u8)p_current_data[6];
499     
500             for( i_loop = 0; i_loop < (i_section_length - 9) / 4 ; i_loop++ )
501             {
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)
505                                     << 8 )
506                                | *(p_current_data + i_loop * 4 + 11);
507     
508                 /* If program = 0, we're having info about NIT not PMT */
509                 if( i_program_id )
510                 {
511                     /* Add this program */
512                     p_pgrm = input_AddProgram( p_input, i_program_id, 
513                                                sizeof( pgrm_ts_data_t ) );
514                    
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;
518     
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;
525                     
526                     p_es_demux->p_psi_section = 
527                                             malloc( sizeof( psi_section_t ) );
528                     p_es_demux->p_psi_section->b_is_complete = 0;
529                 }
530             }
531             
532             p_current_data += 3 + i_section_length;
533
534         } while( i_current_section < p_psi->i_last_section_number );
535
536         /* Go to the beginning of the next section */
537         p_stream_data->i_pat_version = p_psi->i_version_number;
538
539     }
540 #undef p_psi
541
542 }
543
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 )
552 {
553
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" );
557
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;
560     
561 #define p_psi (p_demux_data->p_psi_section)
562
563     if( p_psi->i_version_number != p_pgrm_data->i_pmt_version ) 
564     {
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;
571         
572         p_current_section = p_psi->buffer;
573         p_current_data = p_psi->buffer;
574
575         p_pgrm_data->i_pcr_pid = ( ((u32)*(p_current_section + 8) & 0x1F) << 8 ) |
576                                     *(p_current_section + 9);
577
578
579         /* Lock stream information */
580         vlc_mutex_lock( &p_input->stream.stream_lock );
581
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 ; )
585         {
586             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 )
590             {
591                 input_DelES( p_input, p_es->p_pgrm->pp_es[i_loop] );
592             }
593         }
594
595         /* Then add what we received in this PMT */
596         do
597         {
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);
603
604             /* For the moment we ignore program descriptors */
605             p_current_data += 12 + i_prog_info_length;
606     
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 )
610             {
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);
616                 
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 ) );
620
621                 /* Tell the interface what kind of stream it is and select 
622                  * the required ones */
623                 {
624                     switch( i_stream_type )
625                     {
626                         case MPEG1_VIDEO_ES:
627                         case MPEG2_VIDEO_ES:
628                             p_new_es->i_fourcc = VLC_FOURCC('m','p','g','v');
629                             p_new_es->i_cat = VIDEO_ES;
630                             break;
631                         case MPEG1_AUDIO_ES:
632                         case MPEG2_AUDIO_ES:
633                             p_new_es->i_fourcc = VLC_FOURCC('m','p','g','a');
634                             p_new_es->i_cat = AUDIO_ES;
635                             break;
636                         case A52_AUDIO_ES:
637                             if ( !b_vls_compat )
638                                 p_new_es->i_fourcc = VLC_FOURCC('a','5','2',' ');
639                             else
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;
643                             break;
644                         case LPCM_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;
648                             break;
649                         case DVD_SPU_ES:
650                             if ( !b_vls_compat )
651                                 p_new_es->i_fourcc = VLC_FOURCC('s','p','u',' ');
652                             else
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;
656                             break;
657                         case SDDS_AUDIO_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;
661                             break;
662                         case DTS_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;
666                             break;
667                         /* 'b' stands for 'buggy' */
668                         case A52B_AUDIO_ES:
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;
672                             break;
673                         case LPCMB_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;
677                             break;
678                         case DVDB_SPU_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;
682                             break;
683                         default :
684                             p_new_es->i_fourcc = 0;
685                             p_new_es->i_cat = UNKNOWN_ES;
686                             break;
687                     }
688                 }
689                 
690                 p_current_data += 5 + i_es_info_length;
691             }
692
693             /* Go to the beginning of the next section*/
694             p_current_data += 3 + i_section_length;
695            
696             p_current_section++;
697             
698         } while( i_current_section < p_psi->i_last_section_number );
699
700         p_pgrm_data->i_pmt_version = p_psi->i_version_number;
701
702         /* if no program is selected :*/
703         if( !p_input->stream.p_selected_program )
704         {
705             pgrm_descriptor_t *     p_pgrm_to_select;
706             u16 i_id = (u16)config_GetInt( p_input, "program" );
707
708             if( i_id != 0 ) /* if user specified a program */
709             {
710                 p_pgrm_to_select = input_FindProgram( p_input, i_id );
711
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 );
714             }
715             else
716                     p_input->pf_set_program( p_input, p_es->p_pgrm );
717         }
718         
719         /* inform interface that stream has changed */
720         p_input->stream.b_changed = 1;
721         /*  Remove lock */
722         vlc_mutex_unlock( &p_input->stream.stream_lock );
723     }
724     
725 #undef p_psi
726 }
727
728 #elif defined MODULE_NAME_IS_ts_dvbpsi
729 /*
730  * PSI Decoding using libdvbcss 
731  */
732
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 )
740 {
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;
744
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;
747
748     switch( p_es_demux_data->i_psi_type)
749     {
750         case PSI_IS_PAT:
751             dvbpsi_PushPacket( 
752                     ( dvbpsi_handle ) p_stream_demux_data->p_pat_handle,
753                     p_data->p_demux_start );
754             break;
755         case PSI_IS_PMT:
756             p_pgrm_demux_data = ( pgrm_ts_data_t * )p_es->p_pgrm->p_demux_data;
757             dvbpsi_PushPacket( 
758                     ( dvbpsi_handle ) p_pgrm_demux_data->p_pmt_handle,
759                     p_data->p_demux_start );
760             break;
761         default:
762             msg_Warn( p_input, "received unknown PSI in DemuxPSI" );
763     }
764     
765     input_DeletePacket( p_input->p_method_data, p_data );
766 }
767
768 /*****************************************************************************
769  * HandlePAT: will treat a PAT returned by dvbpsi
770  *****************************************************************************/
771
772 void TS_DVBPSI_HandlePAT( input_thread_t * p_input, dvbpsi_pat_t * p_new_pat )
773 {
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;
780
781     vlc_mutex_lock( &p_input->stream.stream_lock );
782     
783     p_stream_data = (stream_ts_data_t *)p_input->stream.p_demux_data;
784     
785     if ( !p_new_pat->b_current_next || 
786             p_stream_data->i_pat_version == PAT_UNINITIALIZED  )
787     {
788         /* Delete all programs */
789         while( p_input->stream.i_pgrm_number )
790         {
791             input_DelProgram( p_input, p_input->stream.pp_programs[0] );
792         }
793     
794         /* treat the new programs list */
795         p_pgrm = p_new_pat->p_first_program;
796         
797         while( p_pgrm )
798         {
799             /* If program = 0, we're having info about NIT not PMT */
800             if( p_pgrm->i_number )
801             {
802                 /* Add this program */
803                 p_new_pgrm = input_AddProgram( p_input, p_pgrm->i_number, 
804                                             sizeof( pgrm_ts_data_t ) );
805
806                 p_pgrm_demux = (pgrm_ts_data_t *)p_new_pgrm->p_demux_data;
807                 p_pgrm_demux->i_pmt_version = PMT_UNINITIALIZED;
808         
809                 /* Add the PMT ES to this program */
810                 p_current_es = input_AddES( p_input, p_new_pgrm,
811                                             (u16) p_pgrm->i_pid,
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;
816                         
817                 p_es_demux->p_psi_section = malloc( sizeof( psi_section_t ) );
818                 if ( p_es_demux->p_psi_section == NULL )
819                 {
820                     msg_Err( p_input, "out of memory" );
821                     p_input->b_error = 1;
822                     return;
823                 }
824             
825                 p_es_demux->p_psi_section->b_is_complete = 0;
826                 
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, 
831                             p_input );
832
833                 if( p_pgrm_demux->p_pmt_handle == NULL )
834                 {
835                     msg_Err( p_input, "could not create PMT decoder" );
836                     p_input->b_error = 1;
837                     return;
838                 }
839
840             }
841             p_pgrm = p_pgrm->p_next; 
842         }
843         
844         p_stream_data->i_pat_version = p_new_pat->i_version;
845     }
846     vlc_mutex_unlock( &p_input->stream.stream_lock );
847 }
848
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 )
853 {
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" );
859    
860     vlc_mutex_lock( &p_input->stream.stream_lock );
861     
862     p_pgrm = input_FindProgram( p_input, p_new_pmt->i_program_number );
863
864     if( p_pgrm == NULL )
865     {
866         msg_Warn( p_input, "PMT of unreferenced program found" );
867         return;
868     }
869
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;
872
873     if( !p_new_pmt->b_current_next || 
874             p_pgrm_demux->i_pmt_version == PMT_UNINITIALIZED )
875     {
876         p_es = p_new_pmt->p_first_es;
877         while( p_es )
878         {
879             /* Add this 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 )
883             {
884                 msg_Err( p_input, "could not add ES %d", p_es->i_pid );
885                 p_input->b_error = 1;
886                 return;
887             }
888
889             switch( p_es->i_type )
890             {
891                 case MPEG1_VIDEO_ES:
892                 case MPEG2_VIDEO_ES:
893                     p_new_es->i_fourcc = VLC_FOURCC('m','p','g','v');
894                     p_new_es->i_cat = VIDEO_ES;
895                     break;
896                 case MPEG1_AUDIO_ES:
897                 case MPEG2_AUDIO_ES:
898                     p_new_es->i_fourcc = VLC_FOURCC('m','p','g','a');
899                     p_new_es->i_cat = AUDIO_ES;
900                     break;
901                 case A52_AUDIO_ES:
902                     if ( !b_vls_compat )
903                         p_new_es->i_fourcc = VLC_FOURCC('a','5','2',' ');
904                     else
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;
908                     break;
909                 case DVD_SPU_ES:
910                 case A52_AUDIO_ES:
911                     if ( !b_vls_compat )
912                         p_new_es->i_fourcc = VLC_FOURCC('s','p','u',' ');
913                     else
914                         p_new_es->i_fourcc = VLC_FOURCC('s','p','u','b');
915                     p_new_es->i_cat = SPU_ES;
916                     p_new_es->i_stream_id = 0xBD;
917                     break;
918                 case LPCM_AUDIO_ES:
919                     p_new_es->i_fourcc = VLC_FOURCC('l','p','c','m');
920                     p_new_es->i_cat = AUDIO_ES;
921                     p_new_es->i_stream_id = 0xBD;
922                     break;
923                 case SDDS_AUDIO_ES:
924                     p_new_es->i_fourcc = VLC_FOURCC('s','d','d','s');
925                     p_new_es->i_stream_id = 0xBD;
926                     p_new_es->i_cat = AUDIO_ES;
927                     break;
928                 case DTS_AUDIO_ES:
929                     p_new_es->i_fourcc = VLC_FOURCC('d','t','s',' ');
930                     p_new_es->i_stream_id = 0xBD;
931                     p_new_es->i_cat = AUDIO_ES;
932                     break;
933                 case A52B_AUDIO_ES:
934                     p_new_es->i_fourcc = VLC_FOURCC('a','5','2','b');
935                     p_new_es->i_cat = AUDIO_ES;
936                     p_new_es->i_stream_id = 0xBD;
937                     break;
938                 case DVDB_SPU_ES:
939                     p_new_es->i_fourcc = VLC_FOURCC('s','p','u','b');
940                     p_new_es->i_cat = SPU_ES;
941                     p_new_es->i_stream_id = 0xBD;
942                     break;
943                 case LPCMB_AUDIO_ES:
944                     p_new_es->i_fourcc = VLC_FOURCC('l','p','c','b');
945                     p_new_es->i_cat = AUDIO_ES;
946                     p_new_es->i_stream_id = 0xBD;
947                     break;
948                 default:
949                     p_new_es->i_fourcc = 0;
950                     p_new_es->i_cat = UNKNOWN_ES;
951             }
952
953             if(    ( p_new_es->i_cat == AUDIO_ES )
954                 || (p_new_es->i_cat == SPU_ES ) )
955             {
956                 dvbpsi_descriptor_t *p_dr = p_es->p_first_descriptor;
957                 while( p_dr && ( p_dr->i_tag != 0x0a ) )
958                     p_dr = p_dr->p_next;
959                 if( p_dr )
960                 {
961                     dvbpsi_iso639_dr_t *p_decoded =
962                                                 dvbpsi_DecodeISO639Dr( p_dr );
963                     if( p_decoded->i_code_count > 0 )
964                     {
965                         const iso639_lang_t * p_iso;
966                         p_iso = GetLang_2T((char*)p_decoded->i_iso_639_code);
967                         if(p_iso)
968                         {
969                             if(p_iso->psz_native_name[0])
970                                 strcpy( p_new_es->psz_desc,
971                                         p_iso->psz_native_name );
972                             else
973                                 strcpy( p_new_es->psz_desc,
974                                         p_iso->psz_eng_name );
975                         }
976                         else
977                         {
978                             strncpy( p_new_es->psz_desc,
979                                      p_decoded->i_iso_639_code, 3 );
980                         }
981                     }
982                 }
983                 switch( p_es->i_type )
984                 {
985                     case MPEG1_AUDIO_ES:
986                     case MPEG2_AUDIO_ES:
987                         strcat( p_new_es->psz_desc, " (mpeg)" );
988                         break;
989                     case LPCM_AUDIO_ES:
990                     case LPCMB_AUDIO_ES:
991                         strcat( p_new_es->psz_desc, " (lpcm)" );
992                         break;
993                     case A52_AUDIO_ES:
994                     case A52B_AUDIO_ES:
995                         strcat( p_new_es->psz_desc, " (A52)" );
996                         break;
997                 }
998             }
999
1000             p_es = p_es->p_next;
1001         }
1002         
1003         /* if no program is selected :*/
1004         if( !p_input->stream.p_selected_program )
1005         {
1006             pgrm_descriptor_t *     p_pgrm_to_select;
1007             u16 i_id = (u16)config_GetInt( p_input, "program" );
1008
1009             if( i_id != 0 ) /* if user specified a program */
1010             {
1011                 p_pgrm_to_select = input_FindProgram( p_input, i_id );
1012
1013                 if( p_pgrm_to_select && p_pgrm_to_select == p_pgrm )
1014                     p_input->pf_set_program( p_input, p_pgrm_to_select );
1015             }
1016             else
1017                     p_input->pf_set_program( p_input, p_pgrm );
1018         }
1019         /* if the pmt belongs to the currently selected program, we
1020          * reselect it to update its ES */
1021         else if( p_pgrm == p_input->stream.p_selected_program )
1022         {
1023             p_input->pf_set_program( p_input, p_pgrm );
1024         }
1025         
1026         p_pgrm_demux->i_pmt_version = p_new_pmt->i_version;
1027         p_input->stream.b_changed = 1;
1028     }
1029     vlc_mutex_unlock( &p_input->stream.stream_lock );
1030 }
1031 #endif