]> git.sesse.net Git - vlc/blob - plugins/dvd/dvd_es.c
e96fbd92364bb3a7e4c4b76e94d326e35600767d
[vlc] / plugins / dvd / dvd_es.c
1 /* dvd_es.c: functions to find and select ES
2  *****************************************************************************
3  * Copyright (C) 1998-2001 VideoLAN
4  * $Id: dvd_es.c,v 1.11 2002/05/18 14:03:13 gbazin Exp $
5  *
6  * Author: Stéphane Borel <stef@via.ecp.fr>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  * 
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
21  *****************************************************************************/
22
23 /*****************************************************************************
24  * Preamble
25  *****************************************************************************/
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include <videolan/vlc.h>
31
32 #ifdef HAVE_UNISTD_H
33 #   include <unistd.h>
34 #endif
35
36 #include <fcntl.h>
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <string.h>
40 #include <errno.h>
41
42 #ifdef STRNCASECMP_IN_STRINGS_H
43 #   include <strings.h>
44 #endif
45
46 #ifdef GOD_DAMN_DMCA
47 #   include "dummy_dvdcss.h"
48 #else
49 #   include <dvdcss/dvdcss.h>
50 #endif
51
52 #include "stream_control.h"
53 #include "input_ext-intf.h"
54 #include "input_ext-dec.h"
55 #include "input_ext-plugins.h"
56
57 #include "dvd.h"
58 #include "dvd_ifo.h"
59 #include "dvd_summary.h"
60 #include "iso_lang.h"
61
62 /*****************************************************************************
63  * Local prototypes
64  *****************************************************************************/
65
66 void DVDLaunchDecoders( input_thread_t * p_input );
67
68 #define vmg p_dvd->p_ifo->vmg
69 #define vts p_dvd->p_ifo->vts
70
71 #define ADDES( stream_id, private_id, type, cat, lang, size )           \
72     i_id = ( (private_id) << 8 ) | (stream_id);                         \
73     p_es = input_AddES( p_input, NULL, i_id, size );                    \
74     p_es->i_stream_id = (stream_id);                                    \
75     p_es->i_type = (type);                                              \
76     p_es->i_cat = (cat);                                                \
77     if( lang )                                                          \
78     {                                                                   \
79         strcpy( p_es->psz_desc, DecodeLanguage( lang ) );               \
80     }
81
82
83 /*****************************************************************************
84  * DVDReadVideo: read video ES
85  *****************************************************************************/
86 void DVDReadVideo( input_thread_t * p_input )
87 {
88     thread_dvd_data_t * p_dvd;
89     es_descriptor_t *   p_es;
90     int                 i_id;
91     int                 i_ratio;
92
93     p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);
94
95     /* ES 0 -> video MPEG2 */
96     IfoPrintVideo( p_dvd );
97     i_ratio = vts.manager_inf.video_attr.i_ratio;
98     
99     if( i_ratio )
100     {
101         ADDES( 0xe0, 0, MPEG2_VIDEO_ES, VIDEO_ES, 0, sizeof(int) );
102         *(int*)(p_es->p_demux_data) = i_ratio;
103     }
104     else
105     {
106         ADDES( 0xe0, 0, MPEG2_VIDEO_ES, VIDEO_ES, 0, 0 );
107     }
108         
109 }
110
111 /*****************************************************************************
112  * DVDReadAudio: read audio ES
113  *****************************************************************************/
114 #define audio_status \
115     vts.title_unit.p_title[p_dvd->i_title_id-1].title.pi_audio_status[i-1]
116     
117 void DVDReadAudio( input_thread_t * p_input )
118 {
119     thread_dvd_data_t * p_dvd;
120     es_descriptor_t *   p_es;
121     int                 i_lang;
122     int                 i_id;
123     int                 i;
124
125     p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);
126     p_dvd->i_audio_nb = 0;
127     
128     /* Audio ES, in the order they appear in .ifo */
129     for( i = 1 ; i <= vts.manager_inf.i_audio_nb ; i++ )
130     {
131         IfoPrintAudio( p_dvd, i );
132
133         /* audio channel is active if first byte is 0x80 */
134         if( audio_status.i_available )
135         {
136             p_dvd->i_audio_nb++;
137             i_lang = vts.manager_inf.p_audio_attr[i-1].i_lang_code;
138             i_id = audio_status.i_position;
139
140             switch( vts.manager_inf.p_audio_attr[i-1].i_coding_mode )
141             {
142             case 0x00:              /* AC3 */
143                 ADDES( 0xbd, 0x80 + audio_status.i_position,
144                        AC3_AUDIO_ES, AUDIO_ES, i_lang, 0 );
145                 p_es->b_audio = 1;
146                 strcat( p_es->psz_desc, " (ac3)" );
147
148                 break;
149             case 0x02:
150             case 0x03:              /* MPEG audio */
151                 ADDES( 0xc0 + audio_status.i_position, 0,
152                        MPEG2_AUDIO_ES, AUDIO_ES, i_lang, 0 );
153                 p_es->b_audio = 1;
154                 strcat( p_es->psz_desc, " (mpeg)" );
155
156                 break;
157             case 0x04:              /* LPCM */
158                 ADDES( 0xbd, 0xa0 + audio_status.i_position,
159                        LPCM_AUDIO_ES, AUDIO_ES, i_lang, 0 );
160                 p_es->b_audio = 1;
161                 strcat( p_es->psz_desc, " (lpcm)" );
162
163                 break;
164             case 0x06:              /* DTS */
165                 i_id = ( ( 0x88 + audio_status.i_position ) << 8 ) | 0xbd;
166                 intf_ErrMsg( "dvd warning: DTS audio not handled yet"
167                              "(0x%x)", i_id );
168                 break;
169             default:
170                 i_id = 0;
171                 intf_ErrMsg( "dvd warning: unknown audio type %.2x",
172                          vts.manager_inf.p_audio_attr[i-1].i_coding_mode );
173             }
174         }
175     }
176 }
177 #undef audio_status
178
179 /*****************************************************************************
180  * DVDReadSPU: read subpictures ES
181  *****************************************************************************/
182 #define spu_status \
183     vts.title_unit.p_title[p_dvd->i_title_id-1].title.pi_spu_status[i-1]
184 #define palette \
185     vts.title_unit.p_title[p_dvd->i_title_id-1].title.pi_yuv_color
186
187 void DVDReadSPU( input_thread_t * p_input )
188 {
189     thread_dvd_data_t * p_dvd;
190     es_descriptor_t *   p_es;
191     int                 i_id;
192     int                 i;
193            
194     p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);
195     p_dvd->i_spu_nb = 0;
196
197     for( i = 1 ; i <= vts.manager_inf.i_spu_nb; i++ )
198     {
199         IfoPrintSpu( p_dvd, i );
200
201         if( spu_status.i_available )
202         {
203             p_dvd->i_spu_nb++;
204
205             /*  there are several streams for one spu */
206             if(  vts.manager_inf.video_attr.i_ratio )
207             {
208                 /* 16:9 */
209                 switch( vts.manager_inf.video_attr.i_perm_displ )
210                 {
211                 case 1:
212                     i_id = spu_status.i_position_pan;
213                     break;
214                 case 2:
215                     i_id = spu_status.i_position_letter;
216                     break;
217                 default:
218                     i_id = spu_status.i_position_wide;
219                     break;
220                 }
221             }
222             else
223             {
224                 /* 4:3 */
225                 i_id = spu_status.i_position_43;
226             }
227
228             if( vmg.title.pi_yuv_color )
229             {
230                 ADDES( 0xbd, 0x20 + i_id, DVD_SPU_ES, SPU_ES,
231                        vts.manager_inf.p_spu_attr[i-1].i_lang_code,
232                        sizeof(int) + 16*sizeof(u32) );
233                 *(int*)p_es->p_demux_data = 0xBeeF;
234                 memcpy( (char*)p_es->p_demux_data + sizeof(int),
235                         palette, 16*sizeof(u32) ); 
236             }
237             else
238             {
239                 ADDES( 0xbd, 0x20 + i_id, DVD_SPU_ES, SPU_ES,
240                    vts.manager_inf.p_spu_attr[i-1].i_lang_code, 0 );
241             }
242         }
243     }
244 }
245 #undef palette
246 #undef spu_status
247
248 #undef vts
249 #undef vmg
250
251 /*****************************************************************************
252  * DVDLaunchDecoders: select ES for video, audio and spu
253  *****************************************************************************/
254 void DVDLaunchDecoders( input_thread_t * p_input )
255 {
256     thread_dvd_data_t *  p_dvd;
257     int                  i_audio;
258     int                  i_spu;
259
260     p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);
261
262     /* Select Video stream (always 0) */
263     if( p_main->b_video )
264     {
265         input_SelectES( p_input, p_input->stream.pp_es[0] );
266     }
267
268     /* Select audio stream */
269     if( p_main->b_audio && p_dvd->i_audio_nb > 0 )
270     {
271         /* For audio: first one if none or a not existing one specified */
272         i_audio = config_GetIntVariable( "audio-channel" );
273         if( i_audio <= 0 || i_audio > p_dvd->i_audio_nb )
274         {
275             config_PutIntVariable( "audio-channel", 1 );
276             i_audio = 1;
277         }
278         
279         if( ( config_GetIntVariable( "audio-type" ) == REQUESTED_AC3 ) )
280         {
281             int     i_ac3 = i_audio;
282             while( ( p_input->stream.pp_es[i_ac3]->i_type !=
283                      AC3_AUDIO_ES ) && ( i_ac3 <=
284                      p_dvd->p_ifo->vts.manager_inf.i_audio_nb ) )
285             {
286                 i_ac3++;
287             }
288             if( p_input->stream.pp_es[i_ac3]->i_type == AC3_AUDIO_ES )
289             {
290                 input_SelectES( p_input,
291                                 p_input->stream.pp_es[i_ac3] );
292             }
293         }
294         else
295         {
296             input_SelectES( p_input,
297                             p_input->stream.pp_es[i_audio] );
298         }
299     }
300
301     /* Select subtitle */
302     if( p_main->b_video && p_dvd->i_spu_nb > 0 )
303     {
304         /* for spu, default is none */
305         i_spu = config_GetIntVariable( "spu-channel" );
306         if( i_spu < 0 || i_spu > p_dvd->i_spu_nb )
307         {
308             config_PutIntVariable( "spu-channel", 0 );
309             i_spu = 0;
310         }
311         if( i_spu > 0 )
312         {
313             i_spu += p_dvd->p_ifo->vts.manager_inf.i_audio_nb;
314             input_SelectES( p_input, p_input->stream.pp_es[i_spu] );
315         }
316     }
317 }