From 6856d81c6826e9698fe0154903f509d5a82917bb Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 30 Jul 2014 02:21:35 +0200 Subject: stream: hack-fix rtmp-level seeking This didn't work, because the timebase was wrong. According to the ffmpeg doxygen, if the stream index is -1 (which is what we used), the timebase is AV_TIME_BASE. But this didn't work, and it really expected the stream's timebase. Quite "surprising", since this feature (avio_seek_time) is used by rtmp only. Fixing this properly is too hard, so hack-fix our way around it. STREAM_CTRL_SEEK_TO_TIME is also used by DVD/BD, so a new STREAM_CTRL_AVSEEK is added. We simply pass-through the request verbatim. --- demux/demux_lavf.c | 11 +++++++---- stream/cache.c | 1 + stream/stream.h | 8 ++++++++ stream/stream_lavf.c | 13 ++++++------- 4 files changed, 22 insertions(+), 11 deletions(-) diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c index 9a44e9ac35..41263ceabf 100644 --- a/demux/demux_lavf.c +++ b/demux/demux_lavf.c @@ -183,11 +183,14 @@ static int64_t mp_read_seek(void *opaque, int stream_idx, int64_t ts, int flags) { struct demuxer *demuxer = opaque; struct stream *stream = demuxer->stream; - struct lavf_priv *priv = demuxer->priv; - AVStream *st = priv->avfc->streams[stream_idx]; - double pts = (double)ts * st->time_base.num / st->time_base.den; - int ret = stream_control(stream, STREAM_CTRL_SEEK_TO_TIME, &pts); + struct stream_avseek cmd = { + .stream_index = stream_idx, + .timestamp = ts, + .flags = flags, + }; + + int ret = stream_control(stream, STREAM_CTRL_AVSEEK, &cmd); return ret < 1 ? AVERROR(ENOSYS) : 0; } diff --git a/stream/cache.c b/stream/cache.c index b1b3c9301f..6bd729c6fa 100644 --- a/stream/cache.c +++ b/stream/cache.c @@ -412,6 +412,7 @@ static bool control_needs_flush(int stream_ctrl) { switch (stream_ctrl) { case STREAM_CTRL_SEEK_TO_TIME: + case STREAM_CTRL_AVSEEK: case STREAM_CTRL_SET_ANGLE: case STREAM_CTRL_SET_CURRENT_TITLE: return true; diff --git a/stream/stream.h b/stream/stream.h index 344e8b55ef..2cd3d9f5fa 100644 --- a/stream/stream.h +++ b/stream/stream.h @@ -101,6 +101,7 @@ enum stream_ctrl { STREAM_CTRL_TV_LAST_CHAN, STREAM_CTRL_DVB_SET_CHANNEL, STREAM_CTRL_DVB_STEP_CHANNEL, + STREAM_CTRL_AVSEEK, }; struct stream_lang_req { @@ -120,6 +121,13 @@ struct stream_dvd_info_req { #define TV_COLOR_SATURATION 3 #define TV_COLOR_CONTRAST 4 +// for STREAM_CTRL_AVSEEK +struct stream_avseek { + int stream_index; + int64_t timestamp; + int flags; +}; + struct stream; typedef struct stream_info_st { const char *name; diff --git a/stream/stream_lavf.c b/stream/stream_lavf.c index c736ade45f..8d8ceb3f94 100644 --- a/stream/stream_lavf.c +++ b/stream/stream_lavf.c @@ -101,8 +101,7 @@ static int control(stream_t *s, int cmd, void *arg) AVIOContext *avio = s->priv; if (!avio && cmd != STREAM_CTRL_RECONNECT) return -1; - int64_t size, ts; - double pts; + int64_t size; switch(cmd) { case STREAM_CTRL_GET_SIZE: size = avio_size(avio); @@ -111,13 +110,13 @@ static int control(stream_t *s, int cmd, void *arg) return 1; } break; - case STREAM_CTRL_SEEK_TO_TIME: - pts = *(double *)arg; - ts = pts * AV_TIME_BASE; - ts = avio_seek_time(avio, -1, ts, 0); - if (ts >= 0) + case STREAM_CTRL_AVSEEK: { + struct stream_avseek *c = arg; + int64_t r = avio_seek_time(avio, c->stream_index, c->timestamp, c->flags); + if (r >= 0) return 1; break; + } case STREAM_CTRL_GET_METADATA: { *(struct mp_tags **)arg = read_icy(s); if (!*(struct mp_tags **)arg) -- cgit v1.2.3