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.
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.132 2002/03/05 17:46:33 stef Exp $
13 * Author: Stéphane Borel <stef@via.ecp.fr>
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.
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.
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 *****************************************************************************/
30 /*****************************************************************************
32 *****************************************************************************/
37 #include <videolan/vlc.h>
44 #include <sys/types.h>
49 #ifdef STRNCASECMP_IN_STRINGS_H
54 # include <io.h> /* read() */
58 # include "dummy_dvdcss.h"
60 # include <videolan/dvdcss.h>
63 #include "stream_control.h"
64 #include "input_ext-intf.h"
65 #include "input_ext-dec.h"
66 #include "input_ext-plugins.h"
68 #include "input_dvd.h"
70 #include "dvd_summary.h"
75 /* how many packets DVDDemux will read in each loop */
76 #define DVD_READ_ONCE 64
78 /*****************************************************************************
80 *****************************************************************************/
82 /* called from outside */
83 static int DVDOpen ( struct input_thread_s * );
84 static void DVDClose ( struct input_thread_s * );
85 static int DVDSetArea ( struct input_thread_s *, struct input_area_s * );
86 static int DVDSetProgram ( struct input_thread_s *, pgrm_descriptor_t * );
87 static int DVDRead ( struct input_thread_s *, byte_t *, size_t );
88 static void DVDSeek ( struct input_thread_s *, off_t );
90 static int DVDRewind ( struct input_thread_s * );
91 static int DVDDemux ( struct input_thread_s * );
92 static int DVDInit ( struct input_thread_s * );
93 static void DVDEnd ( struct input_thread_s * );
95 /* called only inside */
96 static void DVDLaunchDecoders( input_thread_t * p_input );
97 static int DVDChooseAngle( thread_dvd_data_t * );
98 static int DVDFindCell( thread_dvd_data_t * );
99 static int DVDFindSector( thread_dvd_data_t * );
100 static int DVDChapterSelect( thread_dvd_data_t *, int );
102 /*****************************************************************************
103 * Functions exported as capabilities. They are declared as static so that
104 * we don't pollute the namespace too much.
105 *****************************************************************************/
106 void _M( access_getfunctions)( function_list_t * p_function_list )
108 #define input p_function_list->functions.access
109 input.pf_open = DVDOpen;
110 input.pf_close = DVDClose;
111 input.pf_read = DVDRead;
112 input.pf_set_area = DVDSetArea;
113 input.pf_set_program = DVDSetProgram;
114 input.pf_seek = DVDSeek;
118 void _M( demux_getfunctions)( function_list_t * p_function_list )
120 #define demux p_function_list->functions.demux
121 demux.pf_init = DVDInit;
122 demux.pf_end = DVDEnd;
123 demux.pf_demux = DVDDemux;
124 demux.pf_rewind = DVDRewind;
129 * Data demux functions
132 /*****************************************************************************
133 * DVDInit: initializes DVD structures
134 *****************************************************************************/
135 static int DVDInit( input_thread_t * p_input )
138 if( strncmp( p_input->p_access_module->psz_name, "dvd", 3 ) )
143 vlc_mutex_lock( &p_input->stream.stream_lock );
145 DVDLaunchDecoders( p_input );
147 vlc_mutex_unlock( &p_input->stream.stream_lock );
152 /*****************************************************************************
153 * DVDEnd: frees unused data
154 *****************************************************************************/
155 static void DVDEnd( input_thread_t * p_input )
159 /*****************************************************************************
161 *****************************************************************************/
162 #define PEEK( SIZE ) \
163 i_result = input_Peek( p_input, &p_peek, SIZE ); \
164 if( i_result == -1 ) \
168 else if( i_result < SIZE ) \
174 static int DVDDemux( input_thread_t * p_input )
178 data_packet_t * p_data;
183 /* Read headers to compute payload length */
184 for( i = 0 ; i < DVD_READ_ONCE ; i++ )
187 /* Read what we believe to be a packet header. */
191 if( U32_AT( p_peek ) != 0x1BA )
193 /* That's the case for all packets, except pack header. */
194 i_packet_size = U16_AT( p_peek + 4 );
198 /* MPEG-2 Pack header. */
202 /* Fetch a packet of the appropriate size. */
203 i_result = input_SplitBuffer( p_input, &p_data, i_packet_size + 6 );
209 /* In MPEG-2 pack headers we still have to read stuffing bytes. */
210 if( (p_data->p_demux_start[3] == 0xBA) && (i_packet_size == 8) )
212 size_t i_stuffing = (p_data->p_demux_start[13] & 0x7);
213 /* Force refill of the input buffer - though we don't care
214 * about p_peek. Please note that this is unoptimized. */
216 p_input->p_current_data += i_stuffing;
219 input_DemuxPS( p_input, p_data );
226 /*****************************************************************************
227 * DVDRewind : reads a stream backward
228 *****************************************************************************/
229 static int DVDRewind( input_thread_t * p_input )
237 * Data access functions
240 /*****************************************************************************
242 *****************************************************************************/
243 static int DVDOpen( struct input_thread_s *p_input )
245 struct stat stat_info;
251 dvdcss_handle dvdhandle;
252 thread_dvd_data_t * p_dvd;
253 input_area_t * p_area;
254 boolean_t b_options = 0;
260 psz_orig = psz_parser = psz_device = strdup( p_input->psz_name );
267 /* Parse input string :
268 * [device][@rawdevice][@[title][,[chapter][,angle]]] */
269 while( *psz_parser && *psz_parser != '@' )
274 if( *psz_parser == '@' )
276 /* Maybe found raw device or option list */
278 psz_raw = ++psz_parser;
285 if( *psz_parser && !strtol( psz_parser, NULL, 10 ) )
287 /* what we've found is either a raw device or a partial option
288 * list e.g. @,29 or both a device and a list ; search end of string */
289 while( *psz_parser && *psz_parser != '@' )
294 if( *psz_parser == '@' )
296 /* found end of raw device, and beginning of options */
303 psz_parser = psz_raw + 1;
304 for( i=0 ; i<3 ; i++ )
308 /* we have only a raw device */
311 if( strtol( psz_parser, NULL, 10 ) )
313 /* we have only a partial list of options, no device */
314 psz_parser = psz_raw;
325 /* found beginning of options ; no raw device specified */
333 i_title = (int)strtol( psz_parser, &psz_next, 10 );
336 psz_parser = psz_next + 1;
337 i_chapter = (int)strtol( psz_parser, &psz_next, 10 );
340 i_angle = (int)strtol( psz_next + 1, NULL, 10 );
344 i_title = i_title ? i_title : 1;
345 i_chapter = i_chapter ? i_chapter : 1;
346 i_angle = i_angle ? i_angle : 1;
353 /* check the raw device */
354 if( stat( psz_raw, &stat_info ) == -1 )
356 intf_WarnMsg( 3, "dvd warning: cannot stat() raw"
358 psz_raw, strerror(errno));
360 *(psz_raw - 1) = '@';
368 if( !S_ISCHR(stat_info.st_mode) )
370 intf_WarnMsg( 3, "dvd warning: raw device %s is"
371 " not a valid char device", psz_raw );
373 *(psz_raw - 1) = '@';
379 psz_env = malloc( strlen("DVDCSS_RAW_DEVICE=")
380 + strlen( psz_raw ) + 1 );
381 sprintf( psz_env, "DVDCSS_RAW_DEVICE=%s", psz_raw );
394 if( !p_input->psz_access )
396 /* no device and no access specified: we probably don't want DVD */
400 psz_device = config_GetPszVariable( INPUT_DVD_DEVICE_VAR );
403 /* check block device */
404 if( stat( psz_device, &stat_info ) == -1 )
406 intf_ErrMsg( "input error: cannot stat() device `%s' (%s)",
407 psz_device, strerror(errno));
412 if( !S_ISBLK(stat_info.st_mode) && !S_ISCHR(stat_info.st_mode) )
414 intf_WarnMsg( 3, "input: DVD plugin discarded"
415 " (not a valid block device)" );
424 intf_WarnMsg( 2, "input: dvd=%s raw=%s title=%d chapter=%d angle=%d",
425 psz_device, psz_raw, i_title, i_chapter, i_angle );
432 vlc_mutex_lock( &p_input->stream.stream_lock );
434 p_input->stream.i_method = INPUT_METHOD_DVD;
436 /* If we are here we can control the pace... */
437 p_input->stream.b_pace_control = 1;
439 p_input->stream.b_seekable = 1;
440 p_input->stream.p_selected_area->i_size = 0;
442 p_input->stream.p_selected_area->i_tell = 0;
444 vlc_mutex_unlock( &p_input->stream.stream_lock );
449 dvdhandle = dvdcss_open( psz_device );
451 /* free allocated strings */
452 if( psz_device != psz_orig )
457 if( dvdhandle == NULL )
459 intf_ErrMsg( "dvd error: dvdcss can't open device" );
463 p_dvd = malloc( sizeof(thread_dvd_data_t) );
466 intf_ErrMsg( "dvd error: out of memory" );
470 p_dvd->dvdhandle = (dvdcss_handle) dvdhandle;
471 p_input->p_access_data = (void *)p_dvd;
473 if( dvdcss_seek( p_dvd->dvdhandle, 0, DVDCSS_NOFLAGS ) < 0 )
475 intf_ErrMsg( "dvd error: %s", dvdcss_error( p_dvd->dvdhandle ) );
479 /* Ifo allocation & initialisation */
480 if( IfoCreate( p_dvd ) < 0 )
482 intf_ErrMsg( "dvd error: allcation error in ifo" );
487 if( IfoInit( p_dvd->p_ifo ) < 0 )
489 intf_ErrMsg( "dvd error: fatal failure in ifo" );
490 IfoDestroy( p_dvd->p_ifo );
495 /* Set stream and area data */
496 vlc_mutex_lock( &p_input->stream.stream_lock );
498 /* Initialize ES structures */
499 input_InitStream( p_input, sizeof( stream_ps_data_t ) );
501 #define title_inf p_dvd->p_ifo->vmg.title_inf
502 intf_WarnMsg( 2, "dvd info: number of titles: %d", title_inf.i_title_nb );
504 #define area p_input->stream.pp_areas
505 /* We start from 1 here since the default area 0
506 * is reserved for video_ts.vob */
507 for( i = 1 ; i <= title_inf.i_title_nb ; i++ )
509 input_AddArea( p_input );
511 /* Titles are Program Chains */
514 /* Absolute start offset and size
515 * We can only set that with vts ifo, so we do it during the
516 * first call to DVDSetArea */
517 area[i]->i_start = 0;
520 /* Number of chapters */
521 area[i]->i_part_nb = title_inf.p_attr[i-1].i_chapter_nb;
524 /* Offset to vts_i_0.ifo */
525 area[i]->i_plugin_data = p_dvd->p_ifo->i_start +
526 title_inf.p_attr[i-1].i_start_sector;
530 p_dvd->i_title = i_title <= title_inf.i_title_nb ? i_title : 1;
534 p_area = p_input->stream.pp_areas[p_dvd->i_title];
536 p_dvd->i_chapter = i_chapter < p_area->i_part_nb ? i_chapter : 1;
537 p_area->i_part = p_dvd->i_chapter;
539 p_dvd->i_angle = i_angle;
541 /* set title, chapter, audio and subpic */
542 if( DVDSetArea( p_input, p_area ) )
544 vlc_mutex_unlock( &p_input->stream.stream_lock );
548 vlc_mutex_unlock( &p_input->stream.stream_lock );
554 /*****************************************************************************
555 * DVDClose: close dvd
556 *****************************************************************************/
557 static void DVDClose( struct input_thread_s *p_input )
559 thread_dvd_data_t * p_dvd;
561 p_dvd = (thread_dvd_data_t*)p_input->p_access_data;
563 IfoDestroy( p_dvd->p_ifo );
565 p_input->p_access_data = (void *)(p_dvd->dvdhandle);
568 /* Clean up libdvdcss */
569 dvdcss_close( (dvdcss_handle) p_input->p_access_data );
572 /*****************************************************************************
573 * DVDSetProgram: Does nothing, a DVD is mono-program
574 *****************************************************************************/
575 static int DVDSetProgram( input_thread_t * p_input,
576 pgrm_descriptor_t * p_program )
578 if( p_input->stream.p_selected_program != p_program )
580 thread_dvd_data_t * p_dvd;
583 p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);
584 i_angle = p_program->i_number;
586 memcpy( p_program, p_input->stream.p_selected_program,
587 sizeof(pgrm_descriptor_t) );
588 p_program->i_number = i_angle;
589 p_input->stream.p_selected_program = p_program;
592 p_dvd->p_ifo->vts.title_unit.p_title[p_dvd->i_title_id-1].title
593 if( title.p_cell_play[p_dvd->i_prg_cell].i_category & 0xf000 )
595 if( ( p_program->i_number - p_dvd->i_angle ) < 0 )
599 p_dvd->i_prg_cell += ( p_program->i_number - p_dvd->i_angle );
600 p_dvd->i_angle = p_program->i_number;
602 DVDFindSector( p_dvd );
603 p_dvd->i_cell += p_dvd->i_angle_cell;
607 p_dvd->i_angle = p_program->i_number;
610 intf_WarnMsg( 3, "dvd info: angle %d selected", p_dvd->i_angle );
616 /*****************************************************************************
617 * DVDSetArea: initialize input data for title x, chapter y.
618 * It should be called for each user navigation request.
619 *****************************************************************************
620 * Take care that i_title starts from 0 (vmg) and i_chapter start from 1.
621 * Note that you have to take the lock before entering here.
622 *****************************************************************************/
623 static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area )
625 thread_dvd_data_t * p_dvd;
626 es_descriptor_t * p_es;
633 p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);
635 /* we can't use the interface slider until initilization is complete */
636 p_input->stream.b_seekable = 0;
638 if( p_area != p_input->stream.p_selected_area )
640 /* Reset the Chapter position of the old title */
641 p_input->stream.p_selected_area->i_part = 0;
644 * We have to load all title information
646 /* Change the default area */
647 p_input->stream.p_selected_area =
648 p_input->stream.pp_areas[p_area->i_id];
650 /* title number: it is not vts nb!,
651 * it is what appears in the interface list */
652 p_dvd->i_title = p_area->i_id;
653 p_dvd->p_ifo->i_title = p_dvd->i_title;
655 /* set number of chapters of current title */
656 p_dvd->i_chapter_nb = p_area->i_part_nb;
659 if( IfoTitleSet( p_dvd->p_ifo ) < 0 )
661 intf_ErrMsg( "dvd error: fatal error in vts ifo" );
663 p_input->b_error = 1;
667 #define vmg p_dvd->p_ifo->vmg
668 #define vts p_dvd->p_ifo->vts
669 /* title position inside the selected vts */
670 i_vts_title = vmg.title_inf.p_attr[p_dvd->i_title-1].i_title_num;
672 vts.title_inf.p_title_start[i_vts_title-1].i_title_id;
674 intf_WarnMsg( 3, "dvd: title %d vts_title %d pgc %d",
675 p_dvd->i_title, i_vts_title, p_dvd->i_title_id );
680 p_dvd->i_angle_nb = vmg.title_inf.p_attr[p_dvd->i_title-1].i_angle_nb;
681 if( ( p_dvd->i_angle <= 0 ) || p_dvd->i_angle > p_dvd->i_angle_nb )
687 * Set selected title start and size
690 /* title set offset XXX: convert to block values */
691 p_dvd->i_title_start =
692 vts.i_pos + vts.manager_inf.i_title_vob_start_sector;
694 /* last video cell */
696 p_dvd->i_prg_cell = -1 +
697 vts.title_unit.p_title[p_dvd->i_title_id-1].title.i_cell_nb;
699 if( DVDFindCell( p_dvd ) < 0 )
701 intf_ErrMsg( "dvd error: can't find title end" );
702 p_input->b_error = 1;
706 /* temporary hack to fix size in some dvds */
707 if( p_dvd->i_cell >= vts.cell_inf.i_cell_nb )
709 p_dvd->i_cell = vts.cell_inf.i_cell_nb - 1;
713 p_dvd->i_size = vts.cell_inf.p_cell_map[p_dvd->i_cell].i_end_sector;
715 if( DVDChapterSelect( p_dvd, 1 ) < 0 )
717 intf_ErrMsg( "dvd error: can't find first chapter" );
718 p_input->b_error = 1;
722 /* Force libdvdcss to check its title key.
723 * It is only useful for title cracking method. Methods using the
724 * decrypted disc key are fast enough to check the key at each seek */
726 if( dvdcss_seek( p_dvd->dvdhandle, p_dvd->i_start,
727 DVDCSS_SEEK_KEY ) < 0 )
729 intf_ErrMsg( "dvd error: %s", dvdcss_error( p_dvd->dvdhandle ) );
733 p_dvd->i_size -= p_dvd->i_sector + 1;
735 IfoPrintTitle( p_dvd );
737 /* Area definition */
738 p_input->stream.p_selected_area->i_start = LB2OFF( p_dvd->i_start );
739 p_input->stream.p_selected_area->i_size = LB2OFF( p_dvd->i_size );
742 /* start at the beginning of the title */
743 /* FIXME: create a conf option to select whether to restart
745 p_input->stream.p_selected_area->i_tell = 0;
746 p_input->stream.p_selected_area->i_part = 1;
750 * Destroy obsolete ES by reinitializing programs
751 * and find all ES in title with ifo data
753 if( p_input->stream.pp_programs != NULL )
755 /* We don't use input_EndStream here since
756 * we keep area structures */
758 /* Unselect all ES */
760 for( i = 0 ; i < p_input->stream.i_selected_es_number ; i++ )
762 input_UnselectES( p_input, p_input->stream.pp_selected_es[i] );
766 for( i = 0 ; i < p_input->stream.i_es_number ; i++ )
768 input_DelES( p_input, p_input->stream.pp_es[i] );
771 for( i = 0 ; i < p_input->stream.i_pgrm_number ; i++ )
773 input_DelProgram( p_input, p_input->stream.pp_programs[i] );
776 if( p_input->stream.pp_selected_es )
778 free( p_input->stream.pp_selected_es );
779 p_input->stream.pp_selected_es = NULL;
781 p_input->stream.i_selected_es_number = 0;
786 input_AddProgram( p_input, 1, sizeof( stream_ps_data_t ) );
787 p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
789 for( i = 1 ; i < p_dvd->i_angle_nb ; i++ )
791 input_AddProgram( p_input, i+1, 0 );
794 DVDSetProgram( p_input,
795 p_input->stream.pp_programs[p_dvd->i_angle-1] );
798 /* No PSM to read in DVD mode, we already have all information */
799 p_input->stream.p_selected_program->b_is_ok = 1;
803 /* ES 0 -> video MPEG2 */
804 IfoPrintVideo( p_dvd );
806 p_es = input_AddES( p_input, NULL, 0xe0, 0 );
807 p_es->i_stream_id = 0xe0;
808 p_es->i_type = MPEG2_VIDEO_ES;
809 p_es->i_cat = VIDEO_ES;
811 #define audio_status \
812 vts.title_unit.p_title[p_dvd->i_title_id-1].title.pi_audio_status[i-1]
813 /* Audio ES, in the order they appear in .ifo */
814 for( i = 1 ; i <= vts.manager_inf.i_audio_nb ; i++ )
816 IfoPrintAudio( p_dvd, i );
818 /* audio channel is active if first byte is 0x80 */
819 if( audio_status.i_available )
823 switch( vts.manager_inf.p_audio_attr[i-1].i_coding_mode )
826 i_id = ( ( 0x80 + audio_status.i_position ) << 8 ) | 0xbd;
827 p_es = input_AddES( p_input, NULL, i_id, 0 );
828 p_es->i_stream_id = 0xbd;
829 p_es->i_type = AC3_AUDIO_ES;
831 p_es->i_cat = AUDIO_ES;
832 strcpy( p_es->psz_desc, DecodeLanguage( hton16(
833 vts.manager_inf.p_audio_attr[i-1].i_lang_code ) ) );
834 strcat( p_es->psz_desc, " (ac3)" );
838 case 0x03: /* MPEG audio */
839 i_id = 0xc0 + audio_status.i_position;
840 p_es = input_AddES( p_input, NULL, i_id, 0 );
841 p_es->i_stream_id = i_id;
842 p_es->i_type = MPEG2_AUDIO_ES;
844 p_es->i_cat = AUDIO_ES;
845 strcpy( p_es->psz_desc, DecodeLanguage( hton16(
846 vts.manager_inf.p_audio_attr[i-1].i_lang_code ) ) );
847 strcat( p_es->psz_desc, " (mpeg)" );
850 case 0x04: /* LPCM */
852 i_id = ( ( 0xa0 + audio_status.i_position ) << 8 ) | 0xbd;
853 p_es = input_AddES( p_input, NULL, i_id, 0 );
854 p_es->i_stream_id = 0xbd;
855 p_es->i_type = LPCM_AUDIO_ES;
857 p_es->i_cat = AUDIO_ES;
858 strcpy( p_es->psz_desc, DecodeLanguage( hton16(
859 vts.manager_inf.p_audio_attr[i-1].i_lang_code ) ) );
860 strcat( p_es->psz_desc, " (lpcm)" );
864 i_id = ( ( 0x88 + audio_status.i_position ) << 8 ) | 0xbd;
865 intf_ErrMsg( "dvd warning: DTS audio not handled yet"
870 intf_ErrMsg( "dvd warning: unknown audio type %.2x",
871 vts.manager_inf.p_audio_attr[i-1].i_coding_mode );
877 vts.title_unit.p_title[p_dvd->i_title_id-1].title.pi_spu_status[i-1]
881 for( i = 1 ; i <= vts.manager_inf.i_spu_nb; i++ )
883 IfoPrintSpu( p_dvd, i );
885 if( spu_status.i_available )
889 /* there are several streams for one spu */
890 if( vts.manager_inf.video_attr.i_ratio )
893 switch( vts.manager_inf.video_attr.i_perm_displ )
896 i_id = ( ( 0x20 + spu_status.i_position_pan ) << 8 )
900 i_id = ( ( 0x20 + spu_status.i_position_letter ) << 8 )
904 i_id = ( ( 0x20 + spu_status.i_position_wide ) << 8 )
912 i_id = ( ( 0x20 + spu_status.i_position_43 ) << 8 )
915 p_es = input_AddES( p_input, NULL, i_id, 0 );
916 p_es->i_stream_id = 0xbd;
917 p_es->i_type = DVD_SPU_ES;
918 p_es->i_cat = SPU_ES;
919 strcpy( p_es->psz_desc, DecodeLanguage( hton16(
920 vts.manager_inf.p_spu_attr[i-1].i_lang_code ) ) );
925 /* FIXME: hack to check that the demuxer is ready, and set
927 if( p_input->p_demux_module )
929 DVDLaunchDecoders( p_input );
935 p_area = p_input->stream.p_selected_area;
944 if( p_area->i_part != p_dvd->i_chapter )
946 if( ( p_area->i_part > 0 ) &&
947 ( p_area->i_part <= p_area->i_part_nb ))
949 if( DVDChapterSelect( p_dvd, p_area->i_part ) < 0 )
951 intf_ErrMsg( "dvd error: can't set chapter in area" );
952 p_input->b_error = 1;
956 p_input->stream.p_selected_area->i_tell =
957 LB2OFF( p_dvd->i_start ) - p_area->i_start;
958 p_input->stream.p_selected_area->i_part = p_dvd->i_chapter;
960 intf_WarnMsg( 4, "dvd info: chapter %d start at: %lld",
961 p_area->i_part, p_area->i_tell );
966 p_dvd->i_chapter = 1;
971 p_dvd->p_ifo->vts.title_unit.p_title[p_dvd->i_title_id-1].title
973 /* warn interface that something has changed */
974 p_input->stream.b_seekable = 1;
975 p_input->stream.b_changed = 1;
981 /*****************************************************************************
982 * DVDRead: reads data packets.
983 *****************************************************************************
984 * Returns -1 in case of error, 0 in case of EOF, otherwise the number of
986 *****************************************************************************/
987 static int DVDRead( input_thread_t * p_input,
988 byte_t * p_buffer, size_t i_count )
990 thread_dvd_data_t * p_dvd;
998 p_dvd = (thread_dvd_data_t *)(p_input->p_access_data);
1005 i_blocks = OFF2LB(i_count);
1009 i_sector = p_dvd->i_title_start + p_dvd->i_sector;
1010 i_block_once = p_dvd->i_end_sector - p_dvd->i_sector + 1;
1012 /* Get the position of the next cell if we're at cell end */
1013 if( i_block_once <= 0 )
1018 p_dvd->i_angle_cell++;
1020 /* Find cell index in adress map */
1021 if( DVDFindSector( p_dvd ) < 0 )
1023 intf_ErrMsg( "dvd error: can't find next cell" );
1027 /* Position the fd pointer on the right address */
1028 if( ( i_sector = dvdcss_seek( p_dvd->dvdhandle,
1029 p_dvd->i_title_start + p_dvd->i_sector,
1030 DVDCSS_SEEK_MPEG ) ) < 0 )
1032 intf_ErrMsg( "dvd error: %s", dvdcss_error( p_dvd->dvdhandle ) );
1036 /* update chapter : it will be easier when we have navigation
1038 if( p_dvd->i_chapter < ( p_dvd->i_chapter_nb - 1 ) )
1040 if( title.p_cell_play[p_dvd->i_prg_cell].i_category & 0xf000 )
1042 i_angle = p_dvd->i_angle - 1;
1048 if( title.chapter_map.pi_start_cell[p_dvd->i_chapter] <=
1049 ( p_dvd->i_prg_cell - i_angle + 1 ) )
1056 i_block_once = p_dvd->i_end_sector - p_dvd->i_sector + 1;
1059 /* The number of blocks read is the max between the requested
1060 * value and the leaving block in the cell */
1061 if( i_block_once > i_blocks )
1063 i_block_once = i_blocks;
1066 intf_WarnMsg( 2, "Sector: 0x%x Read: %d Chapter: %d", p_dvd->i_sector, i_block_once, p_dvd->i_chapter );
1069 /* Reads from DVD */
1070 i_read_blocks = dvdcss_read( p_dvd->dvdhandle, p_buffer,
1071 i_block_once, DVDCSS_READ_DECRYPT );
1073 i_blocks -= i_read_blocks;
1074 p_buffer += LB2OFF( i_read_blocks );
1075 i_read_total += i_read_blocks;
1077 /* Update global position */
1078 p_dvd->i_sector += i_read_blocks;
1081 vlc_mutex_lock( &p_input->stream.stream_lock );
1083 p_input->stream.p_selected_area->i_tell =
1084 LB2OFF( i_sector + i_read_total ) -
1085 p_input->stream.p_selected_area->i_start;
1088 /* We modify i_part only at end of chapter not to erase
1089 * some modification from the interface */
1090 p_input->stream.p_selected_area->i_part = p_dvd->i_chapter;
1093 if( p_input->stream.p_selected_area->i_tell
1094 >= p_input->stream.p_selected_area->i_size )
1096 if( ( p_dvd->i_title + 1 ) >= p_input->stream.i_area_nb )
1099 vlc_mutex_unlock( &p_input->stream.stream_lock );
1104 intf_WarnMsg( 4, "dvd info: new title" );
1106 DVDSetArea( p_input, p_input->stream.pp_areas[p_dvd->i_title] );
1107 vlc_mutex_unlock( &p_input->stream.stream_lock );
1108 return LB2OFF( i_read_total );
1111 vlc_mutex_unlock( &p_input->stream.stream_lock );
1113 if( i_read_blocks != i_block_once )
1118 return LB2OFF( i_read_total );
1121 /*****************************************************************************
1122 * DVDSeek : Goes to a given position on the stream.
1123 *****************************************************************************
1124 * This one is used by the input and translate chronological position from
1125 * input to logical position on the device.
1126 * The lock should be taken before calling this function.
1127 *****************************************************************************/
1128 static void DVDSeek( input_thread_t * p_input, off_t i_off )
1130 thread_dvd_data_t * p_dvd;
1137 p_dvd = ( thread_dvd_data_t * )(p_input->p_access_data);
1139 vlc_mutex_lock( &p_input->stream.stream_lock );
1140 /* we have to take care of offset of beginning of title */
1141 p_dvd->i_sector = OFF2LB(i_off + p_input->stream.p_selected_area->i_start)
1142 - p_dvd->i_title_start;
1143 vlc_mutex_unlock( &p_input->stream.stream_lock );
1148 /* parse vobu address map to find program cell */
1149 while( title.p_cell_play[i_prg_cell].i_end_sector < p_dvd->i_sector )
1154 p_dvd->i_prg_cell = i_prg_cell;
1156 if( DVDChooseAngle( p_dvd ) < 0 )
1158 p_input->b_error = 1;
1164 /* Find first title cell which is inside program cell */
1165 if( DVDFindCell( p_dvd ) < 0 )
1167 /* no following cell : we're at eof */
1168 intf_ErrMsg( "dvd error: cell seeking failed" );
1169 p_input->b_error = 1;
1173 i_cell = p_dvd->i_cell;
1175 #define cell p_dvd->p_ifo->vts.cell_inf.p_cell_map[i_cell]
1176 /* parse cell address map to find title cell containing sector */
1177 while( cell.i_end_sector < p_dvd->i_sector )
1182 p_dvd->i_cell = i_cell;
1184 /* if we're inside a multi-angle zone, we have to choose i_sector
1185 * in the current angle ; we can't do it all the time since cells
1186 * can be very wide out of such zones */
1187 if( title.p_cell_play[p_dvd->i_prg_cell].i_category & 0xf000 )
1189 p_dvd->i_sector = __MAX(
1190 cell.i_start_sector,
1191 title.p_cell_play[p_dvd->i_prg_cell].i_start_sector );
1194 p_dvd->i_end_sector = __MIN(
1196 title.p_cell_play[p_dvd->i_prg_cell].i_end_sector );
1198 /* update chapter */
1199 if( title.p_cell_play[p_dvd->i_prg_cell].i_category & 0xf000 )
1201 i_angle = p_dvd->i_angle - 1;
1207 if( p_dvd->i_chapter_nb > 1 )
1209 while( ( title.chapter_map.pi_start_cell[i_chapter] <=
1210 ( p_dvd->i_prg_cell - i_angle + 1 ) ) &&
1211 ( i_chapter < ( p_dvd->i_chapter_nb - 1 ) ) )
1221 p_dvd->i_chapter = i_chapter;
1223 if( ( i_block = dvdcss_seek( p_dvd->dvdhandle,
1224 p_dvd->i_title_start + p_dvd->i_sector,
1225 DVDCSS_SEEK_MPEG ) ) < 0 )
1227 intf_ErrMsg( "dvd error: %s", dvdcss_error( p_dvd->dvdhandle ) );
1228 p_input->b_error = 1;
1232 vlc_mutex_lock( &p_input->stream.stream_lock );
1233 p_input->stream.p_selected_area->i_part = p_dvd->i_chapter;
1234 p_input->stream.p_selected_area->i_tell =
1235 LB2OFF ( i_block ) - p_input->stream.p_selected_area->i_start;
1236 vlc_mutex_unlock( &p_input->stream.stream_lock );
1238 intf_WarnMsg( 7, "Program Cell: %d Cell: %d Chapter: %d",
1239 p_dvd->i_prg_cell, p_dvd->i_cell, p_dvd->i_chapter );
1244 #define cell p_dvd->p_ifo->vts.cell_inf
1246 /*****************************************************************************
1247 * DVDFindCell: adjust the title cell index with the program cell
1248 *****************************************************************************/
1249 static int DVDFindCell( thread_dvd_data_t * p_dvd )
1254 i_cell = p_dvd->i_cell;
1255 i_index = p_dvd->i_prg_cell;
1257 if( i_cell >= cell.i_cell_nb )
1262 while( ( ( title.p_cell_pos[i_index].i_vob_id !=
1263 cell.p_cell_map[i_cell].i_vob_id ) ||
1264 ( title.p_cell_pos[i_index].i_cell_id !=
1265 cell.p_cell_map[i_cell].i_cell_id ) ) &&
1266 ( i_cell < cell.i_cell_nb - 1 ) )
1272 intf_WarnMsg( 12, "FindCell: i_cell %d i_index %d found %d nb %d",
1279 p_dvd->i_cell = i_cell;
1286 /*****************************************************************************
1287 * DVDFindSector: find cell index in adress map from index in
1288 * information table program map and give corresponding sectors.
1289 *****************************************************************************/
1290 static int DVDFindSector( thread_dvd_data_t * p_dvd )
1293 if( p_dvd->i_sector > title.p_cell_play[p_dvd->i_prg_cell].i_end_sector )
1295 p_dvd->i_prg_cell++;
1297 if( DVDChooseAngle( p_dvd ) < 0 )
1303 if( DVDFindCell( p_dvd ) < 0 )
1305 intf_ErrMsg( "dvd error: can't find sector" );
1309 /* Find start and end sectors of new cell */
1311 p_dvd->i_sector = __MAX(
1312 p_dvd->p_ifo->vts.cell_inf.p_cell_map[p_dvd->i_cell].i_start_sector,
1313 title.p_cell_play[p_dvd->i_prg_cell].i_start_sector );
1314 p_dvd->i_end_sector = __MIN(
1315 p_dvd->p_ifo->vts.cell_inf.p_cell_map[p_dvd->i_cell].i_end_sector,
1316 title.p_cell_play[p_dvd->i_prg_cell].i_end_sector );
1318 p_dvd->i_sector = title.p_cell_play[p_dvd->i_prg_cell].i_start_sector;
1319 p_dvd->i_end_sector = title.p_cell_play[p_dvd->i_prg_cell].i_end_sector;
1323 intf_WarnMsg( 12, "cell: %d sector1: 0x%x end1: 0x%x\n"
1324 "index: %d sector2: 0x%x end2: 0x%x\n"
1325 "category: 0x%x ilvu end: 0x%x vobu start 0x%x",
1327 p_dvd->p_ifo->vts.cell_inf.p_cell_map[p_dvd->i_cell].i_start_sector,
1328 p_dvd->p_ifo->vts.cell_inf.p_cell_map[p_dvd->i_cell].i_end_sector,
1330 title.p_cell_play[p_dvd->i_prg_cell].i_start_sector,
1331 title.p_cell_play[p_dvd->i_prg_cell].i_end_sector,
1332 title.p_cell_play[p_dvd->i_prg_cell].i_category,
1333 title.p_cell_play[p_dvd->i_prg_cell].i_first_ilvu_vobu_esector,
1334 title.p_cell_play[p_dvd->i_prg_cell].i_last_vobu_start_sector );
1340 /*****************************************************************************
1341 * DVDChapterSelect: find the cell corresponding to requested chapter
1342 *****************************************************************************/
1343 static int DVDChapterSelect( thread_dvd_data_t * p_dvd, int i_chapter )
1346 /* Find cell index in Program chain for current chapter */
1347 p_dvd->i_prg_cell = title.chapter_map.pi_start_cell[i_chapter-1] - 1;
1349 p_dvd->i_sector = 0;
1351 DVDChooseAngle( p_dvd );
1353 /* Search for cell_index in cell adress_table and initialize
1355 if( DVDFindSector( p_dvd ) < 0 )
1357 intf_ErrMsg( "dvd error: can't select chapter" );
1361 /* start is : beginning of vts vobs + offset to vob x */
1362 p_dvd->i_start = p_dvd->i_title_start + p_dvd->i_sector;
1364 /* Position the fd pointer on the right address */
1365 if( ( p_dvd->i_start = dvdcss_seek( p_dvd->dvdhandle,
1367 DVDCSS_SEEK_MPEG ) ) < 0 )
1369 intf_ErrMsg( "dvd error: %s", dvdcss_error( p_dvd->dvdhandle ) );
1373 p_dvd->i_chapter = i_chapter;
1377 /*****************************************************************************
1378 * DVDChooseAngle: select the cell corresponding to the selected angle
1379 *****************************************************************************/
1380 static int DVDChooseAngle( thread_dvd_data_t * p_dvd )
1382 /* basic handling of angles */
1383 switch( ( ( title.p_cell_play[p_dvd->i_prg_cell].i_category & 0xf000 )
1386 /* we enter a muli-angle section */
1388 p_dvd->i_prg_cell += p_dvd->i_angle - 1;
1389 p_dvd->i_angle_cell = 0;
1391 /* we exit a multi-angle section */
1394 p_dvd->i_prg_cell += p_dvd->i_angle_nb - p_dvd->i_angle;
1402 /*****************************************************************************
1404 *****************************************************************************/
1405 static void DVDLaunchDecoders( input_thread_t * p_input )
1407 thread_dvd_data_t * p_dvd;
1411 p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);
1413 /* Select Video stream (always 0) */
1414 if( p_main->b_video )
1416 input_SelectES( p_input, p_input->stream.pp_es[0] );
1419 /* Select audio stream */
1420 if( p_main->b_audio )
1422 /* For audio: first one if none or a not existing one specified */
1423 i_audio = config_GetIntVariable( INPUT_CHANNEL_VAR );
1424 if( i_audio < 0 /*|| i_audio > i_audio_nb*/ )
1426 config_PutIntVariable( INPUT_CHANNEL_VAR, 1 );
1429 if( i_audio > 0 /*&& i_audio_nb > 0*/ )
1431 if( config_GetIntVariable( AOUT_SPDIF_VAR ) ||
1432 ( config_GetIntVariable( INPUT_AUDIO_VAR ) ==
1435 int i_ac3 = i_audio;
1436 while( ( p_input->stream.pp_es[i_ac3]->i_type !=
1437 AC3_AUDIO_ES ) && ( i_ac3 <=
1438 p_dvd->p_ifo->vts.manager_inf.i_audio_nb ) )
1442 if( p_input->stream.pp_es[i_ac3]->i_type == AC3_AUDIO_ES )
1444 input_SelectES( p_input,
1445 p_input->stream.pp_es[i_ac3] );
1450 input_SelectES( p_input,
1451 p_input->stream.pp_es[i_audio] );
1456 /* Select subtitle */
1457 if( p_main->b_video )
1459 /* for spu, default is none */
1460 i_spu = config_GetIntVariable( INPUT_SUBTITLE_VAR );
1461 if( i_spu < 0 /*|| i_spu > i_spu_nb*/ )
1463 config_PutIntVariable( INPUT_SUBTITLE_VAR, 0 );
1466 if( i_spu > 0 /* && i_spu_nb > 0*/ )
1468 i_spu += p_dvd->p_ifo->vts.manager_inf.i_audio_nb;
1469 input_SelectES( p_input, p_input->stream.pp_es[i_spu] );