1 /* es.c: functions to find and select ES
2 *****************************************************************************
3 * Copyright (C) 1998-2001 VideoLAN
4 * $Id: es.c,v 1.5 2003/05/05 22:23:32 gbazin Exp $
6 * Author: Stéphane Borel <stef@via.ecp.fr>
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.
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.
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 *****************************************************************************/
23 /*****************************************************************************
25 *****************************************************************************/
31 #include <vlc/input.h>
38 #include <sys/types.h>
43 #ifdef STRNCASECMP_IN_STRINGS_H
50 # include <dvdcss/dvdcss.h>
58 /*****************************************************************************
60 *****************************************************************************/
62 void DVDLaunchDecoders( input_thread_t * p_input );
64 #define vmg p_dvd->p_ifo->vmg
65 #define vts p_dvd->p_ifo->vts
67 #define ADDES( stream_id, private_id, fourcc, cat, lang, descr, size ) \
68 i_id = ( (private_id) << 8 ) | (stream_id); \
71 psz_descr = malloc( strlen(DecodeLanguage( lang )) + \
72 strlen(descr) + 1 ); \
73 if( psz_descr ) {strcpy( psz_descr, DecodeLanguage( lang ) ); \
74 strcat( psz_descr, descr );} \
75 p_es = input_AddES( p_input, NULL, i_id, cat, \
77 if( psz_descr ) free( psz_descr ); \
79 p_es->i_stream_id = (stream_id); \
80 p_es->i_fourcc = (fourcc);
83 /*****************************************************************************
84 * DVDReadVideo: read video ES
85 *****************************************************************************/
86 void DVDReadVideo( input_thread_t * p_input )
88 thread_dvd_data_t * p_dvd;
89 es_descriptor_t * p_es;
93 p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);
95 /* ES 0 -> video MPEG2 */
96 IfoPrintVideo( p_dvd );
97 i_ratio = vts.manager_inf.video_attr.i_ratio;
101 ADDES( 0xe0, 0, VLC_FOURCC('m','p','g','v'), VIDEO_ES, 0,
103 *(int*)(p_es->p_demux_data) = i_ratio;
107 ADDES( 0xe0, 0, VLC_FOURCC('m','p','g','v'), VIDEO_ES, 0, "", 0 );
112 /*****************************************************************************
113 * DVDReadAudio: read audio ES
114 *****************************************************************************/
115 #define audio_status \
116 vts.title_unit.p_title[p_dvd->i_title_id-1].title.pi_audio_status[i-1]
118 void DVDReadAudio( input_thread_t * p_input )
120 thread_dvd_data_t * p_dvd;
121 es_descriptor_t * p_es;
126 p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);
127 p_dvd->i_audio_nb = 0;
129 /* Audio ES, in the order they appear in .ifo */
130 for( i = 1 ; i <= vts.manager_inf.i_audio_nb ; i++ )
132 IfoPrintAudio( p_dvd, i );
134 /* audio channel is active if first byte is 0x80 */
135 if( audio_status.i_available )
138 i_lang = vts.manager_inf.p_audio_attr[i-1].i_lang_code;
139 i_id = audio_status.i_position;
141 switch( vts.manager_inf.p_audio_attr[i-1].i_coding_mode )
144 ADDES( 0xbd, 0x80 + audio_status.i_position,
145 VLC_FOURCC('a','5','2','b'), AUDIO_ES, i_lang,
150 case 0x03: /* MPEG audio */
151 ADDES( 0xc0 + audio_status.i_position, 0,
152 VLC_FOURCC('m','p','g','a'), AUDIO_ES, i_lang,
156 case 0x04: /* LPCM */
157 ADDES( 0xbd, 0xa0 + audio_status.i_position,
158 VLC_FOURCC('l','p','c','b'), AUDIO_ES, i_lang,
163 ADDES( 0xbd, 0x88 + audio_status.i_position,
164 VLC_FOURCC('d','t','s','b'), AUDIO_ES, i_lang,
170 msg_Err( p_input, "unknown audio type %.2x",
171 vts.manager_inf.p_audio_attr[i-1].i_coding_mode );
178 /*****************************************************************************
179 * DVDReadSPU: read subpictures ES
180 *****************************************************************************/
182 vts.title_unit.p_title[p_dvd->i_title_id-1].title.pi_spu_status[i-1]
184 vts.title_unit.p_title[p_dvd->i_title_id-1].title.pi_yuv_color
186 void DVDReadSPU( input_thread_t * p_input )
188 thread_dvd_data_t * p_dvd;
189 es_descriptor_t * p_es;
193 p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);
196 for( i = 1 ; i <= vts.manager_inf.i_spu_nb; i++ )
198 IfoPrintSpu( p_dvd, i );
200 if( spu_status.i_available )
204 /* there are several streams for one spu */
205 if( vts.manager_inf.video_attr.i_ratio )
208 switch( vts.manager_inf.video_attr.i_perm_displ )
211 i_id = spu_status.i_position_pan;
214 i_id = spu_status.i_position_letter;
217 i_id = spu_status.i_position_wide;
224 i_id = spu_status.i_position_43;
227 if( vmg.title.pi_yuv_color )
229 ADDES( 0xbd, 0x20 + i_id, VLC_FOURCC('s','p','u','b'), SPU_ES,
230 vts.manager_inf.p_spu_attr[i-1].i_lang_code, "",
231 sizeof(int) + 16*sizeof(u32) );
232 *(int*)p_es->p_demux_data = 0xBeeF;
233 memcpy( (char*)p_es->p_demux_data + sizeof(int),
234 palette, 16*sizeof(u32) );
238 ADDES( 0xbd, 0x20 + i_id, VLC_FOURCC('s','p','u','b'), SPU_ES,
239 vts.manager_inf.p_spu_attr[i-1].i_lang_code, "", 0 );
250 /*****************************************************************************
251 * DVDLaunchDecoders: select ES for video, audio and spu
252 *****************************************************************************/
253 void DVDLaunchDecoders( input_thread_t * p_input )
255 thread_dvd_data_t * p_dvd;
256 unsigned int i_audio;
259 p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);
261 /* Select Video stream (always 0) */
262 input_SelectES( p_input, p_input->stream.pp_es[0] );
264 /* Select audio stream */
265 if( p_dvd->i_audio_nb > 0 )
267 /* For audio: first one if none or a not existing one specified */
268 i_audio = config_GetInt( p_input, "audio-channel" );
269 if( i_audio <= 0 || i_audio > p_dvd->i_audio_nb )
271 config_PutInt( p_input, "audio-channel", 1 );
275 if( ( config_GetInt( p_input, "audio-type" )
279 while( ( p_input->stream.pp_es[i_a52]->i_fourcc !=
280 VLC_FOURCC('a','5','2','b') ) && ( i_a52 <=
281 p_dvd->p_ifo->vts.manager_inf.i_audio_nb ) )
285 if( p_input->stream.pp_es[i_a52]->i_fourcc
286 == VLC_FOURCC('a','5','2','b') )
288 input_SelectES( p_input,
289 p_input->stream.pp_es[i_a52] );
294 input_SelectES( p_input,
295 p_input->stream.pp_es[i_audio] );
299 /* Select subtitle */
300 if( p_dvd->i_spu_nb )
302 /* for spu, default is none */
303 i_spu = config_GetInt( p_input, "spu-channel" );
304 if( i_spu < 0 || i_spu > p_dvd->i_spu_nb )
306 config_PutInt( p_input, "spu-channel", 0 );
311 unsigned int i = 0, j = 0;
312 for( i = 0; i < p_input->stream.i_es_number; i++ )
314 if ( p_input->stream.pp_es[i]->i_fourcc
315 == VLC_FOURCC('s','p','u','b') )
318 if ( i_spu == j ) break;
323 input_SelectES( p_input, p_input->stream.pp_es[i] );