1 /*****************************************************************************
2 * es.c: functions to handle elementary streams.
3 *****************************************************************************
4 * Copyright (C) 2001 VideoLAN
5 * $Id: es.c,v 1.6 2003/05/05 22:23:32 gbazin Exp $
7 * Author: Stéphane Borel <stef@via.ecp.fr>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
31 #include <vlc/input.h>
38 #include <sys/types.h>
43 #ifdef STRNCASECMP_IN_STRINGS_H
50 void dvdplay_LaunchDecoders( input_thread_t * p_input );
52 /*****************************************************************************
54 *****************************************************************************/
55 void dvdplay_DeleteES( input_thread_t* p_input )
57 free( p_input->stream.pp_selected_es );
59 p_input->stream.pp_selected_es = NULL;
60 p_input->stream.i_selected_es_number = 0;
62 while( p_input->stream.i_es_number )
64 input_DelES( p_input, p_input->stream.pp_es[0] );
67 free( p_input->stream.pp_es );
69 p_input->stream.pp_es = NULL;
70 p_input->stream.i_es_number = 0;
74 #define ADDES( id, fourcc, cat, lang, descr, size ) \
75 msg_Dbg( p_input, "new es 0x%x", i_id ); \
78 psz_descr = malloc( strlen(DecodeLanguage( lang )) + \
79 strlen(descr) + 1 ); \
80 if( psz_descr ) {strcpy( psz_descr, DecodeLanguage( lang ) ); \
81 strcat( psz_descr, descr );} \
82 p_es = input_AddES( p_input, NULL, id, cat, \
84 if( psz_descr ) free( psz_descr ); \
86 p_es->i_stream_id = i_id & 0xff; \
87 p_es->i_fourcc = (fourcc);
89 /*****************************************************************************
90 * dvdplay_Video: read video ES
91 *****************************************************************************/
92 void dvdplay_Video( input_thread_t * p_input )
95 es_descriptor_t * p_es;
96 video_attr_t * p_attr;
99 p_dvd = (dvd_data_t*)(p_input->p_access_data);
100 p_attr = dvdplay_video_attr( p_dvd->vmg );
102 /* ES 0 -> video MPEG2 */
105 if( p_attr->display_aspect_ratio )
107 ADDES( 0xe0, VLC_FOURCC('m','p','g','v'), VIDEO_ES, 0,
109 *(int*)(p_es->p_demux_data) = p_attr->display_aspect_ratio;
113 ADDES( 0xe0, VLC_FOURCC('m','p','g','v'), VIDEO_ES, 0, "", 0 );
118 /*****************************************************************************
119 * dvdplay_Audio: read audio ES
120 *****************************************************************************/
121 void dvdplay_Audio( input_thread_t * p_input )
124 es_descriptor_t * p_es;
125 audio_attr_t * p_attr;
133 p_dvd = (dvd_data_t*)(p_input->p_access_data);
134 p_dvd->i_audio_nb = 0;
135 dvdplay_audio_info( p_dvd->vmg, &i_audio_nr, &i_audio );
137 /* Audio ES, in the order they appear in .ifo */
138 for( i = 1 ; i <= i_audio_nr ; i++ )
140 if( ( i_id = dvdplay_audio_id( p_dvd->vmg, i-1 ) ) > 0 )
142 p_attr = dvdplay_audio_attr( p_dvd->vmg, i-1 );
143 i_channels = p_attr->channels;
144 i_lang = p_attr->lang_code;
148 switch( p_attr->audio_format )
151 ADDES( i_id, VLC_FOURCC('a','5','2','b'), AUDIO_ES, i_lang,
156 case 0x03: /* MPEG audio */
157 ADDES( i_id, VLC_FOURCC('m','p','g','a'), AUDIO_ES, i_lang,
161 case 0x04: /* LPCM */
162 ADDES( i_id, VLC_FOURCC('l','p','c','b'), AUDIO_ES, i_lang,
166 case 0x05: /* SDDS */
167 ADDES( i_id, VLC_FOURCC('s','d','d','b'), AUDIO_ES, i_lang,
172 ADDES( i_id, VLC_FOURCC('d','t','s','b'), AUDIO_ES, i_lang,
178 msg_Warn( p_input, "unknown audio type %.2x",
179 p_attr->audio_format );
185 /*****************************************************************************
186 * dvdplay_Subp: read subpictures ES
187 *****************************************************************************/
188 void dvdplay_Subp( input_thread_t * p_input )
191 es_descriptor_t * p_es;
192 subp_attr_t * p_attr;
199 p_dvd = (dvd_data_t*)(p_input->p_access_data);
202 dvdplay_subp_info( p_dvd->vmg, &i_subp_nr, &i_subp );
203 pi_palette = dvdplay_subp_palette( p_dvd->vmg );
205 for( i = 1 ; i <= i_subp_nr; i++ )
207 if( ( i_id = dvdplay_subp_id( p_dvd->vmg, i-1 ) ) >= 0 )
209 p_attr = dvdplay_subp_attr( p_dvd->vmg, i-1 );
214 ADDES( i_id, VLC_FOURCC('s','p','u','b'), SPU_ES,
215 p_attr->lang_code, "", sizeof(int) + 16*sizeof(u32) );
216 *(int*)p_es->p_demux_data = 0xBeeF;
217 memcpy( (void*)p_es->p_demux_data + sizeof(int),
218 pi_palette, 16*sizeof(u32) );
222 ADDES( i_id, VLC_FOURCC('s','p','u','b'), SPU_ES,
223 p_attr->lang_code, "", 0 );
229 /*****************************************************************************
230 * dvdplay_LaunchDecoders
231 *****************************************************************************/
232 void dvdplay_LaunchDecoders( input_thread_t * p_input )
240 p_dvd = (dvd_data_t*)(p_input->p_access_data);
242 /* For audio: check user settings first, then check dvdplay settings. */
243 i_audio = config_GetInt( p_input, "audio-channel" );
244 if( i_audio <= 0 || i_audio > p_dvd->i_audio_nb )
246 /* if i_audio = -1 dvdplay_audio_info() will select a default channel,
247 * otherwise it warns libdvdplay that we have chosen another stream. */
250 dvdplay_audio_info( p_dvd->vmg, &i_audio_nr, &i_audio );
252 /* For spu: check user settings first, the check dvdplay settings. */
253 i_subp = config_GetInt( p_input, "spu-channel" );
254 if( i_subp <= 0 || i_subp > p_dvd->i_spu_nb )
258 dvdplay_subp_info( p_dvd->vmg, &i_subp_nr, &i_subp );
260 input_SelectES( p_input, p_input->stream.pp_es[0] );
262 if( i_audio > p_dvd->i_audio_nb ) i_audio = 1;
263 if( ( i_audio > 0 ) && ( p_dvd->i_audio_nb > 0 ) )
265 if( config_GetInt( p_input, "audio-type" ) == REQUESTED_A52 )
269 while( ( i_a52 < p_dvd->i_audio_nb ) &&
270 ( p_input->stream.pp_es[i_a52]->i_fourcc !=
271 VLC_FOURCC('a','5','2','b') ) )
275 if( p_input->stream.pp_es[i_a52]->i_fourcc ==
276 VLC_FOURCC('a','5','2','b') )
278 input_SelectES( p_input,
279 p_input->stream.pp_es[i_a52] );
281 /* warn libdvdplay that we have chosen another stream */
282 dvdplay_audio_info( p_dvd->vmg, &i_audio_nr, &i_a52 );
286 /* none found, select the default one */
287 input_SelectES( p_input,
288 p_input->stream.pp_es[i_audio] );
293 input_SelectES( p_input,
294 p_input->stream.pp_es[i_audio] );
298 if( i_subp > p_dvd->i_spu_nb ) i_subp = -1;
299 if( ( i_subp > 0 ) && ( p_dvd->i_spu_nb > 0 ) )
301 i_subp += p_dvd->i_audio_nb;
302 input_SelectES( p_input, p_input->stream.pp_es[i_subp] );
306 /*****************************************************************************
308 *****************************************************************************/
309 void dvdplay_ES( input_thread_t * p_input )
311 dvdplay_DeleteES ( p_input );
312 dvdplay_Video ( p_input );
313 dvdplay_Audio ( p_input );
314 dvdplay_Subp ( p_input );
315 dvdplay_LaunchDecoders( p_input );