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