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