📄 files.c
字号:
/* $Id: files.c,v 1.4 2006/09/26 21:18:18 dgp85 Exp $ Copyright (C) 2000, 2004 Herbert Valerio Riedel <hvr@gnu.org> 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#include <string.h>#include <stdlib.h>#include <stddef.h>#include <math.h>#include <cdio/cdio.h>#include <cdio/bytesex.h>#include <cdio/util.h>/* Public headers */#include <libvcd/files.h>#include <libvcd/types.h>#include <libvcd/logging.h>/* FIXME! Make this local */#include <libvcd/files_private.h>/* Private headers */#include "vcd_assert.h"#include "mpeg_stream.h"#include "obj.h"#include "pbc.h"#include "util.h"static const char _rcsid[] = "$Id: files.c,v 1.4 2006/09/26 21:18:18 dgp85 Exp $";inline static bool_pal_p (const struct vcd_mpeg_stream_vid_info *_info){ return (_info->vsize == 288 || _info->vsize == 576);}static int_derive_vid_type (const struct vcd_mpeg_stream_info *_info, bool svcd){ if (_info->shdr[0].seen) return _pal_p (&_info->shdr[0]) ? 0x7 : 0x3; if (_info->shdr[2].seen) { if (svcd) vcd_warn ("stream with 0xE2 still stream id not allowed for IEC62107 compliant SVCDs"); return _pal_p (&_info->shdr[2]) ? 0x6 : 0x2; } if (_info->shdr[1].seen) return _pal_p (&_info->shdr[1]) ? 0x5 : 0x1; return 0;}static int_derive_ogt_type (const struct vcd_mpeg_stream_info *_info, bool svcd){ if (!svcd) return 0; if ((_info->ogt[3] || _info->ogt[2]) && _info->ogt[1] && _info->ogt[0]) return 0x3; if (_info->ogt[1] && _info->ogt[0]) return 0x2; if (_info->ogt[0]) return 0x1; vcd_debug ("OGT streams available: %d %d %d %d", _info->ogt[0], _info->ogt[1], _info->ogt[2], _info->ogt[3]); return 0x0;}static int_derive_aud_type (const struct vcd_mpeg_stream_info *_info, bool svcd){ if (!_info->ahdr[0].seen) return 0; /* no MPEG audio */ if (svcd) { if (_info->ahdr[2].seen) return 3; /* MC */ if (_info->ahdr[1].seen) return 2; /* 2 streams */ return 1; /* just one stream */ } else switch (_info->ahdr[0].mode) { case MPEG_SINGLE_CHANNEL: return 1; break; case MPEG_STEREO: case MPEG_JOINT_STEREO: return 2; break; case MPEG_DUAL_CHANNEL: return 3; break; } return 0;}voidset_entries_vcd (VcdObj *obj, void *buf){ CdioListNode *node = NULL; int idx = 0; int track_idx = 0; EntriesVcd_t entries_vcd; vcd_assert (sizeof(EntriesVcd_t) == 2048); vcd_assert (_cdio_list_length (obj->mpeg_track_list) <= MAX_ENTRIES); vcd_assert (_cdio_list_length (obj->mpeg_track_list) > 0); memset(&entries_vcd, 0, sizeof(entries_vcd)); /* paranoia / fixme */ switch (obj->type) { case VCD_TYPE_VCD: strncpy(entries_vcd.ID, ENTRIES_ID_VCD, 8); entries_vcd.version = ENTRIES_VERSION_VCD; entries_vcd.sys_prof_tag = ENTRIES_SPTAG_VCD; break; case VCD_TYPE_VCD11: strncpy(entries_vcd.ID, ENTRIES_ID_VCD, 8); entries_vcd.version = ENTRIES_VERSION_VCD11; entries_vcd.sys_prof_tag = ENTRIES_SPTAG_VCD11; break; case VCD_TYPE_VCD2: strncpy(entries_vcd.ID, ENTRIES_ID_VCD, 8); entries_vcd.version = ENTRIES_VERSION_VCD2; entries_vcd.sys_prof_tag = ENTRIES_SPTAG_VCD2; break; case VCD_TYPE_SVCD: if (!obj->svcd_vcd3_entrysvd) strncpy(entries_vcd.ID, ENTRIES_ID_SVCD, 8); else { vcd_warn ("setting ENTRYSVD signature for *DEPRECATED* VCD 3.0 type SVCD"); strncpy(entries_vcd.ID, ENTRIES_ID_VCD3, 8); } entries_vcd.version = ENTRIES_VERSION_SVCD; entries_vcd.sys_prof_tag = ENTRIES_SPTAG_SVCD; break; case VCD_TYPE_HQVCD: strncpy(entries_vcd.ID, ENTRIES_ID_SVCD, 8); entries_vcd.version = ENTRIES_VERSION_HQVCD; entries_vcd.sys_prof_tag = ENTRIES_SPTAG_HQVCD; break; default: vcd_assert_not_reached (); break; } idx = 0; track_idx = 2; _CDIO_LIST_FOREACH (node, obj->mpeg_sequence_list) { mpeg_sequence_t *track = _cdio_list_node_data (node); uint32_t lsect = track->relative_start_extent; CdioListNode *node2; lsect += obj->iso_size; entries_vcd.entry[idx].n = cdio_to_bcd8(track_idx); cdio_lba_to_msf(cdio_lsn_to_lba(lsect), &(entries_vcd.entry[idx].msf)); idx++; lsect += obj->track_front_margin; _CDIO_LIST_FOREACH (node2, track->entry_list) { entry_t *_entry = _cdio_list_node_data (node2); /* additional entries */ vcd_assert (idx < MAX_ENTRIES); entries_vcd.entry[idx].n = cdio_to_bcd8(track_idx); cdio_lba_to_msf(lsect + cdio_lsn_to_lba(_entry->aps.packet_no), &(entries_vcd.entry[idx].msf)); idx++; } track_idx++; } entries_vcd.entry_count = uint16_to_be (idx); memcpy(buf, &entries_vcd, sizeof(entries_vcd));}static void_set_bit (uint8_t bitset[], unsigned bitnum){ unsigned _byte = bitnum / 8; unsigned _bit = bitnum % 8; bitset[_byte] |= (1 << _bit);}uint32_t get_psd_size (VcdObj *obj, bool extended){ if (extended) vcd_assert (_vcd_obj_has_cap_p (obj, _CAP_PBC_X)); if (!_vcd_pbc_available (obj)) return 0; if (extended) return obj->psdx_size; return obj->psd_size;}voidset_psd_vcd (VcdObj *obj, void *buf, bool extended){ CdioListNode *node; if (extended) vcd_assert (_vcd_obj_has_cap_p (obj, _CAP_PBC_X)); vcd_assert (_vcd_pbc_available (obj)); _CDIO_LIST_FOREACH (node, obj->pbc_list) { pbc_t *_pbc = _cdio_list_node_data (node); char *_buf = buf; unsigned offset = (extended ? _pbc->offset_ext : _pbc->offset); vcd_assert (offset % INFO_OFFSET_MULT == 0); _vcd_pbc_node_write (obj, _pbc, _buf + offset, extended); }}voidset_lot_vcd(VcdObj *obj, void *buf, bool extended){ LotVcd_t *lot_vcd = NULL; CdioListNode *node; if (extended) vcd_assert (_vcd_obj_has_cap_p (obj, _CAP_PBC_X)); vcd_assert (_vcd_pbc_available (obj)); lot_vcd = _vcd_malloc (sizeof (LotVcd_t)); memset(lot_vcd, 0xff, sizeof(LotVcd_t)); lot_vcd->reserved = 0x0000; _CDIO_LIST_FOREACH (node, obj->pbc_list) { pbc_t *_pbc = _cdio_list_node_data (node); unsigned int offset = extended ? _pbc->offset_ext : _pbc->offset; vcd_assert (offset % INFO_OFFSET_MULT == 0); if (_pbc->rejected) continue; offset /= INFO_OFFSET_MULT; lot_vcd->offset[_pbc->lid - 1] = uint16_to_be (offset); } memcpy(buf, lot_vcd, sizeof(LotVcd_t)); free(lot_vcd);}voidset_info_vcd(VcdObj *obj, void *buf){ InfoVcd_t info_vcd; CdioListNode *node = NULL; int n = 0; vcd_assert (sizeof (InfoVcd_t) == 2048); vcd_assert (_cdio_list_length (obj->mpeg_track_list) <= 98); memset (&info_vcd, 0, sizeof (info_vcd)); switch (obj->type) { case VCD_TYPE_VCD: strncpy (info_vcd.ID, INFO_ID_VCD, sizeof (info_vcd.ID)); info_vcd.version = INFO_VERSION_VCD; info_vcd.sys_prof_tag = INFO_SPTAG_VCD; break; case VCD_TYPE_VCD11: strncpy (info_vcd.ID, INFO_ID_VCD, sizeof (info_vcd.ID)); info_vcd.version = INFO_VERSION_VCD11; info_vcd.sys_prof_tag = INFO_SPTAG_VCD11; break; case VCD_TYPE_VCD2: strncpy (info_vcd.ID, INFO_ID_VCD, sizeof (info_vcd.ID)); info_vcd.version = INFO_VERSION_VCD2; info_vcd.sys_prof_tag = INFO_SPTAG_VCD2; break; case VCD_TYPE_SVCD: strncpy (info_vcd.ID, INFO_ID_SVCD, sizeof (info_vcd.ID)); info_vcd.version = INFO_VERSION_SVCD; info_vcd.sys_prof_tag = INFO_SPTAG_SVCD; break; case VCD_TYPE_HQVCD: strncpy (info_vcd.ID, INFO_ID_HQVCD, sizeof (info_vcd.ID)); info_vcd.version = INFO_VERSION_HQVCD; info_vcd.sys_prof_tag = INFO_SPTAG_HQVCD; break; default: vcd_assert_not_reached (); break; } iso9660_strncpy_pad (info_vcd.album_desc, obj->info_album_id, sizeof(info_vcd.album_desc), ISO9660_DCHARS); /* fixme, maybe it's VCD_ACHARS? */ info_vcd.vol_count = uint16_to_be (obj->info_volume_count); info_vcd.vol_id = uint16_to_be (obj->info_volume_number); if (_vcd_obj_has_cap_p (obj, _CAP_PAL_BITS)) { /* NTSC/PAL bitset */ n = 0; _CDIO_LIST_FOREACH (node, obj->mpeg_track_list) { mpeg_track_t *track = _cdio_list_node_data (node); const struct vcd_mpeg_stream_vid_info *_info = &track->info->shdr[0]; if (vcd_mpeg_get_norm (_info) == MPEG_NORM_PAL || vcd_mpeg_get_norm (_info) == MPEG_NORM_PAL_S) _set_bit(info_vcd.pal_flags, n); else if (_pal_p (_info)) { vcd_warn ("INFO.{VCD,SVD}: assuming PAL-type resolution for track #%d" " -- are we creating a X(S)VCD?", n); _set_bit(info_vcd.pal_flags, n); } n++; } } if (_vcd_obj_has_cap_p (obj, _CAP_PBC)) { info_vcd.flags.restriction = obj->info_restriction; info_vcd.flags.use_lid2 = obj->info_use_lid2; info_vcd.flags.use_track3 = obj->info_use_seq2; if (_vcd_obj_has_cap_p (obj, _CAP_PBC_X) &&_vcd_pbc_available (obj)) info_vcd.flags.pbc_x = true; info_vcd.psd_size = uint32_to_be (get_psd_size (obj, false)); info_vcd.offset_mult = _vcd_pbc_available (obj) ? INFO_OFFSET_MULT : 0; info_vcd.lot_entries = uint16_to_be (_vcd_pbc_max_lid (obj)); if (_cdio_list_length (obj->mpeg_segment_list)) { unsigned segments = 0; if (!_vcd_pbc_available (obj)) vcd_warn ("segment items available, but no PBC items set!" " SPIs will be unreachable"); _CDIO_LIST_FOREACH (node, obj->mpeg_segment_list) { mpeg_segment_t *segment = _cdio_list_node_data (node); unsigned idx; InfoSpiContents contents = { 0, }; contents.video_type = _derive_vid_type (segment->info, _vcd_obj_has_cap_p (obj, _CAP_4C_SVCD)); contents.audio_type = _derive_aud_type (segment->info, _vcd_obj_has_cap_p (obj, _CAP_4C_SVCD)); contents.ogt = _derive_ogt_type (segment->info, _vcd_obj_has_cap_p (obj, _CAP_4C_SVCD)); if (!contents.video_type && !contents.audio_type) vcd_warn ("segment item '%s' seems contains neither video nor audio", segment->id); for (idx = 0; idx < segment->segment_count; idx++) { vcd_assert (segments + idx < MAX_SEGMENTS); info_vcd.spi_contents[segments + idx] = contents; if (!contents.item_cont) contents.item_cont = true; } segments += idx; } info_vcd.item_count = uint16_to_be (segments); cdio_lba_to_msf (cdio_lsn_to_lba(obj->mpeg_segment_start_extent), &info_vcd.first_seg_addr); } } memcpy(buf, &info_vcd, sizeof(info_vcd));}static voidset_tracks_svd_v30 (VcdObj *obj, void *buf){ char tracks_svd_buf[ISO_BLOCKSIZE] = { 0, }; TracksSVD_v30 *tracks_svd = (void *) tracks_svd_buf; CdioListNode *node; double playtime; int n; strncpy (tracks_svd->file_id, TRACKS_SVD_FILE_ID, sizeof (TRACKS_SVD_FILE_ID)-1); tracks_svd->version = TRACKS_SVD_VERSION; tracks_svd->tracks = _cdio_list_length (obj->mpeg_track_list); n = 0; playtime = 0; _CDIO_LIST_FOREACH (node, obj->mpeg_track_list) { mpeg_track_t *track = _cdio_list_node_data (node); int i; playtime += track->info->playing_time; tracks_svd->track[n].audio_info = track->info->ahdr[0].seen ? 0x2 : 0x0; /* fixme */ tracks_svd->track[n].audio_info |= track->info->ahdr[1].seen ? 0x20 : 0x0; /* fixme */ tracks_svd->track[n].ogt_info = 0x0; for (i = 0; i < 4; i++) if (track->info->ogt[i]) tracks_svd->track[n].ogt_info |= 1 << (i * 2); /* fixme */ /* setting playtime */ { double i, f; while (playtime >= 6000.0) playtime -= 6000.0; f = modf(playtime, &i); cdio_lba_to_msf (i * 75, &tracks_svd->track[n].cum_playing_time); tracks_svd->track[n].cum_playing_time.f = cdio_to_bcd8 (floor (f * 75.0)); } n++; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -