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.127 2002/03/04 01:53:56 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 #define PARSE( chr, action ) \
241 psz_parser = p_input->psz_name; \
242 while( *(psz_parser) && *(psz_parser) != (chr) ) \
247 if( *(psz_parser) == (chr) ) \
249 *(psz_parser) = '\0'; \
253 /*****************************************************************************
255 *****************************************************************************/
256 static int DVDOpen( struct input_thread_s *p_input )
258 struct stat stat_info;
259 char * psz_parser = p_input->psz_name;
260 char * psz_device = p_input->psz_name;
263 dvdcss_handle dvdhandle;
264 thread_dvd_data_t * p_dvd;
265 input_area_t * p_area;
266 boolean_t b_need_free = 0;
267 boolean_t b_options = 0;
273 /* Parse input string :
274 * [device][@rawdevice][@[title][,[chapter][,angle]]] */
275 while( *psz_parser && *psz_parser != '@' )
280 if( *psz_parser == '@' )
282 /* Found raw device */
284 psz_raw = ++psz_parser;
291 if( !strtol( psz_parser, NULL, 10 ) )
293 while( *psz_parser && *psz_parser != '@' )
298 if( *psz_parser == '@' )
306 psz_parser = psz_raw + 1;
307 for( i=0 ; i<3 ; i++ )
313 if( strtol( psz_parser, NULL, 10 ) )
315 psz_parser = psz_raw;
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;
351 psz_device = config_GetPszVariable( INPUT_DVD_DEVICE_VAR );
355 if( stat( psz_device, &stat_info ) == -1 )
357 intf_ErrMsg( "input error: cannot stat() device `%s' (%s)",
358 psz_device, strerror(errno));
363 if( !S_ISBLK(stat_info.st_mode) && !S_ISCHR(stat_info.st_mode) )
365 intf_WarnMsg( 3, "input: DVD plugin discarded"
366 " (not a valid block device)" );
375 setenv( "DVDCSS_RAW_DEVICE", psz_raw, 1 );
383 intf_WarnMsg( 2, "input: dvd=%s raw=%s title=%d chapter=%d angle=%d",
384 psz_device, psz_raw, i_title, i_chapter, i_angle );
391 vlc_mutex_lock( &p_input->stream.stream_lock );
393 p_input->stream.i_method = INPUT_METHOD_DVD;
395 /* If we are here we can control the pace... */
396 p_input->stream.b_pace_control = 1;
398 p_input->stream.b_seekable = 1;
399 p_input->stream.p_selected_area->i_size = 0;
401 p_input->stream.p_selected_area->i_tell = 0;
403 vlc_mutex_unlock( &p_input->stream.stream_lock );
408 dvdhandle = dvdcss_open( psz_device );
415 if( dvdhandle == NULL )
417 intf_ErrMsg( "dvd error: dvdcss can't open device" );
421 p_dvd = malloc( sizeof(thread_dvd_data_t) );
424 intf_ErrMsg( "dvd error: out of memory" );
428 p_dvd->dvdhandle = (dvdcss_handle) dvdhandle;
429 p_input->p_access_data = (void *)p_dvd;
431 p_dvd->i_title = i_title;
432 p_dvd->i_chapter = i_chapter;
433 p_dvd->i_angle = i_angle;
435 if( dvdcss_seek( p_dvd->dvdhandle, 0, DVDCSS_NOFLAGS ) < 0 )
437 intf_ErrMsg( "dvd error: %s", dvdcss_error( p_dvd->dvdhandle ) );
441 /* Ifo allocation & initialisation */
442 if( IfoCreate( p_dvd ) < 0 )
444 intf_ErrMsg( "dvd error: allcation error in ifo" );
449 if( IfoInit( p_dvd->p_ifo ) < 0 )
451 intf_ErrMsg( "dvd error: fatal failure in ifo" );
452 IfoDestroy( p_dvd->p_ifo );
457 /* Set stream and area data */
458 vlc_mutex_lock( &p_input->stream.stream_lock );
460 /* Initialize ES structures */
461 input_InitStream( p_input, sizeof( stream_ps_data_t ) );
463 #define title_inf p_dvd->p_ifo->vmg.title_inf
464 intf_WarnMsg( 2, "dvd info: number of titles: %d", title_inf.i_title_nb );
466 #define area p_input->stream.pp_areas
467 /* We start from 1 here since the default area 0
468 * is reserved for video_ts.vob */
469 for( i = 1 ; i <= title_inf.i_title_nb ; i++ )
471 input_AddArea( p_input );
473 /* Titles are Program Chains */
476 /* Absolute start offset and size
477 * We can only set that with vts ifo, so we do it during the
478 * first call to DVDSetArea */
479 area[i]->i_start = 0;
482 /* Number of chapters */
483 area[i]->i_part_nb = title_inf.p_attr[i-1].i_chapter_nb;
486 /* Number of angles */
487 area[i]->i_angle_nb = 0;
488 area[i]->i_angle = 1;
490 /* Offset to vts_i_0.ifo */
491 area[i]->i_plugin_data = p_dvd->p_ifo->i_start +
492 title_inf.p_attr[i-1].i_start_sector;
497 p_area = p_input->stream.pp_areas[i_title];
498 p_area->i_part = i_chapter;
500 /* set title, chapter, audio and subpic */
501 if( DVDSetArea( p_input, p_area ) )
503 vlc_mutex_unlock( &p_input->stream.stream_lock );
507 vlc_mutex_unlock( &p_input->stream.stream_lock );
513 /*****************************************************************************
514 * DVDClose: close dvd
515 *****************************************************************************/
516 static void DVDClose( struct input_thread_s *p_input )
518 thread_dvd_data_t * p_dvd;
520 p_dvd = (thread_dvd_data_t*)p_input->p_access_data;
522 IfoDestroy( p_dvd->p_ifo );
524 p_input->p_access_data = (void *)(p_dvd->dvdhandle);
527 /* Clean up libdvdcss */
528 dvdcss_close( (dvdcss_handle) p_input->p_access_data );
531 /*****************************************************************************
532 * DVDSetProgram: Does nothing, a DVD is mono-program
533 *****************************************************************************/
534 static int DVDSetProgram( input_thread_t * p_input,
535 pgrm_descriptor_t * p_program )
540 /*****************************************************************************
541 * DVDSetArea: initialize input data for title x, chapter y.
542 * It should be called for each user navigation request.
543 *****************************************************************************
544 * Take care that i_title starts from 0 (vmg) and i_chapter start from 1.
545 * Note that you have to take the lock before entering here.
546 *****************************************************************************/
547 static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area )
549 thread_dvd_data_t * p_dvd;
550 es_descriptor_t * p_es;
557 p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);
559 /* we can't use the interface slider until initilization is complete */
560 p_input->stream.b_seekable = 0;
562 if( p_area != p_input->stream.p_selected_area )
564 /* Reset the Chapter position of the old title */
565 p_input->stream.p_selected_area->i_part = 0;
568 * We have to load all title information
570 /* Change the default area */
571 p_input->stream.p_selected_area =
572 p_input->stream.pp_areas[p_area->i_id];
574 /* title number: it is not vts nb!,
575 * it is what appears in the interface list */
576 p_dvd->i_title = p_area->i_id;
577 p_dvd->p_ifo->i_title = p_dvd->i_title;
579 /* set number of chapters of current title */
580 p_dvd->i_chapter_nb = p_area->i_part_nb;
583 if( IfoTitleSet( p_dvd->p_ifo ) < 0 )
585 intf_ErrMsg( "dvd error: fatal error in vts ifo" );
587 p_input->b_error = 1;
591 #define vmg p_dvd->p_ifo->vmg
592 #define vts p_dvd->p_ifo->vts
593 /* title position inside the selected vts */
594 i_vts_title = vmg.title_inf.p_attr[p_dvd->i_title-1].i_title_num;
596 vts.title_inf.p_title_start[i_vts_title-1].i_title_id;
598 intf_WarnMsg( 3, "dvd: title %d vts_title %d pgc %d",
599 p_dvd->i_title, i_vts_title, p_dvd->i_title_id );
604 p_dvd->i_angle_nb = vmg.title_inf.p_attr[p_dvd->i_title-1].i_angle_nb;
605 if( ( p_dvd->i_angle <= 0 ) || p_dvd->i_angle > p_dvd->i_angle_nb )
611 * Set selected title start and size
614 /* title set offset XXX: convert to block values */
615 p_dvd->i_title_start =
616 vts.i_pos + vts.manager_inf.i_title_vob_start_sector;
618 /* last video cell */
620 p_dvd->i_prg_cell = -1 +
621 vts.title_unit.p_title[p_dvd->i_title_id-1].title.i_cell_nb;
623 if( DVDFindCell( p_dvd ) < 0 )
625 intf_ErrMsg( "dvd error: can't find title end" );
626 p_input->b_error = 1;
630 /* temporary hack to fix size in some dvds */
631 if( p_dvd->i_cell >= vts.cell_inf.i_cell_nb )
633 p_dvd->i_cell = vts.cell_inf.i_cell_nb - 1;
637 p_dvd->i_size = vts.cell_inf.p_cell_map[p_dvd->i_cell].i_end_sector;
639 if( DVDChapterSelect( p_dvd, 1 ) < 0 )
641 intf_ErrMsg( "dvd error: can't find first chapter" );
642 p_input->b_error = 1;
646 /* Force libdvdcss to check its title key.
647 * It is only useful for title cracking method. Methods using the
648 * decrypted disc key are fast enough to check the key at each seek */
650 if( dvdcss_seek( p_dvd->dvdhandle, p_dvd->i_start,
651 DVDCSS_SEEK_KEY ) < 0 )
653 intf_ErrMsg( "dvd error: %s", dvdcss_error( p_dvd->dvdhandle ) );
657 p_dvd->i_size -= p_dvd->i_sector + 1;
659 IfoPrintTitle( p_dvd );
661 /* Area definition */
662 p_input->stream.p_selected_area->i_start = LB2OFF( p_dvd->i_start );
663 p_input->stream.p_selected_area->i_size = LB2OFF( p_dvd->i_size );
664 p_input->stream.p_selected_area->i_angle_nb = p_dvd->i_angle_nb;
665 p_input->stream.p_selected_area->i_angle = p_dvd->i_angle;
668 /* start at the beginning of the title */
669 /* FIXME: create a conf option to select whether to restart
671 p_input->stream.p_selected_area->i_tell = 0;
672 p_input->stream.p_selected_area->i_part = 1;
676 * Destroy obsolete ES by reinitializing program 0
677 * and find all ES in title with ifo data
679 if( p_input->stream.pp_programs != NULL )
681 /* We don't use input_EndStream here since
682 * we keep area structures */
684 for( i = 0 ; i < p_input->stream.i_selected_es_number ; i++ )
686 input_UnselectES( p_input, p_input->stream.pp_selected_es[i] );
689 free( p_input->stream.pp_selected_es );
690 input_DelProgram( p_input, p_input->stream.p_selected_program );
692 p_input->stream.pp_selected_es = NULL;
693 p_input->stream.i_selected_es_number = 0;
696 input_AddProgram( p_input, 0, sizeof( stream_ps_data_t ) );
697 p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
698 // p_input->stream.p_new_program = p_input->stream.pp_programs[0];
700 /* No PSM to read in DVD mode, we already have all information */
701 p_input->stream.p_selected_program->b_is_ok = 1;
705 /* ES 0 -> video MPEG2 */
706 IfoPrintVideo( p_dvd );
708 p_es = input_AddES( p_input, p_input->stream.p_selected_program,
710 p_es->i_stream_id = 0xe0;
711 p_es->i_type = MPEG2_VIDEO_ES;
712 p_es->i_cat = VIDEO_ES;
714 #define audio_status \
715 vts.title_unit.p_title[p_dvd->i_title_id-1].title.pi_audio_status[i-1]
716 /* Audio ES, in the order they appear in .ifo */
717 for( i = 1 ; i <= vts.manager_inf.i_audio_nb ; i++ )
719 IfoPrintAudio( p_dvd, i );
721 /* audio channel is active if first byte is 0x80 */
722 if( audio_status.i_available )
726 switch( vts.manager_inf.p_audio_attr[i-1].i_coding_mode )
729 i_id = ( ( 0x80 + audio_status.i_position ) << 8 ) | 0xbd;
730 p_es = input_AddES( p_input,
731 p_input->stream.p_selected_program, i_id, 0 );
732 p_es->i_stream_id = 0xbd;
733 p_es->i_type = AC3_AUDIO_ES;
735 p_es->i_cat = AUDIO_ES;
736 strcpy( p_es->psz_desc, DecodeLanguage( hton16(
737 vts.manager_inf.p_audio_attr[i-1].i_lang_code ) ) );
738 strcat( p_es->psz_desc, " (ac3)" );
742 case 0x03: /* MPEG audio */
743 i_id = 0xc0 + audio_status.i_position;
744 p_es = input_AddES( p_input,
745 p_input->stream.p_selected_program, i_id
747 p_es->i_stream_id = i_id;
748 p_es->i_type = MPEG2_AUDIO_ES;
750 p_es->i_cat = AUDIO_ES;
751 strcpy( p_es->psz_desc, DecodeLanguage( hton16(
752 vts.manager_inf.p_audio_attr[i-1].i_lang_code ) ) );
753 strcat( p_es->psz_desc, " (mpeg)" );
756 case 0x04: /* LPCM */
758 i_id = ( ( 0xa0 + audio_status.i_position ) << 8 ) | 0xbd;
759 p_es = input_AddES( p_input,
760 p_input->stream.p_selected_program,
762 p_es->i_stream_id = 0xbd;
763 p_es->i_type = LPCM_AUDIO_ES;
765 p_es->i_cat = AUDIO_ES;
766 strcpy( p_es->psz_desc, DecodeLanguage( hton16(
767 vts.manager_inf.p_audio_attr[i-1].i_lang_code ) ) );
768 strcat( p_es->psz_desc, " (lpcm)" );
772 i_id = ( ( 0x88 + audio_status.i_position ) << 8 ) | 0xbd;
773 intf_ErrMsg( "dvd warning: DTS audio not handled yet"
778 intf_ErrMsg( "dvd warning: unknown audio type %.2x",
779 vts.manager_inf.p_audio_attr[i-1].i_coding_mode );
785 vts.title_unit.p_title[p_dvd->i_title_id-1].title.pi_spu_status[i-1]
789 for( i = 1 ; i <= vts.manager_inf.i_spu_nb; i++ )
791 IfoPrintSpu( p_dvd, i );
793 if( spu_status.i_available )
797 /* there are several streams for one spu */
798 if( vts.manager_inf.video_attr.i_ratio )
801 switch( vts.manager_inf.video_attr.i_perm_displ )
804 i_id = ( ( 0x20 + spu_status.i_position_pan ) << 8 )
808 i_id = ( ( 0x20 + spu_status.i_position_letter ) << 8 )
812 i_id = ( ( 0x20 + spu_status.i_position_wide ) << 8 )
820 i_id = ( ( 0x20 + spu_status.i_position_43 ) << 8 )
823 p_es = input_AddES( p_input,
824 p_input->stream.p_selected_program,
826 p_es->i_stream_id = 0xbd;
827 p_es->i_type = DVD_SPU_ES;
828 p_es->i_cat = SPU_ES;
829 strcpy( p_es->psz_desc, DecodeLanguage( hton16(
830 vts.manager_inf.p_spu_attr[i-1].i_lang_code ) ) );
835 /* FIXME: hack to check that the demuxer is ready, and set
837 if( p_input->p_demux_module )
839 DVDLaunchDecoders( p_input );
845 p_area = p_input->stream.p_selected_area;
854 if( p_area->i_part != p_dvd->i_chapter )
856 if( ( p_area->i_part > 0 ) &&
857 ( p_area->i_part <= p_area->i_part_nb ))
859 if( DVDChapterSelect( p_dvd, p_area->i_part ) < 0 )
861 intf_ErrMsg( "dvd error: can't set chapter in area" );
862 p_input->b_error = 1;
866 p_input->stream.p_selected_area->i_tell =
867 LB2OFF( p_dvd->i_start ) - p_area->i_start;
868 p_input->stream.p_selected_area->i_part = p_dvd->i_chapter;
870 intf_WarnMsg( 4, "dvd info: chapter %d start at: %lld",
871 p_area->i_part, p_area->i_tell );
876 p_dvd->i_chapter = 1;
881 p_dvd->p_ifo->vts.title_unit.p_title[p_dvd->i_title_id-1].title
882 if( p_area->i_angle != p_dvd->i_angle )
884 if( title.p_cell_play[p_dvd->i_prg_cell].i_category & 0xf000 )
886 if( ( p_area->i_angle - p_dvd->i_angle ) < 0 )
890 p_dvd->i_prg_cell += ( p_area->i_angle - p_dvd->i_angle );
891 p_dvd->i_angle = p_area->i_angle;
893 DVDFindSector( p_dvd );
894 p_dvd->i_cell += p_dvd->i_angle_cell;
898 p_dvd->i_angle = p_area->i_angle;
901 intf_WarnMsg( 3, "dvd info: angle %d selected", p_area->i_angle );
904 /* warn interface that something has changed */
905 p_input->stream.b_seekable = 1;
906 p_input->stream.b_changed = 1;
912 /*****************************************************************************
913 * DVDRead: reads data packets.
914 *****************************************************************************
915 * Returns -1 in case of error, 0 in case of EOF, otherwise the number of
917 *****************************************************************************/
918 static int DVDRead( input_thread_t * p_input,
919 byte_t * p_buffer, size_t i_count )
921 thread_dvd_data_t * p_dvd;
929 p_dvd = (thread_dvd_data_t *)(p_input->p_access_data);
936 i_blocks = OFF2LB(i_count);
940 i_sector = p_dvd->i_title_start + p_dvd->i_sector;
941 i_block_once = p_dvd->i_end_sector - p_dvd->i_sector + 1;
943 /* Get the position of the next cell if we're at cell end */
944 if( i_block_once <= 0 )
949 p_dvd->i_angle_cell++;
951 /* Find cell index in adress map */
952 if( DVDFindSector( p_dvd ) < 0 )
954 intf_ErrMsg( "dvd error: can't find next cell" );
958 /* Position the fd pointer on the right address */
959 if( ( i_sector = dvdcss_seek( p_dvd->dvdhandle,
960 p_dvd->i_title_start + p_dvd->i_sector,
961 DVDCSS_SEEK_MPEG ) ) < 0 )
963 intf_ErrMsg( "dvd error: %s", dvdcss_error( p_dvd->dvdhandle ) );
967 /* update chapter : it will be easier when we have navigation
969 if( p_dvd->i_chapter < ( p_dvd->i_chapter_nb - 1 ) )
971 if( title.p_cell_play[p_dvd->i_prg_cell].i_category & 0xf000 )
973 i_angle = p_dvd->i_angle - 1;
979 if( title.chapter_map.pi_start_cell[p_dvd->i_chapter] <=
980 ( p_dvd->i_prg_cell - i_angle + 1 ) )
987 i_block_once = p_dvd->i_end_sector - p_dvd->i_sector + 1;
990 /* The number of blocks read is the max between the requested
991 * value and the leaving block in the cell */
992 if( i_block_once > i_blocks )
994 i_block_once = i_blocks;
997 intf_WarnMsg( 2, "Sector: 0x%x Read: %d Chapter: %d", p_dvd->i_sector, i_block_once, p_dvd->i_chapter );
1000 /* Reads from DVD */
1001 i_read_blocks = dvdcss_read( p_dvd->dvdhandle, p_buffer,
1002 i_block_once, DVDCSS_READ_DECRYPT );
1004 i_blocks -= i_read_blocks;
1005 p_buffer += LB2OFF( i_read_blocks );
1006 i_read_total += i_read_blocks;
1008 /* Update global position */
1009 p_dvd->i_sector += i_read_blocks;
1012 vlc_mutex_lock( &p_input->stream.stream_lock );
1014 p_input->stream.p_selected_area->i_tell =
1015 LB2OFF( i_sector + i_read_total ) -
1016 p_input->stream.p_selected_area->i_start;
1019 /* We modify i_part only at end of chapter not to erase
1020 * some modification from the interface */
1021 p_input->stream.p_selected_area->i_part = p_dvd->i_chapter;
1024 if( p_input->stream.p_selected_area->i_tell
1025 >= p_input->stream.p_selected_area->i_size )
1027 if( ( p_dvd->i_title + 1 ) >= p_input->stream.i_area_nb )
1030 vlc_mutex_unlock( &p_input->stream.stream_lock );
1035 intf_WarnMsg( 4, "dvd info: new title" );
1037 DVDSetArea( p_input, p_input->stream.pp_areas[p_dvd->i_title] );
1038 vlc_mutex_unlock( &p_input->stream.stream_lock );
1039 return LB2OFF( i_read_total );
1042 vlc_mutex_unlock( &p_input->stream.stream_lock );
1044 if( i_read_blocks != i_block_once )
1049 return LB2OFF( i_read_total );
1052 /*****************************************************************************
1053 * DVDSeek : Goes to a given position on the stream.
1054 *****************************************************************************
1055 * This one is used by the input and translate chronological position from
1056 * input to logical position on the device.
1057 * The lock should be taken before calling this function.
1058 *****************************************************************************/
1059 static void DVDSeek( input_thread_t * p_input, off_t i_off )
1061 thread_dvd_data_t * p_dvd;
1068 p_dvd = ( thread_dvd_data_t * )(p_input->p_access_data);
1070 vlc_mutex_lock( &p_input->stream.stream_lock );
1071 /* we have to take care of offset of beginning of title */
1072 p_dvd->i_sector = OFF2LB(i_off + p_input->stream.p_selected_area->i_start)
1073 - p_dvd->i_title_start;
1074 vlc_mutex_unlock( &p_input->stream.stream_lock );
1079 /* parse vobu address map to find program cell */
1080 while( title.p_cell_play[i_prg_cell].i_end_sector < p_dvd->i_sector )
1085 p_dvd->i_prg_cell = i_prg_cell;
1087 if( DVDChooseAngle( p_dvd ) < 0 )
1089 p_input->b_error = 1;
1095 /* Find first title cell which is inside program cell */
1096 if( DVDFindCell( p_dvd ) < 0 )
1098 /* no following cell : we're at eof */
1099 intf_ErrMsg( "dvd error: cell seeking failed" );
1100 p_input->b_error = 1;
1104 i_cell = p_dvd->i_cell;
1106 #define cell p_dvd->p_ifo->vts.cell_inf.p_cell_map[i_cell]
1107 /* parse cell address map to find title cell containing sector */
1108 while( cell.i_end_sector < p_dvd->i_sector )
1113 p_dvd->i_cell = i_cell;
1115 /* if we're inside a multi-angle zone, we have to choose i_sector
1116 * in the current angle ; we can't do it all the time since cells
1117 * can be very wide out of such zones */
1118 if( title.p_cell_play[p_dvd->i_prg_cell].i_category & 0xf000 )
1120 p_dvd->i_sector = __MAX(
1121 cell.i_start_sector,
1122 title.p_cell_play[p_dvd->i_prg_cell].i_start_sector );
1125 p_dvd->i_end_sector = __MIN(
1127 title.p_cell_play[p_dvd->i_prg_cell].i_end_sector );
1129 /* update chapter */
1130 if( title.p_cell_play[p_dvd->i_prg_cell].i_category & 0xf000 )
1132 i_angle = p_dvd->i_angle - 1;
1138 if( p_dvd->i_chapter_nb > 1 )
1140 while( ( title.chapter_map.pi_start_cell[i_chapter] <=
1141 ( p_dvd->i_prg_cell - i_angle + 1 ) ) &&
1142 ( i_chapter < ( p_dvd->i_chapter_nb - 1 ) ) )
1152 p_dvd->i_chapter = i_chapter;
1154 if( ( i_block = dvdcss_seek( p_dvd->dvdhandle,
1155 p_dvd->i_title_start + p_dvd->i_sector,
1156 DVDCSS_SEEK_MPEG ) ) < 0 )
1158 intf_ErrMsg( "dvd error: %s", dvdcss_error( p_dvd->dvdhandle ) );
1159 p_input->b_error = 1;
1163 vlc_mutex_lock( &p_input->stream.stream_lock );
1164 p_input->stream.p_selected_area->i_part = p_dvd->i_chapter;
1165 p_input->stream.p_selected_area->i_tell =
1166 LB2OFF ( i_block ) - p_input->stream.p_selected_area->i_start;
1167 vlc_mutex_unlock( &p_input->stream.stream_lock );
1169 intf_WarnMsg( 7, "Program Cell: %d Cell: %d Chapter: %d",
1170 p_dvd->i_prg_cell, p_dvd->i_cell, p_dvd->i_chapter );
1175 #define cell p_dvd->p_ifo->vts.cell_inf
1177 /*****************************************************************************
1178 * DVDFindCell: adjust the title cell index with the program cell
1179 *****************************************************************************/
1180 static int DVDFindCell( thread_dvd_data_t * p_dvd )
1185 i_cell = p_dvd->i_cell;
1186 i_index = p_dvd->i_prg_cell;
1188 if( i_cell >= cell.i_cell_nb )
1193 while( ( ( title.p_cell_pos[i_index].i_vob_id !=
1194 cell.p_cell_map[i_cell].i_vob_id ) ||
1195 ( title.p_cell_pos[i_index].i_cell_id !=
1196 cell.p_cell_map[i_cell].i_cell_id ) ) &&
1197 ( i_cell < cell.i_cell_nb - 1 ) )
1203 intf_WarnMsg( 12, "FindCell: i_cell %d i_index %d found %d nb %d",
1210 p_dvd->i_cell = i_cell;
1217 /*****************************************************************************
1218 * DVDFindSector: find cell index in adress map from index in
1219 * information table program map and give corresponding sectors.
1220 *****************************************************************************/
1221 static int DVDFindSector( thread_dvd_data_t * p_dvd )
1224 if( p_dvd->i_sector > title.p_cell_play[p_dvd->i_prg_cell].i_end_sector )
1226 p_dvd->i_prg_cell++;
1228 if( DVDChooseAngle( p_dvd ) < 0 )
1234 if( DVDFindCell( p_dvd ) < 0 )
1236 intf_ErrMsg( "dvd error: can't find sector" );
1240 /* Find start and end sectors of new cell */
1242 p_dvd->i_sector = __MAX(
1243 p_dvd->p_ifo->vts.cell_inf.p_cell_map[p_dvd->i_cell].i_start_sector,
1244 title.p_cell_play[p_dvd->i_prg_cell].i_start_sector );
1245 p_dvd->i_end_sector = __MIN(
1246 p_dvd->p_ifo->vts.cell_inf.p_cell_map[p_dvd->i_cell].i_end_sector,
1247 title.p_cell_play[p_dvd->i_prg_cell].i_end_sector );
1249 p_dvd->i_sector = title.p_cell_play[p_dvd->i_prg_cell].i_start_sector;
1250 p_dvd->i_end_sector = title.p_cell_play[p_dvd->i_prg_cell].i_end_sector;
1254 intf_WarnMsg( 12, "cell: %d sector1: 0x%x end1: 0x%x\n"
1255 "index: %d sector2: 0x%x end2: 0x%x\n"
1256 "category: 0x%x ilvu end: 0x%x vobu start 0x%x",
1258 p_dvd->p_ifo->vts.cell_inf.p_cell_map[p_dvd->i_cell].i_start_sector,
1259 p_dvd->p_ifo->vts.cell_inf.p_cell_map[p_dvd->i_cell].i_end_sector,
1261 title.p_cell_play[p_dvd->i_prg_cell].i_start_sector,
1262 title.p_cell_play[p_dvd->i_prg_cell].i_end_sector,
1263 title.p_cell_play[p_dvd->i_prg_cell].i_category,
1264 title.p_cell_play[p_dvd->i_prg_cell].i_first_ilvu_vobu_esector,
1265 title.p_cell_play[p_dvd->i_prg_cell].i_last_vobu_start_sector );
1271 /*****************************************************************************
1272 * DVDChapterSelect: find the cell corresponding to requested chapter
1273 *****************************************************************************/
1274 static int DVDChapterSelect( thread_dvd_data_t * p_dvd, int i_chapter )
1277 /* Find cell index in Program chain for current chapter */
1278 p_dvd->i_prg_cell = title.chapter_map.pi_start_cell[i_chapter-1] - 1;
1280 p_dvd->i_sector = 0;
1282 DVDChooseAngle( p_dvd );
1284 /* Search for cell_index in cell adress_table and initialize
1286 if( DVDFindSector( p_dvd ) < 0 )
1288 intf_ErrMsg( "dvd error: can't select chapter" );
1292 /* start is : beginning of vts vobs + offset to vob x */
1293 p_dvd->i_start = p_dvd->i_title_start + p_dvd->i_sector;
1295 /* Position the fd pointer on the right address */
1296 if( ( p_dvd->i_start = dvdcss_seek( p_dvd->dvdhandle,
1298 DVDCSS_SEEK_MPEG ) ) < 0 )
1300 intf_ErrMsg( "dvd error: %s", dvdcss_error( p_dvd->dvdhandle ) );
1304 p_dvd->i_chapter = i_chapter;
1308 /*****************************************************************************
1309 * DVDChooseAngle: select the cell corresponding to the selected angle
1310 *****************************************************************************/
1311 static int DVDChooseAngle( thread_dvd_data_t * p_dvd )
1313 /* basic handling of angles */
1314 switch( ( ( title.p_cell_play[p_dvd->i_prg_cell].i_category & 0xf000 )
1317 /* we enter a muli-angle section */
1319 p_dvd->i_prg_cell += p_dvd->i_angle - 1;
1320 p_dvd->i_angle_cell = 0;
1322 /* we exit a multi-angle section */
1325 p_dvd->i_prg_cell += p_dvd->i_angle_nb - p_dvd->i_angle;
1333 /*****************************************************************************
1335 *****************************************************************************/
1336 static void DVDLaunchDecoders( input_thread_t * p_input )
1338 thread_dvd_data_t * p_dvd;
1342 p_dvd = (thread_dvd_data_t*)(p_input->p_access_data);
1344 /* Select Video stream (always 0) */
1345 if( p_main->b_video )
1347 input_SelectES( p_input, p_input->stream.pp_es[0] );
1350 /* Select audio stream */
1351 if( p_main->b_audio )
1353 /* For audio: first one if none or a not existing one specified */
1354 i_audio = config_GetIntVariable( INPUT_CHANNEL_VAR );
1355 if( i_audio < 0 /*|| i_audio > i_audio_nb*/ )
1357 config_PutIntVariable( INPUT_CHANNEL_VAR, 1 );
1360 if( i_audio > 0 /*&& i_audio_nb > 0*/ )
1362 if( config_GetIntVariable( AOUT_SPDIF_VAR ) ||
1363 ( config_GetIntVariable( INPUT_AUDIO_VAR ) ==
1366 int i_ac3 = i_audio;
1367 while( ( p_input->stream.pp_es[i_ac3]->i_type !=
1368 AC3_AUDIO_ES ) && ( i_ac3 <=
1369 p_dvd->p_ifo->vts.manager_inf.i_audio_nb ) )
1373 if( p_input->stream.pp_es[i_ac3]->i_type == AC3_AUDIO_ES )
1375 input_SelectES( p_input,
1376 p_input->stream.pp_es[i_ac3] );
1381 input_SelectES( p_input,
1382 p_input->stream.pp_es[i_audio] );
1387 /* Select subtitle */
1388 if( p_main->b_video )
1390 /* for spu, default is none */
1391 i_spu = config_GetIntVariable( INPUT_SUBTITLE_VAR );
1392 if( i_spu < 0 /*|| i_spu > i_spu_nb*/ )
1394 config_PutIntVariable( INPUT_SUBTITLE_VAR, 0 );
1397 if( i_spu > 0 /* && i_spu_nb > 0*/ )
1399 i_spu += p_dvd->p_ifo->vts.manager_inf.i_audio_nb;
1400 input_SelectES( p_input, p_input->stream.pp_es[i_spu] );