From: Stéphane Borel Date: Fri, 1 Mar 2002 01:12:28 +0000 (+0000) Subject: *dvd and dvdread support for input III. X-Git-Tag: 0.3.0~160 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=9b393dab29dcbe72d5a55084f434bdcd602c28b0;p=vlc *dvd and dvdread support for input III. Dvdread is known to segfault at title change. I'm working on this. --- diff --git a/configure b/configure index 6e83f50b30..ec8a6f8c15 100755 --- a/configure +++ b/configure @@ -6387,7 +6387,7 @@ if test "${with_dvdcss+set}" = set; then case "x${withval}" in xlocal-static|xyes) # local libdvdcss, statically linked - #BUILTINS="${BUILTINS} dvd" + BUILTINS="${BUILTINS} dvd" if test x${CAN_BUILD_LIBDVDCSS} = x1 then NEED_LIBDVDCSS=1 @@ -6398,7 +6398,7 @@ if test "${with_dvdcss+set}" = set; then ;; xlocal-shared) # local libdvdcss, dynamically linked - #PLUGINS="${PLUGINS} dvd" + PLUGINS="${PLUGINS} dvd" if test x${CAN_BUILD_LIBDVDCSS} = x1 then NEED_LIBDVDCSS=1 @@ -6408,7 +6408,7 @@ if test "${with_dvdcss+set}" = set; then ;; xno) # don't use libdvdcss at all, build a DVD module that can dlopen() it - #BUILTINS="${BUILTINS} dvd" + BUILTINS="${BUILTINS} dvd" DUMMY_LIBDVDCSS=1 SRC_DVD_EXTRA="${SRC_DVD_EXTRA} dummy_dvdcss.c" CFLAGS_DVD="${CFLAGS_DVD} -DGOD_DAMN_DMCA" @@ -6417,7 +6417,7 @@ if test "${with_dvdcss+set}" = set; then ;; *) # existing libdvdcss - #PLUGINS="${PLUGINS} dvd" + PLUGINS="${PLUGINS} dvd" if test "x$withval" != "xyes" then LIB_DVD="${LIB_DVD} -L"$withval"/lib" @@ -6430,14 +6430,14 @@ else # if libdvdcss is in the archive, or to use the dummy replacement otherwise. if test x${CAN_BUILD_LIBDVDCSS} = x1 then - #BUILTINS="${BUILTINS} dvd" + BUILTINS="${BUILTINS} dvd" NEED_LIBDVDCSS=1 STATIC_LIBDVDCSS=1 CFLAGS_DVD="${CFLAGS_DVD} -I../../extras/libdvdcss" LIB_DVD="${LIB_DVD} lib/libdvdcss.a ${LIB_LIBDVDCSS}" else # XXX: no check for libdl is done, don't try this at home ! - #BUILTINS="${BUILTINS} dvd" + BUILTINS="${BUILTINS} dvd" DUMMY_LIBDVDCSS=1 SRC_DVD_EXTRA="${SRC_DVD_EXTRA} dummy_dvdcss.c" CFLAGS_DVD="${CFLAGS_DVD} -DGOD_DAMN_DMCA" diff --git a/configure.in b/configure.in index 85e51ab057..a2e3afd029 100644 --- a/configure.in +++ b/configure.in @@ -788,7 +788,7 @@ AC_ARG_WITH(dvdcss, [ case "x${withval}" in xlocal-static|xyes) # local libdvdcss, statically linked - #BUILTINS="${BUILTINS} dvd" + BUILTINS="${BUILTINS} dvd" if test x${CAN_BUILD_LIBDVDCSS} = x1 then NEED_LIBDVDCSS=1 @@ -799,7 +799,7 @@ AC_ARG_WITH(dvdcss, ;; xlocal-shared) # local libdvdcss, dynamically linked - #PLUGINS="${PLUGINS} dvd" + PLUGINS="${PLUGINS} dvd" if test x${CAN_BUILD_LIBDVDCSS} = x1 then NEED_LIBDVDCSS=1 @@ -809,7 +809,7 @@ AC_ARG_WITH(dvdcss, ;; xno) # don't use libdvdcss at all, build a DVD module that can dlopen() it - #BUILTINS="${BUILTINS} dvd" + BUILTINS="${BUILTINS} dvd" DUMMY_LIBDVDCSS=1 SRC_DVD_EXTRA="${SRC_DVD_EXTRA} dummy_dvdcss.c" CFLAGS_DVD="${CFLAGS_DVD} -DGOD_DAMN_DMCA" @@ -818,7 +818,7 @@ AC_ARG_WITH(dvdcss, ;; *) # existing libdvdcss - #PLUGINS="${PLUGINS} dvd" + PLUGINS="${PLUGINS} dvd" if test "x$withval" != "xyes" then LIB_DVD="${LIB_DVD} -L"$withval"/lib" @@ -830,14 +830,14 @@ AC_ARG_WITH(dvdcss, # if libdvdcss is in the archive, or to use the dummy replacement otherwise. [ if test x${CAN_BUILD_LIBDVDCSS} = x1 then - #BUILTINS="${BUILTINS} dvd" + BUILTINS="${BUILTINS} dvd" NEED_LIBDVDCSS=1 STATIC_LIBDVDCSS=1 CFLAGS_DVD="${CFLAGS_DVD} -I../../extras/libdvdcss" LIB_DVD="${LIB_DVD} lib/libdvdcss.a ${LIB_LIBDVDCSS}" else # XXX: no check for libdl is done, don't try this at home ! - #BUILTINS="${BUILTINS} dvd" + BUILTINS="${BUILTINS} dvd" DUMMY_LIBDVDCSS=1 SRC_DVD_EXTRA="${SRC_DVD_EXTRA} dummy_dvdcss.c" CFLAGS_DVD="${CFLAGS_DVD} -DGOD_DAMN_DMCA" diff --git a/plugins/dvd/dvd.c b/plugins/dvd/dvd.c index 86ab196b16..680f320c3e 100644 --- a/plugins/dvd/dvd.c +++ b/plugins/dvd/dvd.c @@ -2,7 +2,7 @@ * dvd.c : DVD input module for vlc ***************************************************************************** * Copyright (C) 2000-2001 VideoLAN - * $Id: dvd.c,v 1.21 2002/03/01 00:33:18 massiot Exp $ + * $Id: dvd.c,v 1.22 2002/03/01 01:12:28 stef Exp $ * * Authors: Samuel Hocevar * @@ -37,8 +37,8 @@ /***************************************************************************** * Capabilities defined in the other files. *****************************************************************************/ -void _M( access_getfunctions )( function_list_t * p_function_list ); -void _M( demux_getfunctions )( function_list_t * p_function_list ); +void _M( access_getfunctions)( function_list_t * p_function_list ); +void _M( demux_getfunctions)( function_list_t * p_function_list ); /***************************************************************************** * Local prototypes. @@ -58,17 +58,19 @@ MODULE_CONFIG_STOP MODULE_INIT_START #ifdef GOD_DAMN_DMCA SET_DESCRIPTION( "DVD input module, uses libdvdcss if present" ) + ADD_CAPABILITY( DEMUX, 190 ) + ADD_CAPABILITY( ACCESS, 90 ) #else SET_DESCRIPTION( "DVD input module, linked with libdvdcss" ) + ADD_CAPABILITY( DEMUX, 200 ) + ADD_CAPABILITY( ACCESS, 100 ) #endif - ADD_CAPABILITY( ACCESS, 0 ) - ADD_CAPABILITY( DEMUX, 0 ) ADD_SHORTCUT( "dvd" ) MODULE_INIT_STOP MODULE_ACTIVATE_START - _M( access_getfunctions )( &p_module->p_functions->access ); - _M( demux_getfunctions )( &p_module->p_functions->demux ); + _M( access_getfunctions)( &p_module->p_functions->access ); + _M( demux_getfunctions)( &p_module->p_functions->demux ); #ifdef GOD_DAMN_DMCA ProbeLibDVDCSS(); #endif diff --git a/plugins/dvd/input_dvd.c b/plugins/dvd/input_dvd.c index 0d0e7f0fbe..dcc1d6d538 100644 --- a/plugins/dvd/input_dvd.c +++ b/plugins/dvd/input_dvd.c @@ -9,7 +9,7 @@ * -dvd_udf to find files ***************************************************************************** * Copyright (C) 1998-2001 VideoLAN - * $Id: input_dvd.c,v 1.122 2002/02/27 03:47:56 sam Exp $ + * $Id: input_dvd.c,v 1.123 2002/03/01 01:12:28 stef Exp $ * * Author: Stéphane Borel * @@ -78,23 +78,25 @@ #include "debug.h" -/* how many blocks DVDRead will read in each loop */ -#define DVD_BLOCK_READ_ONCE 64 +/* how many packets DVDDemux will read in each loop */ +#define DVD_READ_ONCE 64 /***************************************************************************** * Local prototypes *****************************************************************************/ + /* called from outside */ -static int DVDProbe ( struct input_thread_s * ); -static void DVDInit ( struct input_thread_s * ); -static void DVDEnd ( struct input_thread_s * ); -static void DVDOpen ( struct input_thread_s * ); +static int DVDOpen ( struct input_thread_s * ); static void DVDClose ( struct input_thread_s * ); static int DVDSetArea ( struct input_thread_s *, struct input_area_s * ); static int DVDSetProgram ( struct input_thread_s *, pgrm_descriptor_t * ); -static int DVDRead ( struct input_thread_s *, data_packet_t ** ); +static int DVDRead ( struct input_thread_s *, byte_t *, size_t ); static void DVDSeek ( struct input_thread_s *, off_t ); + static int DVDRewind ( struct input_thread_s * ); +static int DVDDemux ( struct input_thread_s * ); +static int DVDInit ( struct input_thread_s * ); +static void DVDEnd ( struct input_thread_s * ); /* called only inside */ static int DVDChooseAngle( thread_dvd_data_t * ); @@ -102,115 +104,300 @@ static int DVDFindCell( thread_dvd_data_t * ); static int DVDFindSector( thread_dvd_data_t * ); static int DVDChapterSelect( thread_dvd_data_t *, int ); -/***************************************************************************** - * Declare a buffer manager - *****************************************************************************/ -#define FLAGS BUFFERS_UNIQUE_SIZE -#define NB_LIFO 1 -DECLARE_BUFFERS_SHARED( FLAGS, NB_LIFO ); -DECLARE_BUFFERS_INIT( FLAGS, NB_LIFO ); -DECLARE_BUFFERS_END_SHARED( FLAGS, NB_LIFO ); -DECLARE_BUFFERS_NEWPACKET_SHARED( FLAGS, NB_LIFO ); -DECLARE_BUFFERS_DELETEPACKET_SHARED( FLAGS, NB_LIFO, 1000 ); -DECLARE_BUFFERS_NEWPES( FLAGS, NB_LIFO ); -DECLARE_BUFFERS_DELETEPES( FLAGS, NB_LIFO, 1000 ); -DECLARE_BUFFERS_TOIO( FLAGS, DVD_LB_SIZE ); -DECLARE_BUFFERS_SHAREBUFFER( FLAGS ); - /***************************************************************************** * Functions exported as capabilities. They are declared as static so that * we don't pollute the namespace too much. *****************************************************************************/ -void _M( input_getfunctions )( function_list_t * p_function_list ) +void _M( access_getfunctions)( function_list_t * p_function_list ) { -#define input p_function_list->functions.input - input.pf_probe = DVDProbe; - input.pf_init = DVDInit; +#define input p_function_list->functions.access input.pf_open = DVDOpen; input.pf_close = DVDClose; - input.pf_end = DVDEnd; - input.pf_init_bit_stream = InitBitstream; input.pf_read = DVDRead; input.pf_set_area = DVDSetArea; input.pf_set_program = DVDSetProgram; - input.pf_demux = input_DemuxPS; - input.pf_new_packet = input_NewPacket; - input.pf_new_pes = input_NewPES; - input.pf_delete_packet = input_DeletePacket; - input.pf_delete_pes = input_DeletePES; - input.pf_rewind = DVDRewind; input.pf_seek = DVDSeek; #undef input } +void _M( demux_getfunctions)( function_list_t * p_function_list ) +{ +#define demux p_function_list->functions.demux + demux.pf_init = DVDInit; + demux.pf_end = DVDEnd; + demux.pf_demux = DVDDemux; + demux.pf_rewind = DVDRewind; +#undef demux +} + /* - * Data reading functions + * Data demux functions */ /***************************************************************************** - * DVDProbe: verifies that the stream is a PS stream + * DVDInit: initializes DVD structures *****************************************************************************/ -static int DVDProbe( input_thread_t * p_input ) +static int DVDInit( input_thread_t * p_input ) { - char * psz_name = p_input->p_source; + thread_dvd_data_t * p_dvd; + int i_audio; + int i_spu; + + if( strncmp( p_input->p_access_module->psz_name, "dvd", 3 ) ) + { + return -1; + } + + p_dvd = (thread_dvd_data_t*)(p_input->p_access_data); + + /* Select Video stream (always 0) */ + if( p_main->b_video ) + { + input_SelectES( p_input, p_input->stream.pp_es[0] ); + } - if( ( strlen(psz_name) > 4 ) && !strncasecmp( psz_name, "dvd:", 4 ) ) + /* Select audio stream */ + if( p_main->b_audio ) { - /* If the user specified "dvd:" then it's probably a DVD */ - return 0; + /* For audio: first one if none or a not existing one specified */ + i_audio = config_GetIntVariable( INPUT_CHANNEL_VAR ); + if( i_audio < 0 /*|| i_audio > i_audio_nb*/ ) + { + config_PutIntVariable( INPUT_CHANNEL_VAR, 1 ); + i_audio = 1; + } + if( i_audio > 0 /*&& i_audio_nb > 0*/ ) + { + if( config_GetIntVariable( AOUT_SPDIF_VAR ) || + ( config_GetIntVariable( INPUT_AUDIO_VAR ) == + REQUESTED_AC3 ) ) + { + int i_ac3 = i_audio; + while( ( p_input->stream.pp_es[i_ac3]->i_type != + AC3_AUDIO_ES ) && ( i_ac3 <= + p_dvd->p_ifo->vts.manager_inf.i_audio_nb ) ) + { + i_ac3++; + } + if( p_input->stream.pp_es[i_ac3]->i_type == AC3_AUDIO_ES ) + { + input_SelectES( p_input, + p_input->stream.pp_es[i_ac3] ); + } + } + else + { + input_SelectES( p_input, + p_input->stream.pp_es[i_audio] ); + } + } } - return -1; + /* Select subtitle */ + if( p_main->b_video ) + { + /* for spu, default is none */ + i_spu = config_GetIntVariable( INPUT_SUBTITLE_VAR ); + if( i_spu < 0 /*|| i_spu > i_spu_nb*/ ) + { + config_PutIntVariable( INPUT_SUBTITLE_VAR, 0 ); + i_spu = 0; + } + if( i_spu > 0 /* && i_spu_nb > 0*/ ) + { + i_spu += p_dvd->p_ifo->vts.manager_inf.i_audio_nb; + input_SelectES( p_input, p_input->stream.pp_es[i_spu] ); + } + } + + return 0; } /***************************************************************************** - * DVDInit: initializes DVD structures + * DVDEnd: frees unused data + *****************************************************************************/ +static void DVDEnd( input_thread_t * p_input ) +{ +} + +/***************************************************************************** + * DVDDemux *****************************************************************************/ -static void DVDInit( input_thread_t * p_input ) +#define PEEK( SIZE ) \ + i_result = input_Peek( p_input, &p_peek, SIZE ); \ + if( i_result == -1 ) \ + { \ + return( -1 ); \ + } \ + else if( i_result < SIZE ) \ + { \ + /* EOF */ \ + return( 0 ); \ + } + +static int DVDDemux( input_thread_t * p_input ) +{ + int i; + byte_t * p_peek; + data_packet_t * p_data; + ssize_t i_result; + int i_packet_size; + + + /* Read headers to compute payload length */ + for( i = 0 ; i < DVD_READ_ONCE ; i++ ) + { + + /* Read what we believe to be a packet header. */ + PEEK( 4 ); + + /* Default header */ + if( U32_AT( p_peek ) != 0x1BA ) + { + /* That's the case for all packets, except pack header. */ + i_packet_size = U16_AT( p_peek + 4 ); + } + else + { + /* MPEG-2 Pack header. */ + i_packet_size = 8; + } + + /* Fetch a packet of the appropriate size. */ + i_result = input_SplitBuffer( p_input, &p_data, i_packet_size + 6 ); + if( i_result <= 0 ) + { + return( i_result ); + } + + /* In MPEG-2 pack headers we still have to read stuffing bytes. */ + if( (p_data->p_demux_start[3] == 0xBA) && (i_packet_size == 8) ) + { + size_t i_stuffing = (p_data->p_demux_start[13] & 0x7); + /* Force refill of the input buffer - though we don't care + * about p_peek. Please note that this is unoptimized. */ + PEEK( i_stuffing ); + p_input->p_current_data += i_stuffing; + } + + input_DemuxPS( p_input, p_data ); + + } + + return i; +} + +/***************************************************************************** + * DVDRewind : reads a stream backward + *****************************************************************************/ +static int DVDRewind( input_thread_t * p_input ) { + return( -1 ); +} + + + +/* + * Data access functions + */ + +/***************************************************************************** + * DVDOpen: open dvd + *****************************************************************************/ +static int DVDOpen( struct input_thread_s *p_input ) +{ + struct stat stat_info; + char * psz_parser = p_input->psz_name; + char * psz_device = p_input->psz_name; + dvdcss_handle dvdhandle; thread_dvd_data_t * p_dvd; input_area_t * p_area; int i_title; int i_chapter; int i; - p_dvd = malloc( sizeof(thread_dvd_data_t) ); - if( p_dvd == NULL ) + /* Parse input string : device[@rawdevice] */ + while( *psz_parser && *psz_parser != '@' ) { - intf_ErrMsg( "dvd error: out of memory" ); - p_input->b_error = 1; - return; + psz_parser++; } - p_input->p_plugin_data = (void *)p_dvd; + if( *psz_parser == '@' ) + { + /* Found raw device */ + *psz_parser = '\0'; + psz_parser++; + + config_PutPszVariable( "DVDCSS_RAW_DEVICE", psz_parser ); + } - if( (p_input->p_method_data = input_BuffersInit()) == NULL ) + if( stat( psz_device, &stat_info ) == -1 ) { - p_input->b_error = 1; - return; + intf_ErrMsg( "input error: cannot stat() device `%s' (%s)", + psz_device, strerror(errno)); + return( -1 ); + } + if( !S_ISBLK(stat_info.st_mode) && !S_ISCHR(stat_info.st_mode) ) + { + intf_WarnMsg( 3, "input : DVD plugin discarded" + " (not a valid block device)" ); + return -1; + } + + intf_WarnMsg( 2, "input: dvd=%s raw=%s", psz_device, psz_parser ); + + /* + * set up input + */ + p_input->i_mtu = 0; + + vlc_mutex_lock( &p_input->stream.stream_lock ); + + p_input->stream.i_method = INPUT_METHOD_DVD; + + /* If we are here we can control the pace... */ + p_input->stream.b_pace_control = 1; + + p_input->stream.b_seekable = 1; + p_input->stream.p_selected_area->i_size = 0; + + p_input->stream.p_selected_area->i_tell = 0; + + vlc_mutex_unlock( &p_input->stream.stream_lock ); + + /* + * get plugin ready + */ + dvdhandle = dvdcss_open( psz_device ); + + if( dvdhandle == NULL ) + { + intf_ErrMsg( "dvd error: dvdcss can't open device" ); + return -1; } - p_dvd->dvdhandle = (dvdcss_handle) p_input->p_handle; + p_dvd = malloc( sizeof(thread_dvd_data_t) ); + if( p_dvd == NULL ) + { + intf_ErrMsg( "dvd error: out of memory" ); + return -1; + } + + p_dvd->dvdhandle = (dvdcss_handle) dvdhandle; + p_input->p_access_data = (void *)p_dvd; if( dvdcss_seek( p_dvd->dvdhandle, 0, DVDCSS_NOFLAGS ) < 0 ) { intf_ErrMsg( "dvd error: %s", dvdcss_error( p_dvd->dvdhandle ) ); - input_BuffersEnd( p_input->p_method_data ); - p_input->b_error = 1; - return; + return -1; } - /* We read DVD_BLOCK_READ_ONCE in each loop */ - p_dvd->i_block_once = DVD_BLOCK_READ_ONCE; - /* Ifo allocation & initialisation */ if( IfoCreate( p_dvd ) < 0 ) { intf_ErrMsg( "dvd error: allcation error in ifo" ); free( p_dvd ); - input_BuffersEnd( p_input->p_method_data ); - p_input->b_error = 1; - return; + return -1; } if( IfoInit( p_dvd->p_ifo ) < 0 ) @@ -218,9 +405,7 @@ static void DVDInit( input_thread_t * p_input ) intf_ErrMsg( "dvd error: fatal failure in ifo" ); IfoDestroy( p_dvd->p_ifo ); free( p_dvd ); - input_BuffersEnd( p_input->p_method_data ); - p_input->b_error = 1; - return; + return -1; } /* Set stream and area data */ @@ -282,98 +467,34 @@ static void DVDInit( input_thread_t * p_input ) p_area->i_part = i_chapter; /* set title, chapter, audio and subpic */ - DVDSetArea( p_input, p_area ); - - vlc_mutex_unlock( &p_input->stream.stream_lock ); - - return; -} - -/***************************************************************************** - * DVDOpen: open dvd - *****************************************************************************/ -static void DVDOpen( struct input_thread_s *p_input ) -{ - dvdcss_handle dvdhandle; - char * psz_parser; - char * psz_device; - - vlc_mutex_lock( &p_input->stream.stream_lock ); - - p_input->stream.i_method = INPUT_METHOD_DVD; - - /* If we are here we can control the pace... */ - p_input->stream.b_pace_control = 1; - - p_input->stream.b_seekable = 1; - p_input->stream.p_selected_area->i_size = 0; - - p_input->stream.p_selected_area->i_tell = 0; - - vlc_mutex_unlock( &p_input->stream.stream_lock ); - - /* Parse input string : dvd:device[@rawdevice] */ - if( strlen( p_input->p_source ) > 4 - && !strncasecmp( p_input->p_source, "dvd:", 4 ) ) - { - psz_parser = psz_device = p_input->p_source + 4; - } - else + if( DVDSetArea( p_input, p_area ) ) { - psz_parser = psz_device = p_input->p_source; - } - - while( *psz_parser && *psz_parser != '@' ) - { - psz_parser++; - } - - if( *psz_parser == '@' ) - { - /* Found raw device */ - *psz_parser = '\0'; - psz_parser++; - - config_PutPszVariable( "DVDCSS_RAW_DEVICE", psz_parser ); + vlc_mutex_unlock( &p_input->stream.stream_lock ); + return -1; } - intf_WarnMsg( 2, "input: dvd=%s raw=%s", psz_device, psz_parser ); - - dvdhandle = dvdcss_open( psz_device ); + vlc_mutex_unlock( &p_input->stream.stream_lock ); - if( dvdhandle == NULL ) - { - intf_ErrMsg( "dvd error: dvdcss can't open device" ); - p_input->b_error = 1; - return; - } + return 0; - p_input->p_handle = (void *) dvdhandle; } /***************************************************************************** * DVDClose: close dvd *****************************************************************************/ static void DVDClose( struct input_thread_s *p_input ) -{ - /* Clean up libdvdcss */ - dvdcss_close( (dvdcss_handle) p_input->p_handle ); -} - -/***************************************************************************** - * DVDEnd: frees unused data - *****************************************************************************/ -static void DVDEnd( input_thread_t * p_input ) { thread_dvd_data_t * p_dvd; - p_dvd = (thread_dvd_data_t*)p_input->p_plugin_data; + p_dvd = (thread_dvd_data_t*)p_input->p_access_data; IfoDestroy( p_dvd->p_ifo ); + p_input->p_access_data = (void *)(p_dvd->dvdhandle); free( p_dvd ); - input_BuffersEnd( p_input->p_method_data ); + /* Clean up libdvdcss */ + dvdcss_close( (dvdcss_handle) p_input->p_access_data ); } /***************************************************************************** @@ -400,11 +521,9 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area ) int i_vts_title; int i_audio_nb = 0; int i_spu_nb = 0; - int i_audio; - int i_spu; int i; - p_dvd = (thread_dvd_data_t*)p_input->p_plugin_data; + p_dvd = (thread_dvd_data_t*)(p_input->p_access_data); /* we can't use the interface slider until initilization is complete */ p_input->stream.b_seekable = 0; @@ -546,6 +665,7 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area ) input_AddProgram( p_input, 0, sizeof( stream_ps_data_t ) ); p_input->stream.p_selected_program = p_input->stream.pp_programs[0]; +// p_input->stream.p_new_program = p_input->stream.pp_programs[0]; /* No PSM to read in DVD mode, we already have all information */ p_input->stream.p_selected_program->b_is_ok = 1; @@ -560,11 +680,7 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area ) p_es->i_stream_id = 0xe0; p_es->i_type = MPEG2_VIDEO_ES; p_es->i_cat = VIDEO_ES; - if( p_main->b_video ) - { - input_SelectES( p_input, p_es ); - } - + #define audio_status \ vts.title_unit.p_title[p_dvd->i_title_id-1].title.pi_audio_status[i-1] /* Audio ES, in the order they appear in .ifo */ @@ -685,55 +801,14 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area ) } } #undef spu_status - if( p_main->b_audio ) + + /* FIXME: hack to check that the demuxer is ready, and set + * the decoders */ + if( p_input->pf_init ) { - /* For audio: first one if none or a not existing one specified */ - i_audio = config_GetIntVariable( INPUT_CHANNEL_VAR ); - if( i_audio < 0 || i_audio > i_audio_nb ) - { - i_audio = 1; - } - if( i_audio > 0 && i_audio_nb > 0 ) - { - if( config_GetIntVariable( AOUT_SPDIF_VAR ) || - ( config_GetIntVariable( INPUT_AUDIO_VAR ) == - REQUESTED_AC3 ) ) - { - int i_ac3 = i_audio; - while( ( p_input->stream.pp_es[i_ac3]->i_type != - AC3_AUDIO_ES ) && ( i_ac3 <= - vts.manager_inf.i_audio_nb ) ) - { - i_ac3++; - } - if( p_input->stream.pp_es[i_ac3]->i_type == AC3_AUDIO_ES ) - { - input_SelectES( p_input, - p_input->stream.pp_es[i_ac3] ); - } - } - else - { - input_SelectES( p_input, - p_input->stream.pp_es[i_audio] ); - } - } + p_input->pf_init( p_input ); } - if( p_main->b_video ) - { - /* for spu, default is none */ - i_spu = config_GetIntVariable( INPUT_SUBTITLE_VAR ); - if( i_spu < 0 || i_spu > i_spu_nb ) - { - i_spu = 0; - } - if( i_spu > 0 && i_spu_nb > 0 ) - { - i_spu += vts.manager_inf.i_audio_nb; - input_SelectES( p_input, p_input->stream.pp_es[i_spu] ); - } - } } /* i_title >= 0 */ else { @@ -808,160 +883,106 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area ) * DVDRead: reads data packets. ***************************************************************************** * Returns -1 in case of error, 0 in case of EOF, otherwise the number of - * packets. + * bytes. *****************************************************************************/ static int DVDRead( input_thread_t * p_input, - data_packet_t ** pp_data ) + byte_t * p_buffer, size_t i_count ) { thread_dvd_data_t * p_dvd; - struct iovec p_vec[DVD_BLOCK_READ_ONCE]; - u8 * pi_cur; int i_block_once; - int i_packet_size; - int i_iovec; - int i_packet; - int i_pos; int i_read_blocks; + int i_read_total; int i_sector; + int i_blocks; boolean_t b_eoc; - data_packet_t * p_data; - p_dvd = (thread_dvd_data_t *)p_input->p_plugin_data; - - *pp_data = NULL; + p_dvd = (thread_dvd_data_t *)(p_input->p_access_data); + i_sector = 0; + i_read_total = 0; + i_read_blocks = 0; b_eoc = 0; - i_sector = p_dvd->i_title_start + p_dvd->i_sector; - i_block_once = p_dvd->i_end_sector - p_dvd->i_sector + 1; + i_blocks = OFF2LB(i_count); - /* Get the position of the next cell if we're at cell end */ - if( i_block_once <= 0 ) + while( i_blocks ) { - int i_angle; - - p_dvd->i_cell++; - p_dvd->i_angle_cell++; + i_sector = p_dvd->i_title_start + p_dvd->i_sector; + i_block_once = p_dvd->i_end_sector - p_dvd->i_sector + 1; - /* Find cell index in adress map */ - if( DVDFindSector( p_dvd ) < 0 ) + /* Get the position of the next cell if we're at cell end */ + if( i_block_once <= 0 ) { - intf_ErrMsg( "dvd error: can't find next cell" ); - return 1; - } + int i_angle; - /* Position the fd pointer on the right address */ - if( ( i_sector = dvdcss_seek( p_dvd->dvdhandle, - p_dvd->i_title_start + p_dvd->i_sector, - DVDCSS_SEEK_MPEG ) ) < 0 ) - { - intf_ErrMsg( "dvd error: %s", dvdcss_error( p_dvd->dvdhandle ) ); - return -1; - } + p_dvd->i_cell++; + p_dvd->i_angle_cell++; - /* update chapter : it will be easier when we have navigation - * ES support */ - if( p_dvd->i_chapter < ( p_dvd->i_chapter_nb - 1 ) ) - { - if( title.p_cell_play[p_dvd->i_prg_cell].i_category & 0xf000 ) + /* Find cell index in adress map */ + if( DVDFindSector( p_dvd ) < 0 ) { - i_angle = p_dvd->i_angle - 1; + intf_ErrMsg( "dvd error: can't find next cell" ); + return 1; } - else + + /* Position the fd pointer on the right address */ + if( ( i_sector = dvdcss_seek( p_dvd->dvdhandle, + p_dvd->i_title_start + p_dvd->i_sector, + DVDCSS_SEEK_MPEG ) ) < 0 ) { - i_angle = 0; + intf_ErrMsg( "dvd error: %s", dvdcss_error( p_dvd->dvdhandle ) ); + return -1; } - if( title.chapter_map.pi_start_cell[p_dvd->i_chapter] <= - ( p_dvd->i_prg_cell - i_angle + 1 ) ) + + /* update chapter : it will be easier when we have navigation + * ES support */ + if( p_dvd->i_chapter < ( p_dvd->i_chapter_nb - 1 ) ) { - p_dvd->i_chapter++; - b_eoc = 1; + if( title.p_cell_play[p_dvd->i_prg_cell].i_category & 0xf000 ) + { + i_angle = p_dvd->i_angle - 1; + } + else + { + i_angle = 0; + } + if( title.chapter_map.pi_start_cell[p_dvd->i_chapter] <= + ( p_dvd->i_prg_cell - i_angle + 1 ) ) + { + p_dvd->i_chapter++; + b_eoc = 1; + } } - } - - i_block_once = p_dvd->i_end_sector - p_dvd->i_sector + 1; - } - - /* The number of blocks read is the max between the requested - * value and the leaving block in the cell */ - if( i_block_once > p_dvd->i_block_once ) - { - i_block_once = p_dvd->i_block_once; - } -/* -intf_WarnMsg( 2, "Sector: 0x%x Read: %d Chapter: %d", p_dvd->i_sector, i_block_once, p_dvd->i_chapter ); -*/ - /* Get iovecs */ - *pp_data = p_data = input_BuffersToIO( p_input->p_method_data, p_vec, - DVD_BLOCK_READ_ONCE ); - - if ( p_data == NULL ) - { - return( -1 ); - } - - /* Reads from DVD */ - i_read_blocks = dvdcss_readv( p_dvd->dvdhandle, p_vec, - i_block_once, DVDCSS_READ_DECRYPT ); - - /* Update global position */ - p_dvd->i_sector += i_read_blocks; - - i_packet = 0; - - /* Read headers to compute payload length */ - for( i_iovec = 0 ; i_iovec < i_read_blocks ; i_iovec++ ) - { - data_packet_t * p_current = p_data; - i_pos = 0; + i_block_once = p_dvd->i_end_sector - p_dvd->i_sector + 1; + } - while( i_pos < DVD_LB_SIZE ) + /* The number of blocks read is the max between the requested + * value and the leaving block in the cell */ + if( i_block_once > i_blocks ) { - pi_cur = (u8*)p_vec[i_iovec].iov_base + i_pos; - - /* Default header */ - if( U32_AT( pi_cur ) != 0x1BA ) - { - /* That's the case for all packets, except pack header. */ - i_packet_size = U16_AT( pi_cur + 4 ); - } - else - { - /* MPEG-2 Pack header. */ - i_packet_size = 8; - } - - if( i_pos != 0 ) - { - *pp_data = input_ShareBuffer( p_input->p_method_data, - p_current ); - } - else - { - *pp_data = p_data; - p_data = p_data->p_next; - } + i_block_once = i_blocks; + } + /* + intf_WarnMsg( 2, "Sector: 0x%x Read: %d Chapter: %d", p_dvd->i_sector, i_block_once, p_dvd->i_chapter ); + */ - (*pp_data)->p_payload_start = (*pp_data)->p_demux_start = - (*pp_data)->p_demux_start + i_pos; + /* Reads from DVD */ + i_read_blocks = dvdcss_read( p_dvd->dvdhandle, p_buffer, + i_block_once, DVDCSS_READ_DECRYPT ); - (*pp_data)->p_payload_end = - (*pp_data)->p_payload_start + i_packet_size + 6; + i_blocks -= i_read_blocks; + p_buffer += LB2OFF( i_read_blocks ); + i_read_total += i_read_blocks; - i_packet++; - i_pos += i_packet_size + 6; - pp_data = &(*pp_data)->p_next; - } + /* Update global position */ + p_dvd->i_sector += i_read_blocks; } - p_input->pf_delete_packet( p_input->p_method_data, p_data ); - *pp_data = NULL; - vlc_mutex_lock( &p_input->stream.stream_lock ); p_input->stream.p_selected_area->i_tell = - LB2OFF( i_sector + i_read_blocks ) - + LB2OFF( i_sector + i_read_total ) - p_input->stream.p_selected_area->i_start; if( b_eoc ) { @@ -985,25 +1006,17 @@ intf_WarnMsg( 2, "Sector: 0x%x Read: %d Chapter: %d", p_dvd->i_sector, i_block_o p_dvd->i_title++; DVDSetArea( p_input, p_input->stream.pp_areas[p_dvd->i_title] ); vlc_mutex_unlock( &p_input->stream.stream_lock ); - return( i_packet ); + return LB2OFF( i_read_total ); } vlc_mutex_unlock( &p_input->stream.stream_lock ); - +/* if( i_read_blocks != i_block_once ) { return -1; } - - return( i_packet ); -} - -/***************************************************************************** - * DVDRewind : reads a stream backward - *****************************************************************************/ -static int DVDRewind( input_thread_t * p_input ) -{ - return( -1 ); +*/ + return LB2OFF( i_read_total ); } /***************************************************************************** @@ -1022,7 +1035,7 @@ static void DVDSeek( input_thread_t * p_input, off_t i_off ) int i_chapter; int i_angle; - p_dvd = ( thread_dvd_data_t * )p_input->p_plugin_data; + p_dvd = ( thread_dvd_data_t * )(p_input->p_access_data); /* we have to take care of offset of beginning of title */ p_dvd->i_sector = OFF2LB(i_off + p_input->stream.p_selected_area->i_start) @@ -1122,7 +1135,6 @@ static void DVDSeek( input_thread_t * p_input, off_t i_off ) intf_WarnMsg( 7, "Program Cell: %d Cell: %d Chapter: %d", p_dvd->i_prg_cell, p_dvd->i_cell, p_dvd->i_chapter ); - return; } diff --git a/plugins/dvd/input_dvd.h b/plugins/dvd/input_dvd.h index b6e848e53a..9f3e00d531 100644 --- a/plugins/dvd/input_dvd.h +++ b/plugins/dvd/input_dvd.h @@ -2,7 +2,7 @@ * input_dvd.h: thread structure of the DVD plugin ***************************************************************************** * Copyright (C) 1999-2001 VideoLAN - * $Id: input_dvd.h,v 1.24 2001/06/12 22:14:44 sam Exp $ + * $Id: input_dvd.h,v 1.25 2002/03/01 01:12:28 stef Exp $ * * Author: Stéphane Borel * @@ -36,9 +36,6 @@ typedef struct thread_dvd_data_s { dvdcss_handle dvdhandle; /* libdvdcss handle */ - int i_block_once; // Nb of block read once by - // readv - /* Navigation information */ int i_title; int i_title_id; diff --git a/plugins/dvdread/dvdread.c b/plugins/dvdread/dvdread.c index 4dfbc4d849..ddfdbe0915 100644 --- a/plugins/dvdread/dvdread.c +++ b/plugins/dvdread/dvdread.c @@ -2,7 +2,7 @@ * dvdread.c : DvdRead input module for vlc ***************************************************************************** * Copyright (C) 2001 VideoLAN - * $Id: dvdread.c,v 1.10 2002/02/26 01:17:13 stef Exp $ + * $Id: dvdread.c,v 1.11 2002/03/01 01:12:28 stef Exp $ * * Authors: Samuel Hocevar * @@ -32,7 +32,8 @@ /***************************************************************************** * Capabilities defined in the other files. *****************************************************************************/ -void _M( input_getfunctions )( function_list_t * p_function_list ); +void _M( access_getfunctions)( function_list_t * p_function_list ); +void _M( demux_getfunctions)( function_list_t * p_function_list ); /***************************************************************************** * Build configuration tree. @@ -42,13 +43,14 @@ MODULE_CONFIG_STOP MODULE_INIT_START SET_DESCRIPTION( "DVDRead input module" ) - ADD_CAPABILITY( INPUT, 110 ) + ADD_CAPABILITY( DEMUX, 210 ) + ADD_CAPABILITY( ACCESS, 110 ) ADD_SHORTCUT( "dvdread" ) - MODULE_INIT_STOP MODULE_ACTIVATE_START - _M( input_getfunctions )( &p_module->p_functions->input ); + _M( access_getfunctions)( &p_module->p_functions->access ); + _M( demux_getfunctions)( &p_module->p_functions->demux ); MODULE_ACTIVATE_STOP MODULE_DEACTIVATE_START diff --git a/plugins/dvdread/input_dvdread.c b/plugins/dvdread/input_dvdread.c index 6b33fc3219..cdd35b1500 100644 --- a/plugins/dvdread/input_dvdread.c +++ b/plugins/dvdread/input_dvdread.c @@ -6,7 +6,7 @@ * It depends on: libdvdread for ifo files and block reading. ***************************************************************************** * Copyright (C) 2001 VideoLAN - * $Id: input_dvdread.c,v 1.21 2002/02/24 20:51:09 gbazin Exp $ + * $Id: input_dvdread.c,v 1.22 2002/03/01 01:12:28 stef Exp $ * * Author: Stéphane Borel * @@ -78,133 +78,284 @@ * Local prototypes *****************************************************************************/ /* called from outside */ -static int DvdReadProbe ( struct input_thread_s * ); -static void DvdReadInit ( struct input_thread_s * ); +static int DvdReadInit ( struct input_thread_s * ); static void DvdReadEnd ( struct input_thread_s * ); -static void DvdReadOpen ( struct input_thread_s * ); +static int DvdReadDemux ( struct input_thread_s * ); +static int DvdReadRewind ( struct input_thread_s * ); + +static int DvdReadOpen ( struct input_thread_s * ); static void DvdReadClose ( struct input_thread_s * ); static int DvdReadSetArea ( struct input_thread_s *, struct input_area_s * ); static int DvdReadSetProgram( struct input_thread_s *, pgrm_descriptor_t * ); -static int DvdReadRead ( struct input_thread_s *, data_packet_t ** ); +static int DvdReadRead ( struct input_thread_s *, byte_t *, size_t ); static void DvdReadSeek ( struct input_thread_s *, off_t ); -static int DvdReadRewind ( struct input_thread_s * ); /* called only from here */ static void DvdReadHandleDSI( thread_dvd_data_t * p_dvd, u8 * p_data ); static void DvdReadFindCell ( thread_dvd_data_t * p_dvd ); -/***************************************************************************** - * Declare a buffer manager - *****************************************************************************/ -#define FLAGS BUFFERS_UNIQUE_SIZE -#define NB_LIFO 1 -DECLARE_BUFFERS_SHARED( FLAGS, NB_LIFO ); -DECLARE_BUFFERS_INIT( FLAGS, NB_LIFO ); -DECLARE_BUFFERS_END_SHARED( FLAGS, NB_LIFO ); -DECLARE_BUFFERS_NEWPACKET_SHARED( FLAGS, NB_LIFO ); -DECLARE_BUFFERS_DELETEPACKET_SHARED( FLAGS, NB_LIFO, 1000 ); -DECLARE_BUFFERS_NEWPES( FLAGS, NB_LIFO ); -DECLARE_BUFFERS_DELETEPES( FLAGS, NB_LIFO, 1000 ); -DECLARE_BUFFERS_TOIO( FLAGS, DVD_VIDEO_LB_LEN ); -DECLARE_BUFFERS_SHAREBUFFER( FLAGS ); - /***************************************************************************** * Functions exported as capabilities. They are declared as static so that * we don't pollute the namespace too much. *****************************************************************************/ -void _M( input_getfunctions )( function_list_t * p_function_list ) +void _M( access_getfunctions )( function_list_t * p_function_list ) +{ +#define access p_function_list->functions.access + access.pf_open = DvdReadOpen; + access.pf_close = DvdReadClose; + access.pf_read = DvdReadRead; + access.pf_set_area = DvdReadSetArea; + access.pf_set_program = DvdReadSetProgram; + access.pf_seek = DvdReadSeek; +#undef access +} + +void _M( demux_getfunctions )( function_list_t * p_function_list ) { -#define input p_function_list->functions.input - input.pf_probe = DvdReadProbe; - input.pf_init = DvdReadInit; - input.pf_open = DvdReadOpen; - input.pf_close = DvdReadClose; - input.pf_end = DvdReadEnd; - input.pf_init_bit_stream = InitBitstream; - input.pf_read = DvdReadRead; - input.pf_set_area = DvdReadSetArea; - input.pf_set_program = DvdReadSetProgram; - input.pf_demux = input_DemuxPS; - input.pf_new_packet = input_NewPacket; - input.pf_new_pes = input_NewPES; - input.pf_delete_packet = input_DeletePacket; - input.pf_delete_pes = input_DeletePES; - input.pf_rewind = DvdReadRewind; - input.pf_seek = DvdReadSeek; - -#undef input +#define demux p_function_list->functions.demux + demux.pf_init = DvdReadInit; + demux.pf_end = DvdReadEnd; + demux.pf_demux = DvdReadDemux; + demux.pf_rewind = DvdReadRewind; +#undef demux } /* - * Data reading functions + * Data demux functions */ /***************************************************************************** - * DvdReadProbe: verifies that the stream is a PS stream + * DvdReadInit: initializes DVD structures *****************************************************************************/ -static int DvdReadProbe( input_thread_t *p_input ) +static int DvdReadInit( input_thread_t * p_input ) { - char * psz_name = p_input->p_source; + thread_dvd_data_t * p_dvd; - if((( strlen(psz_name) > 8 ) && !strncasecmp( psz_name, "dvdread:", 8 )) - ||(( strlen(psz_name) > 4 ) && !strncasecmp( psz_name, "dvd:", 4 ))) + if( strncmp( p_input->p_access_module->psz_name, "dvdread", 7 ) ) { - return 0; + return -1; + } + + p_dvd = (thread_dvd_data_t*)(p_input->p_access_data); + + if( p_main->b_video ) + { + input_SelectES( p_input, p_input->stream.pp_es[0] ); } - return -1; + if( p_main->b_audio ) + { + /* For audio: first one if none or a not existing one specified */ + int i_audio = config_GetIntVariable( INPUT_CHANNEL_VAR ); + if( i_audio < 0 /*|| i_audio > i_audio_nb*/ ) + { + config_PutIntVariable( INPUT_CHANNEL_VAR, 1 ); + i_audio = 1; + } + if( i_audio > 0/* && i_audio_nb > 0*/ ) + { + if( config_GetIntVariable( AOUT_SPDIF_VAR ) || + ( config_GetIntVariable( INPUT_AUDIO_VAR ) == + REQUESTED_AC3 ) ) + { + int i_ac3 = i_audio; + while( ( p_input->stream.pp_es[i_ac3]->i_type != + AC3_AUDIO_ES ) && ( i_ac3 <= + p_dvd->p_vts_file->vtsi_mat->nr_of_vts_audio_streams ) ) + { + i_ac3++; + } + if( p_input->stream.pp_es[i_ac3]->i_type == AC3_AUDIO_ES ) + { + input_SelectES( p_input, + p_input->stream.pp_es[i_ac3] ); + } + } + else + { + input_SelectES( p_input, + p_input->stream.pp_es[i_audio] ); + } + } + } + + if( p_main->b_video ) + { + /* for spu, default is none */ + int i_spu = config_GetIntVariable( INPUT_SUBTITLE_VAR ); + if( i_spu < 0 /*|| i_spu > i_spu_nb*/ ) + { + config_PutIntVariable( INPUT_SUBTITLE_VAR, 0 ); + i_spu = 0; + } + if( i_spu > 0 /*&& i_spu_nb > 0*/ ) + { + i_spu += p_dvd->p_vts_file->vtsi_mat->nr_of_vts_audio_streams; + input_SelectES( p_input, p_input->stream.pp_es[i_spu] ); + } + } + + return 0; } /***************************************************************************** - * DvdReadInit: initializes DVD structures + * DvdReadEnd: frees unused data *****************************************************************************/ -static void DvdReadInit( input_thread_t * p_input ) +static void DvdReadEnd( input_thread_t * p_input ) { - thread_dvd_data_t * p_dvd; - input_area_t * p_area; - int i_title; - int i_chapter; - int i; +} + +/***************************************************************************** + * DvdReadDemux + *****************************************************************************/ +#define PEEK( SIZE ) \ + i_result = input_Peek( p_input, &p_peek, SIZE ); \ + if( i_result == -1 ) \ + { \ + return( -1 ); \ + } \ + else if( i_result < SIZE ) \ + { \ + /* EOF */ \ + return( 0 ); \ + } + +static int DvdReadDemux( input_thread_t * p_input ) +{ + int i; + byte_t * p_peek; + data_packet_t * p_data; + ssize_t i_result; + int i_packet_size; + + + /* Read headers to compute payload length */ + for( i = 0 ; i < DVD_BLOCK_READ_ONCE ; i++ ) + { + + /* Read what we believe to be a packet header. */ + PEEK( 4 ); + + /* Default header */ + if( U32_AT( p_peek ) != 0x1BA ) + { + /* That's the case for all packets, except pack header. */ + i_packet_size = U16_AT( p_peek + 4 ); + } + else + { + /* MPEG-2 Pack header. */ + i_packet_size = 8; + } + + /* Fetch a packet of the appropriate size. */ + i_result = input_SplitBuffer( p_input, &p_data, i_packet_size + 6 ); + if( i_result <= 0 ) + { + return( i_result ); + } + + /* In MPEG-2 pack headers we still have to read stuffing bytes. */ + if( (p_data->p_demux_start[3] == 0xBA) && (i_packet_size == 8) ) + { + size_t i_stuffing = (p_data->p_demux_start[13] & 0x7); + /* Force refill of the input buffer - though we don't care + * about p_peek. Please note that this is unoptimized. */ + PEEK( i_stuffing ); + p_input->p_current_data += i_stuffing; + } + + input_DemuxPS( p_input, p_data ); + + } + + return i; +} + +/***************************************************************************** + * DVDRewind : reads a stream backward + *****************************************************************************/ +static int DvdReadRewind( input_thread_t * p_input ) +{ + return( -1 ); +} + +/* + * Data access functions + */ + +/***************************************************************************** + * DvdReadOpen: open libdvdread + *****************************************************************************/ +static int DvdReadOpen( struct input_thread_s *p_input ) +{ + struct stat stat_info; + thread_dvd_data_t * p_dvd; + dvd_reader_t * p_dvdread; + input_area_t * p_area; + int i_title; + int i_chapter; + int i; + + if( stat( p_input->psz_name, &stat_info ) == -1 ) + { + intf_ErrMsg( "input error: cannot stat() device `%s' (%s)", + p_input->psz_name, strerror(errno)); + return( -1 ); + } + if( !S_ISBLK(stat_info.st_mode) && + !S_ISCHR(stat_info.st_mode) && + !S_ISDIR(stat_info.st_mode) ) + { + intf_WarnMsg( 3, "input : DvdRead plugin discarded" + " (not a valid source)" ); + return -1; + } + + p_dvdread = DVDOpen( p_input->psz_name ); + if( ! p_dvdread ) + { + intf_ErrMsg( "dvdread error: libdvdcss can't open source" ); + return -1; + } + + /* set up input */ + p_input->i_mtu = 0; p_dvd = malloc( sizeof(thread_dvd_data_t) ); if( p_dvd == NULL ) { intf_ErrMsg( "dvdread error: out of memory" ); - p_input->b_error = 1; - return; + return -1; } - /* we take the pointer to dvd_reader_t back */ - p_dvd->p_dvdread = (dvd_reader_t *)p_input->p_plugin_data; + p_dvd->p_dvdread = p_dvdread; p_dvd->p_title = NULL; p_dvd->p_vts_file = NULL; - p_input->p_plugin_data = (void *)p_dvd; - - if( (p_input->p_method_data = input_BuffersInit()) == NULL ) - { - free( p_dvd ); - p_input->b_error = 1; - return; - } - - /* We read DVD_BLOCK_READ_ONCE in each loop */ - p_dvd->i_block_once = DVD_BLOCK_READ_ONCE; + p_input->p_access_data = (void *)p_dvd; /* Ifo allocation & initialisation */ if( ! ( p_dvd->p_vmg_file = ifoOpen( p_dvd->p_dvdread, 0 ) ) ) { intf_ErrMsg( "dvdread error: can't open VMG info" ); - input_BuffersEnd( p_input->p_method_data ); free( p_dvd ); - p_input->b_error = 1; - return; + return -1; } intf_WarnMsg( 2, "dvdread info: VMG opened" ); /* Set stream and area data */ vlc_mutex_lock( &p_input->stream.stream_lock ); + p_input->stream.i_method = INPUT_METHOD_DVD; + + /* If we are here we can control the pace... */ + p_input->stream.b_pace_control = 1; + p_input->stream.b_seekable = 1; + + p_input->stream.p_selected_area->i_size = 0; + p_input->stream.p_selected_area->i_tell = 0; + /* Initialize ES structures */ input_InitStream( p_input, sizeof( stream_ps_data_t ) ); @@ -263,89 +414,35 @@ static void DvdReadInit( input_thread_t * p_input ) p_area = p_input->stream.pp_areas[i_title]; /* set title, chapter, audio and subpic */ - DvdReadSetArea( p_input, p_area ); - - vlc_mutex_unlock( &p_input->stream.stream_lock ); - - return; -} - -/***************************************************************************** - * DvdReadOpen: open libdvdread - *****************************************************************************/ -static void DvdReadOpen( struct input_thread_s *p_input ) -{ - dvd_reader_t *p_dvdread; - - vlc_mutex_lock( &p_input->stream.stream_lock ); - - p_input->stream.i_method = INPUT_METHOD_DVD; - - /* If we are here we can control the pace... */ - p_input->stream.b_pace_control = 1; - p_input->stream.b_seekable = 1; - - p_input->stream.p_selected_area->i_size = 0; - p_input->stream.p_selected_area->i_tell = 0; - - vlc_mutex_unlock( &p_input->stream.stream_lock ); - - /* XXX: put this shit in an access plugin */ - if( strlen( p_input->p_source ) > 8 - && !strncasecmp( p_input->p_source, "dvdread:", 8 ) ) - { - p_dvdread = DVDOpen( p_input->p_source + 8 ); - } - else if( strlen( p_input->p_source ) > 4 - && !strncasecmp( p_input->p_source, "dvd:", 4 ) ) - { - p_dvdread = DVDOpen( p_input->p_source + 4 ); - } - else - { - p_dvdread = DVDOpen( p_input->p_source ); - } - - if( ! p_dvdread ) + if( DvdReadSetArea( p_input, p_area ) ) { - p_input->b_error = 1; - return; + vlc_mutex_unlock( &p_input->stream.stream_lock ); + return -1; } - /* the vlc input doesn't handle the file descriptor with libdvdread */ - p_input->i_handle = -1; + vlc_mutex_unlock( &p_input->stream.stream_lock ); - /* p_dvdread is stored in p_plugin_data until we have - * malloc'ed a dvd_thread_data_t */ - p_input->p_plugin_data = (void *) p_dvdread; + return 0; } /***************************************************************************** * DvdReadClose: close libdvdread *****************************************************************************/ static void DvdReadClose( struct input_thread_s *p_input ) -{ - DVDClose( ((thread_dvd_data_t*)p_input->p_plugin_data)->p_dvdread ); - free( p_input->p_plugin_data ); - p_input->p_plugin_data = NULL; - -} - -/***************************************************************************** - * DvdReadEnd: frees unused data - *****************************************************************************/ -static void DvdReadEnd( input_thread_t * p_input ) { thread_dvd_data_t * p_dvd; - p_dvd = (thread_dvd_data_t *)p_input->p_plugin_data; + p_dvd = (thread_dvd_data_t *)p_input->p_access_data; /* close libdvdread */ DVDCloseFile( p_dvd->p_title ); ifoClose( p_dvd->p_vts_file ); ifoClose( p_dvd->p_vmg_file ); - input_BuffersEnd( p_input->p_method_data ); + DVDClose( p_dvd->p_dvdread ); + free( p_dvd ); + p_input->p_access_data = NULL; + } /***************************************************************************** @@ -372,7 +469,7 @@ static int DvdReadSetArea( input_thread_t * p_input, input_area_t * p_area ) int pgc_id = 0; int pgn = 0; - p_dvd = (thread_dvd_data_t*)p_input->p_plugin_data; + p_dvd = (thread_dvd_data_t*)p_input->p_access_data; /* we can't use the interface slider until initilization is complete */ p_input->stream.b_seekable = 0; @@ -417,7 +514,6 @@ static int DvdReadSetArea( input_thread_t * p_input, input_area_t * p_area ) intf_ErrMsg( "dvdread error: fatal error in vts ifo" ); ifoClose( p_vmg ); DVDClose( p_dvd->p_dvdread ); - p_input->b_error = 1; return -1; } @@ -535,10 +631,6 @@ static int DvdReadSetArea( input_thread_t * p_input, input_area_t * p_area ) p_es->i_stream_id = 0xe0; p_es->i_type = MPEG2_VIDEO_ES; p_es->i_cat = VIDEO_ES; - if( p_main->b_video ) - { - input_SelectES( p_input, p_es ); - } #define audio_control \ p_dvd->p_vts_file->vts_pgcit->pgci_srp[pgc_id-1].pgc->audio_control[i-1] @@ -664,55 +756,14 @@ static int DvdReadSetArea( input_thread_t * p_input, input_area_t * p_area ) } } #undef spu_control - if( p_main->b_audio ) - { - /* For audio: first one if none or a not existing one specified */ - int i_audio = config_GetIntVariable( INPUT_CHANNEL_VAR ); - if( i_audio < 0 || i_audio > i_audio_nb ) - { - i_audio = 1; - } - if( i_audio > 0 && i_audio_nb > 0 ) - { - if( config_GetIntVariable( AOUT_SPDIF_VAR ) || - ( config_GetIntVariable( INPUT_AUDIO_VAR ) == - REQUESTED_AC3 ) ) - { - int i_ac3 = i_audio; - while( ( p_input->stream.pp_es[i_ac3]->i_type != - AC3_AUDIO_ES ) && ( i_ac3 <= - p_vts->vtsi_mat->nr_of_vts_audio_streams ) ) - { - i_ac3++; - } - if( p_input->stream.pp_es[i_ac3]->i_type == AC3_AUDIO_ES ) - { - input_SelectES( p_input, - p_input->stream.pp_es[i_ac3] ); - } - } - else - { - input_SelectES( p_input, - p_input->stream.pp_es[i_audio] ); - } - } - } - if( p_main->b_video ) + /* FIXME: hack to check that the demuxer is ready, and set + * the decoders */ + if( p_input->pf_init ) { - /* for spu, default is none */ - int i_spu = config_GetIntVariable( INPUT_SUBTITLE_VAR ); - if( i_spu < 0 || i_spu > i_spu_nb ) - { - i_spu = 0; - } - if( i_spu > 0 && i_spu_nb > 0 ) - { - i_spu += p_vts->vtsi_mat->nr_of_vts_audio_streams; - input_SelectES( p_input, p_input->stream.pp_es[i_spu] ); - } + p_input->pf_init( p_input ); } + } /* i_title >= 0 */ else { @@ -774,55 +825,53 @@ static int DvdReadSetArea( input_thread_t * p_input, input_area_t * p_area ) * EOF. *****************************************************************************/ static int DvdReadRead( input_thread_t * p_input, - data_packet_t ** pp_data ) + byte_t * p_buffer, size_t i_count ) { thread_dvd_data_t * p_dvd; - u8 p_data[DVD_VIDEO_LB_LEN]; - struct iovec p_vec[DVD_BLOCK_READ_ONCE]; - u8 * pi_cur; + byte_t * p_buf; + int i_blocks_once; int i_blocks; int i_read; - int i_iovec; - int i_packet_size; - int i_packet; - int i_pos; - data_packet_t * p_data_p; + int i_read_total; boolean_t b_eot = 0; - p_dvd = (thread_dvd_data_t *)p_input->p_plugin_data; - - *pp_data = NULL; + p_dvd = (thread_dvd_data_t *)p_input->p_access_data; + p_buf = p_buffer; /* * Playback by cell in this pgc, starting at the cell for our chapter. */ + i_blocks = OFF2LB( i_count ); + i_read_total = 0; + i_read = 0; - /* - * End of pack, we select the following one - */ - if( ! p_dvd->i_pack_len ) + while( i_blocks ) { - /* - * Read NAV packet. + /* + * End of pack, we select the following one */ - if( ( i_read = DVDReadBlocks( p_dvd->p_title, p_dvd->i_next_vobu, - 1, p_data ) ) != 1 ) + if( ! p_dvd->i_pack_len ) { - intf_ErrMsg( "dvdread error: read failed for block %d", - p_dvd->i_next_vobu ); - return -1; - } + /* + * Read NAV packet. + */ + if( ( i_read = DVDReadBlocks( p_dvd->p_title, p_dvd->i_next_vobu, + 1, p_buf ) ) != 1 ) + { + intf_ErrMsg( "dvdread error: read failed for block %d", + p_dvd->i_next_vobu ); + return -1; + } - /* basic check to be sure we don't have a empty title - * go to next title if so */ - assert( p_data[41] == 0xbf && p_data[1027] == 0xbf ); - if( p_data[41] == 0xbf && p_data[1027] == 0xbf ) - { + /* basic check to be sure we don't have a empty title + * go to next title if so */ + //assert( p_buffer[41] == 0xbf && p_buffer[1027] == 0xbf ); + /* * Parse the contained dsi packet. */ - DvdReadHandleDSI( p_dvd, p_data ); + DvdReadHandleDSI( p_dvd, p_buf ); /* End of File */ if( p_dvd->i_next_vobu >= p_dvd->i_end_block + 1 ) @@ -833,99 +882,40 @@ static int DvdReadRead( input_thread_t * p_input, assert( p_dvd->i_pack_len < 1024 ); /* FIXME: Ugly kludge: we send the pack block to the input for it * sometimes has a zero scr and restart the sync */ - //p_dvd->i_cur_block ++; - p_dvd->i_pack_len++; + p_dvd->i_cur_block ++; + //p_dvd->i_pack_len++; + + i_read_total++; + p_buf += DVD_VIDEO_LB_LEN; + i_blocks--; } - else + + /* + * Compute the number of blocks to read + */ + i_blocks_once = p_dvd->i_pack_len >= i_blocks + ? i_blocks : p_dvd->i_pack_len; + p_dvd->i_pack_len -= i_blocks_once; + + /* Reads from DVD */ + i_read = DVDReadBlocks( p_dvd->p_title, p_dvd->i_cur_block, + i_blocks_once, p_buf ); + if( i_read != i_blocks_once ) { - b_eot = 1; - p_dvd->i_pack_len = 0; - return 1; + intf_ErrMsg( "dvdread error: read failed for %d/%d blocks at 0x%02x", + i_read, i_blocks_once, p_dvd->i_cur_block ); + return -1; } - } - /* - * Compute the number of blocks to read - */ - i_blocks = p_dvd->i_pack_len >= DVD_BLOCK_READ_ONCE - ? DVD_BLOCK_READ_ONCE : p_dvd->i_pack_len; - p_dvd->i_pack_len -= i_blocks; + i_blocks -= i_read; + i_read_total += i_read; + p_dvd->i_cur_block += i_read; + p_buf += LB2OFF( i_read ); - /* Get iovecs */ - *pp_data = p_data_p = input_BuffersToIO( p_input->p_method_data, p_vec, - DVD_BLOCK_READ_ONCE ); - - if ( p_data_p == NULL ) - { - return( -1 ); } - - /* Reads from DVD */ - i_read = DVDReadVBlocks( p_dvd->p_title, p_dvd->i_cur_block, - i_blocks, p_vec ); - if( i_read != i_blocks ) - { - intf_ErrMsg( "dvdread error: read failed for %d/%d blocks at 0x%02x", - i_read, i_blocks, p_dvd->i_cur_block ); - return -1; - } - - p_dvd->i_cur_block += i_read; /* intf_WarnMsg( 12, "dvdread i_blocks: %d len: %d current: 0x%02x", i_read, p_dvd->i_pack_len, p_dvd->i_cur_block ); */ - i_packet = 0; - - /* Read headers to compute payload length */ - for( i_iovec = 0 ; i_iovec < i_read ; i_iovec++ ) - { - data_packet_t * p_current = p_data_p; - i_pos = 0; - - while( i_pos < DVD_VIDEO_LB_LEN ) - { - pi_cur = (u8*)p_vec[i_iovec].iov_base + i_pos; - - /*default header */ - if( U32_AT( pi_cur ) != 0x1BA ) - { - /* That's the case for all packets, except pack header. */ - i_packet_size = U16_AT( pi_cur + 4 ); - } - else - { - /* MPEG-2 Pack header. */ - i_packet_size = 8; - } - if( i_pos != 0 ) - { - *pp_data = input_ShareBuffer( p_input->p_method_data, - p_current ); - } - else - { - *pp_data = p_data_p; - p_data_p = p_data_p->p_next; - } - - (*pp_data)->p_payload_start = (*pp_data)->p_demux_start = - (*pp_data)->p_demux_start + i_pos; - - - (*pp_data)->p_payload_end = - (*pp_data)->p_payload_start + i_packet_size + 6; - -// pp_packets[i_packet]->p_next = NULL; -// pp_packets[i_packet]->b_discard_payload = 0; - - i_packet++; - i_pos += i_packet_size + 6; - pp_data = &(*pp_data)->p_next; - } - } - - p_input->pf_delete_packet( p_input->p_method_data, p_data_p ); - *pp_data = NULL; vlc_mutex_lock( &p_input->stream.stream_lock ); @@ -962,18 +952,10 @@ static int DvdReadRead( input_thread_t * p_input, vlc_mutex_unlock( &p_input->stream.stream_lock ); - return i_read; + return LB2OFF( i_read_total ); } #undef p_pgc -/***************************************************************************** - * DVDRewind : reads a stream backward - *****************************************************************************/ -static int DvdReadRewind( input_thread_t * p_input ) -{ - return( -1 ); -} - /***************************************************************************** * DvdReadSeek : Goes to a given position on the stream. ***************************************************************************** @@ -993,7 +975,7 @@ static void DvdReadSeek( input_thread_t * p_input, off_t i_off ) i_off += p_input->stream.p_selected_area->i_start; i_lb = OFF2LB( i_off ); - p_dvd = ( thread_dvd_data_t * )p_input->p_plugin_data; + p_dvd = ( thread_dvd_data_t * )p_input->p_access_data; /* find cell */ while( p_dvd->p_cur_pgc->cell_playback[i_cell].last_sector < i_lb ) diff --git a/plugins/dvdread/input_dvdread.h b/plugins/dvdread/input_dvdread.h index bbc9c7629d..905f5a1126 100644 --- a/plugins/dvdread/input_dvdread.h +++ b/plugins/dvdread/input_dvdread.h @@ -2,7 +2,7 @@ * input_dvdread.h: thread structure of the DVD plugin ***************************************************************************** * Copyright (C) 1999-2001 VideoLAN - * $Id: input_dvdread.h,v 1.4 2002/01/23 03:15:31 stef Exp $ + * $Id: input_dvdread.h,v 1.5 2002/03/01 01:12:28 stef Exp $ * * Author: Stéphane Borel * @@ -66,7 +66,5 @@ typedef struct thread_dvd_data_s boolean_t b_eoc; int i_angle_nb; int i_angle; - - int i_block_once; // Nb of block read once } thread_dvd_data_t; diff --git a/src/input/input.c b/src/input/input.c index fd3e64deb1..f301283b97 100644 --- a/src/input/input.c +++ b/src/input/input.c @@ -4,7 +4,7 @@ * decoders. ***************************************************************************** * Copyright (C) 1998-2001 VideoLAN - * $Id: input.c,v 1.180 2002/03/01 00:33:18 massiot Exp $ + * $Id: input.c,v 1.181 2002/03/01 01:12:28 stef Exp $ * * Authors: Christophe Massiot * Alexis Guillard @@ -128,6 +128,20 @@ input_thread_t *input_CreateThread ( playlist_item_t *p_item, int *pi_status ) /* Set status */ p_input->i_status = THREAD_CREATE; + + /* Demux */ + p_input->pf_init = NULL; + p_input->pf_end = NULL; + p_input->pf_demux = NULL; + p_input->pf_rewind = NULL; + + /* Access */ + p_input->pf_open = NULL; + p_input->pf_close = NULL; + p_input->pf_read = NULL; + p_input->pf_seek = NULL; + p_input->pf_set_area = NULL; + p_input->pf_set_program = NULL; /* Initialize statistics */ p_input->c_loops = 0;