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

📄 dvdnav.c

📁 vlc源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/***************************************************************************** * dvdnav.c: DVD module using the dvdnav library. ***************************************************************************** * Copyright (C) 2004 the VideoLAN team * $Id: 9c4677044631e76949f3215e11403e37eedee506 $ * * Authors: Laurent Aimar <fenrir@via.ecp.fr> * * 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_demux.h>#include <vlc_charset.h>#include <vlc_interface.h>#ifdef HAVE_UNISTD_H#   include <unistd.h>#endif#ifdef HAVE_SYS_TYPES_H#   include <sys/types.h>#endif#ifdef HAVE_SYS_STAT_H#   include <sys/stat.h>#endif#ifdef HAVE_FCNTL_H#   include <fcntl.h>#endif#include "vlc_keys.h"#include "vlc_iso_lang.h"/* FIXME we should find a better way than including that */#include "../../src/text/iso-639_def.h"#include <dvdnav/dvdnav.h>#include "../demux/ps.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 MENU_TEXT N_("Start directly in menu")#define MENU_LONGTEXT N_( \    "Start the DVD directly in the main menu. This "\    "will try to skip all the useless warning introductions." )#define LANGUAGE_DEFAULT ("en")static int  Open ( vlc_object_t * );static void Close( vlc_object_t * );vlc_module_begin();    set_shortname( N_("DVD with menus") );    set_description( N_("DVDnav Input") );    set_category( CAT_INPUT );    set_subcategory( SUBCAT_INPUT_ACCESS );    add_integer( "dvdnav-angle", 1, NULL, ANGLE_TEXT,        ANGLE_LONGTEXT, false );    add_integer( "dvdnav-caching", DEFAULT_PTS_DELAY / 1000, NULL,        CACHING_TEXT, CACHING_LONGTEXT, true );    add_bool( "dvdnav-menu", true, NULL,        MENU_TEXT, MENU_LONGTEXT, false );    set_capability( "access_demux", 5 );    add_shortcut( "dvd" );    add_shortcut( "dvdnav" );    set_callbacks( Open, Close );vlc_module_end();/* Shall we use libdvdnav's read ahead cache? */#define DVD_READ_CACHE 1/***************************************************************************** * Local prototypes *****************************************************************************/typedef struct{    VLC_COMMON_MEMBERS    demux_t        *p_demux;    vlc_mutex_t     lock;    bool      b_moved;    bool      b_clicked;    int             i_key_action;    bool      b_still;    int64_t         i_still_end;} event_thread_t;static void* EventThread( vlc_object_t * );struct demux_sys_t{    dvdnav_t    *dvdnav;    /* track */    ps_track_t  tk[PS_TK_COUNT];    int         i_mux_rate;    /* for spu variables */    input_thread_t *p_input;    /* event */    event_thread_t *p_ev;    /* palette for menus */    uint32_t clut[16];    uint8_t  palette[4][4];    bool b_spu_change;    /* */    int i_aspect;    int           i_title;    input_title_t **title;    /* lenght of program group chain */    mtime_t     i_pgc_length;};static int Control( demux_t *, int, va_list );static int Demux( demux_t * );static int DemuxBlock( demux_t *, const uint8_t *, int );static void DemuxTitles( demux_t * );static void ESSubtitleUpdate( demux_t * );static void ButtonUpdate( demux_t *, bool );static void ESNew( demux_t *, int );static int ProbeDVD( demux_t *, char * );static char *DemuxGetLanguageCode( demux_t *p_demux, const char *psz_var );static int ControlInternal( demux_t *, int, ... );/***************************************************************************** * DemuxOpen: *****************************************************************************/static int Open( vlc_object_t *p_this ){    demux_t     *p_demux = (demux_t*)p_this;    demux_sys_t *p_sys;    dvdnav_t    *p_dvdnav;    int         i_angle;    char        *psz_name;    char        *psz_code;    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    /* Try some simple probing to avoid going through dvdnav_open too often */    if( ProbeDVD( p_demux, psz_name ) != VLC_SUCCESS )    {        free( psz_name );        return VLC_EGENERIC;    }    /* Open dvdnav */    if( dvdnav_open( &p_dvdnav, psz_name ) != DVDNAV_STATUS_OK )    {        msg_Warn( p_demux, "cannot open dvdnav" );        free( psz_name );        return VLC_EGENERIC;    }    free( psz_name );    /* Fill p_demux field */    DEMUX_INIT_COMMON(); p_sys = p_demux->p_sys;    p_sys->dvdnav = p_dvdnav;    ps_track_init( p_sys->tk );    p_sys->i_aspect = -1;    p_sys->i_mux_rate = 0;    p_sys->i_pgc_length = 0;    p_sys->b_spu_change = false;    if( 1 )    {        // Hack for libdvdnav CVS.        // Without it dvdnav_get_number_of_titles() fails.        // Remove when fixed in libdvdnav CVS.        uint8_t buffer[DVD_VIDEO_LB_LEN];        int i_event, i_len;        if( dvdnav_get_next_block( p_sys->dvdnav, buffer, &i_event, &i_len )              == DVDNAV_STATUS_ERR )        {            msg_Warn( p_demux, "dvdnav_get_next_block failed" );        }        dvdnav_sector_search( p_sys->dvdnav, 0, SEEK_SET );    }    /* Configure dvdnav */    if( dvdnav_set_readahead_flag( p_sys->dvdnav, DVD_READ_CACHE ) !=          DVDNAV_STATUS_OK )    {        msg_Warn( p_demux, "cannot set read-a-head flag" );    }    if( dvdnav_set_PGC_positioning_flag( p_sys->dvdnav, 1 ) !=          DVDNAV_STATUS_OK )    {        msg_Warn( p_demux, "cannot set PGC positioning flag" );    }    /* Set menu language     * XXX A menu-language may be better than sub-language */    psz_code = DemuxGetLanguageCode( p_demux, "sub-language" );    if( dvdnav_menu_language_select( p_sys->dvdnav, psz_code ) !=        DVDNAV_STATUS_OK )    {        msg_Warn( p_demux, "can't set menu language to '%s' (%s)",                  psz_code, dvdnav_err_to_string( p_sys->dvdnav ) );        /* We try to fall back to 'en' */        if( strcmp( psz_code, LANGUAGE_DEFAULT ) )            dvdnav_menu_language_select( p_sys->dvdnav, (char*)LANGUAGE_DEFAULT );    }    free( psz_code );    /* Set audio language */    psz_code = DemuxGetLanguageCode( p_demux, "audio-language" );    if( dvdnav_audio_language_select( p_sys->dvdnav, psz_code ) !=        DVDNAV_STATUS_OK )    {        msg_Warn( p_demux, "can't set audio language to '%s' (%s)",                  psz_code, dvdnav_err_to_string( p_sys->dvdnav ) );        /* We try to fall back to 'en' */        if( strcmp( psz_code, LANGUAGE_DEFAULT ) )            dvdnav_audio_language_select( p_sys->dvdnav, (char*)LANGUAGE_DEFAULT );    }    free( psz_code );    /* Set spu language */    psz_code = DemuxGetLanguageCode( p_demux, "sub-language" );    if( dvdnav_spu_language_select( p_sys->dvdnav, psz_code ) !=        DVDNAV_STATUS_OK )    {        msg_Warn( p_demux, "can't set spu language to '%s' (%s)",                  psz_code, dvdnav_err_to_string( p_sys->dvdnav ) );        /* We try to fall back to 'en' */        if( strcmp( psz_code, LANGUAGE_DEFAULT ) )            dvdnav_spu_language_select(p_sys->dvdnav, (char*)LANGUAGE_DEFAULT );    }    free( psz_code );    DemuxTitles( p_demux );    var_Create( p_demux, "dvdnav-menu", VLC_VAR_BOOL|VLC_VAR_DOINHERIT );    var_Get( p_demux, "dvdnav-menu", &val );    if( val.b_bool )    {        msg_Dbg( p_demux, "trying to go to dvd menu" );        if( dvdnav_title_play( p_sys->dvdnav, 1 ) != DVDNAV_STATUS_OK )        {            msg_Err( p_demux, "cannot set title (can't decrypt DVD?)" );            intf_UserFatal( p_demux, false, _("Playback failure"),                            _("VLC cannot set the DVD's title. It possibly "                              "cannot decrypt the entire disk.") );            dvdnav_close( p_sys->dvdnav );            free( p_sys );            return VLC_EGENERIC;        }        if( dvdnav_menu_call( p_sys->dvdnav, DVD_MENU_Title ) !=            DVDNAV_STATUS_OK )        {            /* Try going to menu root */            if( dvdnav_menu_call( p_sys->dvdnav, DVD_MENU_Root ) !=                DVDNAV_STATUS_OK )                    msg_Warn( p_demux, "cannot go to dvd menu" );        }    }    var_Create( p_demux, "dvdnav-angle", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );    var_Get( p_demux, "dvdnav-angle", &val );    i_angle = val.i_int > 0 ? val.i_int : 1;    /* Update default_pts to a suitable value for dvdnav access */    var_Create( p_demux, "dvdnav-caching", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );    /* FIXME hack hack hack hack FIXME */    /* Get p_input and create variable */    p_sys->p_input = vlc_object_find( p_demux, VLC_OBJECT_INPUT, FIND_PARENT );    var_Create( p_sys->p_input, "x-start", VLC_VAR_INTEGER );    var_Create( p_sys->p_input, "y-start", VLC_VAR_INTEGER );    var_Create( p_sys->p_input, "x-end", VLC_VAR_INTEGER );    var_Create( p_sys->p_input, "y-end", VLC_VAR_INTEGER );    var_Create( p_sys->p_input, "color", VLC_VAR_ADDRESS );    var_Create( p_sys->p_input, "menu-palette", VLC_VAR_ADDRESS );    var_Create( p_sys->p_input, "highlight", VLC_VAR_BOOL );    var_Create( p_sys->p_input, "highlight-mutex", VLC_VAR_MUTEX );    /* Now create our event thread catcher */    p_sys->p_ev = vlc_object_create( p_demux, sizeof( event_thread_t ) );    p_sys->p_ev->p_demux = p_demux;    vlc_thread_create( p_sys->p_ev, "dvdnav event thread handler", EventThread,                       VLC_THREAD_PRIORITY_LOW, false );    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;    /* stop the event handler */    vlc_object_kill( p_sys->p_ev );    vlc_thread_join( p_sys->p_ev );    vlc_object_release( p_sys->p_ev );    var_Destroy( p_sys->p_input, "highlight-mutex" );    var_Destroy( p_sys->p_input, "highlight" );    var_Destroy( p_sys->p_input, "x-start" );    var_Destroy( p_sys->p_input, "x-end" );    var_Destroy( p_sys->p_input, "y-start" );    var_Destroy( p_sys->p_input, "y-end" );    var_Destroy( p_sys->p_input, "color" );    var_Destroy( p_sys->p_input, "menu-palette" );    vlc_object_release( p_sys->p_input );    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 );        }    }    dvdnav_close( p_sys->dvdnav );    free( p_sys );}/***************************************************************************** * 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_SET_POSITION:        case DEMUX_GET_POSITION:        case DEMUX_GET_TIME:        case DEMUX_GET_LENGTH:        {            uint32_t pos, len;            if( dvdnav_get_position( p_sys->dvdnav, &pos, &len ) !=                  DVDNAV_STATUS_OK || len == 0 )            {                return VLC_EGENERIC;            }            if( i_query == DEMUX_GET_POSITION )            {                pf = (double*)va_arg( args, double* );                *pf = (double)pos / (double)len;                return VLC_SUCCESS;            }            else if( i_query == DEMUX_SET_POSITION )            {                f = (double)va_arg( args, double );                pos = f * len;                if( dvdnav_sector_search( p_sys->dvdnav, pos, SEEK_SET ) ==                      DVDNAV_STATUS_OK )                {                    return VLC_SUCCESS;                }            }            else if( i_query == DEMUX_GET_TIME )            {                pi64 = (int64_t*)va_arg( args, int64_t * );                if( p_sys->i_pgc_length > 0 )                {                    *pi64 = p_sys->i_pgc_length * pos / len;                    return VLC_SUCCESS;                }            }            else if( i_query == DEMUX_GET_LENGTH )            {                pi64 = (int64_t*)va_arg( args, int64_t * );                if( p_sys->i_pgc_length > 0 )                {                    *pi64 = (int64_t)p_sys->i_pgc_length;                    return VLC_SUCCESS;                }            }            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* )) = 0; /* Title offset */            *((int*)va_arg( args, int* )) = 1; /* Chapter offset */            /* Duplicate title infos */            *pi_int = p_sys->i_title;            *ppp_title = malloc( sizeof( input_title_t ** ) * p_sys->i_title );            for( i = 0; i < p_sys->i_title; i++ )            {                (*ppp_title)[i] = vlc_input_title_Duplicate( p_sys->title[i] );            }            return VLC_SUCCESS;        case DEMUX_SET_TITLE:            i = (int)va_arg( args, int );            if( ( i == 0 && dvdnav_menu_call( p_sys->dvdnav, DVD_MENU_Root )                  != DVDNAV_STATUS_OK ) ||                ( i != 0 && dvdnav_title_play( p_sys->dvdnav, i )                  != DVDNAV_STATUS_OK ) )

⌨️ 快捷键说明

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