diff --git a/core/mplayer.c b/core/mplayer.c index 4eb4ff0e23..81302f284f 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -439,6 +439,23 @@ static void print_file_properties(struct MPContext *mpctx, const char *filename) /// step size of mixer changes int volstep = 3; +// Time used to seek external tracks to. +static double get_main_demux_pts(struct MPContext *mpctx) +{ + double main_new_pos = MP_NOPTS_VALUE; + if (mpctx->demuxer) { + for (int type = 0; type < STREAM_TYPE_COUNT; type++) { + struct demux_stream *ds = mpctx->demuxer->ds[type]; + if (ds->sh && main_new_pos == MP_NOPTS_VALUE) { + demux_fill_buffer(mpctx->demuxer, ds); + if (ds->first) + main_new_pos = ds->first->pts; + } + } + } + return main_new_pos; +} + static void set_demux_field(struct MPContext *mpctx, enum stream_type type, struct sh_stream *s) { @@ -456,8 +473,13 @@ static void init_demux_stream(struct MPContext *mpctx, enum stream_type type) struct track *track = mpctx->current_track[type]; set_demux_field(mpctx, type, track ? track->stream : NULL); struct sh_stream *stream = mpctx->sh[type]; - if (stream) + if (stream) { demuxer_switch_track(stream->demuxer, type, stream); + if (track->is_external) { + double pts = get_main_demux_pts(mpctx); + demux_seek(stream->demuxer, pts, audio_delay, SEEK_ABSOLUTE); + } + } } static void cleanup_demux_stream(struct MPContext *mpctx, enum stream_type type) @@ -2863,18 +2885,12 @@ static int seek(MPContext *mpctx, struct seek_params seek, have_external_tracks |= track && track->is_external && track->demuxer; } if (have_external_tracks) { - double main_new_pos = MP_NOPTS_VALUE; - if (seek.type == MPSEEK_ABSOLUTE) + double main_new_pos; + if (seek.type == MPSEEK_ABSOLUTE) { main_new_pos = seek.amount - mpctx->video_offset; - for (int type = 0; type < STREAM_TYPE_COUNT; type++) { - struct demux_stream *ds = mpctx->demuxer->ds[type]; - if (ds->sh && main_new_pos == MP_NOPTS_VALUE) { - demux_fill_buffer(mpctx->demuxer, ds); - if (ds->first) - main_new_pos = ds->first->pts; - } + } else { + main_new_pos = get_main_demux_pts(mpctx); } - assert(main_new_pos != MP_NOPTS_VALUE); for (int type = 0; type < STREAM_TYPE_COUNT; type++) { struct track *track = mpctx->current_track[type]; if (track && track->is_external && track->demuxer) diff --git a/demux/demux.c b/demux/demux.c index 82159057d8..f765b2ae87 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -1077,6 +1077,10 @@ int demux_seek(demuxer_t *demuxer, float rel_seek_secs, float audio_delay, mp_tmsg(MSGT_SEEK, MSGL_WARN, "Cannot seek in this file.\n"); return 0; } + + if (rel_seek_secs == MP_NOPTS_VALUE && (flags & SEEK_ABSOLUTE)) + return 0; + // clear demux buffers: demux_flush(demuxer); demuxer->video->eof = 0; diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c index c1c15f345a..42b687dc20 100644 --- a/demux/demux_lavf.c +++ b/demux/demux_lavf.c @@ -886,9 +886,17 @@ static void demux_seek_lavf(demuxer_t *demuxer, float rel_seek_secs, priv->last_pts += rel_seek_secs * priv->avfc->duration; } else priv->last_pts += rel_seek_secs * AV_TIME_BASE; - if (av_seek_frame(priv->avfc, -1, priv->last_pts, avsflags) < 0) { - avsflags ^= AVSEEK_FLAG_BACKWARD; + + if (!priv->avfc->iformat->read_seek2) { + // Normal seeking. av_seek_frame(priv->avfc, -1, priv->last_pts, avsflags); + } else { + // av_seek_frame() won't work. Use "new" seeking API. We don't use this + // API by default, because there are some major issues. + // Set max_ts==ts, so that demuxing starts from an earlier position in + // the worst case. + avformat_seek_file(priv->avfc, -1, INT64_MIN, + priv->last_pts, priv->last_pts, avsflags); } }