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

📄 vcdplayer.c

📁 linux下的MPEG1
💻 C
📖 第 1 页 / 共 2 页
字号:
/*   $Id: vcdplayer.c,v 1.20 2007/02/21 23:17:14 dgp85 Exp $   Copyright (C) 2002, 2003, 2004, 2005 Rocky Bernstein <rocky@panix.com>    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-1307, USA  */#ifdef HAVE_CONFIG_H#include "config.h"#endif/* Standard includes */#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <unistd.h>#include <time.h>#include <string.h>#ifdef HAVE_STRINGS_H#include <strings.h>#endif#include <errno.h>#ifdef HAVE_VCDNAV#include <libvcd/files.h>#include <cdio/iso9660.h>#else#include "libvcd/files.h"#include "cdio/iso9660.h"#endif#include "vcdplayer.h"#include "vcdio.h"/* This function is _not_ exported by libvcd, its usage should be avoided, most * likely. */void vcdinfo_get_seg_resolution(const vcdinfo_obj_t *p_vcdinfo, segnum_t i_seg,                                /*out*/ uint16_t *max_x, /*out*/ uint16_t *max_y);#define LOG_ERR(p_vcdplayer, s, args...) \       if (p_vcdplayer != NULL && p_vcdplayer->log_err != NULL) \          p_vcdplayer->log_err("%s:  "s, __func__ , ##args)unsigned long int vcdplayer_debug = 0;static void  _vcdplayer_set_origin(vcdplayer_t *p_vcdplayer);/*!  Return true if playback control (PBC) is on*/boolvcdplayer_pbc_is_on(const vcdplayer_t *p_vcdplayer) {  return VCDINFO_INVALID_ENTRY != p_vcdplayer->i_lid; }/* Given an itemid, return the size for the object (via information   previously stored when opening the vcd). */static size_t_vcdplayer_get_item_size(vcdplayer_t *p_vcdplayer, vcdinfo_itemid_t itemid) {  switch (itemid.type) {  case VCDINFO_ITEM_TYPE_ENTRY:    return p_vcdplayer->entry[itemid.num].size;    break;  case VCDINFO_ITEM_TYPE_SEGMENT:    return p_vcdplayer->segment[itemid.num].size;    break;  case VCDINFO_ITEM_TYPE_TRACK:    return p_vcdplayer->track[itemid.num-1].size;    break;  case VCDINFO_ITEM_TYPE_LID:    /* Play list number (LID) */    return 0;    break;  case VCDINFO_ITEM_TYPE_NOTFOUND:  case VCDINFO_ITEM_TYPE_SPAREID2:  default:    LOG_ERR(p_vcdplayer, "%s %d\n", _("bad item type"), itemid.type);    return 0;  }}#define add_format_str_info(val)			\  {							\    const char *str = val;				\    unsigned int len;					\    if (val != NULL) {					\      len=strlen(str);					\      if (len != 0) {					\	strncat(tp, str, TEMP_STR_LEN-(tp-temp_str));	\	tp += len;					\      }							\      saw_control_prefix = false;			\    }							\  }#define add_format_num_info(val, fmt)			\  {							\    char num_str[10];					\    unsigned int len;                                   \    snprintf(num_str, sizeof(num_str), fmt, val);	\    len=strlen(num_str);                                \    if (len != 0) {					\      strncat(tp, num_str, TEMP_STR_LEN-(tp-temp_str));	\      tp += len;					\    }							\    saw_control_prefix = false;				\  }/*!   Take a format string and expand escape sequences, that is sequences that   begin with %, with information from the current VCD.    The expanded string is returned. Here is a list of escape sequences:   %A : The album information    %C : The VCD volume count - the number of CD's in the collection.   %c : The VCD volume num - the number of the CD in the collection.    %F : The VCD Format, e.g. VCD 1.0, VCD 1.1, VCD 2.0, or SVCD   %I : The current entry/segment/playback type, e.g. ENTRY, TRACK, SEGMENT...   %L : The playlist ID prefixed with " LID" if it exists   %N : The current number of the above - a decimal number   %P : The publisher ID    %p : The preparer ID   %S : If we are in a segment (menu), the kind of segment   %T : The track number   %V : The volume set ID   %v : The volume ID       A number between 1 and the volume count.   %% : a %*/char *vcdplayer_format_str(vcdplayer_t *p_vcdplayer, const char format_str[]){#define TEMP_STR_SIZE 256#define TEMP_STR_LEN (TEMP_STR_SIZE-1)  static char    temp_str[TEMP_STR_SIZE];  size_t i;  char * tp = temp_str;  bool saw_control_prefix = false;  size_t format_len = strlen(format_str);  vcdinfo_obj_t *p_vcdinfo = p_vcdplayer->vcd;  memset(temp_str, 0, TEMP_STR_SIZE);  for (i=0; i<format_len; i++) {    if (!saw_control_prefix && format_str[i] != '%') {      *tp++ = format_str[i];      saw_control_prefix = false;      continue;    }    switch(format_str[i]) {    case '%':      if (saw_control_prefix) {	*tp++ = '%';      }      saw_control_prefix = !saw_control_prefix;      break;    case 'A':      add_format_str_info(vcdinfo_strip_trail(vcdinfo_get_album_id(p_vcdinfo),                                               MAX_ALBUM_LEN));      break;    case 'c':      add_format_num_info(vcdinfo_get_volume_num(p_vcdinfo), "%d");      break;    case 'C':      add_format_num_info(vcdinfo_get_volume_count(p_vcdinfo), "%d");      break;    case 'F':      add_format_str_info(vcdinfo_get_format_version_str(p_vcdinfo));      break;    case 'I':      {	switch (p_vcdplayer->play_item.type) {	case VCDINFO_ITEM_TYPE_TRACK:	  strncat(tp, "Track", TEMP_STR_LEN-(tp-temp_str));	  tp += strlen("Track");	break;	case VCDINFO_ITEM_TYPE_ENTRY:  	  strncat(tp, "Entry", TEMP_STR_LEN-(tp-temp_str));	  tp += strlen("Entry");	  break;	case VCDINFO_ITEM_TYPE_SEGMENT:  	  strncat(tp, "Segment", TEMP_STR_LEN-(tp-temp_str));	  tp += strlen("Segment");	  break;	case VCDINFO_ITEM_TYPE_LID:  	  strncat(tp, "List ID", TEMP_STR_LEN-(tp-temp_str));	  tp += strlen("List ID");	  break;	case VCDINFO_ITEM_TYPE_SPAREID2:  	  strncat(tp, "Navigation", TEMP_STR_LEN-(tp-temp_str));	  tp += strlen("Navigation");	  break;	default:	  /* What to do? */          ;	}	saw_control_prefix = false;      }      break;    case 'L':      if (vcdplayer_pbc_is_on(p_vcdplayer)) {        char num_str[20];        snprintf(num_str, sizeof(num_str), " List ID %d", p_vcdplayer->i_lid);        strncat(tp, num_str, TEMP_STR_LEN-(tp-temp_str));        tp += strlen(num_str);      }      saw_control_prefix = false;      break;    case 'N':      add_format_num_info(p_vcdplayer->play_item.num, "%d");      break;    case 'p':      add_format_str_info(vcdinfo_get_preparer_id(p_vcdinfo));      break;    case 'P':      add_format_str_info(vcdinfo_get_publisher_id(p_vcdinfo));      break;    case 'S':      if ( VCDINFO_ITEM_TYPE_SEGMENT==p_vcdplayer->play_item.type ) {        char seg_type_str[30];        snprintf(seg_type_str, sizeof(seg_type_str), " %s",                 vcdinfo_video_type2str(p_vcdinfo, p_vcdplayer->play_item.num));        strncat(tp, seg_type_str, TEMP_STR_LEN-(tp-temp_str));        tp += strlen(seg_type_str);      }      saw_control_prefix = false;      break;    case 'T':      add_format_num_info(p_vcdplayer->i_track, "%d");      break;    case 'V':      add_format_str_info(vcdinfo_get_volumeset_id(p_vcdinfo));      break;    case 'v':      add_format_str_info(vcdinfo_get_volume_id(p_vcdinfo));      break;    default:      *tp++ = '%';       *tp++ = format_str[i];      saw_control_prefix = false;    }  }  return strdup(temp_str);}static void_vcdplayer_update_entry(vcdinfo_obj_t *p_vcdinfo, uint16_t ofs,                         uint16_t *entry, const char *label){  if ( ofs == VCDINFO_INVALID_OFFSET ) {    *entry = VCDINFO_INVALID_ENTRY;  } else {    vcdinfo_offset_t *off = vcdinfo_get_offset_t(p_vcdinfo, ofs);    if (off != NULL) {      *entry = off->lid;      dbg_print(INPUT_DBG_PBC, "%s: LID %d\n", label, off->lid);    } else      *entry = VCDINFO_INVALID_ENTRY;  }}/*!  Update next/prev/return/default navigation buttons   (via p_vcdplayer->i_lid). Update size of play-item   (via p_vcdplayer->play_item).*/voidvcdplayer_update_nav(vcdplayer_t *p_vcdplayer){  int play_item = p_vcdplayer->play_item.num;  vcdinfo_obj_t *p_vcdinfo = p_vcdplayer->vcd;  int min_entry = 1;  int max_entry = 0;  if  (vcdplayer_pbc_is_on(p_vcdplayer)) {        vcdinfo_lid_get_pxd(p_vcdinfo, &(p_vcdplayer->pxd), p_vcdplayer->i_lid);        switch (p_vcdplayer->pxd.descriptor_type) {    case PSD_TYPE_SELECTION_LIST:    case PSD_TYPE_EXT_SELECTION_LIST:      if (p_vcdplayer->pxd.psd == NULL) return;      _vcdplayer_update_entry(p_vcdinfo,                               vcdinf_psd_get_prev_offset(p_vcdplayer->pxd.psd),                              &(p_vcdplayer->prev_entry), "prev");            _vcdplayer_update_entry(p_vcdinfo,                               vcdinf_psd_get_next_offset(p_vcdplayer->pxd.psd),                              &(p_vcdplayer->next_entry), "next");            _vcdplayer_update_entry(p_vcdinfo,                               vcdinf_psd_get_return_offset(p_vcdplayer->pxd.psd),                              &(p_vcdplayer->return_entry), "return");      _vcdplayer_update_entry(p_vcdinfo,                               vcdinfo_get_default_offset(p_vcdinfo,                                                          p_vcdplayer->i_lid),                              &(p_vcdplayer->default_entry), "default");      break;    case PSD_TYPE_PLAY_LIST:      if (p_vcdplayer->pxd.pld == NULL) return;      _vcdplayer_update_entry(p_vcdinfo,                               vcdinf_pld_get_prev_offset(p_vcdplayer->pxd.pld),                              &(p_vcdplayer->prev_entry), "prev");            _vcdplayer_update_entry(p_vcdinfo,                               vcdinf_pld_get_next_offset(p_vcdplayer->pxd.pld),                              &(p_vcdplayer->next_entry), "next");            _vcdplayer_update_entry(p_vcdinfo,                               vcdinf_pld_get_return_offset(p_vcdplayer->pxd.pld),                              &(p_vcdplayer->return_entry), "return");      p_vcdplayer->default_entry = VCDINFO_INVALID_ENTRY;      break;    case PSD_TYPE_END_LIST:      p_vcdplayer->origin_lsn = p_vcdplayer->i_lsn = p_vcdplayer->end_lsn         = VCDINFO_NULL_LSN;      /* Fall through */    case PSD_TYPE_COMMAND_LIST:      p_vcdplayer->next_entry = p_vcdplayer->prev_entry         = p_vcdplayer->return_entry = VCDINFO_INVALID_ENTRY;      p_vcdplayer->default_entry = VCDINFO_INVALID_ENTRY;      break;    }    if (p_vcdplayer->update_title)      p_vcdplayer->update_title();    return;  }  /* PBC is not on. Set up for simplified next, prev, and return. */    switch (p_vcdplayer->play_item.type) {  case VCDINFO_ITEM_TYPE_ENTRY:   case VCDINFO_ITEM_TYPE_SEGMENT:   case VCDINFO_ITEM_TYPE_TRACK:     switch (p_vcdplayer->play_item.type) {    case VCDINFO_ITEM_TYPE_ENTRY:       max_entry = p_vcdplayer->i_entries;      min_entry = 0; /* Can remove when Entries start at 1. */      p_vcdplayer->i_track = vcdinfo_get_track(p_vcdinfo, play_item);      p_vcdplayer->track_lsn = vcdinfo_get_track_lsn(p_vcdinfo,                                                      p_vcdplayer->i_track);      break;    case VCDINFO_ITEM_TYPE_SEGMENT:       max_entry            = p_vcdplayer->i_segments;      p_vcdplayer->i_track = VCDINFO_INVALID_TRACK;            break;    case VCDINFO_ITEM_TYPE_TRACK:       max_entry       = p_vcdplayer->i_tracks;      p_vcdplayer->i_track   = p_vcdplayer->play_item.num;      p_vcdplayer->track_lsn = vcdinfo_get_track_lsn(p_vcdinfo,                                                      p_vcdplayer->i_track);      break;    default: ; /* Handle exceptional cases below */    }            _vcdplayer_set_origin(p_vcdplayer);    /* Set next, prev, return and default to simple and hopefully       useful values.     */    if (play_item+1 >= max_entry)       p_vcdplayer->next_entry = VCDINFO_INVALID_ENTRY;    else       p_vcdplayer->next_entry = play_item+1;        if (play_item-1 >= min_entry)       p_vcdplayer->prev_entry = play_item-1;    else       p_vcdplayer->prev_entry = VCDINFO_INVALID_ENTRY;        p_vcdplayer->default_entry = play_item;    p_vcdplayer->return_entry  = min_entry;    break;  case VCDINFO_ITEM_TYPE_LID:     {      /* Should have handled above. */      break;    }  default: ;  }  p_vcdplayer->update_title();}/*!  Set reading to play an entire track.*/static void_vcdplayer_set_track(vcdplayer_t *p_vcdplayer, unsigned int i_track) {  if (i_track < 1 || i_track > p_vcdplayer->i_tracks)     return;  else {    vcdinfo_obj_t *p_vcdinfo = p_vcdplayer->vcd;    vcdinfo_itemid_t itemid;    itemid.num             = i_track;    itemid.type            = VCDINFO_ITEM_TYPE_TRACK;    p_vcdplayer->i_still   = 0;    p_vcdplayer->i_lsn     = vcdinfo_get_track_lsn(p_vcdinfo, i_track);    p_vcdplayer->play_item = itemid;    p_vcdplayer->i_track   = i_track;    p_vcdplayer->track_lsn = p_vcdplayer->i_lsn;    _vcdplayer_set_origin(p_vcdplayer);    dbg_print(INPUT_DBG_LSN, "LSN: %u\n", p_vcdplayer->i_lsn);  }}/*!  Set reading to play an entry*/static void_vcdplayer_set_entry(vcdplayer_t *p_vcdplayer, unsigned int num) {  vcdinfo_obj_t *p_vcdinfo = p_vcdplayer->vcd;  const unsigned int i_entries = vcdinfo_get_num_entries(p_vcdinfo);  if (num >= i_entries) {    LOG_ERR(p_vcdplayer, "%s %d\n", _("bad entry number"), num);    return;  } else {    vcdinfo_itemid_t itemid;    itemid.num             = num;    itemid.type            = VCDINFO_ITEM_TYPE_ENTRY;    p_vcdplayer->i_still   = 0;    p_vcdplayer->i_lsn     = vcdinfo_get_entry_lsn(p_vcdinfo, num);    p_vcdplayer->play_item = itemid;    p_vcdplayer->i_track   = vcdinfo_get_track(p_vcdinfo, num);    p_vcdplayer->track_lsn = vcdinfo_get_track_lsn(p_vcdinfo,                                                    p_vcdplayer->i_track);    p_vcdplayer->track_end_lsn = p_vcdplayer->track_lsn +       p_vcdplayer->track[p_vcdplayer->i_track-1].size;    _vcdplayer_set_origin(p_vcdplayer);    dbg_print((INPUT_DBG_LSN|INPUT_DBG_PBC), "LSN: %u, track_end LSN: %u\n",               p_vcdplayer->i_lsn, p_vcdplayer->track_end_lsn);  }}/*!  Set reading to play an segment (e.g. still frame)*/static void_vcdplayer_set_segment(vcdplayer_t *p_vcdplayer, unsigned int num) {  vcdinfo_obj_t *p_vcdinfo = p_vcdplayer->vcd;  segnum_t i_segs  = vcdinfo_get_num_segments(p_vcdinfo);  if (num >= i_segs) {    LOG_ERR(p_vcdplayer, "%s %d\n", _("bad segment number"), num);    return;  } else {    vcdinfo_itemid_t itemid;

⌨️ 快捷键说明

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