[FFmpeg-soc] [soc]: r5830 - mms/mmsh.c

spyfeng subversion at mplayerhq.hu
Sat Jun 12 19:10:27 CEST 2010


Author: spyfeng
Date: Sat Jun 12 19:10:27 2010
New Revision: 5830

Log:
add handle_chunk_type function and revised the code.
TODO: parse the asf header and do padding works for data packet.

Modified:
   mms/mmsh.c

Modified: mms/mmsh.c
==============================================================================
--- mms/mmsh.c	Thu Jun 10 19:34:01 2010	(r5829)
+++ mms/mmsh.c	Sat Jun 12 19:10:27 2010	(r5830)
@@ -22,10 +22,15 @@
 #include "internal.h"
 #include "libavutil/intreadwrite.h"
 #include <string.h>
+#include "libavutil/avstring.h"
 
 #define CHUNK_TYPE_DATA        0x4424
 #define CHUNK_TYPE_ASF_HEADER  0x4824
 #define CHUNK_TYPE_END         0x4524
+#define CHUNK_TYPE_STREAM_CHANGE 0x4324
+
+#define CHUNK_HEADER_LENGTH 4
+#define EXT_HEADER_LENGTH   8
 
 #define USERAGENT "User-Agent: NSPlayer/4.1.0.3856\r\n"
 #define CLIENTGUID "Pragma: xClientGUID={c77e7400-738a-11d2-9add-0020af0a3278}\r\n"
@@ -77,8 +82,7 @@ typedef struct
     int asf_header_read_size;
     int asf_data_remaining_len;
 
-    char path[256];
-    char host[128];
+    char location[1024];
     int seekable;
     int stream_num;
     int request_seq;
@@ -189,6 +193,12 @@ static int get_and_parse_http_header(MMS
     }
 }
 
+static int asf_header_parser(MMSHContext * mms)
+{
+    //TODO
+    return 0;
+}
+
 static uint16_t http_header_data_parser(MMSHContext *mms)
 {
     uint16_t chunk_type;
@@ -203,8 +213,6 @@ static uint16_t http_header_data_parser(
             mms->asf_header_pos = pos + 12; // start from asf header data
             mms->asf_header_len = chunk_len - 8;
         }
-        if (chunk_type == CHUNK_TYPE_ASF_HEADER || chunk_type == CHUNK_TYPE_DATA)
-            mms->chunk_seq = AV_RL32(pos + 4);
         data_len -= chunk_len + 4;
         pos += chunk_len + 4;
         if (data_len <= 0) {
@@ -212,7 +220,7 @@ static uint16_t http_header_data_parser(
             return -1;
         }
         if (chunk_type == CHUNK_TYPE_ASF_HEADER) {
-            //TODO parse asf header
+            asf_header_parser(mms);
         }
     }
     return 0;
@@ -251,6 +259,21 @@ static int get_http_header_data(MMSHCont
             return -1;
         }
         av_free(tmp);
+    } else if (flag == 3){
+        int header_len;
+        res = url_read(mms->mms_hd, mms->http_header_data, CHUNK_HEADER_LENGTH);
+        if (res != CHUNK_HEADER_LENGTH) {
+            dprintf(NULL, "read chunk header failed with flag = 3!\n");
+            return AVERROR(EIO);
+        }
+        // read header
+        header_len = AV_RL16(mms->http_header_data + 2);
+        res = url_read_complete(mms->mms_hd, mms->http_header_data + 4, header_len);
+        if (res != header_len) {
+            dprintf(NULL, "read chunk data failed with flag = 3!\n");
+            return AVERROR(EIO);
+        }
+        asf_header_parser(mms);
     } else {
         dprintf(NULL, "http response has no data!\n");
         return -1;
@@ -282,65 +305,68 @@ static int get_http_answer(MMSHContext *
     return 0;
 }
 
-static int mmsh_open_cnx(URLContext *h)
+static int mmsh_open_cnx(MMSHContext *mms)
 {
-    MMSHContext *mms = h->priv_data;
+    int port, err;
+    char tcpname[256], path[256], host[128];
+
     if (mms->mms_hd) {
         url_close(mms->mms_hd);
     }
-    return 0;
-}
-
-static int mmsh_open(URLContext *h, const char *uri, int flags)
-{
-    MMSHContext *mms;
-    int port, err;
-    char tcpname[256];
-
-    h->is_streamed = 1;
-    mms = h->priv_data = av_mallocz(sizeof(MMSHContext));
-    if (!h->priv_data)
-        return AVERROR(ENOMEM);
-
     ff_url_split(NULL, 0, NULL, 0,
-            mms->host, sizeof(mms->host), &port, mms->path,
-            sizeof(mms->path), uri);
+            host, sizeof(host), &port, path, sizeof(path), mms->location);
     if(port<0)
         port = 80; // defaut mmsh protocol port
 
-    ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, mms->host, port, NULL);
+    ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, host, port, NULL);
     err = url_open(&mms->mms_hd, tcpname, URL_RDWR);
     if (err)
