fixed: seeks in mmsh
authorspiff <spiff@xbmc.org>
Tue, 1 Nov 2011 12:14:09 +0000 (13:14 +0100)
committerspiff <spiff@xbmc.org>
Tue, 1 Nov 2011 13:27:34 +0000 (14:27 +0100)
this backports upstream commits aedb87c5786a4e55e68475ec190,
60fcc19bff (partially), 237bcaa27518337898628af4ac527226b64550d6

thanks a million to michael niedermayer for giving this priority!

lib/ffmpeg/libavformat/mmsh.c
lib/ffmpeg/patches/0058-fixed-seeks-in-mmsh.patch [new file with mode: 0644]

index 257b973..3ae886f 100644 (file)
@@ -54,6 +54,7 @@ typedef enum {
 
 typedef struct {
     MMSContext mms;
+    uint8_t location[1024];
     int request_seq;  ///< request packet sequence
     int chunk_seq;    ///< data packet sequence
 } MMSHContext;
@@ -210,10 +211,10 @@ static int get_http_header_data(MMSHContext *mmsh)
     return 0;
 }
 
-static int mmsh_open(URLContext *h, const char *uri, int flags)
+static int mmsh_open_internal(URLContext *h, const char *uri, int flags, int timestamp, int64_t pos)
 {
     int i, port, err;
-    char httpname[256], path[256], host[128], location[1024];
+    char httpname[256], path[256], host[128];
     char *stream_selection = NULL;
     char headers[1024];
     MMSHContext *mmsh;
@@ -224,10 +225,10 @@ static int mmsh_open(URLContext *h, const char *uri, int flags)
         return AVERROR(ENOMEM);
     mmsh->request_seq = h->is_streamed = 1;
     mms = &mmsh->mms;
-    av_strlcpy(location, uri, sizeof(location));
+    av_strlcpy(mmsh->location, uri, sizeof(mmsh->location));
 
     av_url_split(NULL, 0, NULL, 0,
-        host, sizeof(host), &port, path, sizeof(path), location);
+        host, sizeof(host), &port, path, sizeof(path), mmsh->location);
     if (port<0)
         port = 80; // default mmsh protocol port
     ff_url_join(httpname, sizeof(httpname), "http", NULL, host, port, path);
@@ -283,8 +284,9 @@ static int mmsh_open(URLContext *h, const char *uri, int flags)
                    CLIENTGUID
                    "Pragma: stream-switch-count=%d\r\n"
                    "Pragma: stream-switch-entry=%s\r\n"
+                   "Pragma: no-cache,rate)1.000000,stream-time=%u"
                    "Connection: Close\r\n\r\n",
-                   host, port, mmsh->request_seq++, mms->stream_num, stream_selection);
+                   host, port, mmsh->request_seq++, mms->stream_num, stream_selection, timestamp);
     av_freep(&stream_selection);
     if (err < 0) {
         av_log(NULL, AV_LOG_ERROR, "Build play request failed!\n");
@@ -313,6 +315,11 @@ fail:
     return err;
 }
 
+static int mmsh_open(URLContext *h, const char *uri, int flags)
+{
+    return mmsh_open_internal(h, uri, flags, 0, 0);
+}
+
 static int handle_chunk_type(MMSHContext *mmsh)
 {
     MMSContext *mms = &mmsh->mms;
@@ -359,11 +366,45 @@ static int mmsh_read(URLContext *h, uint8_t *buf, int size)
     return res;
 }
 
+static int64_t mmsh_read_seek(URLContext *h, int stream_index,
+                        int64_t timestamp, int flags)
+{
+    MMSHContext *mmsh = h->priv_data;
+    MMSContext *mms   = &mmsh->mms;
+    int ret;
+
+    ret= mmsh_open_internal(h, mmsh->location, 0, FFMAX(timestamp, 0), 0);
+
+    if(ret>=0){
+        if (mms->mms_hd)
+            url_close(mms->mms_hd);
+        av_freep(&mms->streams);
+        av_freep(&mms->asf_header);
+        av_free(mmsh);
+        mmsh = h->priv_data;
+        mms   = &mmsh->mms;
+        mms->asf_header_read_size= mms->asf_header_size;
+    }else
+        h->priv_data= mmsh;
+    return ret;
+}
+
+static int64_t mmsh_seek(URLContext *h, int64_t pos, int whence)
+{
+    MMSHContext *mmsh = h->priv_data;
+    MMSContext *mms   = &mmsh->mms;
+
+    if(pos == 0 && whence == SEEK_CUR)
+        return mms->asf_header_read_size + mms->remaining_in_len + mmsh->chunk_seq * mms->asf_packet_len;
+    return AVERROR(ENOSYS);
+}
+
 URLProtocol ff_mmsh_protocol = {
     .name      = "mmsh",
     .url_open  = mmsh_open,
     .url_read  = mmsh_read,
     .url_write = NULL,
-    .url_seek  = NULL,
+    .url_seek  = mmsh_seek,
     .url_close = mmsh_close,
+    .url_read_seek  = mmsh_read_seek,
 };
