⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dvdread.c

📁 vlc源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/***************************************************************************** * dvdread.c : DvdRead input module for vlc ***************************************************************************** * Copyright (C) 2001-2006 the VideoLAN team * $Id: 3e51aadc00c43bf6fa9aa761dcba7b2b30e1a0cc $ * * Authors: Stéphane Borel <stef@via.ecp.fr> *          Gildas Bazin <gbazin@videolan.org> * * 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#ifdef HAVE_CONFIG_H# include "config.h"#endif#include <vlc_common.h>#include <vlc_plugin.h>#include <vlc_input.h>#include <vlc_access.h>#include <vlc_charset.h>#include <vlc_interface.h>#include <vlc_iso_lang.h>#include "../demux/ps.h"#ifdef HAVE_UNISTD_H#   include <unistd.h>#endif#include <fcntl.h>#include <sys/types.h>#include <sys/stat.h>#ifdef HAVE_DVDREAD_DVD_READER_H  #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>#else  #include <libdvdread/dvd_reader.h>  #include <libdvdread/ifo_types.h>  #include <libdvdread/ifo_read.h>  #include <libdvdread/nav_read.h>  #include <libdvdread/nav_print.h>#endif#include <assert.h>/***************************************************************************** * Module descriptor *****************************************************************************/#define ANGLE_TEXT N_("DVD angle")#define ANGLE_LONGTEXT N_( \    "Default DVD angle." )#define CACHING_TEXT N_("Caching value in ms")#define CACHING_LONGTEXT N_( \    "Caching value for DVDs. " \    "This value should be set in milliseconds." )#define CSSMETHOD_TEXT N_("Method used by libdvdcss for decryption")#define CSSMETHOD_LONGTEXT N_( \    "Set the method used by libdvdcss for key decryption.\n" \    "title: decrypted title key is guessed from the encrypted sectors of " \           "the stream. Thus it should work with a file as well as the " \           "DVD device. But it sometimes takes much time to decrypt a title " \           "key and may even fail. With this method, the key is only checked "\           "at the beginning of each title, so it won't work if the key " \           "changes in the middle of a title.\n" \    "disc: the disc key is first cracked, then all title keys can be " \           "decrypted instantly, which allows us to check them often.\n" \    "key: the same as \"disc\" if you don't have a file with player keys " \           "at compilation time. If you do, the decryption of the disc key " \           "will be faster with this method. It is the one that was used by " \           "libcss.\n" \    "The default method is: key.")static const char *const psz_css_list[] = { "title", "disc", "key" };static const char *const psz_css_list_text[] = { N_("title"), N_("Disc"), N_("Key") };static int  Open ( vlc_object_t * );static void Close( vlc_object_t * );vlc_module_begin();    set_shortname( N_("DVD without menus") );    set_description( N_("DVDRead Input (DVD without menu support)") );    set_category( CAT_INPUT );    set_subcategory( SUBCAT_INPUT_ACCESS );    add_integer( "dvdread-angle", 1, NULL, ANGLE_TEXT,        ANGLE_LONGTEXT, false );    add_integer( "dvdread-caching", DEFAULT_PTS_DELAY / 1000, NULL,        CACHING_TEXT, CACHING_LONGTEXT, true );    add_string( "dvdread-css-method", NULL, NULL, CSSMETHOD_TEXT,                CSSMETHOD_LONGTEXT, true );        change_string_list( psz_css_list, psz_css_list_text, 0 );    set_capability( "access_demux", 0 );    add_shortcut( "dvd" );    add_shortcut( "dvdread" );    add_shortcut( "dvdsimple" );    set_callbacks( Open, Close );vlc_module_end();/* how many blocks DVDRead will read in each loop */#define DVD_BLOCK_READ_ONCE 4/***************************************************************************** * Local prototypes *****************************************************************************/struct demux_sys_t{    /* DVDRead state */    dvd_reader_t *p_dvdread;    dvd_file_t   *p_title;    ifo_handle_t *p_vmg_file;    ifo_handle_t *p_vts_file;    int i_title;    int i_chapter, i_chapters;    int i_angle, i_angles;    tt_srpt_t    *p_tt_srpt;    pgc_t        *p_cur_pgc;    dsi_t        dsi_pack;    int          i_ttn;    int i_pack_len;    int i_cur_block;    int i_next_vobu;    int i_mux_rate;    /* Current title start/end blocks */    int i_title_start_block;    int i_title_end_block;    int i_title_blocks;    int i_title_offset;    mtime_t i_title_cur_time;    int i_title_start_cell;    int i_title_end_cell;    int i_cur_cell;    int i_next_cell;    mtime_t i_cell_cur_time;    mtime_t i_cell_duration;    /* Track */    ps_track_t    tk[PS_TK_COUNT];    int           i_titles;    input_title_t **titles;    /* Video */    int i_aspect;    /* SPU */    uint32_t clut[16];};static int Control   ( demux_t *, int, va_list );static int Demux     ( demux_t * );static int DemuxBlock( demux_t *, uint8_t *, int );static void DemuxTitles( demux_t *, int * );static void ESNew( demux_t *, int, int );static int  DvdReadSetArea  ( demux_t *, int, int, int );static void DvdReadSeek     ( demux_t *, int );static void DvdReadHandleDSI( demux_t *, uint8_t * );static void DvdReadFindCell ( demux_t * );/***************************************************************************** * Open: *****************************************************************************/static int Open( vlc_object_t *p_this ){    demux_t      *p_demux = (demux_t*)p_this;    demux_sys_t  *p_sys;    char         *psz_name;    char         *psz_dvdcss_env;    dvd_reader_t *p_dvdread;    ifo_handle_t *p_vmg_file;    vlc_value_t  val;    if( !p_demux->psz_path || !*p_demux->psz_path )    {        /* Only when selected */        if( !p_this->b_force ) return VLC_EGENERIC;        psz_name = var_CreateGetString( p_this, "dvd" );        if( !psz_name )        {            psz_name = strdup("");        }    }    else        psz_name = ToLocaleDup( p_demux->psz_path );#ifdef WIN32    if( psz_name[0] && psz_name[1] == ':' &&        psz_name[2] == '\\' && psz_name[3] == '\0' ) psz_name[2] = '\0';#endif    /* Override environment variable DVDCSS_METHOD with config option */    psz_dvdcss_env = config_GetPsz( p_demux, "dvdread-css-method" );    if( psz_dvdcss_env && *psz_dvdcss_env )#ifdef HAVE_SETENV        setenv( "DVDCSS_METHOD", psz_dvdcss_env, 1 );#else    {        /* FIXME: this create a small memory leak */        char *psz_env;        psz_env = malloc( strlen("DVDCSS_METHOD=") +                          strlen( psz_dvdcss_env ) + 1 );        if( !psz_env )        {            free( psz_dvdcss_env );            return VLC_ENOMEM;        }        sprintf( psz_env, "%s%s", "DVDCSS_METHOD=", psz_dvdcss_env );        putenv( psz_env );    }#endif    free( psz_dvdcss_env );    /* Open dvdread */    if( !(p_dvdread = DVDOpen( psz_name )) )    {        msg_Err( p_demux, "DVDRead cannot open source: %s", psz_name );        intf_UserFatal( p_demux, false, _("Playback failure"),                        _("DVDRead could not open the disk \"%s\"."), psz_name );        free( psz_name );        return VLC_EGENERIC;    }    free( psz_name );    /* Ifo allocation & initialisation */    if( !( p_vmg_file = ifoOpen( p_dvdread, 0 ) ) )    {        msg_Warn( p_demux, "cannot open VMG info" );        return VLC_EGENERIC;    }    msg_Dbg( p_demux, "VMG opened" );    /* Fill p_demux field */    DEMUX_INIT_COMMON(); p_sys = p_demux->p_sys;    ps_track_init( p_sys->tk );    p_sys->i_aspect = -1;    p_sys->i_title_cur_time = (mtime_t) 0;    p_sys->i_cell_cur_time = (mtime_t) 0;    p_sys->i_cell_duration = (mtime_t) 0;    p_sys->p_dvdread = p_dvdread;    p_sys->p_vmg_file = p_vmg_file;    p_sys->p_title = NULL;    p_sys->p_vts_file = NULL;    p_sys->i_title = p_sys->i_chapter = -1;    p_sys->i_mux_rate = 0;    var_Create( p_demux, "dvdread-angle", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );    var_Get( p_demux, "dvdread-angle", &val );    p_sys->i_angle = val.i_int > 0 ? val.i_int : 1;    DemuxTitles( p_demux, &p_sys->i_angle );    if( DvdReadSetArea( p_demux, 0, 0, p_sys->i_angle ) != VLC_SUCCESS )    {        Close( p_this );        msg_Err( p_demux, "DvdReadSetArea(0,0,%i) failed (can't decrypt DVD?)",                 p_sys->i_angle );        return VLC_EGENERIC;    }    /* Update default_pts to a suitable value for dvdread access */    var_Create( p_demux, "dvdread-caching",                VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );    return VLC_SUCCESS;}/***************************************************************************** * Close: *****************************************************************************/static void Close( vlc_object_t *p_this ){    demux_t     *p_demux = (demux_t*)p_this;    demux_sys_t *p_sys = p_demux->p_sys;    int i;    for( i = 0; i < PS_TK_COUNT; i++ )    {        ps_track_t *tk = &p_sys->tk[i];        if( tk->b_seen )        {            es_format_Clean( &tk->fmt );            if( tk->es ) es_out_Del( p_demux->out, tk->es );        }    }    /* Close libdvdread */    if( p_sys->p_title ) DVDCloseFile( p_sys->p_title );    if( p_sys->p_vts_file ) ifoClose( p_sys->p_vts_file );    if( p_sys->p_vmg_file ) ifoClose( p_sys->p_vmg_file );    DVDClose( p_sys->p_dvdread );    free( p_sys );}static int64_t dvdtime_to_time( dvd_time_t *dtime, uint8_t still_time ){/* Macro to convert Binary Coded Decimal to Decimal */#define BCD2D(__x__) (((__x__ & 0xf0) >> 4) * 10 + (__x__ & 0x0f))    double f_fps, f_ms;    int64_t i_micro_second = 0;    if (still_time == 0 || still_time == 0xFF)    {        i_micro_second += (int64_t)(BCD2D(dtime->hour)) * 60 * 60 * 1000000;        i_micro_second += (int64_t)(BCD2D(dtime->minute)) * 60 * 1000000;        i_micro_second += (int64_t)(BCD2D(dtime->second)) * 1000000;        switch((dtime->frame_u & 0xc0) >> 6)        {        case 1:            f_fps = 25.0;            break;        case 3:            f_fps = 29.97;            break;        default:            f_fps = 2500.0;            break;        }        f_ms = BCD2D(dtime->frame_u&0x3f) * 1000.0 / f_fps;        i_micro_second += (int64_t)(f_ms * 1000.0);    }    else    {        i_micro_second = still_time;        i_micro_second = (int64_t)((double)i_micro_second * 1000000.0);    }    return i_micro_second;}/***************************************************************************** * Control: *****************************************************************************/static int Control( demux_t *p_demux, int i_query, va_list args ){    demux_sys_t *p_sys = p_demux->p_sys;    double f, *pf;    bool *pb;    int64_t *pi64;    input_title_t ***ppp_title;    int *pi_int;    int i;    switch( i_query )    {        case DEMUX_GET_POSITION:        {            pf = (double*) va_arg( args, double* );            if( p_sys->i_title_blocks > 0 )                *pf = (double)p_sys->i_title_offset / p_sys->i_title_blocks;            else                *pf = 0.0;            return VLC_SUCCESS;        }        case DEMUX_SET_POSITION:        {            f = (double)va_arg( args, double );            DvdReadSeek( p_demux, f * p_sys->i_title_blocks );            return VLC_SUCCESS;        }        case DEMUX_GET_TIME:            pi64 = (int64_t*)va_arg( args, int64_t * );            if( p_demux->info.i_title >= 0 && p_demux->info.i_title < p_sys->i_titles )            {                *pi64 = (int64_t) dvdtime_to_time( &p_sys->p_cur_pgc->playback_time, 0 ) /                        p_sys->i_title_blocks * p_sys->i_title_offset;                return VLC_SUCCESS;            }            *pi64 = 0;            return VLC_EGENERIC;        case DEMUX_GET_LENGTH:            pi64 = (int64_t*)va_arg( args, int64_t * );            if( p_demux->info.i_title >= 0 && p_demux->info.i_title < p_sys->i_titles )            {                *pi64 = (int64_t)dvdtime_to_time( &p_sys->p_cur_pgc->playback_time, 0 );                return VLC_SUCCESS;            }            *pi64 = 0;            return VLC_EGENERIC;        /* Special for access_demux */        case DEMUX_CAN_PAUSE:        case DEMUX_CAN_SEEK:        case DEMUX_CAN_CONTROL_PACE:            /* TODO */            pb = (bool*)va_arg( args, bool * );            *pb = true;            return VLC_SUCCESS;        case DEMUX_SET_PAUSE_STATE:            return VLC_SUCCESS;        case DEMUX_GET_TITLE_INFO:            ppp_title = (input_title_t***)va_arg( args, input_title_t*** );            pi_int    = (int*)va_arg( args, int* );            *((int*)va_arg( args, int* )) = 1; /* Title offset */            *((int*)va_arg( args, int* )) = 1; /* Chapter offset */            /* Duplicate title infos */            *pi_int = p_sys->i_titles;            *ppp_title = malloc( sizeof(input_title_t **) * p_sys->i_titles );            for( i = 0; i < p_sys->i_titles; i++ )            {                (*ppp_title)[i] = vlc_input_title_Duplicate(p_sys->titles[i]);            }            return VLC_SUCCESS;        case DEMUX_SET_TITLE:            i = (int)va_arg( args, int );            if( DvdReadSetArea( p_demux, i, 0, -1 ) != VLC_SUCCESS )            {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -