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