]> git.sesse.net Git - vlc/blob - plugins/dvdread/input_dvdread.c
*Removed numerous deadlocks.
[vlc] / plugins / dvdread / input_dvdread.c
1 /*****************************************************************************
2  * input_dvdread.c: DvdRead plugin.
3  *****************************************************************************
4  * This plugins should handle all the known specificities of the DVD format,
5  * especially the 2048 bytes logical block size.
6  * It depends on: libdvdread for ifo files and block reading.
7  *****************************************************************************
8  * Copyright (C) 2001 VideoLAN
9  * $Id: input_dvdread.c,v 1.23 2002/03/01 14:17:22 stef Exp $
10  *
11  * Author: Stéphane Borel <stef@via.ecp.fr>
12  *
13  * Some code taken form the play_title.c by Billy Biggs <vektor@dumbterm.net>
14  * in libdvdread.
15  *
16  * This program is free software; you can redistribute it and/or modify
17  * it under the terms of the GNU General Public License as published by
18  * the Free Software Foundation; either version 2 of the License, or
19  * (at your option) any later version.
20  * 
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program; if not, write to the Free Software
28  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
29  *****************************************************************************/
30
31 /*****************************************************************************
32  * Preamble
33  *****************************************************************************/
34 #include <stdio.h>
35 #include <stdlib.h>
36
37 #include <videolan/vlc.h>
38
39 #ifdef HAVE_UNISTD_H
40 #   include <unistd.h>
41 #endif
42
43 #include <fcntl.h>
44 #include <sys/types.h>
45 #include <string.h>
46 #include <errno.h>
47 #include <assert.h>
48
49 #ifdef STRNCASECMP_IN_STRINGS_H
50 #   include <strings.h>
51 #endif
52
53 #if defined( WIN32 )
54 #   include <io.h>                                                 /* read() */
55 #else
56 #   include <sys/uio.h>                                      /* struct iovec */
57 #endif
58
59 #if defined( WIN32 )
60 #   include "input_iovec.h"
61 #endif
62
63 #include "stream_control.h"
64 #include "input_ext-intf.h"
65 #include "input_ext-dec.h"
66 #include "input_ext-plugins.h"
67
68 #include "input_dvdread.h"
69
70 #include "iso_lang.h"
71
72 #include "debug.h"
73
74 /* how many blocks DVDRead will read in each loop */
75 #define DVD_BLOCK_READ_ONCE 64
76
77 /*****************************************************************************
78  * Local prototypes
79  *****************************************************************************/
80 /* called from outside */
81 static int  DvdReadInit     ( struct input_thread_s * );
82 static void DvdReadEnd      ( struct input_thread_s * );
83 static int  DvdReadDemux    ( struct input_thread_s * );
84 static int  DvdReadRewind   ( struct input_thread_s * );
85
86 static int  DvdReadOpen     ( struct input_thread_s * );
87 static void DvdReadClose    ( struct input_thread_s * );
88 static int  DvdReadSetArea  ( struct input_thread_s *, struct input_area_s * );
89 static int  DvdReadSetProgram( struct input_thread_s *, pgrm_descriptor_t * );
90 static int  DvdReadRead     ( struct input_thread_s *, byte_t *, size_t );
91 static void DvdReadSeek     ( struct input_thread_s *, off_t );
92
93 /* called only from here */
94 static void DvdReadLauchDecoders( input_thread_t * p_input );
95 static void DvdReadHandleDSI( thread_dvd_data_t * p_dvd, u8 * p_data );
96 static void DvdReadFindCell ( thread_dvd_data_t * p_dvd );
97
98 /*****************************************************************************
99  * Functions exported as capabilities. They are declared as static so that
100  * we don't pollute the namespace too much.
101  *****************************************************************************/
102 void _M( access_getfunctions )( function_list_t * p_function_list )
103 {
104 #define access p_function_list->functions.access
105     access.pf_open             = DvdReadOpen;
106     access.pf_close            = DvdReadClose;
107     access.pf_read             = DvdReadRead;
108     access.pf_set_area         = DvdReadSetArea;
109     access.pf_set_program      = DvdReadSetProgram;
110     access.pf_seek             = DvdReadSeek;
111 #undef access
112 }
113
114 void _M( demux_getfunctions )( function_list_t * p_function_list )
115 {
116 #define demux p_function_list->functions.demux
117     demux.pf_init             = DvdReadInit;
118     demux.pf_end              = DvdReadEnd;
119     demux.pf_demux            = DvdReadDemux;
120     demux.pf_rewind           = DvdReadRewind;
121 #undef demux
122 }
123
124 /*
125  * Data demux functions
126  */
127
128 /*****************************************************************************
129  * DvdReadInit: initializes DVD structures
130  *****************************************************************************/
131 static int DvdReadInit( input_thread_t * p_input )
132 {
133     if( strncmp( p_input->p_access_module->psz_name, "dvdread", 7 ) )
134     {
135         return -1;
136     }
137
138     vlc_mutex_lock( &p_input->stream.stream_lock );
139     
140     DvdReadLauchDecoders( p_input );
141     
142     vlc_mutex_unlock( &p_input->stream.stream_lock );
143
144     return 0;
145 }
146
147 /*****************************************************************************
148  * DvdReadEnd: frees unused data
149  *****************************************************************************/
150 static void DvdReadEnd( input_thread_t * p_input )
151 {
152 }
153
154 /*****************************************************************************
155  * DvdReadDemux
156  *****************************************************************************/
157 #define PEEK( SIZE )                                                        \
158     i_result = input_Peek( p_input, &p_peek, SIZE );                        \
159     if( i_result == -1 )                                                    \
160     {                                                                       \
161         return( -1 );                                                       \
162     }                                                                       \
163     else if( i_result < SIZE )                                              \
164     {                                                                       \
165         /* EOF */                                                           \
166         return( 0 );                                                        \
167     }
168
169 static int DvdReadDemux( input_thread_t * p_input )
170 {
171     int                 i;
172     byte_t *            p_peek;
173     data_packet_t *     p_data;
174     ssize_t             i_result;
175     int                 i_packet_size;
176
177
178     /* Read headers to compute payload length */
179     for( i = 0 ; i < DVD_BLOCK_READ_ONCE ; i++ )
180     {
181
182         /* Read what we believe to be a packet header. */
183         PEEK( 4 );
184             
185         /* Default header */ 
186         if( U32_AT( p_peek ) != 0x1BA )
187         {
188             /* That's the case for all packets, except pack header. */
189             i_packet_size = U16_AT( p_peek + 4 );
190         }
191         else
192         {
193             /* MPEG-2 Pack header. */
194             i_packet_size = 8;
195         }
196
197         /* Fetch a packet of the appropriate size. */
198         i_result = input_SplitBuffer( p_input, &p_data, i_packet_size + 6 );
199         if( i_result <= 0 )
200         {
201             return( i_result );
202         }
203
204         /* In MPEG-2 pack headers we still have to read stuffing bytes. */
205         if( (p_data->p_demux_start[3] == 0xBA) && (i_packet_size == 8) )
206         {
207             size_t i_stuffing = (p_data->p_demux_start[13] & 0x7);
208             /* Force refill of the input buffer - though we don't care
209              * about p_peek. Please note that this is unoptimized. */
210             PEEK( i_stuffing );
211             p_input->p_current_data += i_stuffing;
212         }
213
214         input_DemuxPS( p_input, p_data );
215      
216     }
217
218     return i;
219 }
220
221 /*****************************************************************************
222  * DVDRewind : reads a stream backward
223  *****************************************************************************/
224 static int DvdReadRewind( input_thread_t * p_input )
225 {
226     return( -1 );
227 }
228
229 /*
230  * Data access functions
231  */
232
233 /*****************************************************************************
234  * DvdReadOpen: open libdvdread
235  *****************************************************************************/
236 static int DvdReadOpen( struct input_thread_s *p_input )
237 {
238     struct stat             stat_info;
239     thread_dvd_data_t *     p_dvd;
240     dvd_reader_t *          p_dvdread;
241     input_area_t *          p_area;
242     int                     i_title;
243     int                     i_chapter;
244     int                     i;
245
246     if( stat( p_input->psz_name, &stat_info ) == -1 )
247     {
248         intf_ErrMsg( "input error: cannot stat() device `%s' (%s)",
249                      p_input->psz_name, strerror(errno));
250         return( -1 );
251     }
252     if( !S_ISBLK(stat_info.st_mode) &&
253         !S_ISCHR(stat_info.st_mode) &&
254         !S_ISDIR(stat_info.st_mode) )
255     {
256         intf_WarnMsg( 3, "input : DvdRead plugin discarded"
257                          " (not a valid source)" );
258         return -1;
259     }
260     
261     p_dvdread = DVDOpen( p_input->psz_name );
262     if( ! p_dvdread )
263     {
264         intf_ErrMsg( "dvdread error: libdvdcss can't open source" );
265         return -1;
266     }
267
268     /* set up input  */
269     p_input->i_mtu = 0;
270
271     p_dvd = malloc( sizeof(thread_dvd_data_t) );
272     if( p_dvd == NULL )
273     {
274         intf_ErrMsg( "dvdread error: out of memory" );
275         return -1;
276     }
277
278     p_dvd->p_dvdread = p_dvdread;
279     p_dvd->p_title = NULL;
280     p_dvd->p_vts_file = NULL;
281
282     p_input->p_access_data = (void *)p_dvd;
283
284     /* Ifo allocation & initialisation */
285     if( ! ( p_dvd->p_vmg_file = ifoOpen( p_dvd->p_dvdread, 0 ) ) )
286     {
287         intf_ErrMsg( "dvdread error: can't open VMG info" );
288         free( p_dvd );
289         return -1;
290     }
291     intf_WarnMsg( 2, "dvdread info: VMG opened" );
292
293     /* Set stream and area data */
294     vlc_mutex_lock( &p_input->stream.stream_lock );
295
296     p_input->stream.i_method = INPUT_METHOD_DVD;
297
298     /* If we are here we can control the pace... */
299     p_input->stream.b_pace_control = 1;
300     p_input->stream.b_seekable = 1;
301     
302     p_input->stream.p_selected_area->i_size = 0;
303     p_input->stream.p_selected_area->i_tell = 0;
304
305     /* Initialize ES structures */
306     input_InitStream( p_input, sizeof( stream_ps_data_t ) );
307
308     /* disc input method */
309     p_input->stream.i_method = INPUT_METHOD_DVD;
310
311 #define tt_srpt p_dvd->p_vmg_file->tt_srpt
312     intf_WarnMsg( 2, "dvdread info: number of titles: %d", tt_srpt->nr_of_srpts );
313
314 #define area p_input->stream.pp_areas
315     /* We start from 1 here since the default area 0
316      * is reserved for video_ts.vob */
317     for( i = 1 ; i <= tt_srpt->nr_of_srpts ; i++ )
318     {
319         input_AddArea( p_input );
320
321         /* Titles are Program Chains */
322         area[i]->i_id = i;
323
324         /* Absolute start offset and size
325          * We can only set that with vts ifo, so we do it during the
326          * first call to DVDSetArea */
327         area[i]->i_start = 0;
328         area[i]->i_size = 0;
329
330         /* Number of chapters */
331         area[i]->i_part_nb = tt_srpt->title[i-1].nr_of_ptts;
332         area[i]->i_part = 1;
333
334         /* Number of angles */
335         area[i]->i_angle_nb = 0;
336         area[i]->i_angle = 1;
337
338         area[i]->i_plugin_data = tt_srpt->title[i-1].title_set_nr;
339     }
340 #undef area
341
342     /* Get requested title - if none try the first title */
343     i_title = config_GetIntVariable( INPUT_TITLE_VAR );
344     if( i_title <= 0 || i_title > tt_srpt->nr_of_srpts )
345     {
346         i_title = 1;
347     }
348
349 #undef tt_srpt
350
351     /* Get requested chapter - if none defaults to first one */
352     i_chapter = config_GetIntVariable( INPUT_CHAPTER_VAR );
353     if( i_chapter <= 0 )
354     {
355         i_chapter = 1;
356     }
357
358     p_input->stream.pp_areas[i_title]->i_part = i_chapter;
359
360     p_area = p_input->stream.pp_areas[i_title];
361
362     /* set title, chapter, audio and subpic */
363     if( DvdReadSetArea( p_input, p_area ) )
364     {
365         vlc_mutex_unlock( &p_input->stream.stream_lock );
366         return -1;
367     }
368
369     vlc_mutex_unlock( &p_input->stream.stream_lock );
370
371     return 0;
372 }
373
374 /*****************************************************************************
375  * DvdReadClose: close libdvdread
376  *****************************************************************************/
377 static void DvdReadClose( struct input_thread_s *p_input )
378 {
379     thread_dvd_data_t *     p_dvd;
380
381     p_dvd = (thread_dvd_data_t *)p_input->p_access_data;
382
383     /* close libdvdread */
384     DVDCloseFile( p_dvd->p_title );
385     ifoClose( p_dvd->p_vts_file );
386     ifoClose( p_dvd->p_vmg_file );
387
388     DVDClose( p_dvd->p_dvdread );
389     free( p_dvd );
390     p_input->p_access_data = NULL;
391
392 }
393
394 /*****************************************************************************
395  * DvdReadSetProgram: Does nothing, a DVD is mono-program
396  *****************************************************************************/
397 static int DvdReadSetProgram( input_thread_t * p_input,
398                               pgrm_descriptor_t * p_program )
399 {
400     return 0;
401 }
402
403 #define p_pgc         p_dvd->p_cur_pgc
404
405 /*****************************************************************************
406  * DvdReadSetArea: initialize input data for title x, chapter y.
407  * It should be called for each user navigation request.
408  *****************************************************************************
409  * Take care that i_title starts from 0 (vmg) and i_chapter start from 1.
410  * Note that you have to take the lock before entering here.
411  *****************************************************************************/
412 static int DvdReadSetArea( input_thread_t * p_input, input_area_t * p_area )
413 {
414     thread_dvd_data_t *  p_dvd;
415     int                  pgc_id = 0;
416     int                  pgn = 0;
417
418     p_dvd = (thread_dvd_data_t*)p_input->p_access_data;
419
420     /* we can't use the interface slider until initilization is complete */
421     p_input->stream.b_seekable = 0;
422
423     if( p_area != p_input->stream.p_selected_area )
424     {
425         es_descriptor_t *    p_es;
426         int                  i_cell = 0;
427         int                  i_audio_nb = 0;
428         int                  i_spu_nb = 0;
429         int                  i;
430
431 #define p_vmg         p_dvd->p_vmg_file
432 #define p_vts         p_dvd->p_vts_file
433         if( p_dvd->p_title != NULL )
434         {
435             DVDCloseFile( p_dvd->p_title );
436         }
437
438         if( p_vts != NULL )
439         {
440             ifoClose( p_vts );
441         }
442
443         /* Reset the Chapter position of the old title */
444         p_input->stream.p_selected_area->i_part = 1;
445
446         /*
447          *  We have to load all title information
448          */
449         /* Change the default area */
450         p_input->stream.p_selected_area = p_area;
451
452         intf_WarnMsg( 12, "dvdread: open VTS %d, for title %d",
453             p_vmg->tt_srpt->title[ p_area->i_id - 1 ].title_set_nr,
454             p_area->i_id );
455
456         /* ifo vts */
457         if( ! ( p_vts = ifoOpen( p_dvd->p_dvdread,
458                 p_vmg->tt_srpt->title[ p_area->i_id - 1 ].title_set_nr ) ) )
459         {
460             intf_ErrMsg( "dvdread error: fatal error in vts ifo" );
461             ifoClose( p_vmg );
462             DVDClose( p_dvd->p_dvdread );
463             return -1;
464         }
465
466         /* title position inside the selected vts */
467         p_dvd->i_ttn = p_vmg->tt_srpt->title[ p_area->i_id - 1 ].vts_ttn;
468
469         /*
470          * Set selected title start
471          */
472         pgc_id = p_vts->vts_ptt_srpt->title[p_dvd->i_ttn-1].ptt[0].pgcn;
473         pgn = p_vts->vts_ptt_srpt->title[p_dvd->i_ttn-1].ptt[0].pgn;
474         p_pgc = p_vts->vts_pgcit->pgci_srp[ pgc_id - 1 ].pgc;
475         i_cell = p_pgc->program_map[ pgn - 1 ] - 1;
476
477         p_area->i_start =
478             LB2OFF( p_dvd->p_cur_pgc->cell_playback[ i_cell ].first_sector );
479
480         intf_WarnMsg( 3, "dvdread: start %d vts_title %d pgc %d pgn %d",
481                          p_area->i_id, p_dvd->i_ttn, pgc_id, pgn );
482
483         /*
484          * Find title end
485          */
486         i_cell = p_dvd->p_cur_pgc->nr_of_cells - 1;
487
488         p_dvd->i_end_block = p_pgc->cell_playback[ i_cell ].last_sector;
489         p_area->i_size = LB2OFF( p_dvd->i_end_block )- p_area->i_start;
490
491         intf_WarnMsg( 12, "dvdread: start %lld size %lld end %d",
492                           p_area->i_start , p_area->i_size, p_dvd->i_end_block );
493
494         /*
495          * Set properties for current chapter
496          */
497         /* Remeber current chapter */
498         p_dvd->i_chapter = p_area->i_part;
499         p_dvd->b_eoc = 0;
500
501         pgc_id = p_vts->vts_ptt_srpt->title[
502                     p_dvd->i_ttn-1].ptt[p_area->i_part-1].pgcn;
503         pgn = p_vts->vts_ptt_srpt->title[
504                     p_dvd->i_ttn-1].ptt[p_area->i_part-1].pgn;
505
506         p_pgc = p_vts->vts_pgcit->pgci_srp[pgc_id-1].pgc;
507         p_dvd->i_pack_len = 0;
508         p_dvd->i_next_cell = p_dvd->i_cur_cell = p_pgc->program_map[pgn-1] - 1;
509         DvdReadFindCell( p_dvd );
510
511         p_dvd->i_next_vobu = p_dvd->i_cur_block =
512             p_pgc->cell_playback[p_dvd->i_cur_cell].first_sector;
513
514         /*
515          * Angle management
516          */
517         p_area->i_angle_nb = p_vmg->tt_srpt->title[p_area->i_id-1].nr_of_angles;
518         p_area->i_angle = config_GetIntVariable( INPUT_ANGLE_VAR );
519
520         if( ( p_area->i_angle <= 0 ) || p_area->i_angle > p_area->i_angle_nb )
521         {
522             p_area->i_angle = 1;
523         }
524         p_dvd->i_angle = p_area->i_angle;
525         p_dvd->i_angle_nb = p_area->i_angle_nb;
526
527         /*
528          * We've got enough info, time to open the title set data.
529          */
530         if( ! ( p_dvd->p_title = DVDOpenFile( p_dvd->p_dvdread,
531             p_vmg->tt_srpt->title[ p_area->i_id - 1 ].title_set_nr,
532             DVD_READ_TITLE_VOBS ) ) )
533         {
534             intf_ErrMsg( "dvdread error: can't open title (VTS_%02d_1.VOB)",
535                          p_vmg->tt_srpt->title[p_area->i_id-1].title_set_nr );
536             ifoClose( p_vts );
537             ifoClose( p_vmg );
538             DVDClose( p_dvd->p_dvdread );
539             return -1;
540         }
541
542 //        IfoPrintTitle( p_dvd );
543
544         /*
545          * Destroy obsolete ES by reinitializing program 0
546          * and find all ES in title with ifo data
547          */
548         if( p_input->stream.pp_programs != NULL )
549         {
550             /* We don't use input_EndStream here since
551              * we keep area structures */
552
553             for( i = 0 ; i < p_input->stream.i_selected_es_number ; i++ )
554             {
555                 input_UnselectES( p_input, p_input->stream.pp_selected_es[i] );
556             }
557
558             free( p_input->stream.pp_selected_es );
559             input_DelProgram( p_input, p_input->stream.p_selected_program );
560
561             p_input->stream.pp_selected_es = NULL;
562             p_input->stream.i_selected_es_number = 0;
563         }
564
565         input_AddProgram( p_input, 0, sizeof( stream_ps_data_t ) );
566         p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
567
568         /* No PSM to read in DVD mode, we already have all information */
569         p_input->stream.p_selected_program->b_is_ok = 1;
570
571         p_es = NULL;
572
573         /* ES 0 -> video MPEG2 */
574 //        IfoPrintVideo( p_dvd );
575
576         p_es = input_AddES( p_input, p_input->stream.p_selected_program, 0xe0, 0 );
577         p_es->i_stream_id = 0xe0;
578         p_es->i_type = MPEG2_VIDEO_ES;
579         p_es->i_cat = VIDEO_ES;
580
581 #define audio_control \
582     p_dvd->p_vts_file->vts_pgcit->pgci_srp[pgc_id-1].pgc->audio_control[i-1]
583         /* Audio ES, in the order they appear in .ifo */
584         for( i = 1 ; i <= p_vts->vtsi_mat->nr_of_vts_audio_streams ; i++ )
585         {
586             int i_position = 0;
587             u16 i_id;
588
589 //            IfoPrintAudio( p_dvd, i );
590
591             /* audio channel is active if first byte is 0x80 */
592             if( audio_control & 0x8000 )
593             {
594                 i_audio_nb++;
595                 i_position = ( audio_control & 0x7F00 ) >> 8;
596
597             intf_WarnMsg( 12, "dvd audio position  %d", i_position );
598                 switch( p_vts->vtsi_mat->vts_audio_attr[i-1].audio_format )
599                 {
600                 case 0x00:              /* AC3 */
601                     i_id = ( ( 0x80 + i_position ) << 8 ) | 0xbd;
602                     p_es = input_AddES( p_input,
603                                p_input->stream.p_selected_program, i_id, 0 );
604                     p_es->i_stream_id = 0xbd;
605                     p_es->i_type = AC3_AUDIO_ES;
606                     p_es->b_audio = 1;
607                     p_es->i_cat = AUDIO_ES;
608                     strcpy( p_es->psz_desc, DecodeLanguage( hton16(
609                         p_vts->vtsi_mat->vts_audio_attr[i-1].lang_code ) ) ); 
610                     strcat( p_es->psz_desc, " (ac3)" );
611
612                     break;
613                 case 0x02:
614                 case 0x03:              /* MPEG audio */
615                     i_id = 0xc0 + i_position;
616                     p_es = input_AddES( p_input,
617                                     p_input->stream.p_selected_program, i_id, 0 );
618                     p_es->i_stream_id = i_id;
619                     p_es->i_type = MPEG2_AUDIO_ES;
620                     p_es->b_audio = 1;
621                     p_es->i_cat = AUDIO_ES;
622                     strcpy( p_es->psz_desc, DecodeLanguage( hton16(
623                         p_vts->vtsi_mat->vts_audio_attr[i-1].lang_code ) ) ); 
624                     strcat( p_es->psz_desc, " (mpeg)" );
625
626                     break;
627                 case 0x04:              /* LPCM */
628
629                     i_id = ( ( 0xa0 + i_position ) << 8 ) | 0xbd;
630                     p_es = input_AddES( p_input,
631                                     p_input->stream.p_selected_program, i_id, 0 );
632                     p_es->i_stream_id = i_id;
633                     p_es->i_type = LPCM_AUDIO_ES;
634                     p_es->b_audio = 1;
635                     p_es->i_cat = AUDIO_ES;
636                     strcpy( p_es->psz_desc, DecodeLanguage( hton16(
637                         p_vts->vtsi_mat->vts_audio_attr[i-1].lang_code ) ) ); 
638                     strcat( p_es->psz_desc, " (lpcm)" );
639
640                     break;
641                 case 0x06:              /* DTS */
642                     i_id = ( ( 0x88 + i_position ) << 8 ) | 0xbd;
643                     intf_ErrMsg( "dvd warning: DTS audio not handled yet"
644                                  "(0x%x)", i_id );
645                     break;
646                 default:
647                     i_id = 0;
648                     intf_ErrMsg( "dvd warning: unknown audio type %.2x",
649                              p_vts->vtsi_mat->vts_audio_attr[i-1].audio_format );
650                 }
651             }
652         }
653 #undef audio_control
654 #define spu_control \
655     p_dvd->p_vts_file->vts_pgcit->pgci_srp[pgc_id-1].pgc->subp_control[i-1]
656
657         /* Sub Picture ES */
658
659         for( i = 1 ; i <= p_vts->vtsi_mat->nr_of_vts_subp_streams; i++ )
660         {
661             int i_position = 0;
662             u16 i_id;
663
664 //            IfoPrintSpu( p_dvd, i );
665             intf_WarnMsg( 12, "dvd spu %d 0x%02x", i, spu_control );
666
667             if( spu_control & 0x80000000 )
668             {
669                 i_spu_nb++;
670
671                 /*  there are several streams for one spu */
672                 if(  p_vts->vtsi_mat->vts_video_attr.display_aspect_ratio )
673                 {
674                     /* 16:9 */
675                     switch( p_vts->vtsi_mat->vts_video_attr.permitted_df )
676                     {
677                     case 1:
678                         i_position = spu_control & 0xff;
679                         break;
680                     case 2:
681                         i_position = ( spu_control >> 8 ) & 0xff;
682                         break;
683                     default:
684                         i_position = ( spu_control >> 16 ) & 0xff;
685                         break;
686                     }
687                 }
688                 else
689                 {
690                     /* 4:3 */
691                     i_position = ( spu_control >> 24 ) & 0x7F;
692                 }
693
694                 i_id = ( ( 0x20 + i_position ) << 8 ) | 0xbd;
695                 p_es = input_AddES( p_input,
696                                     p_input->stream.p_selected_program, i_id, 0 );
697                 p_es->i_stream_id = 0xbd;
698                 p_es->i_type = DVD_SPU_ES;
699                 p_es->i_cat = SPU_ES;
700                 strcpy( p_es->psz_desc, DecodeLanguage( hton16(
701                     p_vts->vtsi_mat->vts_subp_attr[i-1].lang_code ) ) ); 
702             }
703         }
704 #undef spu_control
705
706         /* FIXME: hack to check that the demuxer is ready, and set
707          * the decoders */
708         if( p_input->p_demux_module )
709         {
710             DvdReadLauchDecoders( p_input );
711         }
712             
713     } /* i_title >= 0 */
714     else
715     {
716         p_area = p_input->stream.p_selected_area;
717     }
718
719     /*
720      * Chapter selection
721      */
722
723     if( p_area->i_part != p_dvd->i_chapter )
724     {
725         if( ( p_area->i_part > 0 ) &&
726             ( p_area->i_part <= p_area->i_part_nb ))
727         {
728             p_dvd->i_ttn = p_vmg->tt_srpt->title[p_area->i_id-1].vts_ttn;
729             pgc_id = p_vts->vts_ptt_srpt->title[
730                         p_dvd->i_ttn-1].ptt[p_area->i_part-1].pgcn;
731             pgn = p_vts->vts_ptt_srpt->title[
732                         p_dvd->i_ttn-1].ptt[p_area->i_part-1].pgn;
733
734             p_pgc = p_vts->vts_pgcit->pgci_srp[ pgc_id - 1 ].pgc;
735
736             p_dvd->i_cur_cell = p_pgc->program_map[ pgn - 1 ] - 1;
737             p_dvd->i_chapter = p_area->i_part;
738             DvdReadFindCell( p_dvd );
739
740             p_dvd->i_pack_len = 0;
741             p_dvd->i_next_vobu = p_dvd->i_cur_block =
742                     p_pgc->cell_playback[p_dvd->i_cur_cell].first_sector;
743         }
744         else
745         {
746             p_area->i_part = p_dvd->i_chapter;
747         }
748     }
749 #undef p_vts
750 #undef p_vmg
751
752     if( p_area->i_angle != p_dvd->i_angle )
753     {
754         p_dvd->i_angle = p_area->i_angle;
755
756         intf_WarnMsg( 3, "dvd info: angle %d selected", p_area->i_angle );
757     }
758     /* warn interface that something has changed */
759     p_area->i_tell = LB2OFF( p_dvd->i_next_vobu ) - p_area->i_start;
760     p_input->stream.b_seekable = 1;
761     p_input->stream.b_changed = 1;
762
763     return 0;
764 }
765
766
767 /*****************************************************************************
768  * DvdReadRead: reads data packets into the netlist.
769  *****************************************************************************
770  * Returns -1 in case of error, 0 if everything went well, and 1 in case of
771  * EOF.
772  *****************************************************************************/
773 static int DvdReadRead( input_thread_t * p_input,
774                         byte_t * p_buffer, size_t i_count )
775 {
776     thread_dvd_data_t *     p_dvd;
777     byte_t *                p_buf;
778     int                     i_blocks_once;
779     int                     i_blocks;
780     int                     i_read;
781     int                     i_read_total;
782     boolean_t               b_eot = 0;
783
784     p_dvd = (thread_dvd_data_t *)p_input->p_access_data;
785     p_buf = p_buffer;
786
787     /*
788      * Playback by cell in this pgc, starting at the cell for our chapter.
789      */
790     i_blocks = OFF2LB( i_count );
791     i_read_total = 0;
792     i_read = 0;
793
794     while( i_blocks )
795     {
796         /* 
797          * End of pack, we select the following one
798          */
799         if( ! p_dvd->i_pack_len )
800         {
801             /*
802              * Read NAV packet.
803              */
804             if( ( i_read = DVDReadBlocks( p_dvd->p_title, p_dvd->i_next_vobu,
805                            1, p_buf ) ) != 1 )
806             {
807                 intf_ErrMsg( "dvdread error: read failed for block %d",
808                              p_dvd->i_next_vobu );
809                 return -1;
810             }
811
812             /* basic check to be sure we don't have a empty title
813              * go to next title if so */
814             //assert( p_buffer[41] == 0xbf && p_buffer[1027] == 0xbf );
815             
816             /*
817              * Parse the contained dsi packet.
818              */
819
820             DvdReadHandleDSI( p_dvd, p_buf );
821
822             /* End of File */
823             if( p_dvd->i_next_vobu >= p_dvd->i_end_block + 1 )
824             {
825                 return 1;
826             }
827
828             assert( p_dvd->i_pack_len < 1024 );
829             /* FIXME: Ugly kludge: we send the pack block to the input for it
830              * sometimes has a zero scr and restart the sync */
831             p_dvd->i_cur_block ++;
832             //p_dvd->i_pack_len++;
833
834             i_read_total++;
835             p_buf += DVD_VIDEO_LB_LEN;
836             i_blocks--;
837         }
838
839         /*
840          * Compute the number of blocks to read
841          */
842         i_blocks_once = p_dvd->i_pack_len >= i_blocks
843                  ? i_blocks : p_dvd->i_pack_len;
844         p_dvd->i_pack_len -= i_blocks_once;
845
846         /* Reads from DVD */
847         i_read = DVDReadBlocks( p_dvd->p_title, p_dvd->i_cur_block,
848                                 i_blocks_once, p_buf );
849         if( i_read != i_blocks_once )
850         {
851             intf_ErrMsg( "dvdread error: read failed for %d/%d blocks at 0x%02x",
852                          i_read, i_blocks_once, p_dvd->i_cur_block );
853             return -1;
854         }
855
856         i_blocks -= i_read;
857         i_read_total += i_read;
858         p_dvd->i_cur_block += i_read;
859         p_buf += LB2OFF( i_read );
860
861     }
862 /*
863     intf_WarnMsg( 12, "dvdread i_blocks: %d len: %d current: 0x%02x", i_read, p_dvd->i_pack_len, p_dvd->i_cur_block );
864 */
865
866     vlc_mutex_lock( &p_input->stream.stream_lock );
867
868     p_input->stream.p_selected_area->i_tell =
869         LB2OFF( p_dvd->i_cur_block ) -
870             p_input->stream.p_selected_area->i_start;
871
872     if( p_dvd->b_eoc )
873     {
874         /* We modify i_part only at end of chapter not to erase
875          * some modification from the interface */
876         p_input->stream.p_selected_area->i_part = p_dvd->i_chapter;
877         p_dvd->b_eoc = 0;
878     }
879     
880     if( p_input->stream.p_selected_area->i_tell
881             >= p_input->stream.p_selected_area->i_size || b_eot )
882     {
883         if( ( p_input->stream.p_selected_area->i_id + 1 ) >= 
884                         p_input->stream.i_area_nb )
885         {
886             /* EOF */
887             vlc_mutex_unlock( &p_input->stream.stream_lock );
888             return 1;
889         }
890
891         /* EOT */
892         intf_WarnMsg( 4, "dvd info: new title" );
893         DvdReadSetArea( p_input, p_input->stream.pp_areas[
894                         p_input->stream.p_selected_area->i_id+1] );
895         vlc_mutex_unlock( &p_input->stream.stream_lock );
896         return 0;
897     }
898
899     vlc_mutex_unlock( &p_input->stream.stream_lock );
900
901     return LB2OFF( i_read_total );
902 }
903 #undef p_pgc
904
905 /*****************************************************************************
906  * DvdReadSeek : Goes to a given position on the stream.
907  *****************************************************************************
908  * This one is used by the input and translate chronological position from
909  * input to logical position on the device.
910  * The lock should be taken before calling this function.
911  *****************************************************************************/
912 static void DvdReadSeek( input_thread_t * p_input, off_t i_off )
913 {
914     thread_dvd_data_t *     p_dvd;
915     int                     i_lb;
916     int                     i_tmp;
917     int                     i_chapter = 0;
918     int                     i_cell = 0;
919     int                     i_vobu = 0;
920     int                     i_sub_cell = 0;
921
922     vlc_mutex_lock( &p_input->stream.stream_lock );
923     i_off += p_input->stream.p_selected_area->i_start;
924     vlc_mutex_unlock( &p_input->stream.stream_lock );
925     
926     i_lb = OFF2LB( i_off );
927     p_dvd = ( thread_dvd_data_t * )p_input->p_access_data;
928
929     /* find cell */
930     while( p_dvd->p_cur_pgc->cell_playback[i_cell].last_sector < i_lb )
931     {
932         i_cell++;
933     }
934
935     /* find chapter */
936     do
937     {
938         pgc_t *     p_pgc;
939         int         pgc_id, pgn;
940
941         i_chapter++;
942         pgc_id = p_dvd->p_vts_file->vts_ptt_srpt->title[
943                     p_dvd->i_ttn-1].ptt[i_chapter-1].pgcn;
944         pgn = p_dvd->p_vts_file->vts_ptt_srpt->title[
945                     p_dvd->i_ttn-1].ptt[i_chapter-1].pgn;
946
947         p_pgc = p_dvd->p_vts_file->vts_pgcit->pgci_srp[pgc_id-1].pgc;
948         i_tmp = p_pgc->program_map[pgn-1];
949
950     } while( i_tmp <= i_cell );
951
952     /* find vobu */
953     while( p_dvd->p_vts_file->vts_vobu_admap->vobu_start_sectors[i_vobu]
954             <= i_lb )
955     {
956         i_vobu++;
957     }
958
959     /* find sub_cell */
960     while( p_dvd->p_vts_file->vts_c_adt->cell_adr_table[i_sub_cell].start_sector <
961             p_dvd->p_vts_file->vts_vobu_admap->vobu_start_sectors[i_vobu-1] )
962     {
963         i_sub_cell++;
964     }
965
966 /*
967     intf_WarnMsg(12, "cell %d i_sub_cell %d chapter %d vobu %d cell_sector %d vobu_sector %d sub_cell_sector %d",
968             i_cell, i_sub_cell,i_chapter, i_vobu,
969             p_dvd->p_cur_pgc->cell_playback[i_cell].first_sector,
970             p_dvd->p_vts_file->vts_vobu_admap->vobu_start_sectors[i_vobu],
971             p_dvd->p_vts_file->vts_c_adt->cell_adr_table[i_sub_cell-1].start_sector);
972 */
973     p_dvd->i_cur_block = i_lb;
974     p_dvd->i_next_vobu =
975         p_dvd->p_vts_file->vts_vobu_admap->vobu_start_sectors[i_vobu];
976     p_dvd->i_pack_len = p_dvd->i_next_vobu - i_lb;
977     p_dvd->i_cur_cell = i_cell;
978     p_dvd->i_chapter = i_chapter;
979     DvdReadFindCell( p_dvd );
980
981     vlc_mutex_lock( &p_input->stream.stream_lock );
982     p_input->stream.p_selected_area->i_tell =
983         LB2OFF ( p_dvd->i_cur_block )
984          - p_input->stream.p_selected_area->i_start;
985     p_input->stream.p_selected_area->i_part = p_dvd->i_chapter;
986     vlc_mutex_unlock( &p_input->stream.stream_lock );
987
988     return;
989 }
990
991 /*****************************************************************************
992  * DvdReadHandleDSI
993  *****************************************************************************/
994 static void DvdReadHandleDSI( thread_dvd_data_t * p_dvd, u8 * p_data )
995 {
996     navRead_DSI( &(p_dvd->dsi_pack), &(p_data[ DSI_START_BYTE ]) );
997
998     /*
999      * Determine where we go next.  These values are the ones we mostly
1000      * care about.
1001      */
1002     p_dvd->i_cur_block = p_dvd->dsi_pack.dsi_gi.nv_pck_lbn;
1003
1004     /*
1005      * If we're not at the end of this cell, we can determine the next
1006      * VOBU to display using the VOBU_SRI information section of the
1007      * DSI.  Using this value correctly follows the current angle,
1008      * avoiding the doubled scenes in The Matrix, and makes our life
1009      * really happy.
1010      */
1011     if( p_dvd->dsi_pack.vobu_sri.next_vobu != SRI_END_OF_CELL )
1012     {
1013 #if 1
1014         switch( ( p_dvd->dsi_pack.sml_pbi.category & 0xf000 ) >> 12 )
1015         {
1016             case 0x4:
1017                 /* interleaved unit with no angle */
1018                 if( p_dvd->dsi_pack.sml_pbi.ilvu_sa != -1 )
1019                 {
1020                     p_dvd->i_next_vobu = p_dvd->i_cur_block +
1021                         p_dvd->dsi_pack.sml_pbi.ilvu_sa;
1022                     p_dvd->i_pack_len = p_dvd->dsi_pack.sml_pbi.ilvu_ea;
1023                 }
1024                 else
1025                 {
1026                     p_dvd->i_next_vobu = p_dvd->i_cur_block +
1027                         p_dvd->dsi_pack.dsi_gi.vobu_ea + 1;
1028                     p_dvd->i_pack_len = p_dvd->dsi_pack.dsi_gi.vobu_ea;
1029                 }
1030                 break;
1031             case 0x5:
1032                 /* vobu is end of ilvu */
1033                 if( p_dvd->dsi_pack.sml_agli.data[p_dvd->i_angle-1].address )
1034                 {
1035                     p_dvd->i_next_vobu = p_dvd->i_cur_block +
1036                         p_dvd->dsi_pack.sml_agli.data[p_dvd->i_angle-1].address;
1037                     p_dvd->i_pack_len = p_dvd->dsi_pack.sml_pbi.ilvu_ea;
1038
1039                     break;
1040                 }
1041             case 0x6:
1042                 /* vobu is beginning of ilvu */
1043             case 0x9:
1044                 /* next scr is 0 */
1045             case 0xa:
1046                 /* entering interleaved section */
1047             case 0x8:
1048                 /* non interleaved cells in interleaved section */
1049             default:
1050                 p_dvd->i_next_vobu = p_dvd->i_cur_block +
1051                     ( p_dvd->dsi_pack.vobu_sri.next_vobu & 0x7fffffff );
1052                 p_dvd->i_pack_len = p_dvd->dsi_pack.dsi_gi.vobu_ea;
1053                 break;
1054         }
1055 #else
1056         p_dvd->i_next_vobu = p_dvd->i_cur_block +
1057             ( p_dvd->dsi_pack.vobu_sri.next_vobu & 0x7fffffff );
1058         p_dvd->i_pack_len = p_dvd->dsi_pack.dsi_gi.vobu_ea;
1059 #endif
1060     }
1061     else
1062     {
1063         p_dvd->i_cur_cell = p_dvd->i_next_cell;
1064         DvdReadFindCell( p_dvd );
1065
1066         p_dvd->i_pack_len = p_dvd->dsi_pack.dsi_gi.vobu_ea;
1067         p_dvd->i_next_vobu =
1068             p_dvd->p_cur_pgc->cell_playback[p_dvd->i_cur_cell].first_sector;
1069     }
1070
1071 #if 0
1072     intf_WarnMsg( 12, "scr %d lbn 0x%02x vobu_ea %d vob_id %d c_id %d",
1073             p_dvd->dsi_pack.dsi_gi.nv_pck_scr,
1074             p_dvd->dsi_pack.dsi_gi.nv_pck_lbn,
1075             p_dvd->dsi_pack.dsi_gi.vobu_ea,
1076             p_dvd->dsi_pack.dsi_gi.vobu_vob_idn,
1077             p_dvd->dsi_pack.dsi_gi.vobu_c_idn );
1078
1079     intf_WarnMsg( 12, "cat 0x%02x ilvu_ea %d ilvu_sa %d size %d", 
1080             p_dvd->dsi_pack.sml_pbi.category,
1081             p_dvd->dsi_pack.sml_pbi.ilvu_ea,
1082             p_dvd->dsi_pack.sml_pbi.ilvu_sa,
1083             p_dvd->dsi_pack.sml_pbi.size );
1084
1085     intf_WarnMsg( 12, "next_vobu %d next_ilvu1 %d next_ilvu2 %d",
1086             p_dvd->dsi_pack.vobu_sri.next_vobu & 0x7fffffff,
1087             p_dvd->dsi_pack.sml_agli.data[ p_dvd->i_angle - 1 ].address,
1088             p_dvd->dsi_pack.sml_agli.data[ p_dvd->i_angle ].address);
1089 #endif
1090 }
1091
1092 /*****************************************************************************
1093  * DvdReadFindCell
1094  *****************************************************************************/
1095 static void DvdReadFindCell( thread_dvd_data_t * p_dvd )
1096 {
1097     int         pgc_id, pgn;
1098     int         i = 0;
1099     pgc_t *     p_pgc;
1100 #define cell p_dvd->p_cur_pgc->cell_playback
1101     if( cell[p_dvd->i_cur_cell].block_type == BLOCK_TYPE_ANGLE_BLOCK )
1102     {
1103 #if 0
1104         p_dvd->i_next_cell = p_dvd->i_cur_cell + p_dvd->i_angle_nb;
1105         p_dvd->i_cur_cell += p_dvd->i_angle - 1;
1106 #else
1107         p_dvd->i_cur_cell += p_dvd->i_angle - 1;
1108
1109         while( cell[p_dvd->i_cur_cell+i].block_mode != BLOCK_MODE_LAST_CELL )
1110         {
1111             i++;
1112         }
1113         p_dvd->i_next_cell = p_dvd->i_cur_cell + i + 1;
1114 #endif
1115     }
1116     else
1117     {
1118         p_dvd->i_next_cell = p_dvd->i_cur_cell + 1;
1119     }
1120 #undef cell
1121     pgc_id = p_dvd->p_vts_file->vts_ptt_srpt->title[
1122                 p_dvd->i_ttn-1].ptt[p_dvd->i_chapter-1].pgcn;
1123     pgn = p_dvd->p_vts_file->vts_ptt_srpt->title[
1124                 p_dvd->i_ttn-1].ptt[p_dvd->i_chapter-1].pgn;
1125     p_pgc = p_dvd->p_vts_file->vts_pgcit->pgci_srp[pgc_id-1].pgc;
1126
1127     if( p_pgc->program_map[pgn-1] <= p_dvd->i_cur_cell )
1128     {
1129         p_dvd->i_chapter++;
1130         p_dvd->b_eoc = 1;
1131     }
1132 }
1133
1134 /*****************************************************************************
1135  * DvdReadLaunchDecoders
1136  *****************************************************************************/
1137 static void DvdReadLauchDecoders( input_thread_t * p_input )
1138 {
1139     thread_dvd_data_t *  p_dvd;
1140     
1141     p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);            
1142             
1143     if( p_main->b_video )
1144     {
1145         input_SelectES( p_input, p_input->stream.pp_es[0] );
1146     }
1147
1148     if( p_main->b_audio )
1149     {
1150         /* For audio: first one if none or a not existing one specified */
1151         int i_audio = config_GetIntVariable( INPUT_CHANNEL_VAR );
1152         if( i_audio < 0 /*|| i_audio > i_audio_nb*/ )
1153         {
1154             config_PutIntVariable( INPUT_CHANNEL_VAR, 1 );
1155             i_audio = 1;
1156         }
1157         if( i_audio > 0/* && i_audio_nb > 0*/ )
1158         {
1159             if( config_GetIntVariable( AOUT_SPDIF_VAR ) ||
1160                 ( config_GetIntVariable( INPUT_AUDIO_VAR ) ==
1161                   REQUESTED_AC3 ) )
1162             {
1163                 int     i_ac3 = i_audio;
1164                 while( ( p_input->stream.pp_es[i_ac3]->i_type !=
1165                        AC3_AUDIO_ES ) && ( i_ac3 <=
1166                        p_dvd->p_vts_file->vtsi_mat->nr_of_vts_audio_streams ) )
1167                 {
1168                     i_ac3++;
1169                 }
1170                 if( p_input->stream.pp_es[i_ac3]->i_type == AC3_AUDIO_ES )
1171                 {
1172                     input_SelectES( p_input,
1173                                     p_input->stream.pp_es[i_ac3] );
1174                 }
1175             }
1176             else
1177             {
1178                 input_SelectES( p_input,
1179                                 p_input->stream.pp_es[i_audio] );
1180             }
1181         }
1182     }
1183
1184     if( p_main->b_video )
1185     {
1186         /* for spu, default is none */
1187         int i_spu = config_GetIntVariable( INPUT_SUBTITLE_VAR );
1188         if( i_spu < 0 /*|| i_spu > i_spu_nb*/ )
1189         {
1190             config_PutIntVariable( INPUT_SUBTITLE_VAR, 0 );
1191             i_spu = 0;
1192         }
1193         if( i_spu > 0 /*&& i_spu_nb > 0*/ )
1194         {
1195             i_spu += p_dvd->p_vts_file->vtsi_mat->nr_of_vts_audio_streams;
1196             input_SelectES( p_input, p_input->stream.pp_es[i_spu] );
1197         }
1198     }
1199 }