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