-        goto fail;
+        return err;
     // send describe request
-    snprintf (mms->out_buffer, sizeof(mms->out_buffer), mmsh_first_request, mms->path,
-            mms->host, port, mms->request_seq++);
+    snprintf (mms->out_buffer, sizeof(mms->out_buffer), mmsh_first_request, path,
+            host, port, mms->request_seq++);
     err = send_pack(mms);
     if (err)
-        goto fail;
+        return err;
     err = get_http_answer(mms, 1); // TODO match with the first request
     if(err)
-        goto fail;
+        return err;
 
     // send paly request
     if (mms->seekable) {
-        snprintf(mms->out_buffer, sizeof(mms->out_buffer), mmsh_seekable_request, mms->path,
-            mms->host, port, 0, 0, 0, mms->request_seq++, 0, mms->stream_num, mms->stream_selection);
+        snprintf(mms->out_buffer, sizeof(mms->out_buffer), mmsh_seekable_request, path,
+            host, port, 0, 0, 0, mms->request_seq++, 0, mms->stream_num, mms->stream_selection);
     } else {
-        snprintf(mms->out_buffer, sizeof(mms->out_buffer), mmsh_live_request, mms->path,
-            mms->host, port, mms->request_seq++, mms->stream_num, mms->stream_selection);
+        snprintf(mms->out_buffer, sizeof(mms->out_buffer), mmsh_live_request, path,
+            host, port, mms->request_seq++, mms->stream_num, mms->stream_selection);
     }
     err = send_pack(mms);
     if (err)
-        goto fail;
+        return err;
     err = get_http_answer(mms, 2);// TODO mathc with the second request
     if(err)
-        goto fail;
+        return err;
+    return 0;
+}
+
+static int mmsh_open(URLContext *h, const char *uri, int flags)
+{
+    MMSHContext *mms;
+    int err;
+    mms->request_seq = h->is_streamed = 1;
+    mms = h->priv_data = av_mallocz(sizeof(MMSHContext));
+    if (!h->priv_data)
+        return AVERROR(ENOMEM);
+    av_strlcpy(mms->location, uri, sizeof(mms->location));
+
+    err =mmsh_open_cnx(mms);
+    if (err) {
+        dprintf(NULL, "Leaving mmsh open (failure: %d)\n", err);
+        mmsh_close(h);
+        return err;
+    }
     dprintf(NULL, "Leaving mmsh open success.\n");
-fail:
-    mmsh_close(h);
-    dprintf(NULL, "Leaving mmsh open (failure: %d)\n", err);
-    return err;
+    return 0;
 }
 
 static int read_data(MMSHContext *mms, char *buf, int size)
@@ -355,21 +381,62 @@ static int read_data(MMSHContext *mms, c
 
 static int handle_chunk_type(MMSHContext *mms)
 {
+    uint8_t chunk_header[CHUNK_HEADER_LENGTH];
+    uint8_t ext_header[EXT_HEADER_LENGTH];
     uint16_t chunk_type;
-    int chunk_len, res;
-    res = url_read(mms->mms_hd, mms->in_buffer, 4);
-    if (res != 4) { // TODO extact common log code as macro define
+    int chunk_len, res, ext_header_len = 0;
+
+    res = url_read(mms->mms_hd, chunk_header, CHUNK_HEADER_LENGTH);
+    if (res != CHUNK_HEADER_LENGTH) { // TODO extact common log code as macro define
         dprintf(NULL, "read data packet  header failed!\n");
         return AVERROR(EIO);
     }
-    chunk_type = AV_RL16(mms->in_buffer);
-    chunk_len = AV_RL16(mms->in_buffer + 2);
-    if (chunk_type == CHUNK_TYPE_END) {
-        //TODO
-    } else if (chunk_type == CHUNK_TYPE_ASF_HEADER) {
-        //TODO
-    } else if (chunk_type == CHUNK_TYPE_DATA){
-        //TODO
+    chunk_type = AV_RL16(chunk_header);
+    chunk_len = AV_RL16(chunk_header + 2);
+    if (chunk_type == CHUNK_TYPE_END ||chunk_type == CHUNK_TYPE_STREAM_CHANGE) {
+        ext_header_len = 4;
+    } else if (chunk_type == CHUNK_TYPE_ASF_HEADER || chunk_type == CHUNK_TYPE_DATA) {
+        ext_header_len = 8;
+    }
+    if (ext_header_len) {
+        res = url_read(mms->mms_hd, ext_header, ext_header_len);
+        if (res != ext_header_len) {
+            dprintf(NULL, "read ext header failed!\n");
+            return AVERROR(EIO);
+        }
+    }
+    if (chunk_type == CHUNK_TYPE_ASF_HEADER || chunk_type == CHUNK_TYPE_DATA)
+        mms->chunk_seq = AV_RL32(ext_header);
+
+    if(chunk_type == CHUNK_TYPE_END) {
+        if (mms->chunk_seq == 0) {
+            dprintf(NULL, "The stream is end.\n");
+            return -1;
+        }
+        // reconnect
+        mms->request_seq = 1;
+        if ((res = mmsh_open_cnx(mms)) !=0) {
+            dprintf(NULL, Reconnect failed!\n);
+            return res;
+        }
+    } else if (chunk_type == CHUNK_TYPE_STREAM_CHANGE) {
+        if ((res = get_http_header_data(mms, 3)) !=0) {
+            dprintf(NULL,"stream changed! get new header failed!\n");
+            return res;
+        }
+    } else if (chunk_type == CHUNK_TYPE_DATA) {
+        int data_len = chunk_len - ext_header_len;
+        res = url_read_complete(mms->mms_hd, mms->in_buffer, data_len);
+        dprintf(NULL, "data packet len = %d\n", data_len);
+        mms->read_in_ptr = mms->in_buffer;
+        mms->asf_data_remaining_len = data_len; //TODO paddings
+        if (res != data_len) {
+            dprintf(NULL, "read data packet failed!\n");
+            return AVERROR(EIO);
+        }
+    } else {
+        dprintf(NULL, "recv other type packet %d\n", chunk_type);
+        return -1;
     }
     return 0;
 }
@@ -394,21 +461,13 @@ static int mmsh_read(URLContext *h, uint
     } else if (mms->asf_data_remaining_len){
         res =read_data(mms, buf, size);
     } else {
-        // read data packet from network
-            int len;
-            len = handle_chunk_type(mms);
-            if (len > 0) {
-                res = url_read_complete(mms->mms_hd, mms->in_buffer + 4, len);
-                if (res != len) {
-                    dprintf(NULL, "read data packet failed!\n");
-                    return AVERROR(EIO);
-                }
-                mms->read_in_ptr = mms->in_buffer;
-                mms->asf_data_remaining_len = len + 4;
-                res = read_data(mms, buf, size);
-            } else {
-                dprintf(NULL, "other situation!\n");
-            }
+         // read data packet from network
+        res = handle_chunk_type(mms);
+        if (res == 0) {
+            res = read_data(mms, buf, size);
+        } else {
+            dprintf(NULL, "other situation!\n");
+        }
     }
     return res;
 }


More information about the FFmpeg-soc mailing list