]> git.sesse.net Git - vlc/blob - modules/access/dvd/es.c
* ./configure.ac.in: removed -W in favour of -Wtraditional.
[vlc] / modules / access / dvd / es.c
1 /* es.c: functions to find and select ES
2  *****************************************************************************
3  * Copyright (C) 1998-2001 VideoLAN
4  * $Id: es.c,v 1.4 2002/12/06 16:34:04 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 "dvdcss.h"
49 #else
50 #   include <dvdcss/dvdcss.h>
51 #endif
52
53 #include "dvd.h"
54 #include "ifo.h"
55 #include "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, fourcc, 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_fourcc = (fourcc);                                          \
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, VLC_FOURCC('m','p','g','v'), VIDEO_ES, 0, sizeof(int) );
98         *(int*)(p_es->p_demux_data) = i_ratio;
99     }
100     else
101     {
102         ADDES( 0xe0, 0, VLC_FOURCC('m','p','g','v'), 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:              /* A52 */
139                 ADDES( 0xbd, 0x80 + audio_status.i_position,
140                        VLC_FOURCC('a','5','2','b'), AUDIO_ES, i_lang, 0 );
141                 strcat( p_es->psz_desc, " (A52)" );
142
143                 break;
144             case 0x02:
145             case 0x03:              /* MPEG audio */
146                 ADDES( 0xc0 + audio_status.i_position, 0,
147                        VLC_FOURCC('m','p','g','a'), AUDIO_ES, i_lang, 0 );
148                 strcat( p_es->psz_desc, " (mpeg)" );
149
150                 break;
151             case 0x04:              /* LPCM */
152                 ADDES( 0xbd, 0xa0 + audio_status.i_position,
153                        VLC_FOURCC('l','p','c','b'), AUDIO_ES, i_lang, 0 );
154                 strcat( p_es->psz_desc, " (lpcm)" );
155
156                 break;
157             case 0x06:              /* DTS */
158                 ADDES( 0xbd, 0x88 + audio_status.i_position,
159                        VLC_FOURCC('d','t','s','b'), AUDIO_ES, i_lang, 0 );
160                 strcat( p_es->psz_desc, " (dts)" );
161
162                 break;
163             default:
164                 i_id = 0;
165                 msg_Err( p_input, "unknown audio type %.2x",
166                          vts.manager_inf.p_audio_attr[i-1].i_coding_mode );
167             }
168         }
169     }
170 }
171 #undef audio_status
172
173 /*****************************************************************************
174  * DVDReadSPU: read subpictures ES
175  *****************************************************************************/
176 #define spu_status \
177     vts.title_unit.p_title[p_dvd->i_title_id-1].title.pi_spu_status[i-1]
178 #define palette \
179     vts.title_unit.p_title[p_dvd->i_title_id-1].title.pi_yuv_color
180
181 void DVDReadSPU( input_thread_t * p_input )
182 {
183     thread_dvd_data_t * p_dvd;
184     es_descriptor_t *   p_es;
185     int                 i_id;
186     int                 i;
187
188     p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);
189     p_dvd->i_spu_nb = 0;
190
191     for( i = 1 ; i <= vts.manager_inf.i_spu_nb; i++ )
192     {
193         IfoPrintSpu( p_dvd, i );
194
195         if( spu_status.i_available )
196         {
197             p_dvd->i_spu_nb++;
198
199             /*  there are several streams for one spu */
200             if(  vts.manager_inf.video_attr.i_ratio )
201             {
202                 /* 16:9 */
203                 switch( vts.manager_inf.video_attr.i_perm_displ )
204                 {
205                 case 1:
206                     i_id = spu_status.i_position_pan;
207                     break;
208                 case 2:
209                     i_id = spu_status.i_position_letter;
210                     break;
211                 default:
212                     i_id = spu_status.i_position_wide;
213                     break;
214                 }
215             }
216             else
217             {
218                 /* 4:3 */
219                 i_id = spu_status.i_position_43;
220             }
221
222             if( vmg.title.pi_yuv_color )
223             {
224                 ADDES( 0xbd, 0x20 + i_id, VLC_FOURCC('s','p','u','b'), SPU_ES,
225                        vts.manager_inf.p_spu_attr[i-1].i_lang_code,
226                        sizeof(int) + 16*sizeof(u32) );
227                 *(int*)p_es->p_demux_data = 0xBeeF;
228                 memcpy( (char*)p_es->p_demux_data + sizeof(int),
229                         palette, 16*sizeof(u32) );
230             }
231             else
232             {
233                 ADDES( 0xbd, 0x20 + i_id, VLC_FOURCC('s','p','u','b'), SPU_ES,
234                    vts.manager_inf.p_spu_attr[i-1].i_lang_code, 0 );
235             }
236         }
237     }
238 }
239 #undef palette
240 #undef spu_status
241
242 #undef vts
243 #undef vmg
244
245 /*****************************************************************************
246  * DVDLaunchDecoders: select ES for video, audio and spu
247  *****************************************************************************/
248 void DVDLaunchDecoders( input_thread_t * p_input )
249 {
250     thread_dvd_data_t *  p_dvd;
251     unsigned int         i_audio;
252     unsigned int         i_spu;
253
254     p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);
255
256     /* Select Video stream (always 0) */
257     input_SelectES( p_input, p_input->stream.pp_es[0] );
258
259     /* Select audio stream */
260     if( p_dvd->i_audio_nb > 0 )
261     {
262         /* For audio: first one if none or a not existing one specified */
263         i_audio = config_GetInt( p_input, "audio-channel" );
264         if( i_audio <= 0 || i_audio > p_dvd->i_audio_nb )
265         {
266             config_PutInt( p_input, "audio-channel", 1 );
267             i_audio = 1;
268         }
269
270         if( ( config_GetInt( p_input, "audio-type" )
271                == REQUESTED_A52 ) )
272         {
273             int     i_a52 = i_audio;
274             while( ( p_input->stream.pp_es[i_a52]->i_fourcc !=
275                      VLC_FOURCC('a','5','2','b') ) && ( i_a52 <=
276                      p_dvd->p_ifo->vts.manager_inf.i_audio_nb ) )
277             {
278                 i_a52++;
279             }
280             if( p_input->stream.pp_es[i_a52]->i_fourcc
281                  == VLC_FOURCC('a','5','2','b') )
282             {
283                 input_SelectES( p_input,
284                                 p_input->stream.pp_es[i_a52] );
285             }
286         }
287         else
288         {
289             input_SelectES( p_input,
290                             p_input->stream.pp_es[i_audio] );
291         }
292     }
293
294     /* Select subtitle */
295     if( p_dvd->i_spu_nb )
296     {
297         /* for spu, default is none */
298         i_spu = config_GetInt( p_input, "spu-channel" );
299         if( i_spu < 0 || i_spu > p_dvd->i_spu_nb )
300         {
301             config_PutInt( p_input, "spu-channel", 0 );
302             i_spu = 0;
303         }
304         if( i_spu > 0 )
305         {
306             unsigned int i = 0, j = 0;
307             for( i = 0; i < p_input->stream.i_es_number; i++ )
308             {
309                 if ( p_input->stream.pp_es[i]->i_fourcc
310                       == VLC_FOURCC('s','p','u','b') )
311                 {
312                     j++;
313                     if ( i_spu == j ) break;
314                 }
315             }
316             if( i_spu == j )
317             {
318                 input_SelectES( p_input, p_input->stream.pp_es[i] );
319             }
320         }
321     }
322 }