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