diff --git a/lib/ffmpeg/patches/0058-fixed-seeks-in-mmsh.patch b/lib/ffmpeg/patches/0058-fixed-seeks-in-mmsh.patch
new file mode 100644 (file)
index 0000000..c8a630c
--- /dev/null
@@ -0,0 +1,124 @@
+From 4e8274d070a598e60a953c6aed2dd9f4710cd2b4 Mon Sep 17 00:00:00 2001
+From: spiff <spiff@xbmc.org>
+Date: Tue, 1 Nov 2011 13:14:09 +0100
+Subject: [PATCH] fixed: seeks in mmsh
+
+this backports upstream commits aedb87c57, 86a4e55e6, 8475ec190,
+60fcc19bff (partially), 237bcaa27518, 33789862, 8af4ac5272, 26b64550d6
+
+thanks a million to michael niedermayer for giving this priority!
+---
+ lib/ffmpeg/libavformat/mmsh.c |   53 ++++++++++++++++++++++++++++++++++++----
+ 1 files changed, 47 insertions(+), 6 deletions(-)
+
+diff --git a/lib/ffmpeg/libavformat/mmsh.c b/lib/ffmpeg/libavformat/mmsh.c
+index 257b973..3ae886f 100644
+--- a/lib/ffmpeg/libavformat/mmsh.c
++++ b/lib/ffmpeg/libavformat/mmsh.c
+@@ -54,6 +54,7 @@ typedef enum {
+ typedef struct {
+     MMSContext mms;
++    uint8_t location[1024];
+     int request_seq;  ///< request packet sequence
+     int chunk_seq;    ///< data packet sequence
+ } MMSHContext;
+@@ -210,10 +211,10 @@ static int get_http_header_data(MMSHContext *mmsh)
+     return 0;
+ }
+-static int mmsh_open(URLContext *h, const char *uri, int flags)
++static int mmsh_open_internal(URLContext *h, const char *uri, int flags, int timestamp, int64_t pos)
+ {
+     int i, port, err;
+-    char httpname[256], path[256], host[128], location[1024];
++    char httpname[256], path[256], host[128];
+     char *stream_selection = NULL;
+     char headers[1024];
+     MMSHContext *mmsh;
+@@ -224,10 +225,10 @@ static int mmsh_open(URLContext *h, const char *uri, int flags)
+         return AVERROR(ENOMEM);
+     mmsh->request_seq = h->is_streamed = 1;
+     mms = &mmsh->mms;
+-    av_strlcpy(location, uri, sizeof(location));
++    av_strlcpy(mmsh->location, uri, sizeof(mmsh->location));
+     av_url_split(NULL, 0, NULL, 0,
+-        host, sizeof(host), &port, path, sizeof(path), location);
++        host, sizeof(host), &port, path, sizeof(path), mmsh->location);
+     if (port<0)
+         port = 80; // default mmsh protocol port
+     ff_url_join(httpname, sizeof(httpname), "http", NULL, host, port, path);
+@@ -283,8 +284,9 @@ static int mmsh_open(URLContext *h, const char *uri, int flags)
+                    CLIENTGUID
+                    "Pragma: stream-switch-count=%d\r\n"
+                    "Pragma: stream-switch-entry=%s\r\n"
++                   "Pragma: no-cache,rate)1.000000,stream-time=%u"
+                    "Connection: Close\r\n\r\n",
+-                   host, port, mmsh->request_seq++, mms->stream_num, stream_selection);
++                   host, port, mmsh->request_seq++, mms->stream_num, stream_selection, timestamp);
+     av_freep(&stream_selection);
+     if (err < 0) {
+         av_log(NULL, AV_LOG_ERROR, "Build play request failed!\n");
+@@ -313,6 +315,11 @@ fail:
+     return err;
+ }
++static int mmsh_open(URLContext *h, const char *uri, int flags)
++{
++    return mmsh_open_internal(h, uri, flags, 0, 0);
++}
++
+ static int handle_chunk_type(MMSHContext *mmsh)
+ {
+     MMSContext *mms = &mmsh->mms;
+@@ -359,11 +366,45 @@ static int mmsh_read(URLContext *h, uint8_t *buf, int size)
+     return res;
+ }
++static int64_t mmsh_read_seek(URLContext *h, int stream_index,
++                        int64_t timestamp, int flags)
++{
++    MMSHContext *mmsh = h->priv_data;
++    MMSContext *mms   = &mmsh->mms;
++    int ret;
++
++    ret= mmsh_open_internal(h, mmsh->location, 0, FFMAX(timestamp, 0), 0);
++
++    if(ret>=0){
++        if (mms->mms_hd)
++            url_close(mms->mms_hd);
++        av_freep(&mms->streams);
++        av_freep(&mms->asf_header);
++        av_free(mmsh);
++        mmsh = h->priv_data;
++        mms   = &mmsh->mms;
++        mms->asf_header_read_size= mms->asf_header_size;
++    }else
++        h->priv_data= mmsh;
++    return ret;
++}
++
++static int64_t mmsh_seek(URLContext *h, int64_t pos, int whence)
++{
++    MMSHContext *mmsh = h->priv_data;
++    MMSContext *mms   = &mmsh->mms;
++
++    if(pos == 0 && whence == SEEK_CUR)
++        return mms->asf_header_read_size + mms->remaining_in_len + mmsh->chunk_seq * mms->asf_packet_len;
++    return AVERROR(ENOSYS);
++}
++
+ URLProtocol ff_mmsh_protocol = {
+     .name      = "mmsh",
+     .url_open  = mmsh_open,
+     .url_read  = mmsh_read,
+     .url_write = NULL,
+-    .url_seek  = NULL,
++    .url_seek  = mmsh_seek,
+     .url_close = mmsh_close,
++    .url_read_seek  = mmsh_read_seek,
+ };
+-- 
+1.7.5
+