diff options
author | Uoti Urpala <uau@glyph.nonexistent.invalid> | 2009-03-19 05:25:12 +0200 |
---|---|---|
committer | Uoti Urpala <uau@glyph.nonexistent.invalid> | 2009-03-24 04:05:04 +0200 |
commit | 73fb23c1cfc40a9e0683f0a82cb1a669005eaa67 (patch) | |
tree | a67ac6e34674e8466149b2f15743171c08a8d7ee /libmpdemux/demux_mkv.c | |
parent | 327940361170a4d830bc7c120503cdd0396a125a (diff) | |
download | mpv-73fb23c1cfc40a9e0683f0a82cb1a669005eaa67.tar.bz2 mpv-73fb23c1cfc40a9e0683f0a82cb1a669005eaa67.tar.xz |
Add improved relative seek mode
When the new mode is active relative seeks are converted to absolute
ones (current video pts + relative seek amount) and forward/backward
flag before being sent to the demuxer. This mode is used if the
demuxer has set the accurate_seek field in the demuxer struct and
there is a video stream. At the moment the mkv and lavf demuxers
enable the flag.
This change is useful for later Matroska ordered chapter support (and
for more general timelime editing), but also fixes problems in
existing functionality. The main problem with the old mode, where
relative seeks are passed directly to the demuxer, is that the user
wants to seek relative to the currently displayed position but the
demuxer does not know what that position is. There can be an arbitrary
amount of buffering between the demuxer read position and what is
displayed on the screen. In some situations this makes small seeks
fail to move backward at all (especially visible at high playback
speed, when audio needs to be demuxed and decoded further ahead to
fill the output buffers after resampling).
Some container formats that can be used with the lavf demuxer do not
always have reliable timestamps that could be used for unambiguous
absolute seeking. However I made the demuxer always enable the new
mode because it already converted all seeks to absolute ones before
sending them to libavformat, so cases without reliable absolute seeks
were failing already and this should only improve the working cases.
Diffstat (limited to 'libmpdemux/demux_mkv.c')
-rw-r--r-- | libmpdemux/demux_mkv.c | 24 |
1 files changed, 17 insertions, 7 deletions
diff --git a/libmpdemux/demux_mkv.c b/libmpdemux/demux_mkv.c index 8f8a53e6da..ac10a41cb0 100644 --- a/libmpdemux/demux_mkv.c +++ b/libmpdemux/demux_mkv.c @@ -2295,6 +2295,8 @@ demux_mkv_open (demuxer_t *demuxer) demuxer->seekable = 1; } + demuxer->accurate_seek = true; + return DEMUXER_TYPE_MATROSKA; } @@ -2962,6 +2964,12 @@ demux_mkv_fill_buffer (demuxer_t *demuxer, demux_stream_t *ds) static void demux_mkv_seek (demuxer_t *demuxer, float rel_seek_secs, float audio_delay, int flags) { + if (!(flags & (SEEK_BACKWARD | SEEK_FORWARD))) { + if (flags & SEEK_ABSOLUTE || rel_seek_secs < 0) + flags |= SEEK_BACKWARD; + else + flags |= SEEK_FORWARD; + } free_cached_dps (demuxer); if (!(flags & SEEK_FACTOR)) /* time in secs */ { @@ -3016,12 +3024,12 @@ demux_mkv_seek (demuxer_t *demuxer, float rel_seek_secs, float audio_delay, int for (i=0; i < mkv_d->num_cluster_pos; i++) { diff = mkv_d->cluster_positions[i] - target_filepos; - if (rel_seek_secs < 0 && diff < 0 && -diff < min_diff) + if (flags & SEEK_BACKWARD && diff < 0 && -diff < min_diff) { cluster_pos = mkv_d->cluster_positions[i]; min_diff = -diff; } - else if (rel_seek_secs > 0 + else if (flags & SEEK_FORWARD && (diff < 0 ? -1 * diff : diff) < min_diff) { cluster_pos = mkv_d->cluster_positions[i]; @@ -3045,14 +3053,14 @@ demux_mkv_seek (demuxer_t *demuxer, float rel_seek_secs, float audio_delay, int diff = target_timecode + mkv_d->first_tc - (int64_t) mkv_d->indexes[i].timecode * mkv_d->tc_scale / 1000000.0; - if ((flags & SEEK_ABSOLUTE || target_timecode <= mkv_d->last_pts*1000)) { - // Absolute seek or seek backward: find the last index - // position before target time + if (flags & SEEK_BACKWARD) { + // Seek backward: find the last index position + // before target time if (diff < 0 || diff >= min_diff) continue; } else { - // Relative seek forward: find the first index position + // Seek forward: find the first index position // after target time. If no such index exists, find last // position between current position and target time. if (diff <= 0) { @@ -3076,8 +3084,10 @@ demux_mkv_seek (demuxer_t *demuxer, float rel_seek_secs, float audio_delay, int if (demuxer->video->id >= 0) mkv_d->v_skip_to_keyframe = 1; - if (rel_seek_secs > 0.0) + if (flags & SEEK_FORWARD) mkv_d->skip_to_timecode = target_timecode; + else + mkv_d->skip_to_timecode = 0; mkv_d->a_skip_to_keyframe = 1; demux_mkv_fill_buffer(demuxer, NULL); |