📄 info.c
字号:
/* $Id: info.c,v 1.8 2007/03/23 21:47:31 dsalt Exp $ Copyright (C) 2002, 2003, 2004 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 Foundation Software, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*//* Things here refer to higher-level structures usually accessed via vcdinfo_t. For lower-level access which generally use structures other than vcdinfo_t, see inf.c*//* Private headers */#include "info_private.h"#include "vcd_assert.h"#include "pbc.h"#include "util.h"#include "vcd_read.h"#ifdef HAVE_STDLIB_H#include <stdlib.h>#endif#ifdef HAVE_STRING_H#include <string.h>#endif#ifdef HAVE_SYS_TYPES_H#include <sys/types.h>#endif#ifdef HAVE_SYS_STAT_H#include <sys/stat.h>#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#include <cdio/cdio.h>#include <cdio/bytesex.h>#include <cdio/cd_types.h>#include <cdio/util.h>/* Eventually move above libvcd includes but having vcdinfo including. */#include <libvcd/info.h>#include <stdio.h>#include <stddef.h>#include <errno.h>static const char _rcsid[] = "$Id: info.c,v 1.8 2007/03/23 21:47:31 dsalt Exp $";#define BUF_COUNT 16#define BUF_SIZE 80/* Return a pointer to a internal free buffer */static char *_getbuf (void){ static char _buf[BUF_COUNT][BUF_SIZE]; static int _num = -1; _num++; _num %= BUF_COUNT; memset (_buf[_num], 0, BUF_SIZE); return _buf[_num];}/* Initialize/allocate segment portion of vcdinfo_obj_t. Getting exact segments sizes is done in a rather complicated way. A simple approach would be to use the fixed size allocated on disk, but players have trouble with the internal fragmentation padding. More accurate results are obtained by consulting with ISO 9660 information for the corresponding file entry. Another approach to get segment sizes is to read/scan the MPEGs. That would be rather slow.*/static void_init_segments (vcdinfo_obj_t *obj){ InfoVcd_t *info = vcdinfo_get_infoVcd(obj); segnum_t num_segments = vcdinfo_get_num_segments(obj); CdioListNode *entnode; CdioList *entlist; int i; lsn_t last_lsn=0; obj->first_segment_lsn = cdio_msf_to_lsn(&info->first_seg_addr); obj->seg_sizes = _vcd_malloc( num_segments * sizeof(uint32_t *)); if (NULL == obj->seg_sizes || 0 == num_segments) return; entlist = iso9660_fs_readdir(obj->img, "SEGMENT", true); i=0; _CDIO_LIST_FOREACH (entnode, entlist) { iso9660_stat_t *statbuf = _cdio_list_node_data (entnode); if (statbuf->type == _STAT_DIR) continue; while(info->spi_contents[i].item_cont) { obj->seg_sizes[i] = VCDINFO_SEGMENT_SECTOR_SIZE; i++; } /* Should have an entry in the ISO 9660 filesystem. Get and save in statbuf.secsize this size. */ obj->seg_sizes[i] = statbuf->secsize; if (last_lsn >= statbuf->lsn) vcd_warn ("Segments if ISO 9660 directory out of order lsn %ul >= %ul", (unsigned int) last_lsn, (unsigned int) statbuf->lsn); last_lsn = statbuf->lsn; i++; } while(i < num_segments && info->spi_contents[i].item_cont) { obj->seg_sizes[i] = VCDINFO_SEGMENT_SECTOR_SIZE; i++; } if (i != num_segments) vcd_warn ("Number of segments found %d is not number of segments %d", i, num_segments); _cdio_list_free (entlist, true); #if 0 /* Figure all of the segment sector sizes */ for (i=0; i < num_segments; i++) { obj->seg_sizes[i] = VCDINFO_SEGMENT_SECTOR_SIZE; if ( !info->spi_contents[i].item_cont ) { /* Should have an entry in the ISO 9660 filesystem. Get and save in statbuf.secsize this size. */ lsn_t lsn = vcdinfo_get_seg_lsn(obj, i); iso9660_stat_t *statbuf =iso9660_find_fs_lsn(obj->img, lsn); if (NULL != statbuf) { obj->seg_sizes[i] = statbuf->secsize; free(statbuf); } else { vcd_warn ("Trouble finding ISO 9660 size for segment %d.", i); } } }#endif}/*! Return the number of audio channels implied by "audio_type". 0 is returned on error.*/unsigned intvcdinfo_audio_type_num_channels(const vcdinfo_obj_t *obj, unsigned int audio_type) { const int audio_types[2][5] = { { /* VCD 2.0 */ 0, /* no audio*/ 1, /* single channel */ 1, /* stereo */ 2, /* dual channel */ 0}, /* error */ { /* SVCD, HQVCD */ 0, /* no stream */ 1, /* 1 stream */ 2, /* 2 streams */ 1, /* 1 multi-channel stream (surround sound) */ 0} /* error */ }; /* We should also check that the second index is in range too. */ if (audio_type > 4) { return 0; } /* Get first index entry into above audio_type array from vcd_type */ switch (obj->vcd_type) { case VCD_TYPE_VCD: case VCD_TYPE_VCD11: return 1; case VCD_TYPE_VCD2: return 3; break; case VCD_TYPE_HQVCD: case VCD_TYPE_SVCD: return audio_types[1][audio_type]; break; case VCD_TYPE_INVALID: default: /* We have an invalid entry. Set to handle below. */ return 0; }}/*! Return a string describing an audio type.*/const char * vcdinfo_audio_type2str(const vcdinfo_obj_t *obj, unsigned int audio_type){ const char *audio_types[3][5] = { /* INVALID, VCD 1.0, or VCD 1.1 */ { "unknown", "invalid", "", "", "" }, /*VCD 2.0 */ { "no audio", "single channel", "stereo", "dual channel", "error" }, /* SVCD, HQVCD */ { "no stream", "1 stream", "2 streams", "1 multi-channel stream (surround sound)", "error"}, }; unsigned int first_index = 0; /* Get first index entry into above audio_type array from vcd_type */ switch (obj->vcd_type) { case VCD_TYPE_VCD: case VCD_TYPE_VCD11: case VCD_TYPE_VCD2: first_index=1; break; case VCD_TYPE_HQVCD: case VCD_TYPE_SVCD: first_index=2; break; case VCD_TYPE_INVALID: default: /* We have an invalid entry. Set to handle below. */ audio_type=4; } /* We should also check that the second index is in range too. */ if (audio_type > 3) { first_index=0; audio_type=1; } return audio_types[first_index][audio_type];}/*! Note first seg_num is 0!*/const char * vcdinfo_ogt2str(const vcdinfo_obj_t *obj, segnum_t seg_num){ const InfoVcd_t *info = &obj->info; const char *ogt_str[] = { "None", "1 available", "0 & 1 available", "all 4 available" }; return ogt_str[info->spi_contents[seg_num].ogt];}const char * vcdinfo_video_type2str(const vcdinfo_obj_t *obj, segnum_t seg_num){ const char *video_types[] = { "no stream", "NTSC still", "NTSC still (lo+hires)", "NTSC motion", "reserved (0x4)", "PAL still", "PAL still (lo+hires)", "PAL motion", "INVALID ENTRY" }; return video_types[vcdinfo_get_video_type(obj, seg_num)];}/*! \brief Classify itemid_num into the kind of item it is: track #, entry #, segment #. \param itemid is set to contain this classification an the converted entry number. */voidvcdinfo_classify_itemid (uint16_t itemid_num, /*out*/ vcdinfo_itemid_t *itemid){ itemid->num = itemid_num; if (itemid_num < 2) itemid->type = VCDINFO_ITEM_TYPE_NOTFOUND; else if (itemid_num < MIN_ENCODED_TRACK_NUM) { itemid->type = VCDINFO_ITEM_TYPE_TRACK; itemid->num--; } else if (itemid_num < 600) { itemid->type = VCDINFO_ITEM_TYPE_ENTRY; itemid->num -= MIN_ENCODED_TRACK_NUM; } else if (itemid_num < MIN_ENCODED_SEGMENT_NUM) itemid->type = VCDINFO_ITEM_TYPE_LID; else if (itemid_num <= MAX_ENCODED_SEGMENT_NUM) { itemid->type = VCDINFO_ITEM_TYPE_SEGMENT; itemid->num -= (MIN_ENCODED_SEGMENT_NUM); } else itemid->type = VCDINFO_ITEM_TYPE_SPAREID2;}const char *vcdinfo_pin2str (uint16_t itemid_num){ char *buf = _getbuf (); vcdinfo_itemid_t itemid; vcdinfo_classify_itemid(itemid_num, &itemid); strcpy (buf, "??"); switch(itemid.type) { case VCDINFO_ITEM_TYPE_NOTFOUND: snprintf (buf, BUF_SIZE, "play nothing (0x%4.4x)", itemid.num); break; case VCDINFO_ITEM_TYPE_TRACK: snprintf (buf, BUF_SIZE, "SEQUENCE[%d] (0x%4.4x)", itemid.num-1, itemid_num); break; case VCDINFO_ITEM_TYPE_ENTRY: snprintf (buf, BUF_SIZE, "ENTRY[%d] (0x%4.4x)", itemid.num, itemid_num); break; case VCDINFO_ITEM_TYPE_SEGMENT: snprintf (buf, BUF_SIZE, "SEGMENT[%d] (0x%4.4x)", itemid.num, itemid_num); break; case VCDINFO_ITEM_TYPE_LID: snprintf (buf, BUF_SIZE, "spare id (0x%4.4x)", itemid.num); break; case VCDINFO_ITEM_TYPE_SPAREID2: snprintf (buf, BUF_SIZE, "spare id2 (0x%4.4x)", itemid.num); break; } return buf;}/*! Return a string containing the VCD album id, or NULL if there is some problem in getting this. */const char *vcdinfo_get_album_id(const vcdinfo_obj_t *obj){ if ( NULL == obj ) return (NULL); return vcdinf_get_album_id(&obj->info);}/*! Return the VCD ID. NULL is returned if there is some problem in getting this. */char *vcdinfo_get_application_id(vcdinfo_obj_t *p_obj){ if ( NULL == p_obj ) return (NULL); return iso9660_get_application_id(&p_obj->pvd);}/*! Return a pointer to the cdio structure for the CD image opened or NULL if error.*/CdIo *vcdinfo_get_cd_image (const vcdinfo_obj_t *vcd_obj) { if (NULL == vcd_obj) return NULL; return vcd_obj->img;}/*! \fn vcdinfo_selection_get_lid(const vcdinfo_obj_t *obj, lid_t lid, unsigned int selection); \brief Get offset of a selection for a given lid. Return the LID offset associated with a the selection number of the passed-in LID parameter. \return VCDINFO_INVALID_LID is returned if obj on error or obj is NULL. Otherwise the LID offset is returned.*/lid_t vcdinfo_selection_get_lid(const vcdinfo_obj_t *obj, lid_t lid, unsigned int selection) { unsigned int offset; if (NULL == obj) return VCDINFO_INVALID_LID; offset = vcdinfo_selection_get_offset(obj, lid, selection); switch (offset) { case VCDINFO_INVALID_OFFSET: case PSD_OFS_MULTI_DEF: case PSD_OFS_MULTI_DEF_NO_NUM: return VCDINFO_INVALID_LID; default: { vcdinfo_offset_t *ofs = vcdinfo_get_offset_t(obj, offset); return ofs->lid; } }}/*! \fn vcdinfo_selection_get_offset(const vcdinfo_obj_t *obj, lid_t lid, unsigned int selection); \brief Get offset of a selection for a given lid. Return the LID offset associated with a the selection number of the passed-in LID parameter. \return VCDINFO_INVALID_OFFSET is returned if error, obj is NULL or the lid is not some type of selection list. Otherwise the LID offset is returned.*/uint16_t vcdinfo_selection_get_offset(const vcdinfo_obj_t *obj, lid_t lid, unsigned int selection) { unsigned int bsn; PsdListDescriptor_t pxd; vcdinfo_lid_get_pxd(obj, &pxd, lid); if (pxd.descriptor_type != PSD_TYPE_SELECTION_LIST && pxd.descriptor_type != PSD_TYPE_EXT_SELECTION_LIST) { vcd_warn( "Requesting selection of LID %i which not a selection list -" " type is 0x%x", lid, pxd.descriptor_type ); return VCDINFO_INVALID_OFFSET; } bsn=vcdinf_get_bsn(pxd.psd); if ( (selection - bsn + 1) > 0) { return vcdinfo_lid_get_offset(obj, lid, selection-bsn+1); } else { vcd_warn( "Selection number %u too small. bsn %u", selection, bsn ); return VCDINFO_INVALID_OFFSET; }}/** \fn vcdinfo_get_default_offset(const vcdinfo_obj_t *obj, unsinged int lid); \brief Get return offset for a given PLD selector descriptor. \return VCDINFO_INVALID_OFFSET is returned on error or if pld has no "return" entry or pld is NULL. Otherwise the LID offset is returned. */uint16_tvcdinfo_get_default_offset(const vcdinfo_obj_t *obj, lid_t lid){ if (NULL != obj) { PsdListDescriptor_t pxd; vcdinfo_lid_get_pxd(obj, &pxd, lid); switch (pxd.descriptor_type) { case PSD_TYPE_EXT_SELECTION_LIST: case PSD_TYPE_SELECTION_LIST: return vcdinf_psd_get_default_offset(pxd.psd); break; case PSD_TYPE_PLAY_LIST: case PSD_TYPE_END_LIST: case PSD_TYPE_COMMAND_LIST: break; } } return VCDINFO_INVALID_OFFSET;}/*! \brief Get default or multi-default LID. Return the LID offset associated with a the "default" entry of the passed-in LID parameter. Note "default" entries are associated with PSDs that are (extended) selection lists. If the "default" offset is a multi-default, we use entry_num to find the proper "default" LID. Otherwise this routine is exactly like vcdinfo_get_default_lid with the exception of requiring an additional "entry_num" parameter. \return VCDINFO_INVALID_LID is returned on error, or if the LID is not a selection list or no "default" entry. Otherwise the LID offset is returned.*/lid_tvcdinfo_get_multi_default_lid(const vcdinfo_obj_t *obj, lid_t lid, lsn_t lsn)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -