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

📄 access.c

📁 VLC媒体播放程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* access.c: DVD access plugin. ***************************************************************************** * This plugins should handle all the known specificities of the DVD format, * especially the 2048 bytes logical block size. * It depends on: *  -libdvdcss for access and unscrambling *  -ifo.* for ifo parsing and analyse *  -udf.* to find files ***************************************************************************** * Copyright (C) 1998-2001 VideoLAN * $Id: access.c,v 1.15 2003/12/22 14:32:55 sam Exp $ * * Author: St閜hane Borel <stef@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., 59 Temple Place - Suite 330, Boston, MA  02111, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#include <stdio.h>#include <stdlib.h>#include <string.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>#ifdef STRNCASECMP_IN_STRINGS_H#   include <strings.h>#endif#ifdef GOD_DAMN_DMCA#   include "dvdcss.h"#else#   include <dvdcss/dvdcss.h>#endif#include "dvd.h"#include "es.h"#include "seek.h"#include "ifo.h"#include "summary.h"#include "iso_lang.h"/***************************************************************************** * Local prototypes *****************************************************************************//* called from outside */static int  DVDSetArea      ( input_thread_t *, input_area_t * );static int  DVDSetProgram   ( input_thread_t *, pgrm_descriptor_t * );static ssize_t DVDRead      ( input_thread_t *, byte_t *, size_t );static void DVDSeek         ( input_thread_t *, off_t );static char * DVDParse( input_thread_t * );/* * Data access functions */#define DVDTell   LB2OFF( p_dvd->i_vts_start + p_dvd->i_vts_lb ) \                  - p_input->stream.p_selected_area->i_start/***************************************************************************** * DVDOpen: open dvd *****************************************************************************/int E_(DVDOpen) ( vlc_object_t *p_this ){    input_thread_t *     p_input = (input_thread_t *)p_this;    char *               psz_device;    thread_dvd_data_t *  p_dvd;    input_area_t *       p_area;    int                  i;    char *               psz_dvdcss_env;    p_dvd = malloc( sizeof(thread_dvd_data_t) );    if( p_dvd == NULL )    {        msg_Err( p_input, "out of memory" );        return -1;    }    p_input->p_access_data = (void *)p_dvd;    p_input->pf_read = DVDRead;    p_input->pf_seek = DVDSeek;    p_input->pf_set_area = DVDSetArea;    p_input->pf_set_program = DVDSetProgram;    /* Parse command line */    if( !( psz_device = DVDParse( p_input ) ) )    {        free( p_dvd );        return -1;    }    /*     * set up input     */    p_input->i_mtu = 0;    /* override environment variable DVDCSS_METHOD with config option     * (FIXME: this creates a small memory leak) */    psz_dvdcss_env = config_GetPsz( p_input, "dvdcss-method" );    if( psz_dvdcss_env && *psz_dvdcss_env )    {        char *psz_env;        psz_env = malloc( strlen("DVDCSS_METHOD=") +                          strlen( psz_dvdcss_env ) + 1 );        if( !psz_env )        {            free( p_dvd );            return -1;        }        sprintf( psz_env, "%s%s", "DVDCSS_METHOD=", psz_dvdcss_env );        putenv( psz_env );    }    if( psz_dvdcss_env ) free( psz_dvdcss_env );    /*     *  get plugin ready     */    p_dvd->dvdhandle = dvdcss_open( psz_device );    /* free allocated string */    free( psz_device );    if( p_dvd->dvdhandle == NULL )    {        msg_Err( p_input, "dvdcss cannot open device" );        free( p_dvd );        return -1;    }    if( dvdcss_seek( p_dvd->dvdhandle, 0, DVDCSS_NOFLAGS ) < 0 )    {        msg_Err( p_input, "%s", dvdcss_error( p_dvd->dvdhandle ) );        dvdcss_close( p_dvd->dvdhandle );        free( p_dvd );        return -1;    }    /* Ifo allocation & initialisation */    if( IfoCreate( p_dvd ) < 0 )    {        msg_Err( p_input, "allcation error in ifo" );        dvdcss_close( p_dvd->dvdhandle );        free( p_dvd );        return -1;    }    if( IfoInit( p_dvd->p_ifo ) < 0 )    {        msg_Err( p_input, "fatal failure in ifo" );        IfoDestroy( p_dvd->p_ifo );        dvdcss_close( p_dvd->dvdhandle );        free( p_dvd );        return -1;    }    /* Set stream and area data */    vlc_mutex_lock( &p_input->stream.stream_lock );    p_input->stream.i_method = INPUT_METHOD_DVD;    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 ) );#define title_inf p_dvd->p_ifo->vmg.title_inf    msg_Dbg( p_input, "number of titles: %d", title_inf.i_title_nb );#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 <= title_inf.i_title_nb ; i++ )    {        /* Titles are Program Chains */        input_AddArea( p_input, i, title_inf.p_attr[i-1].i_chapter_nb );        /* 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;        /* Offset to vts_i_0.ifo */        area[i]->i_plugin_data = p_dvd->p_ifo->i_start +                       title_inf.p_attr[i-1].i_start_sector;    }#undef area    p_dvd->i_title = p_dvd->i_title <= title_inf.i_title_nb ?                     p_dvd->i_title : 1;#undef title_inf    p_area = p_input->stream.pp_areas[p_dvd->i_title];    p_area->i_part = p_dvd->i_chapter <= p_area->i_part_nb ?                     p_dvd->i_chapter : 1;    p_dvd->i_chapter = 1;    p_dvd->b_new_chapter = 0;    p_dvd->i_audio_nb = 0;    p_dvd->i_spu_nb = 0;    /* set title, chapter, audio and subpic */    if( DVDSetArea( p_input, p_area ) < 0 )    {        vlc_mutex_unlock( &p_input->stream.stream_lock );        IfoDestroy( p_dvd->p_ifo );        dvdcss_close( p_dvd->dvdhandle );        free( p_dvd );        return -1;    }    vlc_mutex_unlock( &p_input->stream.stream_lock );    if( !p_input->psz_demux || !*p_input->psz_demux )    {        p_input->psz_demux = "dvdold";    }    return 0;}/***************************************************************************** * DVDClose: close dvd *****************************************************************************/void E_(DVDClose) ( vlc_object_t *p_this ){    input_thread_t * p_input = (input_thread_t *)p_this;    thread_dvd_data_t *p_dvd = (thread_dvd_data_t*)p_input->p_access_data;    /* This is a very nasty side-effect in the DVD plug-in : language     * selection here influences language selection of other streams. So     * unset those variables (may not be what the user wants).     * FIXME FIXME FIXME FIXME FIXME FIXME FIXME --Meuuh */    config_PutInt( p_input, "audio-channel", -1 );    config_PutInt( p_input, "spu-channel", -1 );    IfoDestroy( p_dvd->p_ifo );    dvdcss_close( p_dvd->dvdhandle );    free( p_dvd );}/***************************************************************************** * DVDSetProgram: used to change angle *****************************************************************************/static int DVDSetProgram( input_thread_t    * p_input,                          pgrm_descriptor_t * p_program ){    if( p_input->stream.p_selected_program != p_program )    {        thread_dvd_data_t *  p_dvd;        int                  i_angle;        vlc_value_t          val;        p_dvd   = (thread_dvd_data_t*)(p_input->p_access_data);        i_angle = p_program->i_number;        /* DVD is actually mono-program: we only need the current angle         * number, so copy the data between programs */        memcpy( p_program,                p_input->stream.p_selected_program,                sizeof(pgrm_descriptor_t) );        p_program->i_number                = i_angle;        p_input->stream.p_selected_program = p_program;#define title \    p_dvd->p_ifo->vts.title_unit.p_title[p_dvd->i_title_id-1].title        if( title.p_cell_play[p_dvd->i_prg_cell].i_category & 0xf000 )        {            if( ( p_program->i_number - p_dvd->i_angle ) < 0 )            {                /* we have to go backwards */                p_dvd->i_map_cell = 0;            }            p_dvd->i_prg_cell += ( p_program->i_number - p_dvd->i_angle );            p_dvd->i_map_cell =  CellPrg2Map( p_dvd );            p_dvd->i_map_cell += p_dvd->i_angle_cell;            p_dvd->i_vts_lb   =  CellFirstSector( p_dvd );            p_dvd->i_last_lb  =  CellLastSector( p_dvd );            p_dvd->i_angle    =  p_program->i_number;        }        else        {            p_dvd->i_angle    =  p_program->i_number;        }#undef title        msg_Dbg( p_input, "angle %d selected", p_dvd->i_angle );        /* Update the navigation variables without triggering a callback */        val.i_int = p_program->i_number;        var_Change( p_input, "program", VLC_VAR_SETVALUE, &val, NULL );    }    return 0;}/***************************************************************************** * DVDSetArea: initialize input data for title x, chapter y. * It should be called for each user navigation request. ***************************************************************************** * Take care that i_title starts from 0 (vmg) and i_chapter start from 1. * Note that you have to take the lock before entering here. *****************************************************************************/#define vmg p_dvd->p_ifo->vmg#define vts p_dvd->p_ifo->vtsstatic void DVDFlushStream( input_thread_t * p_input ){    if( p_input->stream.pp_programs != NULL )    {        /* We don't use input_EndStream here since         * we keep area structures */        while( p_input->stream.i_es_number )        {            input_DelES( p_input, p_input->stream.pp_es[0] );        }        while( p_input->stream.i_pgrm_number )        {            input_DelProgram( p_input, p_input->stream.pp_programs[0] );        }        if( p_input->stream.pp_selected_es )        {            free( p_input->stream.pp_selected_es );            p_input->stream.pp_selected_es = NULL;        }        p_input->stream.i_selected_es_number = 0;    }    return;}static int DVDReadAngle( input_thread_t * p_input ){    thread_dvd_data_t * p_dvd;    int                 i_angle_nb;    int                 i;    p_dvd      = (thread_dvd_data_t*)(p_input->p_access_data);    i_angle_nb = vmg.title_inf.p_attr[p_dvd->i_title-1].i_angle_nb;    input_AddProgram( p_input, 1, sizeof( stream_ps_data_t ) );    p_input->stream.p_selected_program = p_input->stream.pp_programs[0];    for( i = 1 ; i < i_angle_nb ; i++ )    {        input_AddProgram( p_input, i+1, 0 );    }    return i_angle_nb;}static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area ){    thread_dvd_data_t *  p_dvd;    vlc_value_t          val;    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;    if( p_area != p_input->stream.p_selected_area )    {        int i_vts_title;        uint32_t i_first;        uint32_t i_last;        unsigned int i;        /* Reset the Chapter position of the old title */        p_input->stream.p_selected_area->i_part = 1;        p_input->stream.p_selected_area         = p_area;        /*         *  We have to load all title information         */        /* title number as it appears in the interface list */        p_dvd->i_title      = p_area->i_id;        p_dvd->i_chapter_nb = p_area->i_part_nb;        if( IfoTitleSet( p_dvd->p_ifo, p_dvd->i_title ) < 0 )        {            msg_Err( p_input, "fatal error in vts ifo" );            free( p_dvd );            return -1;        }        /* title position inside the selected vts */        i_vts_title       = vmg.title_inf.p_attr[p_dvd->i_title-1].i_title_num;        p_dvd->i_title_id =

⌨️ 快捷键说明

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