📄 input.c
字号:
/***************************************************************************** * input.c: DvdRead plugin. ***************************************************************************** * This plugins should handle all the known specificities of the DVD format, * especially the 2048 bytes logical block size. * It depends on: libdvdread for ifo files and block reading. ***************************************************************************** * Copyright (C) 2001, 2003 VideoLAN * $Id: input.c,v 1.23 2003/09/07 22:49:05 fenrir Exp $ * * Author: St閜hane Borel <stef@via.ecp.fr> * * Some code taken form the play_title.c by Billy Biggs <vektor@dumbterm.net> * in libdvdread. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#include <stdio.h>#include <stdlib.h>#include <vlc/vlc.h>#include <vlc/input.h>#include "../../demux/mpeg/system.h"#ifdef HAVE_UNISTD_H# include <unistd.h>#endif#include <fcntl.h>#include <sys/types.h>#include <sys/stat.h>#include <string.h>#include <errno.h>#include <assert.h>#ifdef STRNCASECMP_IN_STRINGS_H# include <strings.h>#endif#if defined( WIN32 )# include <io.h> /* read() */#endif#include <dvdread/dvd_reader.h>#include <dvdread/ifo_types.h>#include <dvdread/ifo_read.h>#include <dvdread/nav_read.h>#include <dvdread/nav_print.h>#include "input.h"#include "iso_lang.h"/* how many blocks DVDRead will read in each loop */#define DVD_BLOCK_READ_ONCE 64/***************************************************************************** * Private structure *****************************************************************************/struct demux_sys_t{ module_t * p_module; mpeg_demux_t mpeg;};/***************************************************************************** * Local prototypes *****************************************************************************//* called from outside */static int DvdReadDemux ( input_thread_t * );static int DvdReadRewind ( input_thread_t * );static int DvdReadSetArea ( input_thread_t *, input_area_t * );static int DvdReadSetProgram ( input_thread_t *, pgrm_descriptor_t * );static ssize_t DvdReadRead ( input_thread_t *, byte_t *, size_t );static void DvdReadSeek ( input_thread_t *, off_t );/* called only from here */static void DvdReadLauchDecoders( input_thread_t * p_input );static void DvdReadHandleDSI( thread_dvd_data_t * p_dvd, uint8_t * p_data );static void DvdReadFindCell ( thread_dvd_data_t * p_dvd );/* * Data demux functions *//***************************************************************************** * InitDVD: initialize DVD structures *****************************************************************************/int E_(InitDVD) ( vlc_object_t *p_this ){ input_thread_t *p_input = (input_thread_t *)p_this; demux_sys_t * p_demux; if( p_input->stream.i_method != INPUT_METHOD_DVD ) { return VLC_EGENERIC; } p_demux = p_input->p_demux_data = malloc( sizeof(demux_sys_t ) ); if( p_demux == NULL ) { return VLC_ENOMEM; } p_input->p_private = (void*)&p_demux->mpeg; p_demux->p_module = module_Need( p_input, "mpeg-system", NULL ); if( p_demux->p_module == NULL ) { free( p_input->p_demux_data ); return VLC_ENOMOD; } p_input->pf_demux = DvdReadDemux; p_input->pf_demux_control = demux_vaControlDefault; p_input->pf_rewind = NULL; vlc_mutex_lock( &p_input->stream.stream_lock ); DvdReadLauchDecoders( p_input ); vlc_mutex_unlock( &p_input->stream.stream_lock ); return VLC_SUCCESS;}/***************************************************************************** * EndDVD: end DVD structures *****************************************************************************/void E_(EndDVD) ( vlc_object_t *p_this ){ input_thread_t *p_input = (input_thread_t *)p_this; module_Unneed( p_input, p_input->p_demux_data->p_module ); free( p_input->p_demux_data );}/***************************************************************************** * 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) ) { ssize_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; } p_input->p_demux_data->mpeg.pf_demux_ps( p_input, p_data ); } return i;}/***************************************************************************** * DVDRewind : reads a stream backward *****************************************************************************/static int DvdReadRewind( input_thread_t * p_input ){ return -1;}/* * Data access functions *//***************************************************************************** * OpenDVD: open libdvdread *****************************************************************************/int E_(OpenDVD) ( vlc_object_t *p_this ){ input_thread_t * p_input = (input_thread_t *)p_this; char * psz_parser; char * psz_source; char * psz_next; struct stat stat_info; thread_dvd_data_t * p_dvd; dvd_reader_t * p_dvdread; input_area_t * p_area; unsigned int i_title = 1; unsigned int i_chapter = 1; unsigned int i_angle = 1; unsigned int i; psz_source = strdup( p_input->psz_name ); if( psz_source == NULL ) { return VLC_ENOMEM; } p_input->pf_read = DvdReadRead; p_input->pf_seek = DvdReadSeek; p_input->pf_set_area = DvdReadSetArea; p_input->pf_set_program = DvdReadSetProgram; /* Start with the end, because you could have : * dvdread:/Volumes/my@toto/VIDEO_TS@1,1 * (yes, this is kludgy). */ for ( psz_parser = psz_source + strlen(psz_source) - 1; psz_parser >= psz_source && *psz_parser != '@'; psz_parser-- ); if( psz_parser >= psz_source && *psz_parser == '@' ) { /* Found options */ *psz_parser = '\0'; ++psz_parser; i_title = (int)strtol( psz_parser, &psz_next, 10 ); if( *psz_next ) { psz_parser = psz_next + 1; i_chapter = (int)strtol( psz_parser, &psz_next, 10 ); if( *psz_next ) { i_angle = (int)strtol( psz_next + 1, NULL, 10 ); } } i_title = i_title ? i_title : 1; i_chapter = i_chapter ? i_chapter : 1; i_angle = i_angle ? i_angle : 1; } if( !*psz_source ) { free( psz_source ); if( !p_input->psz_access ) { return VLC_EGENERIC; } psz_source = config_GetPsz( p_input, "dvd" ); if( !psz_source ) return VLC_EGENERIC; } if( stat( psz_source, &stat_info ) == -1 ) { msg_Warn( p_input, "cannot stat() source `%s' (%s)", psz_source, strerror(errno) ); free( psz_source ); return VLC_EGENERIC; } if( !S_ISBLK(stat_info.st_mode) && !S_ISCHR(stat_info.st_mode) && !S_ISDIR(stat_info.st_mode) ) { msg_Warn( p_input, "dvdread module discarded (not a valid source)" ); free( psz_source ); return VLC_EGENERIC; } msg_Dbg( p_input, "dvdroot=%s title=%d chapter=%d angle=%d", psz_source, i_title, i_chapter, i_angle ); p_dvdread = DVDOpen( psz_source ); /* free allocated strings */ free( psz_source ); if( ! p_dvdread ) { msg_Err( p_input, "libdvdcss cannot open source" ); return VLC_EGENERIC; } /* set up input */ p_input->i_mtu = 0; p_dvd = malloc( sizeof(thread_dvd_data_t) ); if( p_dvd == NULL ) { msg_Err( p_input, "out of memory" ); return VLC_ENOMEM; } p_dvd->p_dvdread = p_dvdread; p_dvd->p_title = NULL; p_dvd->p_vts_file = NULL; p_input->p_access_data = (void *)p_dvd; /* Ifo allocation & initialisation */ if( ! ( p_dvd->p_vmg_file = ifoOpen( p_dvd->p_dvdread, 0 ) ) ) { msg_Warn( p_input, "cannot open VMG info" ); free( p_dvd ); return VLC_EGENERIC; } msg_Dbg( p_input, "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 = VLC_TRUE; p_input->stream.b_seekable = VLC_TRUE; 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 ) ); /* disc input method */ p_input->stream.i_method = INPUT_METHOD_DVD;#define tt_srpt p_dvd->p_vmg_file->tt_srpt msg_Dbg( p_input, "number of titles: %d", tt_srpt->nr_of_srpts );#define area p_input->stream.pp_areas /* We start from 1 here since the default area 0 * is reserved for video_ts.vob */ for( i = 1 ; i <= tt_srpt->nr_of_srpts ; i++ ) { /* Titles are Program Chains */ input_AddArea( p_input, i, tt_srpt->title[i-1].nr_of_ptts ); /* Absolute start offset and size * We can only set that with vts ifo, so we do it during the * first call to DVDSetArea */ area[i]->i_start = 0; area[i]->i_size = 0; /* Default Chapter */ area[i]->i_part = 1; area[i]->i_plugin_data = tt_srpt->title[i-1].title_set_nr; }#undef area p_dvd->i_title = i_title <= tt_srpt->nr_of_srpts ? i_title : 1;#undef tt_srpt p_area = p_input->stream.pp_areas[p_dvd->i_title]; p_dvd->i_chapter = i_chapter; p_dvd->i_chapter = i_chapter < p_area->i_part_nb ? i_chapter : 1; p_area->i_part = p_dvd->i_chapter; p_dvd->i_angle = i_angle; /* set title, chapter, audio and subpic */ if( DvdReadSetArea( p_input, p_area ) ) { vlc_mutex_unlock( &p_input->stream.stream_lock ); return VLC_EGENERIC; } vlc_mutex_unlock( &p_input->stream.stream_lock ); if( !p_input->psz_demux || !*p_input->psz_demux ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -