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

📄 access.c

📁 video linux conference
💻 C
📖 第 1 页 / 共 3 页
字号:
/***************************************************************************** * vcd.c : VCD input module for vlc using libcdio, libvcd and libvcdinfo. *         vlc-specific things tend to go here. ***************************************************************************** * Copyright (C) 2000, 2003, 2004, 2005 VideoLAN * $Id: access.c 10862 2005-05-01 14:48:08Z rocky $ * * Authors: Rocky Bernstein <rocky@panix.com> *   Some code is based on the non-libcdio VCD plugin (as there really *   isn't real developer documentation yet on how to write a *   navigable plugin.) * * 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 <vlc/vlc.h>#include <vlc/intf.h>#include <vlc/input.h>#include "vlc_keys.h"#include <cdio/cdio.h>#include <cdio/cd_types.h>#include <cdio/logging.h>#include <cdio/util.h>#include <libvcd/info.h>#include <libvcd/logging.h>#include "vcd.h"#include "info.h"#include "intf.h"#define FREE_AND_NULL(ptr) free(ptr); ptr = NULL;extern void VCDSetOrigin( access_t *p_access, lsn_t i_lsn, track_t i_track,                          const vcdinfo_itemid_t *p_itemid );/***************************************************************************** * Local prototypes *****************************************************************************//* First those which are accessed from outside (via pointers). */static block_t *VCDReadBlock    ( access_t * );static int      VCDControl      ( access_t *p_access, int i_query,                                  va_list args );/* Now those which are strictly internal */static vlc_bool_t  VCDEntryPoints  ( access_t * );static vlc_bool_t  VCDLIDs         ( access_t * );static vlc_bool_t  VCDSegments     ( access_t * );static int  VCDTitles       ( access_t * );static char *VCDParse       ( access_t *,                              /*out*/ vcdinfo_itemid_t * p_itemid ,                              /*out*/ vlc_bool_t *play_single_item );static void VCDUpdateVar( access_t *p_access, int i_entry, int i_action,                          const char *p_varname, char *p_label,                          const char *p_debug_label );static vcdinfo_obj_t *vcd_Open   ( vlc_object_t *p_this, const char *psz_dev );/**************************************************************************** * Private functions ****************************************************************************//* FIXME: This variable is a hack. Would be nice to eliminate the   global-ness. */static access_t *p_vcd_access = NULL;/* process messages that originate from libcdio. */static voidcdio_log_handler (cdio_log_level_t level, const char message[]){  const vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_vcd_access->p_sys;  switch (level) {  case CDIO_LOG_DEBUG:  case CDIO_LOG_INFO:    if (p_vcdplayer->i_debug & INPUT_DBG_CDIO)      msg_Dbg( p_vcd_access, message);    break;  case CDIO_LOG_WARN:    msg_Warn( p_vcd_access, message);    break;  case CDIO_LOG_ERROR:  case CDIO_LOG_ASSERT:    msg_Err( p_vcd_access, message);    break;  default:    msg_Warn( p_vcd_access, message,            _("The above message had unknown log level"),            level);  }  return;}/* process messages that originate from vcdinfo. */static voidvcd_log_handler (vcd_log_level_t level, const char message[]){  vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_vcd_access->p_sys;  switch (level) {  case VCD_LOG_DEBUG:  case VCD_LOG_INFO:    if (p_vcdplayer->i_debug & INPUT_DBG_VCDINFO)      msg_Dbg( p_vcd_access, message);    break;  case VCD_LOG_WARN:    msg_Warn( p_vcd_access, message);    break;  case VCD_LOG_ERROR:  case VCD_LOG_ASSERT:    msg_Err( p_vcd_access, message);    break;  default:    msg_Warn( p_vcd_access, "%s\n%s %d", message,            _("The above message had unknown vcdimager log level"),            level);  }  return;}/*****************************************************************************  VCDRead: reads VCD_BLOCKS_ONCE from the VCD and returns that.  NULL is returned if something went wrong. *****************************************************************************/static block_t *VCDReadBlock( access_t * p_access ){    vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys;    const int    i_blocks   = p_vcdplayer->i_blocks_per_read;    block_t     *p_block;    int          i_read;    uint8_t     *p_buf;    i_read = 0;    dbg_print( (INPUT_DBG_LSN), "lsn: %lu",               (long unsigned int) p_vcdplayer->i_lsn );    /* Allocate a block for the reading */    if( !( p_block = block_New( p_access, i_blocks * M2F2_SECTOR_SIZE ) ) )    {        msg_Err( p_access, "cannot get a new block of size: %i",                 i_blocks * M2F2_SECTOR_SIZE );        block_Release( p_block );        return NULL;    }    p_buf = (uint8_t *) p_block->p_buffer;    for ( i_read = 0 ; i_read < i_blocks ; i_read++ )    {      vcdplayer_read_status_t read_status = vcdplayer_read(p_access, p_buf);      p_access->info.i_pos += M2F2_SECTOR_SIZE;      switch ( read_status ) {      case READ_END:        /* End reached. Return NULL to indicated this. */        /* We also set the postion to the end so the higher level           (demux?) doesn't try to keep reading. If everything works out           right this shouldn't have to happen.         */#if 0        if ( p_access->info.i_pos != p_access->info.i_size ) {          msg_Warn( p_access,                    "At end but pos (%llu) is not size (%llu). Adjusting.",                    p_access->info.i_pos, p_access->info.i_size );          p_access->info.i_pos = p_access->info.i_size;        }#endif        block_Release( p_block );        return NULL;      case READ_ERROR:        /* Some sort of error. Should we increment lsn? to skip block?        */        block_Release( p_block );        return NULL;      case READ_STILL_FRAME:        {          /* FIXME The below should be done in an event thread.             Until then...           */#if 1          msleep( MILLISECONDS_PER_SEC * *p_buf );	  VCDSetOrigin(p_access, p_vcdplayer->origin_lsn, p_vcdplayer->i_track,		       &(p_vcdplayer->play_item));          // p_vcd->in_still = VLC_FALSE;          dbg_print(INPUT_DBG_STILL, "still wait time done");#else          vcdIntfStillTime(p_vcdplayer->p_intf, *p_buf);#endif          block_Release( p_block );          return NULL;        }      default:      case READ_BLOCK:        /* Read buffer */        ;      }      p_buf += M2F2_SECTOR_SIZE;      /* Update seekpoint */      if ( VCDINFO_ITEM_TYPE_ENTRY == p_vcdplayer->play_item.type )      {        unsigned int i_entry = p_vcdplayer->play_item.num+1;        lsn_t        i_lsn   = vcdinfo_get_entry_lsn(p_vcdplayer->vcd, i_entry);        if ( p_vcdplayer->i_lsn >= i_lsn && i_lsn != VCDINFO_NULL_LSN )        {            const track_t i_track = p_vcdplayer->i_track;	    dbg_print( (INPUT_DBG_LSN|INPUT_DBG_PBC), 		       "entry change to %d, current LSN %u >= end %u",		       i_entry, p_vcdplayer->i_lsn, i_lsn);            p_vcdplayer->play_item.num = i_entry;            VCDSetOrigin( p_access,  i_lsn, i_track,                          &(p_vcdplayer->play_item) );        }      }    }    return p_block;}/**************************************************************************** * VCDSeek ****************************************************************************/intVCDSeek( access_t * p_access, int64_t i_pos ){    if (!p_access || !p_access->p_sys) return VLC_EGENERIC;    {      vcdplayer_t         *p_vcdplayer = (vcdplayer_t *)p_vcd_access->p_sys;      const input_title_t *t = p_vcdplayer->p_title[p_access->info.i_title];      unsigned int         i_entry = VCDINFO_INVALID_ENTRY;      int i_seekpoint;      /* Next sector to read */      p_access->info.i_pos = i_pos;      p_vcdplayer->i_lsn = (i_pos / (int64_t) M2F2_SECTOR_SIZE) +	p_vcdplayer->origin_lsn;      switch (p_vcdplayer->play_item.type) {      case VCDINFO_ITEM_TYPE_TRACK:      case VCDINFO_ITEM_TYPE_ENTRY:        break ;      default:        p_vcdplayer->b_valid_ep = VLC_FALSE;      }      /* Find entry */      if( p_vcdplayer->b_valid_ep )      {          for( i_entry = 0 ; i_entry < p_vcdplayer->i_entries ; i_entry ++ )          {              if( p_vcdplayer->i_lsn < p_vcdplayer->p_entries[i_entry] )              {                  VCDUpdateVar( p_access, i_entry, VLC_VAR_SETVALUE,                                "chapter", _("Entry"), "Setting entry" );                  break;              }          }          {              vcdinfo_itemid_t itemid;              itemid.num  = i_entry;              itemid.type = VCDINFO_ITEM_TYPE_ENTRY;              VCDSetOrigin(p_access, p_vcdplayer->i_lsn, p_vcdplayer->i_track,                           &itemid);          }        }      dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_SEEK),                 "orig %lu, cur: %lu, offset: %lld, entry %d",                 (long unsigned int) p_vcdplayer->origin_lsn,                  (long unsigned int) p_vcdplayer->i_lsn, i_pos,                 i_entry );       /* Find seekpoint */      for( i_seekpoint = 0; i_seekpoint < t->i_seekpoint; i_seekpoint++ )	{	  if( i_seekpoint + 1 >= t->i_seekpoint ) break;	  if( i_pos < t->seekpoint[i_seekpoint + 1]->i_byte_offset ) break;	}            /* Update current seekpoint */      if( i_seekpoint != p_access->info.i_seekpoint )	{	  dbg_print( (INPUT_DBG_SEEK), "seekpoint change %lu", 		     (long unsigned int) i_seekpoint );	  p_access->info.i_update |= INPUT_UPDATE_SEEKPOINT;	  p_access->info.i_seekpoint = i_seekpoint;	}    }    return VLC_SUCCESS;    }/*****************************************************************************  VCDEntryPoints: Reads the information about the entry points on the disc  and initializes area information with that.  Before calling this track information should have been read in. *****************************************************************************/static vlc_bool_tVCDEntryPoints( access_t * p_access ){  if (!p_access || !p_access->p_sys) return VLC_FALSE;    {    vcdplayer_t       *p_vcdplayer = (vcdplayer_t *) p_access->p_sys;    const unsigned int i_entries   =       vcdinfo_get_num_entries(p_vcdplayer->vcd);    const track_t      i_last_track       = cdio_get_num_tracks(vcdinfo_get_cd_image(p_vcdplayer->vcd))      + cdio_get_first_track_num(vcdinfo_get_cd_image(p_vcdplayer->vcd));    unsigned int i;       if (0 == i_entries) {      LOG_ERR ("no entires found -- something is wrong" );      return VLC_FALSE;    }        p_vcdplayer->p_entries  = malloc( sizeof( lsn_t ) * i_entries );        if( p_vcdplayer->p_entries == NULL )      {	LOG_ERR ("not enough memory for entry points treatment" );	return VLC_FALSE;      }        p_vcdplayer->i_entries = i_entries;        for( i = 0 ; i < i_entries ; i++ )    {	const track_t i_track = vcdinfo_get_track(p_vcdplayer->vcd, i);	if( i_track <= i_last_track ) {	  seekpoint_t *s = vlc_seekpoint_New();	  char psz_entry[100];	  	  snprintf(psz_entry, sizeof(psz_entry), "%s%02d", _("Entry "), i );	  p_vcdplayer->p_entries[i] = vcdinfo_get_entry_lsn(p_vcdplayer->vcd, i);	  	  s->psz_name      = strdup(psz_entry);	  s->i_byte_offset = 	    (p_vcdplayer->p_entries[i] - vcdinfo_get_track_lsn(p_vcdplayer->vcd, i_track))	    * M2F2_SECTOR_SIZE;	  	  dbg_print( INPUT_DBG_MRL, 		     "%s, lsn %d,  byte_offset %ld",		     s->psz_name, p_vcdplayer->p_entries[i], 		     (unsigned long int) s->i_byte_offset);          TAB_APPEND( p_vcdplayer->p_title[i_track-1]->i_seekpoint,                      p_vcdplayer->p_title[i_track-1]->seekpoint, s );        } else          msg_Warn( p_access, "wrong track number found in entry points" );    }    p_vcdplayer->b_valid_ep = VLC_TRUE;    return VLC_TRUE;  }}/***************************************************************************** * VCDSegments: Reads the information about the segments the disc. *****************************************************************************/static vlc_bool_tVCDSegments( access_t * p_access ){    vcdplayer_t   *p_vcdplayer = (vcdplayer_t *) p_access->p_sys;    unsigned int  i;    input_title_t *t;    p_vcdplayer->i_segments = vcdinfo_get_num_segments(p_vcdplayer->vcd);    dbg_print( (INPUT_DBG_CALL|INPUT_DBG_MRL),               "Segments: %d", p_vcdplayer->i_segments);    if ( 0 == p_vcdplayer->i_segments ) return VLC_FALSE;

⌨️ 快捷键说明

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