]> git.sesse.net Git - vlc/blob - plugins/dvd/dvd_es.c
* ./plugins/spudec/spu_decoder.c, ./plugins/dvd/dvd_es.c: temporary fix
[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.8 2002/04/23 20:58:23 sam 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 #include "debug.h"
63
64 /*****************************************************************************
65  * Local prototypes
66  *****************************************************************************/
67
68 void DVDLaunchDecoders( input_thread_t * p_input );
69
70 #define vmg p_dvd->p_ifo->vmg
71 #define vts p_dvd->p_ifo->vts
72
73 #define ADDES( stream_id, private_id, type, cat, lang, size )           \
74     i_id = ( (private_id) << 8 ) | (stream_id);                         \
75     p_es = input_AddES( p_input, NULL, i_id, size );                    \
76     p_es->i_stream_id = (stream_id);                                    \
77     p_es->i_type = (type);                                              \
78     p_es->i_cat = (cat);                                                \
79     if( lang )                                                          \
80     {                                                                   \
81         strcpy( p_es->psz_desc, DecodeLanguage( hton16( lang ) ) );     \
82     }
83
84
85 /*****************************************************************************
86  * DVDReadVideo: read video ES
87  *****************************************************************************/
88 void DVDReadVideo( input_thread_t * p_input )
89 {
90     thread_dvd_data_t * p_dvd;
91     es_descriptor_t *   p_es;
92     int                 i_id;
93     int                 i_ratio;
94
95     p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);
96
97     /* ES 0 -> video MPEG2 */
98     IfoPrintVideo( p_dvd );
99     i_ratio = vts.manager_inf.video_attr.i_ratio;
100     
101     if( i_ratio )
102     {
103         ADDES( 0xe0, 0, MPEG2_VIDEO_ES, VIDEO_ES, 0, sizeof(int) );
104         *(int*)(p_es->p_demux_data) = i_ratio;
105     }
106     else
107     {
108         ADDES( 0xe0, 0, MPEG2_VIDEO_ES, VIDEO_ES, 0, 0 );
109     }
110         
111 }
112
113 /*****************************************************************************
114  * DVDReadAudio: read audio ES
115  *****************************************************************************/
116 #define audio_status \
117     vts.title_unit.p_title[p_dvd->i_title_id-1].title.pi_audio_status[i-1]
118     
119 void DVDReadAudio( input_thread_t * p_input )
120 {
121     thread_dvd_data_t * p_dvd;
122     es_descriptor_t *   p_es;
123     int                 i_lang;
124     int                 i_id;
125     int                 i;
126
127     p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);
128     p_dvd->i_audio_nb = 0;
129     
130     /* Audio ES, in the order they appear in .ifo */
131     for( i = 1 ; i <= vts.manager_inf.i_audio_nb ; i++ )
132     {
133         IfoPrintAudio( p_dvd, i );
134
135         /* audio channel is active if first byte is 0x80 */
136         if( audio_status.i_available )
137         {
138             p_dvd->i_audio_nb++;
139             i_lang = vts.manager_inf.p_audio_attr[i-1].i_lang_code;
140             i_id = audio_status.i_position;
141
142             switch( vts.manager_inf.p_audio_attr[i-1].i_coding_mode )
143             {
144             case 0x00:              /* AC3 */
145                 ADDES( 0xbd, 0x80 + audio_status.i_position,
146                        AC3_AUDIO_ES, AUDIO_ES, i_lang, 0 );
147                 p_es->b_audio = 1;
148                 strcat( p_es->psz_desc, " (ac3)" );
149
150                 break;
151             case 0x02:
152             case 0x03:              /* MPEG audio */
153                 ADDES( 0xc0 + audio_status.i_position, 0,
154                        MPEG2_AUDIO_ES, AUDIO_ES, i_lang, 0 );
155                 p_es->b_audio = 1;
156                 strcat( p_es->psz_desc, " (mpeg)" );
157
158                 break;
159             case 0x04:              /* LPCM */
160                 ADDES( 0xbd, 0xa0 + audio_status.i_position,
161                        LPCM_AUDIO_ES, AUDIO_ES, i_lang, 0 );
162                 p_es->b_audio = 1;
163                 strcat( p_es->psz_desc, " (lpcm)" );
164
165                 break;
166             case 0x06:              /* DTS */
167                 i_id = ( ( 0x88 + audio_status.i_position ) << 8 ) | 0xbd;
168                 intf_ErrMsg( "dvd warning: DTS audio not handled yet"
169                              "(0x%x)", i_id );
170                 break;
171             default:
172                 i_id = 0;
173                 intf_ErrMsg( "dvd warning: unknown audio type %.2x",
174                          vts.manager_inf.p_audio_attr[i-1].i_coding_mode );
175             }
176         }
177     }
178 }
179 #undef audio_status
180
181 /*****************************************************************************
182  * DVDReadSPU: read subpictures ES
183  *****************************************************************************/
184 #define spu_status \
185     vts.title_unit.p_title[p_dvd->i_title_id-1].title.pi_spu_status[i-1]
186 #define palette \
187     vts.title_unit.p_title[p_dvd->i_title_id-1].title.pi_yuv_color
188
189 void DVDReadSPU( input_thread_t * p_input )
190 {
191     thread_dvd_data_t * p_dvd;
192     es_descriptor_t *   p_es;
193     int                 i_id;
194     int                 i;
195            
196     p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);
197     p_dvd->i_spu_nb = 0;
198
199     for( i = 1 ; i <= vts.manager_inf.i_spu_nb; i++ )
200     {
201         IfoPrintSpu( p_dvd, i );
202
203         if( spu_status.i_available )
204         {
205             p_dvd->i_spu_nb++;
206
207             /*  there are several streams for one spu */
208             if(  vts.manager_inf.video_attr.i_ratio )
209             {
210                 /* 16:9 */
211                 switch( vts.manager_inf.video_attr.i_perm_displ )
212                 {
213                 case 1:
214                     i_id = spu_status.i_position_pan;
215                     break;
216                 case 2:
217                     i_id = spu_status.i_position_letter;
218                     break;
219                 default:
220                     i_id = spu_status.i_position_wide;
221                     break;
222                 }
223             }
224             else
225             {
226                 /* 4:3 */
227                 i_id = spu_status.i_position_43;
228             }
229
230             if( vmg.title.pi_yuv_color )
231             {
232                 ADDES( 0xbd, 0x20 + i_id, DVD_SPU_ES, SPU_ES,
233                        vts.manager_inf.p_spu_attr[i-1].i_lang_code,
234                        sizeof(int) + 16*sizeof(u32) );
235                 *(int*)p_es->p_demux_data = 0xBeeF;
236                 memcpy( (void*)p_es->p_demux_data + sizeof(int),
237                         palette, 16*sizeof(u32) ); 
238             }
239             else
240             {
241                 ADDES( 0xbd, 0x20 + i_id, DVD_SPU_ES, SPU_ES,
242                    vts.manager_inf.p_spu_attr[i-1].i_lang_code, 0 );
243             }
244         }
245     }
246 }
247 #undef palette
248 #undef spu_status
249
250 #undef vts
251 #undef vmg
252
253 /*****************************************************************************
254  * DVDLaunchDecoders: select ES for video, audio and spu
255  *****************************************************************************/
256 void DVDLaunchDecoders( input_thread_t * p_input )
257 {
258     thread_dvd_data_t *  p_dvd;
259     int                  i_audio;
260     int                  i_spu;
261
262     p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);
263
264     /* Select Video stream (always 0) */
265     if( p_main->b_video )
266     {
267         input_SelectES( p_input, p_input->stream.pp_es[0] );
268     }
269
270     /* Select audio stream */
271     if( p_main->b_audio && p_dvd->i_audio_nb > 0 )
272     {
273         /* For audio: first one if none or a not existing one specified */
274         i_audio = config_GetIntVariable( "audio-channel" );
275         if( i_audio <= 0 || i_audio > p_dvd->i_audio_nb )
276         {
277             config_PutIntVariable( "audio-channel", 1 );
278             i_audio = 1;
279         }
280         
281         if( ( config_GetIntVariable( "audio-type" ) == REQUESTED_AC3 ) )
282         {
283             int     i_ac3 = i_audio;
284             while( ( p_input->stream.pp_es[i_ac3]->i_type !=
285                      AC3_AUDIO_ES ) && ( i_ac3 <=
286                      p_dvd->p_ifo->vts.manager_inf.i_audio_nb ) )
287             {
288                 i_ac3++;
289             }
290             if( p_input->stream.pp_es[i_ac3]->i_type == AC3_AUDIO_ES )
291             {
292                 input_SelectES( p_input,
293                                 p_input->stream.pp_es[i_ac3] );
294             }
295         }
296         else
297         {
298             input_SelectES( p_input,
299                             p_input->stream.pp_es[i_audio] );
300         }
301     }
302
303     /* Select subtitle */
304     if( p_main->b_video && p_dvd->i_spu_nb > 0 )
305     {
306         /* for spu, default is none */
307         i_spu = config_GetIntVariable( "spu-channel" );
308         if( i_spu < 0 || i_spu > p_dvd->i_spu_nb )
309         {
310             config_PutIntVariable( "spu-channel", 0 );
311             i_spu = 0;
312         }
313         if( i_spu > 0 )
314         {
315             i_spu += p_dvd->p_ifo->vts.manager_inf.i_audio_nb;
316             input_SelectES( p_input, p_input->stream.pp_es[i_spu] );
317         }
318     }
319 }