summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/mp_core.h1
-rw-r--r--core/mplayer.c17
-rw-r--r--demux/demux.h2
-rw-r--r--demux/demux_lavf.c21
-rw-r--r--demux/demux_mpg.c7
-rw-r--r--demux/demux_ts.c1
6 files changed, 39 insertions, 10 deletions
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);
diff --git a/demux/demux.h b/demux/demux.h
index 554730d59f..41551975cc 100644
--- a/demux/demux.h
+++ b/demux/demux.h
@@ -234,6 +234,8 @@ typedef struct demuxer {
/* Set if using absolute seeks for small movements is OK (no pts resets
* that would make pts ambigious, preferably supports back/forward flags */
bool accurate_seek;
+ // File format allows PTS resets (even if the current file is without)
+ bool ts_resets_possible;
enum timestamp_type timestamp_type;
bool warned_queue_overflow;
diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c
index 3312c27523..50f9f1e8f0 100644
--- a/demux/demux_lavf.c
+++ b/demux/demux_lavf.c
@@ -585,6 +585,8 @@ static demuxer_t *demux_open_lavf(demuxer_t *demuxer)
demuxer->video->id = -2; // audio-only / sub-only
}
+ demuxer->ts_resets_possible = priv->avif->flags & AVFMT_TS_DISCONT;
+
// disabled because unreliable per-stream bitrate values returned
// by libavformat trigger this heuristic incorrectly and break things
#if 0
@@ -713,16 +715,27 @@ static void demux_seek_lavf(demuxer_t *demuxer, float rel_seek_secs,
priv->last_pts = 0;
else if (rel_seek_secs < 0)
avsflags = AVSEEK_FLAG_BACKWARD;
+
if (flags & SEEK_FORWARD)
avsflags = 0;
else if (flags & SEEK_BACKWARD)
avsflags = AVSEEK_FLAG_BACKWARD;
+
if (flags & SEEK_FACTOR) {
- if (priv->avfc->duration == 0 || priv->avfc->duration == AV_NOPTS_VALUE)
- return;
- priv->last_pts += rel_seek_secs * priv->avfc->duration;
- } else
+ if (demuxer->movi_end > 0 && demuxer->ts_resets_possible &&
+ !(priv->avif->flags & AVFMT_NO_BYTE_SEEK))
+ {
+ avsflags |= AVSEEK_FLAG_BYTE;
+ priv->last_pts = (demuxer->movi_end - demuxer->movi_start) *
+ rel_seek_secs;
+ } else if (priv->avfc->duration != 0 &&
+ priv->avfc->duration != AV_NOPTS_VALUE)
+ {
+ priv->last_pts = rel_seek_secs * priv->avfc->duration;
+ }
+ } else {
priv->last_pts += rel_seek_secs * AV_TIME_BASE;
+ }
if (!priv->avfc->iformat->read_seek2) {
// Normal seeking.
diff --git a/demux/demux_mpg.c b/demux/demux_mpg.c
index ab157be748..52153b9a6a 100644
--- a/demux/demux_mpg.c
+++ b/demux/demux_mpg.c
@@ -1134,6 +1134,8 @@ static demuxer_t* demux_mpg_es_open(demuxer_t* demuxer)
demuxer->video->sh = new_sh_video(demuxer,0); // create dummy video stream header, id=0
sh_video=demuxer->video->sh;sh_video->ds=demuxer->video;
+ demuxer->ts_resets_possible = true;
+
return demuxer;
}
@@ -1142,6 +1144,9 @@ static demuxer_t *demux_mpg_gxf_open(demuxer_t *demuxer) {
demuxer->video->sh = new_sh_video(demuxer,0);
((sh_video_t *)demuxer->video->sh)->ds = demuxer->video;
demuxer->priv = (void *) 0xffffffff;
+
+ demuxer->ts_resets_possible = true;
+
return demuxer;
}
@@ -1152,6 +1157,8 @@ static demuxer_t* demux_mpg_ps_open(demuxer_t* demuxer)
sh_video=demuxer->video->sh;sh_video->ds=demuxer->video;
+ demuxer->ts_resets_possible = true;
+
if(demuxer->audio->id!=-2) {
if(!ds_fill_buffer(demuxer->audio)){
mp_msg(MSGT_DEMUXER, MSGL_INFO, "MPEG: %s",
diff --git a/demux/demux_ts.c b/demux/demux_ts.c
index 5fe4d2e09c..42da41d532 100644
--- a/demux/demux_ts.c
+++ b/demux/demux_ts.c
@@ -990,6 +990,7 @@ static demuxer_t *demux_open_ts(demuxer_t * demuxer)
demuxer->type= DEMUXER_TYPE_MPEG_TS;
+ demuxer->ts_resets_possible = true;
stream_reset(demuxer->stream);