📄 vcd.c
字号:
vcd_error ("directory section to big for a SVCD"); break; default: vcd_assert_not_reached (); } /* un-alloc small area */ _vcd_salloc_free (obj->iso_bitmap, 18, dirs_size + 2); /* alloc it again! */ _dict_insert (obj, "dir", 18, dirs_size, SM_EOR|SM_EOF); _dict_insert (obj, "ptl", 18 + dirs_size, 1, SM_EOR|SM_EOF); _dict_insert (obj, "ptm", 18 + dirs_size + 1, 1, SM_EOR|SM_EOF); }}static void_finalize_vcd_iso_track (VcdObj *obj){ _vcd_pbc_finalize (obj); _finalize_vcd_iso_track_allocation (obj); _finalize_vcd_iso_track_filesystem (obj);}static int_callback_wrapper (VcdObj *obj, int force){ const int cb_frequency = 75; if (obj->last_cb_call + cb_frequency > obj->sectors_written && !force) return 0; obj->last_cb_call = obj->sectors_written; if (obj->progress_callback) { progress_info_t _pi; _pi.sectors_written = obj->sectors_written; _pi.total_sectors = obj->relative_end_extent + obj->iso_size; _pi.in_track = obj->in_track; _pi.total_tracks = _cdio_list_length (obj->mpeg_sequence_list) + 1; return obj->progress_callback (&_pi, obj->callback_user_data); } else return 0;}static int_write_m2_image_sector (VcdObj *obj, const void *data, uint32_t extent, uint8_t fnum, uint8_t cnum, uint8_t sm, uint8_t ci) { char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, }; vcd_assert (extent == obj->sectors_written); _vcd_make_mode2(buf, data, extent, fnum, cnum, sm, ci); vcd_image_sink_write (obj->image_sink, buf, extent); obj->sectors_written++; return _callback_wrapper (obj, false);}static int_write_m2_raw_image_sector (VcdObj *obj, const void *data, uint32_t extent){ char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, }; vcd_assert (extent == obj->sectors_written); _vcd_make_raw_mode2(buf, data, extent); vcd_image_sink_write (obj->image_sink, buf, extent); obj->sectors_written++; return _callback_wrapper (obj, false);}static void_write_source_mode2_raw (VcdObj *obj, VcdDataSource *source, uint32_t extent){ int n; uint32_t sectors; sectors = vcd_data_source_stat (source) / M2RAW_SECTOR_SIZE; vcd_data_source_seek (source, 0); for (n = 0;n < sectors;n++) { char buf[M2RAW_SECTOR_SIZE] = { 0, }; vcd_data_source_read (source, buf, M2RAW_SECTOR_SIZE, 1); if (_write_m2_raw_image_sector (obj, buf, extent+n)) break; } vcd_data_source_close (source);}static void_write_source_mode2_form1 (VcdObj *obj, VcdDataSource *source, uint32_t extent){ int n; uint32_t sectors, size, last_block_size; size = vcd_data_source_stat (source); sectors = _vcd_len2blocks (size, CDIO_CD_FRAMESIZE); last_block_size = size % CDIO_CD_FRAMESIZE; if (!last_block_size) last_block_size = CDIO_CD_FRAMESIZE; vcd_data_source_seek (source, 0); for (n = 0;n < sectors;n++) { char buf[CDIO_CD_FRAMESIZE] = { 0, }; vcd_data_source_read (source, buf, ((n + 1 == sectors) ? last_block_size : CDIO_CD_FRAMESIZE), 1); if (_write_m2_image_sector (obj, buf, extent+n, 1, 0, ((n+1 < sectors) ? SM_DATA : SM_DATA |SM_EOF), 0)) break; } vcd_data_source_close (source);}static int_write_sequence (VcdObj *obj, int track_idx){ mpeg_sequence_t *track = _cdio_list_node_data (_vcd_list_at (obj->mpeg_sequence_list, track_idx)); CdioListNode *pause_node; int n, lastsect = obj->sectors_written; char buf[2324]; struct { int audio; int video; int zero; int ogt; int unknown; } mpeg_packets = {0, }; { char *norm_str = NULL; const struct vcd_mpeg_stream_vid_info *_info = &track->info->shdr[0]; switch (vcd_mpeg_get_norm (_info)) { case MPEG_NORM_PAL: norm_str = strdup ("PAL SIF (352x288/25fps)"); break; case MPEG_NORM_NTSC: norm_str = strdup ("NTSC SIF (352x240/29.97fps)"); break; case MPEG_NORM_FILM: norm_str = strdup ("FILM SIF (352x240/24fps)"); break; case MPEG_NORM_PAL_S: norm_str = strdup ("PAL 2/3 D1 (480x576/25fps)"); break; case MPEG_NORM_NTSC_S: norm_str = strdup ("NTSC 2/3 D1 (480x480/29.97fps)"); break; case MPEG_NORM_OTHER: { char buf[1024] = { 0, }; switch (_info->vsize) { case 480: case 240: snprintf (buf, sizeof (buf), "NTSC UNKNOWN (%dx%d/%2.2ffps)", _info->hsize, _info->vsize, _info->frate); break; case 288: case 576: snprintf (buf, sizeof (buf), "PAL UNKNOWN (%dx%d/%2.2ffps)", _info->hsize, _info->vsize, _info->frate); break; default: snprintf (buf, sizeof (buf), "UNKNOWN (%dx%d/%2.2ffps)", _info->hsize, _info->vsize, _info->frate); break; } norm_str = strdup (buf); } break; } { char buf[1024] = { 0, }, buf2[1024] = { 0, }; int i; for (i = 0; i < 3; i++) if (track->info->ahdr[i].seen) { const char *_mode_str[] = { 0, "stereo", "jstereo", "dual", "single", 0 }; snprintf (buf, sizeof (buf), "audio[%d]: l%d/%2.1fkHz/%dkbps/%s ", i, track->info->ahdr[i].layer, track->info->ahdr[i].sampfreq / 1000.0, track->info->ahdr[i].bitrate / 1024, _mode_str[track->info->ahdr[i].mode]); strncat (buf2, buf, sizeof(buf2) - strlen(buf2) - 1); } vcd_info ("writing track %d, %s, %s, %s...", track_idx + 2, (track->info->version == MPEG_VERS_MPEG1 ? "MPEG1" : "MPEG2"), norm_str, buf2); } free (norm_str); } for (n = 0; n < obj->track_pregap; n++) _write_m2_image_sector (obj, zero, lastsect++, 0, 0, SM_FORM2, 0); for (n = 0; n < obj->track_front_margin;n++) _write_m2_image_sector (obj, zero, lastsect++, track_idx + 1, 0, SM_FORM2|SM_REALT, 0); pause_node = _cdio_list_begin (track->pause_list); for (n = 0; n < track->info->packets; n++) { int ci = 0, sm = 0, cnum = 0, fnum = 0; struct vcd_mpeg_packet_info pkt_flags; bool set_trigger = false; vcd_mpeg_source_get_packet (track->source, n, buf, &pkt_flags, obj->update_scan_offsets); while (pause_node) { pause_t *_pause = _cdio_list_node_data (pause_node); if (!pkt_flags.has_pts) break; /* no pts */ if (pkt_flags.pts < _pause->time) break; /* our time has not come yet */ /* seems it's time to trigger! */ set_trigger = true; vcd_debug ("setting auto pause trigger for time %f (pts %f) @%d", _pause->time, pkt_flags.pts, n); pause_node = _cdio_list_node_next (pause_node); } switch (vcd_mpeg_packet_get_type (&pkt_flags)) { case PKT_TYPE_VIDEO: mpeg_packets.video++; sm = SM_FORM2|SM_REALT|SM_VIDEO; ci = CI_VIDEO; cnum = CN_VIDEO; break; case PKT_TYPE_OGT: mpeg_packets.ogt++; sm = SM_FORM2|SM_REALT|SM_VIDEO; ci = CI_OGT; cnum = CN_OGT; break; case PKT_TYPE_AUDIO: mpeg_packets.audio++; sm = SM_FORM2|SM_REALT|SM_AUDIO; ci = CI_AUDIO; cnum = CN_AUDIO; if (pkt_flags.audio[1] || pkt_flags.audio[2]) { ci = CI_AUDIO2; cnum = CN_AUDIO2; } break; case PKT_TYPE_ZERO: mpeg_packets.zero++; mpeg_packets.unknown--; case PKT_TYPE_EMPTY: mpeg_packets.unknown++; sm = SM_FORM2|SM_REALT; ci = CI_EMPTY; cnum = CN_EMPTY; break; case PKT_TYPE_INVALID: vcd_error ("invalid mpeg packet found at packet# %d" " -- please fix this mpeg file!", n); vcd_mpeg_source_close (track->source); return 1; break; default: vcd_assert_not_reached (); } if (n == track->info->packets - 1) { sm |= SM_EOR; if (!obj->track_rear_margin) /* if no rear margin... */ sm |= SM_EOF; } if (set_trigger) sm |= SM_TRIG; fnum = track_idx + 1; if (_vcd_obj_has_cap_p (obj, _CAP_4C_SVCD) && !obj->svcd_vcd3_mpegav) /* IEC62107 SVCDs have a simplified subheader */ { fnum = 1; ci = CI_MPEG2; } if (_write_m2_image_sector (obj, buf, lastsect++, fnum, cnum, sm, ci)) break; } vcd_mpeg_source_close (track->source); for (n = 0; n < obj->track_rear_margin; n++) { const uint8_t ci = 0, cnum = 0; uint8_t fnum = track_idx + 1; uint8_t sm = SM_FORM2 | SM_REALT; if (n + 1 == obj->track_rear_margin) sm |= SM_EOF; _write_m2_image_sector (obj, zero, lastsect++, fnum, cnum, sm, ci); } vcd_debug ("MPEG packet statistics: %d video, %d audio, %d zero, %d ogt, %d unknown", mpeg_packets.video, mpeg_packets.audio, mpeg_packets.zero, mpeg_packets.ogt, mpeg_packets.unknown); return 0;}static int_write_segment (VcdObj *obj, mpeg_segment_t *_segment){ CdioListNode *pause_node; unsigned packet_no; int n = obj->sectors_written; vcd_assert (_segment->start_extent == n); pause_node = _cdio_list_begin (_segment->pause_list); for (packet_no = 0; packet_no < (_segment->segment_count * VCDINFO_SEGMENT_SECTOR_SIZE); packet_no++) { uint8_t buf[M2F2_SECTOR_SIZE] = { 0, }; uint8_t fn, cn, sm, ci; if (packet_no < _segment->info->packets) { struct vcd_mpeg_packet_info pkt_flags; bool set_trigger = false; bool _need_eor = false; vcd_mpeg_source_get_packet (_segment->source, packet_no, buf, &pkt_flags, obj->update_scan_offsets); fn = 1; cn = CN_EMPTY; sm = SM_FORM2 | SM_REALT; ci = CI_EMPTY; while (pause_node) { pause_t *_pause = _cdio_list_node_data (pause_node); if (!pkt_flags.has_pts) break; /* no pts */ if (pkt_flags.pts < _pause->time) break; /* our time has not come yet */ /* seems it's time to trigger! */ set_trigger = true; vcd_debug ("setting auto pause trigger for time %f (pts %f) @%d", _pause->time, pkt_flags.pts, n); pause_node = _cdio_list_node_next (pause_node); } switch (vcd_mpeg_packet_get_type (&pkt_flags)) { case PKT_TYPE_VIDEO: sm = SM_FORM2 | SM_REALT | SM_VIDEO; ci = CI_VIDEO; cn = CN_VIDEO; if (pkt_flags.video[1]) ci = CI_STILL, cn = CN_STILL; else if (pkt_flags.video[2]) ci = CI_STILL2, cn = CN_STILL2; if (pkt_flags.video[1] || pkt_flags.video[2]) { /* search for endcode -- hack */ int idx; for (idx = 0; idx <= 2320; idx++) if (buf[idx] == 0x00 && buf[idx + 1] == 0x00 && buf[idx + 2] == 0x01 && buf[idx + 3] == 0xb7) { _need_eor = true; break; } } break; case PKT_TYPE_AUDIO: sm = SM_FORM2 | SM_REALT | SM_AUDIO; ci = CI_AUDIO; cn = CN_AUDIO; break; case PKT_TYPE_EMPTY: ci = CI_EMPTY; cn = CN_EMPTY; break; default: /* fixme -- check.... */ break; } if (_vcd_obj_has_cap_p (obj, _CAP_4C_SVCD)) { cn = 1; sm = SM_FORM2 | SM_REALT | SM_VIDEO; ci = CI_MPEG2; } if (packet_no + 1 == _segment->info->packets) sm |= SM_EOF; if (set_trigger) sm |= SM_TRIG; if (_need_eor) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -