From 8ddfabc5354c82e931334658b60f22ecdb3ebb1b Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 1 Mar 2013 13:20:33 +0100 Subject: core: fix SEEK_FACTOR Emulate percentage-seeks (SEEK_FACTOR) as normal time-seeks if possible. This fixes some issues with (let's call it) low quality implementations of SEEK_FACTOR (e.g. demux_mkv basically interprets this as byte-seek, and also seeking to 99.9% makes it seek back to the start). For weird MPEG formats the demuxer level SEEK_FACTOR is still used. These formats, which can have timestamp resets, are identified by setting demuxer->ts_resets_possible to true. Also, have get_current_pos_ratio() follow the same rules, and calculate the percentage position with the file position if timestamp resets are possible. This actually fixes percentage-seeks in .ts files with demux_lavf.c. This kind of seek is not really used now, but it will be more important when we add a progress bar. Note: seeking in chained ogg files is still completely broken. The main issue is that ffmpeg doesn't provide a sane API for dealing with timestamp resets, and trying to do byte seeks with ogg confuses demuxer and decoder (or something like this) and just does random things. (Tested with two concatenated flac-in-ogg files). --- core/mp_core.h | 1 + core/mplayer.c | 17 +++++++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) (limited to 'core') diff --git a/core/mp_core.h b/core/mp_core.h index 25482ac3ef..58d6bb4791 100644 --- a/core/mp_core.h +++ b/core/mp_core.h @@ -280,6 +280,7 @@ void queue_seek(struct MPContext *mpctx, enum seek_type type, double amount, int exact); int seek_chapter(struct MPContext *mpctx, int chapter, double *seek_pts); double get_time_length(struct MPContext *mpctx); +double get_start_time(struct MPContext *mpctx); double get_current_time(struct MPContext *mpctx); int get_percent_pos(struct MPContext *mpctx); double get_current_pos_ratio(struct MPContext *mpctx); diff --git a/core/mplayer.c b/core/mplayer.c index 78de39cce7..6e0256fbaa 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -2769,9 +2769,12 @@ static int seek(MPContext *mpctx, struct seek_params seek, && seek.amount < mpctx->last_chapter_pts || seek.amount < 0) mpctx->last_chapter_seek = -2; - if (mpctx->timeline && seek.type == MPSEEK_FACTOR) { - seek.amount *= mpctx->timeline[mpctx->num_timeline_parts].start; - seek.type = MPSEEK_ABSOLUTE; + if (seek.type == MPSEEK_FACTOR) { + double len = get_time_length(mpctx); + if (len > 0 && !mpctx->demuxer->ts_resets_possible) { + seek.amount = seek.amount * len + get_start_time(mpctx); + seek.type = MPSEEK_ABSOLUTE; + } } if ((mpctx->demuxer->accurate_seek || mpctx->timeline) && seek.type == MPSEEK_RELATIVE) { @@ -2807,9 +2810,11 @@ static int seek(MPContext *mpctx, struct seek_params seek, int demuxer_style = 0; switch (seek.type) { case MPSEEK_FACTOR: - demuxer_style |= SEEK_FACTOR; // fallthrough + demuxer_style |= SEEK_ABSOLUTE | SEEK_FACTOR; + break; case MPSEEK_ABSOLUTE: demuxer_style |= SEEK_ABSOLUTE; + break; } if (hr_seek || seek.direction < 0) demuxer_style |= SEEK_BACKWARD; @@ -2970,7 +2975,7 @@ double get_current_time(struct MPContext *mpctx) return 0; } -static double get_start_time(struct MPContext *mpctx) +double get_start_time(struct MPContext *mpctx) { struct demuxer *demuxer = mpctx->demuxer; if (!demuxer) @@ -2990,7 +2995,7 @@ double get_current_pos_ratio(struct MPContext *mpctx) double start = get_start_time(mpctx); double len = get_time_length(mpctx); double pos = get_current_time(mpctx); - if (len > 0) { + if (len > 0 && !demuxer->ts_resets_possible) { ans = av_clipf((pos - start) / len, 0, 1); } else { int len = (demuxer->movi_end - demuxer->movi_start); -- cgit v1.2.3