]> git.sesse.net Git - vlc/blob - plugins/dvd/input_dvd.c
* Fixed DVD input under Win32.
[vlc] / plugins / dvd / input_dvd.c
1 /* input_dvd.c: DVD raw reading plugin.
2  *****************************************************************************
3  * This plugins should handle all the known specificities of the DVD format,
4  * especially the 2048 bytes logical block size.
5  * It depends on:
6  *  -libdvdcss for access and unscrambling
7  *  -dvd_ifo for ifo parsing and analyse
8  *  -dvd_udf to find files
9  *****************************************************************************
10  * Copyright (C) 1998-2001 VideoLAN
11  * $Id: input_dvd.c,v 1.126 2002/03/03 17:34:27 xav Exp $
12  *
13  * Author: Stéphane Borel <stef@via.ecp.fr>
14  *
15  * This program is free software; you can redistribute it and/or modify
16  * it under the terms of the GNU General Public License as published by
17  * the Free Software Foundation; either version 2 of the License, or
18  * (at your option) any later version.
19  * 
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
28  *****************************************************************************/
29
30 /*****************************************************************************
31  * Preamble
32  *****************************************************************************/
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.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 <sys/stat.h>
46 #include <string.h>
47 #include <errno.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 #ifdef GOD_DAMN_DMCA
60 #   include "dummy_dvdcss.h"
61 #else
62 #   include <videolan/dvdcss.h>
63 #endif
64
65 #if defined( WIN32 )
66 #   include "input_iovec.h"
67 #endif
68
69 #include "stream_control.h"
70 #include "input_ext-intf.h"
71 #include "input_ext-dec.h"
72 #include "input_ext-plugins.h"
73
74 #include "input_dvd.h"
75 #include "dvd_ifo.h"
76 #include "dvd_summary.h"
77 #include "iso_lang.h"
78
79 #include "debug.h"
80
81 /* how many packets DVDDemux will read in each loop */
82 #define DVD_READ_ONCE 64
83
84 /*****************************************************************************
85  * Local prototypes
86  *****************************************************************************/
87
88 /* called from outside */
89 static int  DVDOpen         ( struct input_thread_s * );
90 static void DVDClose        ( struct input_thread_s * );
91 static int  DVDSetArea      ( struct input_thread_s *, struct input_area_s * );
92 static int  DVDSetProgram   ( struct input_thread_s *, pgrm_descriptor_t * );
93 static int  DVDRead         ( struct input_thread_s *, byte_t *, size_t );
94 static void DVDSeek         ( struct input_thread_s *, off_t );
95
96 static int  DVDRewind       ( struct input_thread_s * );
97 static int  DVDDemux        ( struct input_thread_s * );
98 static int  DVDInit         ( struct input_thread_s * );
99 static void DVDEnd          ( struct input_thread_s * );
100
101 /* called only inside */
102 static void DVDLaunchDecoders( input_thread_t * p_input );
103 static int  DVDChooseAngle( thread_dvd_data_t * );
104 static int  DVDFindCell( thread_dvd_data_t * );
105 static int  DVDFindSector( thread_dvd_data_t * );
106 static int  DVDChapterSelect( thread_dvd_data_t *, int );
107
108 /*****************************************************************************
109  * Functions exported as capabilities. They are declared as static so that
110  * we don't pollute the namespace too much.
111  *****************************************************************************/
112 void _M( access_getfunctions)( function_list_t * p_function_list )
113 {
114 #define input p_function_list->functions.access
115     input.pf_open             = DVDOpen;
116     input.pf_close            = DVDClose;
117     input.pf_read             = DVDRead;
118     input.pf_set_area         = DVDSetArea;
119     input.pf_set_program      = DVDSetProgram;
120     input.pf_seek             = DVDSeek;
121 #undef input
122 }
123
124 void _M( demux_getfunctions)( function_list_t * p_function_list )
125 {
126 #define demux p_function_list->functions.demux
127     demux.pf_init             = DVDInit;
128     demux.pf_end              = DVDEnd;
129     demux.pf_demux            = DVDDemux;
130     demux.pf_rewind           = DVDRewind;
131 #undef demux
132 }
133
134 /*
135  * Data demux functions
136  */
137
138 /*****************************************************************************
139  * DVDInit: initializes DVD structures
140  *****************************************************************************/
141 static int DVDInit( input_thread_t * p_input )
142 {
143
144     if( strncmp( p_input->p_access_module->psz_name, "dvd", 3 ) )
145     {
146         return -1;
147     }
148
149     vlc_mutex_lock( &p_input->stream.stream_lock );
150     
151     DVDLaunchDecoders( p_input );
152     
153     vlc_mutex_unlock( &p_input->stream.stream_lock );
154
155     return 0;
156 }
157
158 /*****************************************************************************
159  * DVDEnd: frees unused data
160  *****************************************************************************/
161 static void DVDEnd( input_thread_t * p_input )
162 {
163 }
164
165 /*****************************************************************************
166  * DVDDemux
167  *****************************************************************************/
168 #define PEEK( SIZE )                                                        \
169     i_result = input_Peek( p_input, &p_peek, SIZE );                        \
170     if( i_result == -1 )                                                    \
171     {                                                                       \
172         return( -1 );                                                       \
173     }                                                                       \
174     else if( i_result < SIZE )                                              \
175     {                                                                       \
176         /* EOF */                                                           \
177         return( 0 );                                                        \
178     }
179
180 static int DVDDemux( input_thread_t * p_input )
181 {
182     int                 i;
183     byte_t *            p_peek;
184     data_packet_t *     p_data;
185     ssize_t             i_result;
186     int                 i_packet_size;
187             
188
189     /* Read headers to compute payload length */
190     for( i = 0 ; i < DVD_READ_ONCE ; i++ )
191     {
192
193         /* Read what we believe to be a packet header. */
194         PEEK( 4 );
195             
196         /* Default header */
197         if( U32_AT( p_peek ) != 0x1BA )
198         {
199             /* That's the case for all packets, except pack header. */
200             i_packet_size = U16_AT( p_peek + 4 );
201         }
202         else
203         {
204             /* MPEG-2 Pack header. */
205             i_packet_size = 8;
206         }
207
208         /* Fetch a packet of the appropriate size. */
209         i_result = input_SplitBuffer( p_input, &p_data, i_packet_size + 6 );
210         if( i_result <= 0 )
211         {
212             return( i_result );
213         }
214
215         /* In MPEG-2 pack headers we still have to read stuffing bytes. */
216         if( (p_data->p_demux_start[3] == 0xBA) && (i_packet_size == 8) )
217         {
218             size_t i_stuffing = (p_data->p_demux_start[13] & 0x7);
219             /* Force refill of the input buffer - though we don't care
220              * about p_peek. Please note that this is unoptimized. */
221             PEEK( i_stuffing );
222             p_input->p_current_data += i_stuffing;
223         }
224
225         input_DemuxPS( p_input, p_data );
226                         
227     }
228     
229     return i;
230 }
231
232 /*****************************************************************************
233  * DVDRewind : reads a stream backward
234  *****************************************************************************/
235 static int DVDRewind( input_thread_t * p_input )
236 {
237     return( -1 );
238 }
239
240
241
242 /*
243  * Data access functions
244  */
245
246 /*****************************************************************************
247  * DVDOpen: open dvd
248  *****************************************************************************/
249 static int DVDOpen( struct input_thread_s *p_input )
250 {
251     struct stat          stat_info;
252     char *               psz_parser = p_input->psz_name;
253     char *               psz_device = p_input->psz_name;
254     dvdcss_handle        dvdhandle;
255     thread_dvd_data_t *  p_dvd;
256     input_area_t *       p_area;
257     int                  i_title;
258     int                  i_chapter;
259     int                  i;
260
261     /* Parse input string : device[@rawdevice] */
262     while( *psz_parser && *psz_parser != '@' )
263     {
264         psz_parser++;
265     }
266
267     if( *psz_parser == '@' )
268     {
269         /* Found raw device */
270         *psz_parser = '\0';
271         psz_parser++;
272
273         config_PutPszVariable( "DVDCSS_RAW_DEVICE", psz_parser );
274     }
275
276     if( stat( psz_device, &stat_info ) == -1 )
277     {
278         intf_ErrMsg( "input error: cannot stat() device `%s' (%s)",
279                      psz_device, strerror(errno));
280         return( -1 );                    
281     }
282     
283 #ifndef WIN32    
284     if( !S_ISBLK(stat_info.st_mode) && !S_ISCHR(stat_info.st_mode) )
285     {
286         intf_WarnMsg( 3, "input : DVD plugin discarded"
287                          " (not a valid block device)" );
288         return -1;
289     }
290 #endif
291
292     intf_WarnMsg( 2, "input: dvd=%s raw=%s", psz_device, psz_parser );
293     
294     /* 
295      * set up input
296      */ 
297     p_input->i_mtu = 0;
298
299     vlc_mutex_lock( &p_input->stream.stream_lock );
300
301     p_input->stream.i_method = INPUT_METHOD_DVD;
302
303     /* If we are here we can control the pace... */
304     p_input->stream.b_pace_control = 1;
305
306     p_input->stream.b_seekable = 1;
307     p_input->stream.p_selected_area->i_size = 0;
308
309     p_input->stream.p_selected_area->i_tell = 0;
310
311     vlc_mutex_unlock( &p_input->stream.stream_lock );
312
313     /*
314      *  get plugin ready
315      */ 
316     dvdhandle = dvdcss_open( psz_device );
317
318     if( dvdhandle == NULL )
319     {
320         intf_ErrMsg( "dvd error: dvdcss can't open device" );
321         return -1;
322     }
323
324     p_dvd = malloc( sizeof(thread_dvd_data_t) );
325     if( p_dvd == NULL )
326     {
327         intf_ErrMsg( "dvd error: out of memory" );
328         return -1;
329     }
330
331     p_dvd->dvdhandle = (dvdcss_handle) dvdhandle;
332     p_input->p_access_data = (void *)p_dvd;
333
334     if( dvdcss_seek( p_dvd->dvdhandle, 0, DVDCSS_NOFLAGS ) < 0 )
335     {
336         intf_ErrMsg( "dvd error: %s", dvdcss_error( p_dvd->dvdhandle ) );
337         return -1;
338     }
339
340     /* Ifo allocation & initialisation */
341     if( IfoCreate( p_dvd ) < 0 )
342     {
343         intf_ErrMsg( "dvd error: allcation error in ifo" );
344         free( p_dvd );
345         return -1;
346     }
347
348     if( IfoInit( p_dvd->p_ifo ) < 0 )
349     {
350         intf_ErrMsg( "dvd error: fatal failure in ifo" );
351         IfoDestroy( p_dvd->p_ifo );
352         free( p_dvd );
353         return -1;
354     }
355
356     /* Set stream and area data */
357     vlc_mutex_lock( &p_input->stream.stream_lock );
358
359     /* Initialize ES structures */
360     input_InitStream( p_input, sizeof( stream_ps_data_t ) );
361
362 #define title_inf p_dvd->p_ifo->vmg.title_inf
363     intf_WarnMsg( 2, "dvd info: number of titles: %d", title_inf.i_title_nb );
364
365 #define area p_input->stream.pp_areas
366     /* We start from 1 here since the default area 0
367      * is reserved for video_ts.vob */
368     for( i = 1 ; i <= title_inf.i_title_nb ; i++ )
369     {
370         input_AddArea( p_input );
371
372         /* Titles are Program Chains */
373         area[i]->i_id = i;
374
375         /* Absolute start offset and size 
376          * We can only set that with vts ifo, so we do it during the
377          * first call to DVDSetArea */
378         area[i]->i_start = 0;
379         area[i]->i_size = 0;
380
381         /* Number of chapters */
382         area[i]->i_part_nb = title_inf.p_attr[i-1].i_chapter_nb;
383         area[i]->i_part = 1;
384
385         /* Number of angles */
386         area[i]->i_angle_nb = 0;
387         area[i]->i_angle = 1;
388
389         /* Offset to vts_i_0.ifo */
390         area[i]->i_plugin_data = p_dvd->p_ifo->i_start +
391                        title_inf.p_attr[i-1].i_start_sector;
392     }   
393 #undef area
394
395     /* Get requested title - if none try the first title */
396     i_title = config_GetIntVariable( INPUT_TITLE_VAR );
397     if( i_title <= 0 || i_title > title_inf.i_title_nb )
398     {
399         i_title = 1;
400     }
401
402 #undef title_inf
403
404     /* Get requested chapter - if none defaults to first one */
405     i_chapter = config_GetIntVariable( INPUT_CHAPTER_VAR );
406     if( i_chapter <= 0 )
407     {
408         i_chapter = 1;
409     }
410
411     p_area = p_input->stream.pp_areas[i_title];
412     p_area->i_part = i_chapter;
413
414     /* set title, chapter, audio and subpic */
415     if( DVDSetArea( p_input, p_area ) )
416     {
417         vlc_mutex_unlock( &p_input->stream.stream_lock );
418         return -1;
419     }
420
421     vlc_mutex_unlock( &p_input->stream.stream_lock );
422
423     return 0;
424
425 }
426
427 /*****************************************************************************
428  * DVDClose: close dvd
429  *****************************************************************************/
430 static void DVDClose( struct input_thread_s *p_input )
431 {
432     thread_dvd_data_t *     p_dvd;
433
434     p_dvd = (thread_dvd_data_t*)p_input->p_access_data;
435
436     IfoDestroy( p_dvd->p_ifo );
437
438     p_input->p_access_data = (void *)(p_dvd->dvdhandle);
439     free( p_dvd );
440
441     /* Clean up libdvdcss */
442     dvdcss_close( (dvdcss_handle) p_input->p_access_data );
443 }
444
445 /*****************************************************************************
446  * DVDSetProgram: Does nothing, a DVD is mono-program
447  *****************************************************************************/
448 static int DVDSetProgram( input_thread_t * p_input, 
449             pgrm_descriptor_t * p_program ) 
450 {
451     return 0;
452 }
453
454 /*****************************************************************************
455  * DVDSetArea: initialize input data for title x, chapter y.
456  * It should be called for each user navigation request.
457  *****************************************************************************
458  * Take care that i_title starts from 0 (vmg) and i_chapter start from 1.
459  * Note that you have to take the lock before entering here.
460  *****************************************************************************/
461 static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area )
462 {
463     thread_dvd_data_t *  p_dvd;
464     es_descriptor_t *    p_es;
465     u16                  i_id;
466     int                  i_vts_title;
467     int                  i_audio_nb = 0;
468     int                  i_spu_nb = 0;
469     int                  i;
470
471     p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);
472
473     /* we can't use the interface slider until initilization is complete */
474     p_input->stream.b_seekable = 0;
475
476     if( p_area != p_input->stream.p_selected_area )
477     {
478         /* Reset the Chapter position of the old title */
479         p_input->stream.p_selected_area->i_part = 0;
480
481         /*
482          *  We have to load all title information
483          */
484         /* Change the default area */
485         p_input->stream.p_selected_area =
486                     p_input->stream.pp_areas[p_area->i_id];
487
488         /* title number: it is not vts nb!,
489          * it is what appears in the interface list */
490         p_dvd->i_title = p_area->i_id;
491         p_dvd->p_ifo->i_title = p_dvd->i_title;
492
493         /* set number of chapters of current title */
494         p_dvd->i_chapter_nb = p_area->i_part_nb;
495
496         /* ifo vts */
497         if( IfoTitleSet( p_dvd->p_ifo ) < 0 )
498         {
499             intf_ErrMsg( "dvd error: fatal error in vts ifo" );
500             free( p_dvd );
501             p_input->b_error = 1;
502             return -1;
503         }
504
505 #define vmg p_dvd->p_ifo->vmg
506 #define vts p_dvd->p_ifo->vts
507         /* title position inside the selected vts */
508         i_vts_title = vmg.title_inf.p_attr[p_dvd->i_title-1].i_title_num;
509         p_dvd->i_title_id =
510             vts.title_inf.p_title_start[i_vts_title-1].i_title_id;
511
512         intf_WarnMsg( 3, "dvd: title %d vts_title %d pgc %d",
513                       p_dvd->i_title, i_vts_title, p_dvd->i_title_id );
514
515         /*
516          * Angle management
517          */
518         p_dvd->i_angle_nb = vmg.title_inf.p_attr[p_dvd->i_title-1].i_angle_nb;
519         p_dvd->i_angle = config_GetIntVariable( INPUT_ANGLE_VAR );
520         if( ( p_dvd->i_angle <= 0 ) || p_dvd->i_angle > p_dvd->i_angle_nb )
521         {
522             p_dvd->i_angle = 1;
523         }
524     
525         /*
526          * Set selected title start and size
527          */
528         
529         /* title set offset XXX: convert to block values */
530         p_dvd->i_title_start =
531             vts.i_pos + vts.manager_inf.i_title_vob_start_sector;
532
533         /* last video cell */
534         p_dvd->i_cell = 0;
535         p_dvd->i_prg_cell = -1 +
536             vts.title_unit.p_title[p_dvd->i_title_id-1].title.i_cell_nb;
537
538         if( DVDFindCell( p_dvd ) < 0 )
539         {
540             intf_ErrMsg( "dvd error: can't find title end" );
541             p_input->b_error = 1;
542             return -1;
543         }
544         
545         /* temporary hack to fix size in some dvds */
546         if( p_dvd->i_cell >= vts.cell_inf.i_cell_nb )
547         {
548             p_dvd->i_cell = vts.cell_inf.i_cell_nb - 1;
549         }
550
551         p_dvd->i_sector = 0;
552         p_dvd->i_size = vts.cell_inf.p_cell_map[p_dvd->i_cell].i_end_sector;
553
554         if( DVDChapterSelect( p_dvd, 1 ) < 0 )
555         {
556             intf_ErrMsg( "dvd error: can't find first chapter" );
557             p_input->b_error = 1;
558             return -1;
559         }
560         
561         /* Force libdvdcss to check its title key.
562          * It is only useful for title cracking method. Methods using the
563          * decrypted disc key are fast enough to check the key at each seek */
564
565         if( dvdcss_seek( p_dvd->dvdhandle, p_dvd->i_start,
566                             DVDCSS_SEEK_KEY ) < 0 )
567         {
568             intf_ErrMsg( "dvd error: %s", dvdcss_error( p_dvd->dvdhandle ) );
569             return -1;
570         }
571
572         p_dvd->i_size -= p_dvd->i_sector + 1;
573
574         IfoPrintTitle( p_dvd );
575
576         /* Area definition */
577         p_input->stream.p_selected_area->i_start = LB2OFF( p_dvd->i_start );
578         p_input->stream.p_selected_area->i_size = LB2OFF( p_dvd->i_size );
579         p_input->stream.p_selected_area->i_angle_nb = p_dvd->i_angle_nb;
580         p_input->stream.p_selected_area->i_angle = p_dvd->i_angle;
581
582 #if 0
583         /* start at the beginning of the title */
584         /* FIXME: create a conf option to select whether to restart
585          * title or not */
586         p_input->stream.p_selected_area->i_tell = 0;
587         p_input->stream.p_selected_area->i_part = 1;
588 #endif
589
590         /*
591          * Destroy obsolete ES by reinitializing program 0
592          * and find all ES in title with ifo data
593          */
594         if( p_input->stream.pp_programs != NULL )
595         {
596             /* We don't use input_EndStream here since
597              * we keep area structures */
598
599             for( i = 0 ; i < p_input->stream.i_selected_es_number ; i++ )
600             {
601                 input_UnselectES( p_input, p_input->stream.pp_selected_es[i] );
602             }
603
604             free( p_input->stream.pp_selected_es );
605             input_DelProgram( p_input, p_input->stream.p_selected_program );
606
607             p_input->stream.pp_selected_es = NULL;
608             p_input->stream.i_selected_es_number = 0;
609         }
610
611         input_AddProgram( p_input, 0, sizeof( stream_ps_data_t ) );
612         p_input->stream.p_selected_program = p_input->stream.pp_programs[0]; 
613 //        p_input->stream.p_new_program = p_input->stream.pp_programs[0]; 
614
615         /* No PSM to read in DVD mode, we already have all information */
616         p_input->stream.p_selected_program->b_is_ok = 1;
617
618         p_es = NULL;
619
620         /* ES 0 -> video MPEG2 */
621         IfoPrintVideo( p_dvd );
622
623         p_es = input_AddES( p_input, p_input->stream.p_selected_program, 
624                 0xe0, 0 );
625         p_es->i_stream_id = 0xe0;
626         p_es->i_type = MPEG2_VIDEO_ES;
627         p_es->i_cat = VIDEO_ES;
628         
629 #define audio_status \
630     vts.title_unit.p_title[p_dvd->i_title_id-1].title.pi_audio_status[i-1]
631         /* Audio ES, in the order they appear in .ifo */
632         for( i = 1 ; i <= vts.manager_inf.i_audio_nb ; i++ )
633         {
634             IfoPrintAudio( p_dvd, i );
635
636             /* audio channel is active if first byte is 0x80 */
637             if( audio_status.i_available )
638             {
639                 i_audio_nb++;
640
641                 switch( vts.manager_inf.p_audio_attr[i-1].i_coding_mode )
642                 {
643                 case 0x00:              /* AC3 */
644                     i_id = ( ( 0x80 + audio_status.i_position ) << 8 ) | 0xbd;
645                     p_es = input_AddES( p_input,
646                                p_input->stream.p_selected_program, i_id, 0 );
647                     p_es->i_stream_id = 0xbd;
648                     p_es->i_type = AC3_AUDIO_ES;
649                     p_es->b_audio = 1;
650                     p_es->i_cat = AUDIO_ES;
651                     strcpy( p_es->psz_desc, DecodeLanguage( hton16(
652                         vts.manager_inf.p_audio_attr[i-1].i_lang_code ) ) ); 
653                     strcat( p_es->psz_desc, " (ac3)" );
654     
655                     break;
656                 case 0x02:
657                 case 0x03:              /* MPEG audio */
658                     i_id = 0xc0 + audio_status.i_position;
659                     p_es = input_AddES( p_input,
660                                     p_input->stream.p_selected_program, i_id
661                                     , 0 );
662                     p_es->i_stream_id = i_id;
663                     p_es->i_type = MPEG2_AUDIO_ES;
664                     p_es->b_audio = 1;
665                     p_es->i_cat = AUDIO_ES;
666                     strcpy( p_es->psz_desc, DecodeLanguage( hton16(
667                         vts.manager_inf.p_audio_attr[i-1].i_lang_code ) ) ); 
668                     strcat( p_es->psz_desc, " (mpeg)" );
669     
670                     break;
671                 case 0x04:              /* LPCM */
672     
673                     i_id = ( ( 0xa0 + audio_status.i_position ) << 8 ) | 0xbd;
674                     p_es = input_AddES( p_input,
675                                     p_input->stream.p_selected_program,
676                                     i_id, 0 );
677                     p_es->i_stream_id = 0xbd;
678                     p_es->i_type = LPCM_AUDIO_ES;
679                     p_es->b_audio = 1;
680                     p_es->i_cat = AUDIO_ES;
681                     strcpy( p_es->psz_desc, DecodeLanguage( hton16(
682                         vts.manager_inf.p_audio_attr[i-1].i_lang_code ) ) ); 
683                     strcat( p_es->psz_desc, " (lpcm)" );
684     
685                     break;
686                 case 0x06:              /* DTS */
687                     i_id = ( ( 0x88 + audio_status.i_position ) << 8 ) | 0xbd;
688                     intf_ErrMsg( "dvd warning: DTS audio not handled yet"
689                                  "(0x%x)", i_id );
690                     break;
691                 default:
692                     i_id = 0;
693                     intf_ErrMsg( "dvd warning: unknown audio type %.2x",
694                              vts.manager_inf.p_audio_attr[i-1].i_coding_mode );
695                 }
696             }
697         }
698 #undef audio_status
699 #define spu_status \
700     vts.title_unit.p_title[p_dvd->i_title_id-1].title.pi_spu_status[i-1]
701
702         /* Sub Picture ES */
703            
704         for( i = 1 ; i <= vts.manager_inf.i_spu_nb; i++ )
705         {
706             IfoPrintSpu( p_dvd, i );
707
708             if( spu_status.i_available )
709             {
710                 i_spu_nb++;
711
712                 /*  there are several streams for one spu */
713                 if(  vts.manager_inf.video_attr.i_ratio )
714                 {
715                     /* 16:9 */
716                     switch( vts.manager_inf.video_attr.i_perm_displ )
717                     {
718                     case 1:
719                         i_id = ( ( 0x20 + spu_status.i_position_pan ) << 8 )
720                                | 0xbd;
721                         break;
722                     case 2:
723                         i_id = ( ( 0x20 + spu_status.i_position_letter ) << 8 )
724                                | 0xbd;
725                         break;
726                     default:
727                         i_id = ( ( 0x20 + spu_status.i_position_wide ) << 8 )
728                                | 0xbd;
729                         break;
730                     }
731                 }
732                 else
733                 {
734                     /* 4:3 */
735                     i_id = ( ( 0x20 + spu_status.i_position_43 ) << 8 )
736                            | 0xbd;
737                 }
738                 p_es = input_AddES( p_input,
739                                     p_input->stream.p_selected_program,
740                                     i_id, 0 );
741                 p_es->i_stream_id = 0xbd;
742                 p_es->i_type = DVD_SPU_ES;
743                 p_es->i_cat = SPU_ES;
744                 strcpy( p_es->psz_desc, DecodeLanguage( hton16(
745                     vts.manager_inf.p_spu_attr[i-1].i_lang_code ) ) ); 
746             }
747         }
748 #undef spu_status
749     
750         /* FIXME: hack to check that the demuxer is ready, and set
751         * the decoders */
752         if( p_input->p_demux_module )
753         {
754             DVDLaunchDecoders( p_input );
755         }
756
757     } /* i_title >= 0 */
758     else
759     {
760         p_area = p_input->stream.p_selected_area;
761     }
762 #undef vts
763 #undef vmg
764
765     /*
766      * Chapter selection
767      */
768
769     if( p_area->i_part != p_dvd->i_chapter )
770     {
771         if( ( p_area->i_part > 0 ) &&
772             ( p_area->i_part <= p_area->i_part_nb ))
773         {
774             if( DVDChapterSelect( p_dvd, p_area->i_part ) < 0 )
775             {
776                 intf_ErrMsg( "dvd error: can't set chapter in area" );
777                 p_input->b_error = 1;
778                 return -1;
779             }
780     
781             p_input->stream.p_selected_area->i_tell =
782                                    LB2OFF( p_dvd->i_start ) - p_area->i_start;
783             p_input->stream.p_selected_area->i_part = p_dvd->i_chapter;
784     
785             intf_WarnMsg( 4, "dvd info: chapter %d start at: %lld",
786                                         p_area->i_part, p_area->i_tell );
787         }
788         else
789         {
790             p_area->i_part = 1;
791             p_dvd->i_chapter = 1;
792         }
793     }
794
795 #define title \
796     p_dvd->p_ifo->vts.title_unit.p_title[p_dvd->i_title_id-1].title
797     if( p_area->i_angle != p_dvd->i_angle )
798     {
799         if( title.p_cell_play[p_dvd->i_prg_cell].i_category & 0xf000 )
800         {
801             if( ( p_area->i_angle - p_dvd->i_angle ) < 0 )
802             {
803                 p_dvd->i_cell = 0;
804             }
805             p_dvd->i_prg_cell += ( p_area->i_angle - p_dvd->i_angle );
806             p_dvd->i_angle = p_area->i_angle;
807     
808             DVDFindSector( p_dvd );
809             p_dvd->i_cell += p_dvd->i_angle_cell;
810         }
811         else
812         {
813             p_dvd->i_angle = p_area->i_angle;
814         }
815
816         intf_WarnMsg( 3, "dvd info: angle %d selected", p_area->i_angle );
817     }
818
819     /* warn interface that something has changed */
820     p_input->stream.b_seekable = 1;
821     p_input->stream.b_changed = 1;
822
823     return 0;
824 }
825
826
827 /*****************************************************************************
828  * DVDRead: reads data packets.
829  *****************************************************************************
830  * Returns -1 in case of error, 0 in case of EOF, otherwise the number of
831  * bytes.
832  *****************************************************************************/
833 static int DVDRead( input_thread_t * p_input,
834                     byte_t * p_buffer, size_t i_count )
835 {
836     thread_dvd_data_t *     p_dvd;
837     int                     i_block_once;
838     int                     i_read_blocks;
839     int                     i_read_total;
840     int                     i_sector;
841     int                     i_blocks;
842     boolean_t               b_eoc;
843
844     p_dvd = (thread_dvd_data_t *)(p_input->p_access_data);
845
846     i_sector = 0;
847     i_read_total = 0;
848     i_read_blocks = 0;
849     b_eoc = 0;
850
851     i_blocks = OFF2LB(i_count);
852
853     while( i_blocks )
854     {
855         i_sector = p_dvd->i_title_start + p_dvd->i_sector;
856         i_block_once = p_dvd->i_end_sector - p_dvd->i_sector + 1;
857
858         /* Get the position of the next cell if we're at cell end */
859         if( i_block_once <= 0 )
860         {
861             int     i_angle;
862
863             p_dvd->i_cell++;
864             p_dvd->i_angle_cell++;
865
866             /* Find cell index in adress map */
867             if( DVDFindSector( p_dvd ) < 0 )
868             {
869                 intf_ErrMsg( "dvd error: can't find next cell" );
870                 return 1;
871             }
872
873             /* Position the fd pointer on the right address */
874             if( ( i_sector = dvdcss_seek( p_dvd->dvdhandle,
875                                 p_dvd->i_title_start + p_dvd->i_sector,
876                                 DVDCSS_SEEK_MPEG ) ) < 0 )
877             {
878                 intf_ErrMsg( "dvd error: %s", dvdcss_error( p_dvd->dvdhandle ) );
879                 return -1;
880             }
881
882             /* update chapter : it will be easier when we have navigation
883              * ES support */
884             if( p_dvd->i_chapter < ( p_dvd->i_chapter_nb - 1 ) )
885             {
886                 if( title.p_cell_play[p_dvd->i_prg_cell].i_category & 0xf000 )
887                 {
888                     i_angle = p_dvd->i_angle - 1;
889                 }
890                 else
891                 {
892                     i_angle = 0;
893                 }
894                 if( title.chapter_map.pi_start_cell[p_dvd->i_chapter] <=
895                     ( p_dvd->i_prg_cell - i_angle + 1 ) )
896                 {
897                     p_dvd->i_chapter++;
898                     b_eoc = 1;
899                 }
900             }
901
902             i_block_once = p_dvd->i_end_sector - p_dvd->i_sector + 1;
903         }
904
905         /* The number of blocks read is the max between the requested
906          * value and the leaving block in the cell */
907         if( i_block_once > i_blocks )
908         {
909             i_block_once = i_blocks;
910         }
911     /*
912     intf_WarnMsg( 2, "Sector: 0x%x Read: %d Chapter: %d", p_dvd->i_sector, i_block_once, p_dvd->i_chapter );
913     */
914
915         /* Reads from DVD */
916         i_read_blocks = dvdcss_read( p_dvd->dvdhandle, p_buffer,
917                                      i_block_once, DVDCSS_READ_DECRYPT );
918
919         i_blocks -= i_read_blocks;
920         p_buffer += LB2OFF( i_read_blocks );
921         i_read_total += i_read_blocks;
922
923         /* Update global position */
924         p_dvd->i_sector += i_read_blocks;
925     }
926
927     vlc_mutex_lock( &p_input->stream.stream_lock );
928
929     p_input->stream.p_selected_area->i_tell =
930         LB2OFF( i_sector + i_read_total ) -
931         p_input->stream.p_selected_area->i_start;
932     if( b_eoc )
933     {
934         /* We modify i_part only at end of chapter not to erase
935          * some modification from the interface */
936         p_input->stream.p_selected_area->i_part = p_dvd->i_chapter;
937     }
938
939     if( p_input->stream.p_selected_area->i_tell
940             >= p_input->stream.p_selected_area->i_size )
941     {
942         if( ( p_dvd->i_title + 1 ) >= p_input->stream.i_area_nb )
943         {
944             /* EOF */
945             vlc_mutex_unlock( &p_input->stream.stream_lock );
946             return 0;
947         }
948
949         /* EOT */
950         intf_WarnMsg( 4, "dvd info: new title" );
951         p_dvd->i_title++;
952         DVDSetArea( p_input, p_input->stream.pp_areas[p_dvd->i_title] );
953         vlc_mutex_unlock( &p_input->stream.stream_lock );
954         return LB2OFF( i_read_total );
955     }
956
957     vlc_mutex_unlock( &p_input->stream.stream_lock );
958 /*
959     if( i_read_blocks != i_block_once )
960     {
961         return -1;
962     }
963 */
964     return LB2OFF( i_read_total );
965 }
966
967 /*****************************************************************************
968  * DVDSeek : Goes to a given position on the stream.
969  *****************************************************************************
970  * This one is used by the input and translate chronological position from
971  * input to logical position on the device.
972  * The lock should be taken before calling this function.
973  *****************************************************************************/
974 static void DVDSeek( input_thread_t * p_input, off_t i_off )
975 {
976     thread_dvd_data_t *     p_dvd;
977     int                     i_block;
978     int                     i_prg_cell;
979     int                     i_cell;
980     int                     i_chapter;
981     int                     i_angle;
982     
983     p_dvd = ( thread_dvd_data_t * )(p_input->p_access_data);
984
985     vlc_mutex_lock( &p_input->stream.stream_lock );
986     /* we have to take care of offset of beginning of title */
987     p_dvd->i_sector = OFF2LB(i_off + p_input->stream.p_selected_area->i_start)
988                        - p_dvd->i_title_start;
989     vlc_mutex_unlock( &p_input->stream.stream_lock );
990
991     i_prg_cell = 0;
992     i_chapter = 0;
993
994     /* parse vobu address map to find program cell */
995     while( title.p_cell_play[i_prg_cell].i_end_sector < p_dvd->i_sector  )
996     {
997         i_prg_cell++;
998     }
999
1000     p_dvd->i_prg_cell = i_prg_cell;
1001
1002     if( DVDChooseAngle( p_dvd ) < 0 )
1003     {
1004         p_input->b_error = 1;
1005         return;        
1006     }
1007
1008     p_dvd->i_cell = 0;
1009
1010     /* Find first title cell which is inside program cell */
1011     if( DVDFindCell( p_dvd ) < 0 )
1012     {
1013         /* no following cell : we're at eof */
1014         intf_ErrMsg( "dvd error: cell seeking failed" );
1015         p_input->b_error = 1;
1016         return;
1017     }
1018
1019     i_cell = p_dvd->i_cell;
1020
1021 #define cell p_dvd->p_ifo->vts.cell_inf.p_cell_map[i_cell]
1022     /* parse cell address map to find title cell containing sector */
1023     while( cell.i_end_sector < p_dvd->i_sector )
1024     {
1025         i_cell++;
1026     }
1027
1028     p_dvd->i_cell = i_cell;
1029
1030     /* if we're inside a multi-angle zone, we have to choose i_sector
1031      * in the current angle ; we can't do it all the time since cells
1032      * can be very wide out of such zones */
1033     if( title.p_cell_play[p_dvd->i_prg_cell].i_category & 0xf000 )
1034     {
1035         p_dvd->i_sector = __MAX(
1036                 cell.i_start_sector,
1037                 title.p_cell_play[p_dvd->i_prg_cell].i_start_sector );
1038     }
1039
1040     p_dvd->i_end_sector = __MIN(
1041             cell.i_end_sector,
1042             title.p_cell_play[p_dvd->i_prg_cell].i_end_sector );
1043 #undef cell
1044     /* update chapter */
1045     if( title.p_cell_play[p_dvd->i_prg_cell].i_category & 0xf000 )
1046     {
1047         i_angle = p_dvd->i_angle - 1;
1048     }
1049     else
1050     {
1051         i_angle = 0;
1052     }
1053     if( p_dvd->i_chapter_nb > 1 )
1054     {
1055         while( ( title.chapter_map.pi_start_cell[i_chapter] <=
1056                     ( p_dvd->i_prg_cell - i_angle + 1 ) ) &&
1057                ( i_chapter < ( p_dvd->i_chapter_nb - 1 ) ) )
1058         {
1059             i_chapter++;
1060         }
1061     }
1062     else
1063     {
1064         i_chapter = 1;
1065     }
1066
1067     p_dvd->i_chapter = i_chapter;
1068
1069     if( ( i_block = dvdcss_seek( p_dvd->dvdhandle,
1070                                  p_dvd->i_title_start + p_dvd->i_sector,
1071                                  DVDCSS_SEEK_MPEG ) ) < 0 )
1072     {
1073         intf_ErrMsg( "dvd error: %s", dvdcss_error( p_dvd->dvdhandle ) );
1074         p_input->b_error = 1;
1075         return;
1076     }
1077
1078     vlc_mutex_lock( &p_input->stream.stream_lock );
1079     p_input->stream.p_selected_area->i_part = p_dvd->i_chapter;
1080     p_input->stream.p_selected_area->i_tell =
1081         LB2OFF ( i_block ) - p_input->stream.p_selected_area->i_start;
1082     vlc_mutex_unlock( &p_input->stream.stream_lock );
1083
1084     intf_WarnMsg( 7, "Program Cell: %d Cell: %d Chapter: %d",
1085                      p_dvd->i_prg_cell, p_dvd->i_cell, p_dvd->i_chapter );
1086
1087     return;
1088 }
1089
1090 #define cell  p_dvd->p_ifo->vts.cell_inf
1091
1092 /*****************************************************************************
1093  * DVDFindCell: adjust the title cell index with the program cell
1094  *****************************************************************************/
1095 static int DVDFindCell( thread_dvd_data_t * p_dvd )
1096 {
1097     int                 i_cell;
1098     int                 i_index;
1099
1100     i_cell = p_dvd->i_cell;
1101     i_index = p_dvd->i_prg_cell;
1102
1103     if( i_cell >= cell.i_cell_nb )
1104     {
1105         return -1;
1106     }
1107
1108     while( ( ( title.p_cell_pos[i_index].i_vob_id !=
1109                    cell.p_cell_map[i_cell].i_vob_id ) ||
1110       ( title.p_cell_pos[i_index].i_cell_id !=
1111                    cell.p_cell_map[i_cell].i_cell_id ) ) &&
1112            ( i_cell < cell.i_cell_nb - 1 ) )
1113     {
1114         i_cell++;
1115     }
1116
1117 /*
1118 intf_WarnMsg( 12, "FindCell: i_cell %d i_index %d found %d nb %d",
1119                     p_dvd->i_cell,
1120                     p_dvd->i_prg_cell,
1121                     i_cell,
1122                     cell.i_cell_nb );
1123 */
1124
1125     p_dvd->i_cell = i_cell;
1126
1127     return 0;    
1128 }
1129
1130 #undef cell
1131
1132 /*****************************************************************************
1133  * DVDFindSector: find cell index in adress map from index in
1134  * information table program map and give corresponding sectors.
1135  *****************************************************************************/
1136 static int DVDFindSector( thread_dvd_data_t * p_dvd )
1137 {
1138
1139     if( p_dvd->i_sector > title.p_cell_play[p_dvd->i_prg_cell].i_end_sector )
1140     {
1141         p_dvd->i_prg_cell++;
1142
1143         if( DVDChooseAngle( p_dvd ) < 0 )
1144         {
1145             return -1;
1146         }
1147     }
1148
1149     if( DVDFindCell( p_dvd ) < 0 )
1150     {
1151         intf_ErrMsg( "dvd error: can't find sector" );
1152         return -1;
1153     }
1154     
1155     /* Find start and end sectors of new cell */
1156 #if 1
1157     p_dvd->i_sector = __MAX(
1158          p_dvd->p_ifo->vts.cell_inf.p_cell_map[p_dvd->i_cell].i_start_sector,
1159          title.p_cell_play[p_dvd->i_prg_cell].i_start_sector );
1160     p_dvd->i_end_sector = __MIN(
1161          p_dvd->p_ifo->vts.cell_inf.p_cell_map[p_dvd->i_cell].i_end_sector,
1162          title.p_cell_play[p_dvd->i_prg_cell].i_end_sector );
1163 #else
1164     p_dvd->i_sector = title.p_cell_play[p_dvd->i_prg_cell].i_start_sector;
1165     p_dvd->i_end_sector = title.p_cell_play[p_dvd->i_prg_cell].i_end_sector;
1166 #endif
1167
1168 /*
1169     intf_WarnMsg( 12, "cell: %d sector1: 0x%x end1: 0x%x\n"
1170                    "index: %d sector2: 0x%x end2: 0x%x\n"
1171                    "category: 0x%x ilvu end: 0x%x vobu start 0x%x", 
1172         p_dvd->i_cell,
1173         p_dvd->p_ifo->vts.cell_inf.p_cell_map[p_dvd->i_cell].i_start_sector,
1174         p_dvd->p_ifo->vts.cell_inf.p_cell_map[p_dvd->i_cell].i_end_sector,
1175         p_dvd->i_prg_cell,
1176         title.p_cell_play[p_dvd->i_prg_cell].i_start_sector,
1177         title.p_cell_play[p_dvd->i_prg_cell].i_end_sector,
1178         title.p_cell_play[p_dvd->i_prg_cell].i_category, 
1179         title.p_cell_play[p_dvd->i_prg_cell].i_first_ilvu_vobu_esector,
1180         title.p_cell_play[p_dvd->i_prg_cell].i_last_vobu_start_sector );
1181 */
1182
1183     return 0;
1184 }
1185
1186 /*****************************************************************************
1187  * DVDChapterSelect: find the cell corresponding to requested chapter
1188  *****************************************************************************/
1189 static int DVDChapterSelect( thread_dvd_data_t * p_dvd, int i_chapter )
1190 {
1191
1192     /* Find cell index in Program chain for current chapter */
1193     p_dvd->i_prg_cell = title.chapter_map.pi_start_cell[i_chapter-1] - 1;
1194     p_dvd->i_cell = 0;
1195     p_dvd->i_sector = 0;
1196
1197     DVDChooseAngle( p_dvd );
1198
1199     /* Search for cell_index in cell adress_table and initialize
1200      * start sector */
1201     if( DVDFindSector( p_dvd ) < 0 )
1202     {
1203         intf_ErrMsg( "dvd error: can't select chapter" );
1204         return -1;
1205     }
1206
1207     /* start is : beginning of vts vobs + offset to vob x */
1208     p_dvd->i_start = p_dvd->i_title_start + p_dvd->i_sector;
1209
1210     /* Position the fd pointer on the right address */
1211     if( ( p_dvd->i_start = dvdcss_seek( p_dvd->dvdhandle,
1212                                         p_dvd->i_start,
1213                                         DVDCSS_SEEK_MPEG ) ) < 0 )
1214     {
1215         intf_ErrMsg( "dvd error: %s", dvdcss_error( p_dvd->dvdhandle ) );
1216         return -1;
1217     }
1218
1219     p_dvd->i_chapter = i_chapter;
1220     return 0;
1221 }
1222
1223 /*****************************************************************************
1224  * DVDChooseAngle: select the cell corresponding to the selected angle
1225  *****************************************************************************/
1226 static int DVDChooseAngle( thread_dvd_data_t * p_dvd )
1227 {
1228     /* basic handling of angles */
1229     switch( ( ( title.p_cell_play[p_dvd->i_prg_cell].i_category & 0xf000 )
1230                     >> 12 ) )
1231     {
1232         /* we enter a muli-angle section */
1233         case 0x5:
1234             p_dvd->i_prg_cell += p_dvd->i_angle - 1;
1235             p_dvd->i_angle_cell = 0;
1236             break;
1237         /* we exit a multi-angle section */
1238         case 0x9:
1239         case 0xd:
1240             p_dvd->i_prg_cell += p_dvd->i_angle_nb - p_dvd->i_angle;
1241             break;
1242     }
1243
1244     return 0;
1245 }
1246
1247 #undef title
1248 /*****************************************************************************
1249  * DVDLaunchDecoders
1250  *****************************************************************************/
1251 static void DVDLaunchDecoders( input_thread_t * p_input )
1252 {
1253     thread_dvd_data_t *  p_dvd;
1254     int                  i_audio;
1255     int                  i_spu;
1256
1257     p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);
1258
1259     /* Select Video stream (always 0) */
1260     if( p_main->b_video )
1261     {
1262         input_SelectES( p_input, p_input->stream.pp_es[0] );
1263     }
1264
1265     /* Select audio stream */
1266     if( p_main->b_audio )
1267     {
1268         /* For audio: first one if none or a not existing one specified */
1269         i_audio = config_GetIntVariable( INPUT_CHANNEL_VAR );
1270         if( i_audio < 0 /*|| i_audio > i_audio_nb*/ )
1271         {
1272             config_PutIntVariable( INPUT_CHANNEL_VAR, 1 );
1273             i_audio = 1;
1274         }
1275         if( i_audio > 0 /*&& i_audio_nb > 0*/ )
1276         {
1277             if( config_GetIntVariable( AOUT_SPDIF_VAR ) ||
1278                 ( config_GetIntVariable( INPUT_AUDIO_VAR ) ==
1279                   REQUESTED_AC3 ) )
1280             {
1281                 int     i_ac3 = i_audio;
1282                 while( ( p_input->stream.pp_es[i_ac3]->i_type !=
1283                          AC3_AUDIO_ES ) && ( i_ac3 <=
1284                          p_dvd->p_ifo->vts.manager_inf.i_audio_nb ) )
1285                 {
1286                     i_ac3++;
1287                 }
1288                 if( p_input->stream.pp_es[i_ac3]->i_type == AC3_AUDIO_ES )
1289                 {
1290                     input_SelectES( p_input,
1291                                     p_input->stream.pp_es[i_ac3] );
1292                 }
1293             }
1294             else
1295             {
1296                 input_SelectES( p_input,
1297                                 p_input->stream.pp_es[i_audio] );
1298             }
1299         }
1300     }
1301
1302     /* Select subtitle */
1303     if( p_main->b_video )
1304     {
1305         /* for spu, default is none */
1306         i_spu = config_GetIntVariable( INPUT_SUBTITLE_VAR );
1307         if( i_spu < 0 /*|| i_spu > i_spu_nb*/ )
1308         {
1309             config_PutIntVariable( INPUT_SUBTITLE_VAR, 0 );
1310             i_spu = 0;
1311         }
1312         if( i_spu > 0 /* && i_spu_nb > 0*/ )
1313         {
1314             i_spu += p_dvd->p_ifo->vts.manager_inf.i_audio_nb;
1315             input_SelectES( p_input, p_input->stream.pp_es[i_spu] );
1316         }
1317     }
1318 }