📄 vcd.c
字号:
default: vcd_assert_not_reached (); break; } return 0;}intvcd_obj_add_dir (VcdObj *obj, const char iso_pathname[]){ char *_iso_pathname; vcd_assert (obj != NULL); vcd_assert (iso_pathname != NULL); _iso_pathname = _vcd_strdup_upper (iso_pathname); if (!iso9660_dirname_valid_p (_iso_pathname)) { vcd_error("pathname `%s' is not a valid iso pathname", _iso_pathname); free (_iso_pathname); return 1; } _cdio_list_append (obj->custom_dir_list, _iso_pathname); _vcd_list_sort (obj->custom_dir_list, (_cdio_list_cmp_func) strcmp); return 0;}intvcd_obj_add_file (VcdObj *obj, const char iso_pathname[], VcdDataSource *file, bool raw_flag){ uint32_t size = 0, sectors = 0; vcd_assert (obj != NULL); vcd_assert (file != NULL); vcd_assert (iso_pathname != NULL); vcd_assert (strlen (iso_pathname) > 0); vcd_assert (file != NULL); size = vcd_data_source_stat (file); /* close file to save file descriptors */ vcd_data_source_close (file); if (raw_flag) { if (!size) { vcd_error("raw mode2 file must not be empty\n"); return 1; } sectors = size / M2RAW_SECTOR_SIZE; if (size % M2RAW_SECTOR_SIZE) { vcd_error("raw mode2 file must have size multiple of %d \n", M2RAW_SECTOR_SIZE); return 1; } } else sectors = _vcd_len2blocks (size, CDIO_CD_FRAMESIZE); { custom_file_t *p; char *_iso_pathname = _vcd_strdup_upper (iso_pathname); if (!iso9660_pathname_valid_p (_iso_pathname)) { vcd_error("pathname `%s' is not a valid iso pathname", _iso_pathname); free (_iso_pathname); return 1; } p = _vcd_malloc (sizeof (custom_file_t)); p->file = file; p->iso_pathname = _iso_pathname; p->raw_flag = raw_flag; p->size = size; p->start_extent = 0; p->sectors = sectors; _cdio_list_append (obj->custom_file_list, p); } return 0;}static void_finalize_vcd_iso_track_allocation (VcdObj *obj){ int n; CdioListNode *node; uint32_t dir_secs = SECTOR_NIL; _dict_clean (obj); /* pre-alloc 16 blocks of ISO9660 required silence */ if (_vcd_salloc (obj->iso_bitmap, 0, 16) == SECTOR_NIL) vcd_assert_not_reached (); /* keep karaoke sectors blank -- well... guess I'm too paranoid :) */ if (_vcd_salloc (obj->iso_bitmap, 75, 75) == SECTOR_NIL) vcd_assert_not_reached (); /* pre-alloc descriptors, PVD */ _dict_insert (obj, "pvd", ISO_PVD_SECTOR, 1, SM_EOR); /* EOR */ /* EVD */ _dict_insert (obj, "evd", ISO_EVD_SECTOR, 1, SM_EOR|SM_EOF); /* EOR+EOF */ /* reserve for iso directory */ dir_secs = _vcd_salloc (obj->iso_bitmap, 18, 75-18); /* VCD information area */ _dict_insert (obj, "info", INFO_VCD_SECTOR, 1, SM_EOF); /* INFO.VCD */ /* EOF */ _dict_insert (obj, "entries", ENTRIES_VCD_SECTOR, 1, SM_EOF); /* ENTRIES.VCD */ /* EOF */ /* PBC */ if (_vcd_pbc_available (obj)) { _dict_insert (obj, "lot", LOT_VCD_SECTOR, LOT_VCD_SIZE, SM_EOF); /* LOT.VCD */ /* EOF */ _dict_insert (obj, "psd", PSD_VCD_SECTOR, _vcd_len2blocks (get_psd_size (obj, false), ISO_BLOCKSIZE), SM_EOF); /* PSD.VCD */ /* EOF */ } if (_vcd_obj_has_cap_p (obj, _CAP_4C_SVCD)) { _dict_insert (obj, "tracks", SECTOR_NIL, 1, SM_EOF); /* TRACKS.SVD */ _dict_insert (obj, "search", SECTOR_NIL, _vcd_len2blocks (get_search_dat_size (obj), ISO_BLOCKSIZE), SM_EOF); /* SEARCH.DAT */ vcd_assert (_dict_get_bykey (obj, "tracks")->sector > INFO_VCD_SECTOR); vcd_assert (_dict_get_bykey (obj, "search")->sector > INFO_VCD_SECTOR); } /* done with primary information area */ obj->mpeg_segment_start_extent = _vcd_len2blocks (_vcd_salloc_get_highest (obj->iso_bitmap) + 1, 75) * 75; /* salloc up to end of vcd sector */ for(n = 0;n < obj->mpeg_segment_start_extent;n++) _vcd_salloc (obj->iso_bitmap, n, 1); vcd_assert (_vcd_salloc_get_highest (obj->iso_bitmap) + 1 == obj->mpeg_segment_start_extent); /* insert segments */ _CDIO_LIST_FOREACH (node, obj->mpeg_segment_list) { mpeg_segment_t *_segment = _cdio_list_node_data (node); _segment->start_extent = _vcd_salloc (obj->iso_bitmap, SECTOR_NIL, _segment->segment_count * VCDINFO_SEGMENT_SECTOR_SIZE); vcd_assert (_segment->start_extent % 75 == 0); vcd_assert (_vcd_salloc_get_highest (obj->iso_bitmap) + 1 == _segment->start_extent + _segment->segment_count * VCDINFO_SEGMENT_SECTOR_SIZE); } obj->ext_file_start_extent = _vcd_salloc_get_highest (obj->iso_bitmap) + 1; vcd_assert (obj->ext_file_start_extent % 75 == 0); /* go on with EXT area */ if (_vcd_obj_has_cap_p (obj, _CAP_4C_SVCD)) { _dict_insert (obj, "scandata", SECTOR_NIL, _vcd_len2blocks (get_scandata_dat_size (obj), ISO_BLOCKSIZE), SM_EOF); } if (_vcd_obj_has_cap_p (obj, _CAP_PBC_X) &&_vcd_pbc_available (obj)) { _dict_insert (obj, "lot_x", SECTOR_NIL, LOT_VCD_SIZE, SM_EOF); _dict_insert (obj, "psd_x", SECTOR_NIL, _vcd_len2blocks (get_psd_size (obj, true), ISO_BLOCKSIZE), SM_EOF); } obj->custom_file_start_extent = _vcd_salloc_get_highest (obj->iso_bitmap) + 1; /* now for the custom files */ _CDIO_LIST_FOREACH (node, obj->custom_file_list) { custom_file_t *p = _cdio_list_node_data (node); if (p->sectors) { p->start_extent = _vcd_salloc(obj->iso_bitmap, SECTOR_NIL, p->sectors); vcd_assert (p->start_extent != SECTOR_NIL); } else /* zero sized files -- set dummy extent */ p->start_extent = obj->custom_file_start_extent; } /* calculate iso size -- after this point no sector shall be allocated anymore */ obj->iso_size = MAX (MIN_ISO_SIZE, _vcd_salloc_get_highest (obj->iso_bitmap) + 1); vcd_debug ("iso9660: highest alloced sector is %lu (using %d as isosize)", (unsigned long int) _vcd_salloc_get_highest (obj->iso_bitmap), obj->iso_size); /* after this point the ISO9660's size is frozen */}static void_finalize_vcd_iso_track_filesystem (VcdObj *obj){ int n; CdioListNode *node; /* create filesystem entries */ switch (obj->type) { case VCD_TYPE_VCD: case VCD_TYPE_VCD11: case VCD_TYPE_VCD2: /* add only necessary directories! */ /* _vcd_directory_mkdir (obj->dir, "CDDA"); */ /* _vcd_directory_mkdir (obj->dir, "CDI"); */ _vcd_directory_mkdir (obj->dir, "EXT"); /* _vcd_directory_mkdir (obj->dir, "KARAOKE"); */ _vcd_directory_mkdir (obj->dir, "MPEGAV"); _vcd_directory_mkdir (obj->dir, "VCD"); /* add segment dir only when there are actually segment play items */ if (_cdio_list_length (obj->mpeg_segment_list)) _vcd_directory_mkdir (obj->dir, "SEGMENT"); _vcd_directory_mkfile (obj->dir, "VCD/ENTRIES.VCD", _dict_get_bykey (obj, "entries")->sector, ISO_BLOCKSIZE, false, 0); _vcd_directory_mkfile (obj->dir, "VCD/INFO.VCD", _dict_get_bykey (obj, "info")->sector, ISO_BLOCKSIZE, false, 0); /* only for vcd2.0 */ if (_vcd_pbc_available (obj)) { _vcd_directory_mkfile (obj->dir, "VCD/LOT.VCD", _dict_get_bykey (obj, "lot")->sector, ISO_BLOCKSIZE*LOT_VCD_SIZE, false, 0); _vcd_directory_mkfile (obj->dir, "VCD/PSD.VCD", _dict_get_bykey (obj, "psd")->sector, get_psd_size (obj, false), false, 0); } break; case VCD_TYPE_SVCD: case VCD_TYPE_HQVCD: _vcd_directory_mkdir (obj->dir, "EXT"); if (!obj->svcd_vcd3_mpegav) _vcd_directory_mkdir (obj->dir, "MPEG2"); else { vcd_warn ("adding MPEGAV dir for *DEPRECATED* SVCD VCD30 mode"); _vcd_directory_mkdir (obj->dir, "MPEGAV"); } /* add segment dir only when there are actually segment play items */ if (_cdio_list_length (obj->mpeg_segment_list)) _vcd_directory_mkdir (obj->dir, "SEGMENT"); _vcd_directory_mkdir (obj->dir, "SVCD"); _vcd_directory_mkfile (obj->dir, "SVCD/ENTRIES.SVD", _dict_get_bykey (obj, "entries")->sector, ISO_BLOCKSIZE, false, 0); _vcd_directory_mkfile (obj->dir, "SVCD/INFO.SVD", _dict_get_bykey (obj, "info")->sector, ISO_BLOCKSIZE, false, 0); if (_vcd_pbc_available (obj)) { _vcd_directory_mkfile (obj->dir, "SVCD/LOT.SVD", _dict_get_bykey (obj, "lot")->sector, ISO_BLOCKSIZE*LOT_VCD_SIZE, false, 0); _vcd_directory_mkfile (obj->dir, "SVCD/PSD.SVD", _dict_get_bykey (obj, "psd")->sector, get_psd_size (obj, false), false, 0); } _vcd_directory_mkfile (obj->dir, "SVCD/SEARCH.DAT", _dict_get_bykey (obj, "search")->sector, get_search_dat_size (obj), false, 0); _vcd_directory_mkfile (obj->dir, "SVCD/TRACKS.SVD", _dict_get_bykey (obj, "tracks")->sector, ISO_BLOCKSIZE, false, 0); break; default: vcd_assert_not_reached (); break; } /* SEGMENTS */ n = 1; _CDIO_LIST_FOREACH (node, obj->mpeg_segment_list) { mpeg_segment_t *segment = _cdio_list_node_data (node); char segment_pathname[128] = { 0, }; const char *fmt = NULL; uint8_t fnum = 0; switch (obj->type) { case VCD_TYPE_VCD2: fmt = "SEGMENT/ITEM%4.4d.DAT"; fnum = 1; break; case VCD_TYPE_SVCD: case VCD_TYPE_HQVCD: fmt = "SEGMENT/ITEM%4.4d.MPG"; fnum = 0; break; default: vcd_assert_not_reached (); } snprintf (segment_pathname, sizeof (segment_pathname), fmt, n); _vcd_directory_mkfile (obj->dir, segment_pathname, segment->start_extent, segment->info->packets * ISO_BLOCKSIZE, true, fnum); vcd_assert (n <= MAX_SEGMENTS); n += segment->segment_count; } /* EXT files */ if (_vcd_obj_has_cap_p (obj, _CAP_PBC_X) &&_vcd_pbc_available (obj)) { /* psd_x -- extended PSD */ _vcd_directory_mkfile (obj->dir, "EXT/PSD_X.VCD", _dict_get_bykey (obj, "psd_x")->sector, get_psd_size (obj, true), false, 1); /* lot_x -- extended LOT */ _vcd_directory_mkfile (obj->dir, "EXT/LOT_X.VCD", _dict_get_bykey (obj, "lot_x")->sector, ISO_BLOCKSIZE*LOT_VCD_SIZE, false, 1); vcd_assert (obj->type == VCD_TYPE_VCD2); } if (_vcd_obj_has_cap_p (obj, _CAP_4C_SVCD)) { /* scandata.dat -- scanpoints */ _vcd_directory_mkfile (obj->dir, "EXT/SCANDATA.DAT", _dict_get_bykey (obj, "scandata")->sector, get_scandata_dat_size (obj), false, 0); } /* custom files/dirs */ _CDIO_LIST_FOREACH (node, obj->custom_dir_list) { char *p = _cdio_list_node_data (node); _vcd_directory_mkdir (obj->dir, p); } _CDIO_LIST_FOREACH (node, obj->custom_file_list) { custom_file_t *p = _cdio_list_node_data (node); _vcd_directory_mkfile (obj->dir, p->iso_pathname, p->start_extent, (p->raw_flag ? (ISO_BLOCKSIZE * (p->size / M2RAW_SECTOR_SIZE)) : p->size), p->raw_flag, 1); } n = 0; _CDIO_LIST_FOREACH (node, obj->mpeg_sequence_list) { char avseq_pathname[128] = { 0, }; const char *fmt = NULL; mpeg_sequence_t *_sequence = _cdio_list_node_data (node); uint32_t extent = _sequence->relative_start_extent; uint8_t file_num = 0; extent += obj->iso_size; switch (obj->type) { case VCD_TYPE_VCD: fmt = "MPEGAV/MUSIC%2.2d.DAT"; file_num = n + 1; break; case VCD_TYPE_VCD11: case VCD_TYPE_VCD2: fmt = "MPEGAV/AVSEQ%2.2d.DAT"; file_num = n + 1; break; case VCD_TYPE_SVCD: case VCD_TYPE_HQVCD: fmt = "MPEG2/AVSEQ%2.2d.MPG"; file_num = 0; /* if vcd3 compat mode, override */ if (obj->svcd_vcd3_mpegav) { fmt = "MPEGAV/AVSEQ%2.2d.MPG"; file_num = n + 1; } break; default: vcd_assert_not_reached (); } vcd_assert (n < 98); snprintf (avseq_pathname, sizeof (avseq_pathname), fmt, n + 1); /* file entry contains front margin, mpeg stream and rear margin */ _vcd_directory_mkfile (obj->dir, avseq_pathname, extent, (obj->track_front_margin + _sequence->info->packets + obj->track_rear_margin) * ISO_BLOCKSIZE, true, file_num); n++; } /* register isofs dir structures */ { uint32_t dirs_size = _vcd_directory_get_size (obj->dir); /* be sure to stay out of information areas */ switch (obj->type) { case VCD_TYPE_VCD: case VCD_TYPE_VCD11: case VCD_TYPE_VCD2: /* karaoke area starts at 03:00 */ if (16 + 2 + dirs_size + 2 >= 75) vcd_error ("directory section to big for a VCD"); break; case VCD_TYPE_SVCD: case VCD_TYPE_HQVCD: /* since no karaoke exists the next fixed area starts at 04:00 */ if (16 + 2 + dirs_size + 2 >= 150)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -