From 3c1cedaa565572c8fdbb6a2c085aaca0bcc39d6f Mon Sep 17 00:00:00 2001
From: hyc <hyc@b3059339-0415-0410-9bf9-f77b7e298cf2>
Date: Tue, 25 May 2010 23:07:28 +0000
Subject: [PATCH] Add support for STREAM_CTRL_SEEK_TO_TIME in ffmpeg streams

git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@31218 b3059339-0415-0410-9bf9-f77b7e298cf2
---
 libmpdemux/demux_lavf.c | 24 +++++++++++++++++++++---
 stream/stream_ffmpeg.c  | 11 ++++++++++-
 2 files changed, 31 insertions(+), 4 deletions(-)

diff --git a/libmpdemux/demux_lavf.c b/libmpdemux/demux_lavf.c
index 67374277ed..3305611876 100644
--- a/libmpdemux/demux_lavf.c
+++ b/libmpdemux/demux_lavf.c
@@ -83,7 +83,8 @@ typedef struct lavf_priv_t{
 }lavf_priv_t;
 
 static int mp_read(void *opaque, uint8_t *buf, int size) {
-    stream_t *stream = opaque;
+    demuxer_t *demuxer = opaque;
+    stream_t *stream = demuxer->stream;
     int ret;
 
     if(stream_eof(stream)) //needed?
@@ -95,7 +96,8 @@ static int mp_read(void *opaque, uint8_t *buf, int size) {
 }
 
 static int64_t mp_seek(void *opaque, int64_t pos, int whence) {
-    stream_t *stream = opaque;
+    demuxer_t *demuxer = opaque;
+    stream_t *stream = demuxer->stream;
     int64_t current_pos;
     mp_msg(MSGT_HEADER,MSGL_DBG2,"mp_seek(%p, %"PRId64", %d)\n", stream, pos, whence);
     if(whence == SEEK_CUR)
@@ -123,6 +125,21 @@ static int64_t mp_seek(void *opaque, int64_t pos, int whence) {
     return pos - stream->start_pos;
 }
 
+static int64_t mp_read_seek(void *opaque, int stream_idx, int64_t ts, int flags) {
+    demuxer_t *demuxer = opaque;
+    stream_t *stream = demuxer->stream;
+    lavf_priv_t *priv = demuxer->priv;
+    AVStream *st = priv->avfc->streams[stream_idx];
+    int ret;
+    double pts;
+
+    pts = (double)ts * st->time_base.num / st->time_base.den;
+    ret = stream_control(stream, STREAM_CTRL_SEEK_TO_TIME, &pts);
+    if (ret < 0)
+        ret = AVERROR(ENOSYS);
+    return ret;
+}
+
 static void list_formats(void) {
     AVInputFormat *fmt;
     mp_msg(MSGT_DEMUX, MSGL_INFO, "Available lavf input formats:\n");
@@ -503,7 +520,8 @@ static demuxer_t* demux_open_lavf(demuxer_t *demuxer){
         av_strlcat(mp_filename, "foobar.dummy", sizeof(mp_filename));
 
     priv->pb = av_alloc_put_byte(priv->buffer, BIO_BUFFER_SIZE, 0,
-                                 demuxer->stream, mp_read, NULL, mp_seek);
+                                 demuxer, mp_read, NULL, mp_seek);
+    priv->pb->read_seek = mp_read_seek;
     priv->pb->is_streamed = !demuxer->stream->end_pos || (demuxer->stream->flags & MP_STREAM_SEEK) != MP_STREAM_SEEK;
 
     if(av_open_input_stream(&avfc, priv->pb, mp_filename, priv->avif, &ap)<0){
diff --git a/stream/stream_ffmpeg.c b/stream/stream_ffmpeg.c
index 30d63001d0..a5e80eb999 100644
--- a/stream/stream_ffmpeg.c
+++ b/stream/stream_ffmpeg.c
@@ -49,7 +49,8 @@ static int seek(stream_t *s, off_t newpos)
 
 static int control(stream_t *s, int cmd, void *arg)
 {
-    int64_t size;
+    int64_t size, ts;
+    double pts;
     switch(cmd) {
     case STREAM_CTRL_GET_SIZE:
         size = url_filesize(s->priv);
@@ -57,6 +58,14 @@ static int control(stream_t *s, int cmd, void *arg)
             *(off_t *)arg = size;
             return 1;
         }
+        break;
+    case STREAM_CTRL_SEEK_TO_TIME:
+        pts = *(double *)arg;
+        ts = pts * AV_TIME_BASE;
+        ts = av_url_read_seek(s->priv, -1, ts, 0);
+        if (ts >= 0)
+            return 1;
+        break;
     }
     return STREAM_UNSUPPORTED;
 }