summaryrefslogtreecommitdiffstats
path: root/demux
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-03-01 13:20:33 +0100
committerwm4 <wm4@nowhere>2013-03-01 14:44:53 +0100
commit8ddfabc5354c82e931334658b60f22ecdb3ebb1b (patch)
tree251eb0c5d0a1a13c7763e834b47d1aeaca0547b2 /demux
parentc82a83d8afd98582e778cbf02a4ecc44e2d6399d (diff)
downloadmpv-8ddfabc5354c82e931334658b60f22ecdb3ebb1b.tar.bz2
mpv-8ddfabc5354c82e931334658b60f22ecdb3ebb1b.tar.xz
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).
Diffstat (limited to 'demux')
-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
4 files changed, 27 insertions, 4 deletions
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);