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