From 304cafd31dfaeee853e138a460b7ba82e65ed420 Mon Sep 17 00:00:00 2001 From: Uoti Urpala Date: Mon, 24 Jan 2011 00:29:01 +0200 Subject: demux_mkv, chapters: change millisecond arithmetic to ns demux_mkv kept various integer timestamps in millisecond units. Matroska timestamp arithmetic is however specified in nanoseconds (even though files typically use 1 ms precision), and using ms units instead of that only made things more complex. Based on the demux_mkv example the general demuxer-level chapter structure also used ms units. Change the demux_mkv arithmetic and demuxer chapter structures to use nanoseconds instead. This also fixes a seeking problem in demux_mkv with files using a TimecodeScale other than the usual 1000000 (confusion between ms and TimecodeScale*ns units). --- libmpdemux/demux_lavf.c | 4 ++-- libmpdemux/demux_mkv.c | 58 +++++++++++++++++++++++-------------------------- libmpdemux/demuxer.c | 12 +++++----- mplayer.c | 13 ++++++----- 4 files changed, 42 insertions(+), 45 deletions(-) diff --git a/libmpdemux/demux_lavf.c b/libmpdemux/demux_lavf.c index 03ffa17c43..c84a17e4e3 100644 --- a/libmpdemux/demux_lavf.c +++ b/libmpdemux/demux_lavf.c @@ -588,8 +588,8 @@ static demuxer_t* demux_open_lavf(demuxer_t *demuxer){ for(i=0; i < avfc->nb_chapters; i++) { AVChapter *c = avfc->chapters[i]; - uint64_t start = av_rescale_q(c->start, c->time_base, (AVRational){1,1000}); - uint64_t end = av_rescale_q(c->end, c->time_base, (AVRational){1,1000}); + uint64_t start = av_rescale_q(c->start, c->time_base, (AVRational){1,1000000000}); + uint64_t end = av_rescale_q(c->end, c->time_base, (AVRational){1,1000000000}); t = av_metadata_get(c->metadata, "title", NULL, 0); demuxer_add_chapter(demuxer, t ? BSTR(t->value) : BSTR(NULL), start, end); } diff --git a/libmpdemux/demux_mkv.c b/libmpdemux/demux_mkv.c index b75f07fd67..499c664360 100644 --- a/libmpdemux/demux_mkv.c +++ b/libmpdemux/demux_mkv.c @@ -184,7 +184,7 @@ typedef struct mkv_demuxer { } *cluster_positions; int num_cluster_pos; - int64_t skip_to_timecode; + uint64_t skip_to_timecode; int v_skip_to_keyframe, a_skip_to_keyframe; int num_audio_tracks; @@ -786,8 +786,8 @@ static int demux_mkv_read_chapters(struct demuxer *demuxer) if (!ca->n_chapter_time_start) mp_msg(MSGT_DEMUX, warn_level, "[mkv] Chapter lacks start time\n"); - chapter.start = ca->chapter_time_start / 1000000; - chapter.end = ca->chapter_time_end / 1000000; + chapter.start = ca->chapter_time_start; + chapter.end = ca->chapter_time_end; if (ca->n_chapter_display) { if (ca->n_chapter_display > 1) @@ -824,14 +824,14 @@ static int demux_mkv_read_chapters(struct demuxer *demuxer) mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] Chapter %u from %02d:%02d:%02d.%03d " "to %02d:%02d:%02d.%03d, %.*s\n", i, - (int) (chapter.start / 60 / 60 / 1000), - (int) ((chapter.start / 60 / 1000) % 60), - (int) ((chapter.start / 1000) % 60), - (int) (chapter.start % 1000), - (int) (chapter.end / 60 / 60 / 1000), - (int) ((chapter.end / 60 / 1000) % 60), - (int) ((chapter.end / 1000) % 60), - (int) (chapter.end % 1000), + (int) (chapter.start / 60 / 60 / 1000000000), + (int) ((chapter.start / 60 / 1000000000) % 60), + (int) ((chapter.start / 1000000000) % 60), + (int) (chapter.start % 1000000000), + (int) (chapter.end / 60 / 60 / 1000000000), + (int) ((chapter.end / 60 / 1000000000) % 60), + (int) ((chapter.end / 1000000000) % 60), + (int) (chapter.end % 1000000000), BSTR_P(name)); if (idx == selected_edition){ @@ -1883,13 +1883,13 @@ static void handle_subtitles(demuxer_t *demuxer, mkv_track_t *track, sub_utf8 = 1; dp = new_demux_packet(size); memcpy(dp->buffer, block, size); - dp->pts = timecode / 1000.0; - dp->duration = block_duration / 1000.0; + dp->pts = timecode / 1e9; + dp->duration = block_duration / 1e9; ds_add_packet(demuxer->sub, dp); } static void handle_realvideo(demuxer_t *demuxer, mkv_track_t *track, - uint8_t *buffer, uint32_t size, int block_bref) + uint8_t *buffer, uint32_t size, int64_t block_bref) { mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; demux_packet_t *dp; @@ -1915,7 +1915,7 @@ static void handle_realvideo(demuxer_t *demuxer, mkv_track_t *track, } static void handle_realaudio(demuxer_t *demuxer, mkv_track_t *track, - uint8_t *buffer, uint32_t size, int block_bref) + uint8_t *buffer, uint32_t size, int64_t block_bref) { mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; int sps = track->sub_packet_size; @@ -2028,7 +2028,7 @@ static int handle_block(demuxer_t *demuxer, uint8_t *block, uint64_t length, mkv_track_t *track = NULL; demux_stream_t *ds = NULL; uint64_t old_length; - int64_t tc; + uint64_t tc; uint32_t *lace_size; uint8_t laces, flags; int i, num, tmp, use_this_block = 1; @@ -2048,10 +2048,8 @@ static int handle_block(demuxer_t *demuxer, uint8_t *block, uint64_t length, return 0; block += old_length - length; - tc = (time * mkv_d->tc_scale + mkv_d->cluster_tc) / 1000000.0 + 0.5; - if (tc < 0) - tc = 0; - current_pts = tc / 1000.0; + tc = time * mkv_d->tc_scale + mkv_d->cluster_tc; + current_pts = tc / 1e9; for (i = 0; i < mkv_d->num_tracks; i++) if (mkv_d->tracks[i]->tnum == num) { @@ -2080,7 +2078,7 @@ static int handle_block(demuxer_t *demuxer, uint8_t *block, uint64_t length, sh_audio_t *sh = (sh_audio_t *) ds->sh; if (block_duration != 0) { - sh->i_bps = length * 1000 / block_duration; + sh->i_bps = length * 1e9 / block_duration; track->fix_i_bps = 0; } else if (track->qt_last_a_pts == 0.0) track->qt_last_a_pts = current_pts; @@ -2186,8 +2184,7 @@ static int demux_mkv_fill_buffer(demuxer_t *demuxer, demux_stream_t *ds) free(block); return 0; } - block_duration = - block_duration * mkv_d->tc_scale / 1000000.0 + 0.5; + block_duration *= mkv_d->tc_scale; break; case MATROSKA_ID_BLOCK: @@ -2387,7 +2384,7 @@ static struct mkv_index *seek_with_cues(struct demuxer *demuxer, int seek_id, * target time after the last entry - then still seek to the first/last * entry if that's further in the direction wanted than mkv_d->last_pts. */ - int64_t min_diff = target_timecode - mkv_d->last_pts * 1000; + int64_t min_diff = target_timecode - (int64_t)(mkv_d->last_pts * 1e9 + 0.5); if (flags & SEEK_BACKWARD) min_diff = -min_diff; min_diff = FFMAX(min_diff, 1); @@ -2395,8 +2392,7 @@ static struct mkv_index *seek_with_cues(struct demuxer *demuxer, int seek_id, if (seek_id < 0 || mkv_d->indexes[i].tnum == seek_id) { int64_t diff = target_timecode - - (int64_t) (mkv_d->indexes[i].timecode * - mkv_d->tc_scale / 1000000.0 + 0.5); + (int64_t) (mkv_d->indexes[i].timecode * mkv_d->tc_scale); if (flags & SEEK_BACKWARD) diff = -diff; if (diff <= 0) { @@ -2442,9 +2438,8 @@ static void demux_mkv_seek(demuxer_t *demuxer, float rel_seek_secs, if (!(flags & SEEK_ABSOLUTE)) /* relative seek */ rel_seek_secs += mkv_d->last_pts; - int64_t target_timecode = rel_seek_secs * 1000.0; - if (target_timecode < 0) - target_timecode = 0; + rel_seek_secs = FFMAX(rel_seek_secs, 0); + int64_t target_timecode = rel_seek_secs * 1e9 + 0.5; if (mkv_d->indexes == NULL) { /* no index was found */ if (seek_creating_index(demuxer, rel_seek_secs, flags) < 0) @@ -2462,7 +2457,8 @@ static void demux_mkv_seek(demuxer_t *demuxer, float rel_seek_secs, if (flags & SEEK_FORWARD) mkv_d->skip_to_timecode = target_timecode; else - mkv_d->skip_to_timecode = index ? index->timecode : 0; + mkv_d->skip_to_timecode = index ? index->timecode * mkv_d->tc_scale + : 0; mkv_d->a_skip_to_keyframe = 1; demux_mkv_fill_buffer(demuxer, NULL); @@ -2496,7 +2492,7 @@ static void demux_mkv_seek(demuxer_t *demuxer, float rel_seek_secs, if (demuxer->video->id >= 0) mkv_d->v_skip_to_keyframe = 1; - mkv_d->skip_to_timecode = index->timecode; + mkv_d->skip_to_timecode = index->timecode * mkv_d->tc_scale; mkv_d->a_skip_to_keyframe = 1; demux_mkv_fill_buffer(demuxer, NULL); diff --git a/libmpdemux/demuxer.c b/libmpdemux/demuxer.c index eb548d4614..098c631631 100644 --- a/libmpdemux/demuxer.c +++ b/libmpdemux/demuxer.c @@ -1316,9 +1316,9 @@ int demuxer_add_chapter(demuxer_t *demuxer, struct bstr name, talloc_strdup(demuxer->chapters, mp_gtext("unknown")); mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_CHAPTER_ID=%d\n", demuxer->num_chapters); - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_CHAPTER_%d_START=%"PRIu64"\n", demuxer->num_chapters, start); + mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_CHAPTER_%d_START=%"PRIu64"\n", demuxer->num_chapters, start / 1000000); if (end) - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_CHAPTER_%d_END=%"PRIu64"\n", demuxer->num_chapters, end); + mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_CHAPTER_%d_END=%"PRIu64"\n", demuxer->num_chapters, end / 1000000); if (name.start) mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_CHAPTER_%d_NAME=%.*s\n", demuxer->num_chapters, BSTR_P(name)); @@ -1371,7 +1371,7 @@ int demuxer_seek_chapter(demuxer_t *demuxer, int chapter, double *seek_pts, if (chapter < 0) chapter = 0; - *seek_pts = demuxer->chapters[chapter].start / 1000.0; + *seek_pts = demuxer->chapters[chapter].start / 1e9; if (chapter_name) *chapter_name = talloc_strdup(NULL, demuxer->chapters[chapter].name); @@ -1388,7 +1388,7 @@ int demuxer_get_current_chapter(demuxer_t *demuxer, double time_now) &chapter) == STREAM_UNSUPPORTED) chapter = -2; } else { - uint64_t now = time_now * 1000 + 0.5; + uint64_t now = time_now * 1e9 + 0.5; for (chapter = demuxer->num_chapters - 1; chapter >= 0; --chapter) { if (demuxer->chapters[chapter].start <= now) break; @@ -1431,8 +1431,8 @@ float demuxer_chapter_time(demuxer_t *demuxer, int chapter, float *end) if (demuxer->num_chapters && demuxer->chapters && chapter >= 0 && chapter < demuxer->num_chapters) { if (end) - *end = demuxer->chapters[chapter].end / 1000.0; - return demuxer->chapters[chapter].start / 1000.0; + *end = demuxer->chapters[chapter].end / 1e9; + return demuxer->chapters[chapter].start / 1e9; } return -1.0; } diff --git a/mplayer.c b/mplayer.c index a72b014349..1d8b74892c 100644 --- a/mplayer.c +++ b/mplayer.c @@ -3734,11 +3734,12 @@ static void build_ordered_chapter_timeline(struct MPContext *mpctx) * specify chapter end times that are one frame too early; * we don't want to try seeking over a one frame gap. */ int64_t join_diff = c->start - starttime - prev_part_offset; - if (part_count == 0 || FFABS(join_diff) > opts->chapter_merge_threshold + if (part_count == 0 + || FFABS(join_diff) > opts->chapter_merge_threshold * 1000000 || sources + j != timeline[part_count - 1].source) { timeline[part_count].source = sources + j; - timeline[part_count].start = starttime / 1000.; - timeline[part_count].source_start = c->start / 1000.; + timeline[part_count].start = starttime / 1e9; + timeline[part_count].source_start = c->start / 1e9; prev_part_offset = c->start - starttime; part_count++; } else if (part_count > 0 && join_diff) { @@ -3748,12 +3749,12 @@ static void build_ordered_chapter_timeline(struct MPContext *mpctx) "offset %d ms.\n", i, (int) join_diff); starttime += join_diff; } - chapters[num_chapters].start = starttime / 1000.; + chapters[num_chapters].start = starttime / 1e9; chapters[num_chapters].name = talloc_strdup(chapters, c->name); starttime += c->end - c->start; num_chapters++; } - timeline[part_count].start = starttime / 1000.; + timeline[part_count].start = starttime / 1e9; if (!part_count) { // None of the parts come from the file itself??? @@ -3768,7 +3769,7 @@ static void build_ordered_chapter_timeline(struct MPContext *mpctx) timeline[part_count].start); if (missing_time) mp_msg(MSGT_CPLAYER, MSGL_ERR, "There are %.3f seconds missing " - "from the timeline!\n", missing_time / 1000.); + "from the timeline!\n", missing_time / 1e9); mp_msg(MSGT_CPLAYER, MSGL_V, "Source files:\n"); for (int i = 0; i < num_sources; i++) mp_msg(MSGT_CPLAYER, MSGL_V, "%d: %s\n", i, -- cgit v1.2.3