📄 vcd.c
字号:
vcd_debug ("setting EOR for SeqEnd at packet# %d ('%s')", packet_no, _segment->id); sm |= SM_EOR; } } else { fn = 1; cn = CN_EMPTY; sm = SM_FORM2 | SM_REALT; ci = CI_EMPTY; if (_vcd_obj_has_cap_p (obj, _CAP_4C_SVCD)) { fn = 0; sm = SM_FORM2; } } _write_m2_image_sector (obj, buf, n, fn, cn, sm, ci); n++; } vcd_mpeg_source_close (_segment->source); return 0;}static uint32_t_get_closest_aps (const struct vcd_mpeg_stream_info *_mpeg_info, double t, struct aps_data *_best_aps){ CdioListNode *node; struct aps_data best_aps; bool first = true; vcd_assert (_mpeg_info != NULL); vcd_assert (_mpeg_info->shdr[0].aps_list != NULL); _CDIO_LIST_FOREACH (node, _mpeg_info->shdr[0].aps_list) { struct aps_data *_aps = _cdio_list_node_data (node); if (first) { best_aps = *_aps; first = false; } else if (fabs (_aps->timestamp - t) < fabs (best_aps.timestamp - t)) best_aps = *_aps; else break; } if (_best_aps) *_best_aps = best_aps; return best_aps.packet_no;}static void_update_entry_points (VcdObj *obj){ CdioListNode *sequence_node; _CDIO_LIST_FOREACH (sequence_node, obj->mpeg_sequence_list) { mpeg_sequence_t *_sequence = _cdio_list_node_data (sequence_node); CdioListNode *entry_node; unsigned last_packet_no = 0; _CDIO_LIST_FOREACH (entry_node, _sequence->entry_list) { entry_t *_entry = _cdio_list_node_data (entry_node); _get_closest_aps (_sequence->info, _entry->time, &_entry->aps); vcd_log ((fabs (_entry->aps.timestamp - _entry->time) > 1 ? VCD_LOG_WARN : VCD_LOG_DEBUG), "requested entry point (id=%s) at %f, " "closest possible entry point at %f", _entry->id, _entry->time, _entry->aps.timestamp); if (last_packet_no == _entry->aps.packet_no) vcd_warn ("entry point '%s' falls into same sector as previous one!", _entry->id); last_packet_no = _entry->aps.packet_no; } }}static int_write_vcd_iso_track (VcdObj *obj, const time_t *create_time){ CdioListNode *node; int n; /* generate dir sectors */ _vcd_directory_dump_entries (obj->dir, _dict_get_bykey (obj, "dir")->buf, _dict_get_bykey (obj, "dir")->sector); _vcd_directory_dump_pathtables (obj->dir, _dict_get_bykey (obj, "ptl")->buf, _dict_get_bykey (obj, "ptm")->buf); /* generate PVD and EVD at last... */ iso9660_set_pvd (_dict_get_bykey (obj, "pvd")->buf, obj->iso_volume_label, obj->iso_publisher_id, obj->iso_preparer_id, obj->iso_application_id, obj->iso_size, _dict_get_bykey (obj, "dir")->buf, _dict_get_bykey (obj, "ptl")->sector, _dict_get_bykey (obj, "ptm")->sector, iso9660_pathtable_get_size (_dict_get_bykey (obj, "ptm")->buf), create_time); iso9660_set_evd (_dict_get_bykey (obj, "evd")->buf); /* fill VCD relevant files with data */ set_info_vcd (obj, _dict_get_bykey (obj, "info")->buf); set_entries_vcd (obj, _dict_get_bykey (obj, "entries")->buf); if (_vcd_pbc_available (obj)) { if (_vcd_obj_has_cap_p (obj, _CAP_PBC_X)) { set_lot_vcd (obj, _dict_get_bykey (obj, "lot_x")->buf, true); set_psd_vcd (obj, _dict_get_bykey (obj, "psd_x")->buf, true); } _vcd_pbc_check_unreferenced (obj); set_lot_vcd (obj, _dict_get_bykey (obj, "lot")->buf, false); set_psd_vcd (obj, _dict_get_bykey (obj, "psd")->buf, false); } if (_vcd_obj_has_cap_p (obj, _CAP_4C_SVCD)) { set_tracks_svd (obj, _dict_get_bykey (obj, "tracks")->buf); set_search_dat (obj, _dict_get_bykey (obj, "search")->buf); set_scandata_dat (obj, _dict_get_bykey (obj, "scandata")->buf); } /* start actually writing stuff */ vcd_info ("writing track 1 (ISO9660)..."); /* 00:02:00 -> 00:04:74 */ for (n = 0;n < obj->mpeg_segment_start_extent; n++) { const void *content = NULL; uint8_t flags = SM_DATA; content = _dict_get_sector (obj, n); flags |= _dict_get_sector_flags (obj, n); if (content == NULL) content = zero; _write_m2_image_sector (obj, content, n, 0, 0, flags, 0); } /* SEGMENTS */ vcd_assert (n == obj->mpeg_segment_start_extent); _CDIO_LIST_FOREACH (node, obj->mpeg_segment_list) { mpeg_segment_t *_segment = _cdio_list_node_data (node); _write_segment (obj, _segment); } n = obj->sectors_written; /* EXT stuff */ vcd_assert (n == obj->ext_file_start_extent); for (;n < obj->custom_file_start_extent; n++) { const void *content = NULL; uint8_t flags = SM_DATA; uint8_t fileno = _vcd_obj_has_cap_p (obj, _CAP_4C_SVCD) ? 0 : 1; content = _dict_get_sector (obj, n); flags |= _dict_get_sector_flags (obj, n); if (content == NULL) { vcd_debug ("unexpected empty EXT sector"); content = zero; } _write_m2_image_sector (obj, content, n, fileno, 0, flags, 0); } /* write custom files */ vcd_assert (n == obj->custom_file_start_extent); _CDIO_LIST_FOREACH (node, obj->custom_file_list) { custom_file_t *p = _cdio_list_node_data (node); vcd_info ("writing file `%s' (%lu bytes%s)", p->iso_pathname, (unsigned long) p->size, p->raw_flag ? ", raw sectors file": ""); if (p->raw_flag) _write_source_mode2_raw (obj, p->file, p->start_extent); else _write_source_mode2_form1 (obj, p->file, p->start_extent); } /* blank unalloced tracks */ while ((n = _vcd_salloc (obj->iso_bitmap, SECTOR_NIL, 1)) < obj->iso_size) _write_m2_image_sector (obj, zero, n, 0, 0, SM_DATA, 0); return 0;}longvcd_obj_get_image_size (VcdObj *obj){ long size_sectors = -1; vcd_assert (!obj->in_output); if (_cdio_list_length (obj->mpeg_sequence_list) > 0) { /* fixme -- make this efficient */ size_sectors = vcd_obj_begin_output (obj); vcd_obj_end_output (obj); } return size_sectors;}longvcd_obj_begin_output (VcdObj *obj){ uint32_t image_size; vcd_assert (obj != NULL); vcd_assert (_cdio_list_length (obj->mpeg_sequence_list) > 0); vcd_assert (!obj->in_output); obj->in_output = true; obj->in_track = 1; obj->sectors_written = 0; obj->iso_bitmap = _vcd_salloc_new (); obj->dir = _vcd_directory_new (); obj->buffer_dict_list = _cdio_list_new (); _finalize_vcd_iso_track (obj); _update_entry_points (obj); image_size = obj->relative_end_extent + obj->iso_size; image_size += obj->leadout_pregap; if (image_size > CDIO_CD_MAX_SECTORS) vcd_error ("image too big (%d sectors > %d sectors)", (unsigned) image_size, (unsigned) CDIO_CD_MAX_SECTORS); { char *_tmp = cdio_lba_to_msf_str (image_size); if (image_size > CDIO_CD_74MIN_SECTORS) vcd_warn ("generated image (%d sectors [%s]) may not fit " "on 74min CDRs (%d sectors)", (unsigned) image_size, _tmp, (unsigned) CDIO_CD_74MIN_SECTORS); free (_tmp); } return image_size;}voidvcd_obj_end_output (VcdObj *obj){ vcd_assert (obj != NULL); vcd_assert (obj->in_output); obj->in_output = false; _vcd_directory_destroy (obj->dir); _vcd_salloc_destroy (obj->iso_bitmap); _dict_clean (obj); _cdio_list_free (obj->buffer_dict_list, true);}intvcd_obj_append_pbc_node (VcdObj *obj, struct _pbc_t *_pbc){ vcd_assert (obj != NULL); vcd_assert (_pbc != NULL); if (!_vcd_obj_has_cap_p (obj, _CAP_PBC)) { vcd_error ("PBC not supported for current VCD type"); return -1; } if (_pbc->item_id && _vcd_pbc_lookup (obj, _pbc->item_id)) { vcd_error ("item id (%s) exists already", _pbc->item_id); return -1; } _cdio_list_append (obj->pbc_list, _pbc); return 0;}intvcd_obj_write_image (VcdObj *obj, VcdImageSink *image_sink, progress_callback_t callback, void *user_data, const time_t *create_time){ CdioListNode *node; vcd_assert (obj != NULL); vcd_assert (obj->in_output); if (!image_sink) return -1; /* start with meta info */ { CdioList *cue_list; vcd_cue_t *_cue; cue_list = _cdio_list_new (); _cdio_list_append (cue_list, (_cue = _vcd_malloc (sizeof (vcd_cue_t)))); _cue->lsn = 0; _cue->type = VCD_CUE_TRACK_START; _CDIO_LIST_FOREACH (node, obj->mpeg_sequence_list) { mpeg_sequence_t *track = _cdio_list_node_data (node); CdioListNode *entry_node; _cdio_list_append (cue_list, (_cue = _vcd_malloc (sizeof (vcd_cue_t)))); _cue->lsn = track->relative_start_extent + obj->iso_size; _cue->lsn -= obj->track_pregap; _cue->type = VCD_CUE_PREGAP_START; _cdio_list_append (cue_list, (_cue = _vcd_malloc (sizeof (vcd_cue_t)))); _cue->lsn = track->relative_start_extent + obj->iso_size; _cue->type = VCD_CUE_TRACK_START; _CDIO_LIST_FOREACH (entry_node, track->entry_list) { entry_t *_entry = _cdio_list_node_data (entry_node); _cdio_list_append (cue_list, (_cue = _vcd_malloc (sizeof (vcd_cue_t)))); _cue->lsn = obj->iso_size; _cue->lsn += track->relative_start_extent; _cue->lsn += obj->track_front_margin; _cue->lsn += _entry->aps.packet_no; _cue->type = VCD_CUE_SUBINDEX; } } /* add last one... */ _cdio_list_append (cue_list, (_cue = _vcd_malloc (sizeof (vcd_cue_t)))); _cue->lsn = obj->relative_end_extent + obj->iso_size; _cue->lsn += obj->leadout_pregap; _cue->type = VCD_CUE_END; /* send it to image object */ vcd_image_sink_set_cuesheet (image_sink, cue_list); _cdio_list_free (cue_list, true); } /* and now for the pay load */ { unsigned track; vcd_assert (obj != NULL); vcd_assert (obj->sectors_written == 0); vcd_assert (obj->in_output); obj->progress_callback = callback; obj->callback_user_data = user_data; obj->image_sink = image_sink; if (_callback_wrapper (obj, true)) return 1; if (_write_vcd_iso_track (obj, create_time)) return 1; if (obj->update_scan_offsets) vcd_info ("'update scan offsets' option enabled for the following tracks!"); for (track = 0;track < _cdio_list_length (obj->mpeg_sequence_list);track++) { obj->in_track++; if (_callback_wrapper (obj, true)) return 1; if (_write_sequence (obj, track)) return 1; } if (obj->leadout_pregap) { int n, lastsect = obj->sectors_written; vcd_debug ("writting post-gap ('leadout pregap')..."); for (n = 0; n < obj->leadout_pregap; n++) _write_m2_image_sector (obj, zero, lastsect++, 0, 0, SM_FORM2, 0); } if (_callback_wrapper (obj, true)) return 1; obj->image_sink = NULL; vcd_image_sink_destroy (image_sink); return 0; /* ok */ }} const char *vcd_version_string (bool full_text){ if (!full_text) return ("GNU VCDImager " VERSION " [" HOST_ARCH "]"); return ("%s (GNU VCDImager) " VERSION "\n" "Written by Herbert Valerio Riedel and Rocky Bernstein.\n" "\n" "http://www.gnu.org/software/vcdimager/\n" "\n" "Copyright (C) 2000-2003 Herbert Valerio Riedel <hvr@gnu.org>\n" " 2003 Rocky Bernstein <rocky@panix.com>\n" "\n
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -