[FFmpeg-devel] [PATCH] ASF-in-Realmedia-RTSP parser.

Ronald S. Bultje rsbultje
Fri Feb 11 03:49:05 CET 2011


Allows playback of streams with the mediatype x-pn-wmt, such as
rtsp://live1.rte.ie/wmtencoder/1516.wma, and fixes issue 1607.

(Needs work - crashes on exit, and the hacks in rtsp.c/asfdec.c are
not acceptable probably.)
---
 libavformat/asfdec.c         |    1 +
 libavformat/rtpdec.c         |    1 +
 libavformat/rtpdec_asf.c     |  116 +++++++++++++++++++++++++++++++++++++-----
 libavformat/rtpdec_formats.h |    1 +
 libavformat/rtspdec.c        |    4 +-
 5 files changed, 108 insertions(+), 15 deletions(-)

diff --git a/libavformat/asfdec.c b/libavformat/asfdec.c
index 35e892c..91839fc 100644
--- a/libavformat/asfdec.c
+++ b/libavformat/asfdec.c
@@ -807,6 +807,7 @@ static int ff_asf_parse_packet(AVFormatContext *s, ByteIOContext *pb, AVPacket *
             assert(ret>=0);
             /* fail safe */
             url_fskip(pb, ret);
+            asf->packet_size_left = asf->packet_padsize = 0; // HACK for x-pn-wmt
 
             asf->packet_pos= url_ftell(pb);
             if (asf->data_object_size != (uint64_t)-1 &&
diff --git a/libavformat/rtpdec.c b/libavformat/rtpdec.c
index c81ba1c..149232a 100644
--- a/libavformat/rtpdec.c
+++ b/libavformat/rtpdec.c
@@ -79,6 +79,7 @@ void av_register_rtp_dynamic_payload_handlers(void)
 
     ff_register_dynamic_payload_handler(&ff_ms_rtp_asf_pfv_handler);
     ff_register_dynamic_payload_handler(&ff_ms_rtp_asf_pfa_handler);
+    ff_register_dynamic_payload_handler(&ff_ms_rtp_asf_wmt_handler);
 
     ff_register_dynamic_payload_handler(&ff_qt_rtp_aud_handler);
     ff_register_dynamic_payload_handler(&ff_qt_rtp_vid_handler);
diff --git a/libavformat/rtpdec_asf.c b/libavformat/rtpdec_asf.c
index db09f8f..74e5a01 100644
--- a/libavformat/rtpdec_asf.c
+++ b/libavformat/rtpdec_asf.c
@@ -146,11 +146,76 @@ static int asfrtp_parse_sdp_line(AVFormatContext *s, int stream_index,
     return 0;
 }
 
+static int wmtrtp_parse_sdp_line(AVFormatContext *s, int stream_index,
+                                 PayloadContext *asf, const char *line)
+{
+    RTSPState *rt = s->priv_data;
+
+    if (av_strstart(line, "RawHeader:buffer;\"", &line)){
+        ByteIOContext pb;
+        int i, ret, len = strlen(line) * 6 / 8;
+        char *buf = av_mallocz(len);
+
+        len = av_base64_decode(buf, line, len);
+        if (rtp_asf_fix_header(buf+8, len-8) < 0)
+            av_log(s, AV_LOG_ERROR,
+                   "Failed to fix invalid RTSP-MS/ASF min_pktsize\n");
+        init_packetizer(&pb, buf+8, len-8);
+        if (rt->asf_ctx) {
+            av_close_input_stream(rt->asf_ctx);
+            rt->asf_ctx = NULL;
+        }
+        ret = av_open_input_stream(&rt->asf_ctx, &pb, "", &ff_asf_demuxer, NULL);
+        if (ret < 0)
+            return ret;
+        rt->asf_pb_pos = url_ftell(&pb);
+        av_free(buf);
+        rt->asf_ctx->pb = NULL;
+
+        for (i = 0; i < rt->asf_ctx->nb_streams; i++){
+            AVStream *st = av_new_stream(s, 0);
+            AVCodecContext *ctx = st->codec;
+            *st = *rt->asf_ctx->streams[i];
+            st->codec = ctx;
+            *st->codec = *rt->asf_ctx->streams[i]->codec;
+            rt->asf_ctx->streams[i]->codec->extradata_size = 0;
+            rt->asf_ctx->streams[i]->codec->extradata = NULL;
+            st->priv_data = s->streams[stream_index]->priv_data;
+        }
+    }
+
+    return 0;
+}
+
 struct PayloadContext {
     ByteIOContext *pktbuf, pb;
     uint8_t *buf;
 };
 
+static int get_packet_data(AVFormatContext *s, PayloadContext *asf,
+                           AVPacket *pkt)
+{
+    ByteIOContext *pb = &asf->pb;
+    int res, i;
+    RTSPState *rt = s->priv_data;
+
+    for (;;) {
+        res = av_read_packet(rt->asf_ctx, pkt);
+        rt->asf_pb_pos = url_ftell(pb);
+        if (res != 0)
+            break;
+        for (i = 0; i < s->nb_streams; i++) {
+            if (s->streams[i]->id == rt->asf_ctx->streams[pkt->stream_index]->id) {
+                pkt->stream_index = i;
+                return 1; // FIXME: return 0 if last packet
+            }
+        }
+        av_free_packet(pkt);
+    }
+
+    return res == 1 ? -1 : res;
+}
+
 /**
  * @return 0 when a packet was written into /p pkt, and no more data is left;
  *         1 when a packet was written into /p pkt, and more packets might be left;
@@ -243,23 +308,36 @@ static int asfrtp_parse_packet(AVFormatContext *s, PayloadContext *asf,
         rt->asf_ctx->pb = pb;
     }
 
-    for (;;) {
-        int i;
+    return get_packet_data(s, asf, pkt);
+}
 
-        res = av_read_packet(rt->asf_ctx, pkt);
-        rt->asf_pb_pos = url_ftell(pb);
-        if (res != 0)
-            break;
-        for (i = 0; i < s->nb_streams; i++) {
-            if (s->streams[i]->id == rt->asf_ctx->streams[pkt->stream_index]->id) {
-                pkt->stream_index = i;
-                return 1; // FIXME: return 0 if last packet
-            }
-        }
-        av_free_packet(pkt);
+/**
+ * @return 0 when a packet was written into /p pkt, and no more data is left;
+ *         1 when a packet was written into /p pkt, and more packets might be left;
+ *        <0 when not enough data was provided to return a full packet, or on error.
+ */
+static int wmtrtp_parse_packet(AVFormatContext *s, PayloadContext *asf,
+                               AVStream *st, AVPacket *pkt,
+                               uint32_t *timestamp,
+                               const uint8_t *buf, int len, int flags)
+{
+    ByteIOContext *pb = &asf->pb;
+    RTSPState *rt = s->priv_data;
+
+    if (!rt->asf_ctx)
+        return -1;
+
+    if (len > 0) {
+        av_free(asf->buf);
+        asf->buf = av_malloc(len-8);
+        memcpy(asf->buf, buf+8, len-8);
+        init_packetizer(pb, asf->buf, len-8);
+        pb->pos += rt->asf_pb_pos;
+        pb->eof_reached = 0;
+        rt->asf_ctx->pb = pb;
     }
 
-    return res == 1 ? -1 : res;
+    return get_packet_data(s, asf, pkt);
 }
 
 static PayloadContext *asfrtp_new_context(void)
@@ -292,3 +370,13 @@ RTPDynamicProtocolHandler ff_ms_rtp_ ## n ## _handler = { \
 
 RTP_ASF_HANDLER(asf_pfv, "x-asf-pf",  AVMEDIA_TYPE_VIDEO);
 RTP_ASF_HANDLER(asf_pfa, "x-asf-pf",  AVMEDIA_TYPE_AUDIO);
+
+RTPDynamicProtocolHandler ff_ms_rtp_asf_wmt_handler = {
+    .enc_name         = "x-pn-wmt",
+    .codec_type       = AVMEDIA_TYPE_DATA,
+    .codec_id         = CODEC_ID_NONE,
+    .parse_sdp_a_line = wmtrtp_parse_sdp_line,
+    .open             = asfrtp_new_context,
+    .close            = asfrtp_free_context,
+    .parse_packet     = wmtrtp_parse_packet,
+};
diff --git a/libavformat/rtpdec_formats.h b/libavformat/rtpdec_formats.h
index 16f5a9d..1b4b2ec 100644
--- a/libavformat/rtpdec_formats.h
+++ b/libavformat/rtpdec_formats.h
@@ -41,6 +41,7 @@ extern RTPDynamicProtocolHandler ff_mp4v_es_dynamic_handler;
 extern RTPDynamicProtocolHandler ff_mpeg4_generic_dynamic_handler;
 extern RTPDynamicProtocolHandler ff_ms_rtp_asf_pfa_handler;
 extern RTPDynamicProtocolHandler ff_ms_rtp_asf_pfv_handler;
+extern RTPDynamicProtocolHandler ff_ms_rtp_asf_wmt_handler;
 extern RTPDynamicProtocolHandler ff_qcelp_dynamic_handler;
 extern RTPDynamicProtocolHandler ff_qdm2_dynamic_handler;
 extern RTPDynamicProtocolHandler ff_qt_rtp_aud_handler;
diff --git a/libavformat/rtspdec.c b/libavformat/rtspdec.c
index 45ed7bb..0373a93 100644
--- a/libavformat/rtspdec.c
+++ b/libavformat/rtspdec.c
@@ -283,7 +283,9 @@ retry:
             for (i = 0; i < rt->nb_rtsp_streams; i++) {
                 rule_nr = 0;
                 for (r = 0; r < s->nb_streams; r++) {
-                    if (s->streams[r]->priv_data == rt->rtsp_streams[i]) {
+                    if (s->streams[r]->priv_data == rt->rtsp_streams[i] &&
+                        s->streams[r]->codec->codec_type != CODEC_TYPE_DATA &&
+                        s->streams[r]->codec->channels > 0) { // HACK for x-pn-wmt
                         if (s->streams[r]->discard != AVDISCARD_ALL) {
                             if (!first)
                                 av_strlcat(rt->last_subscription, ",",
-- 
1.7.2.1




More information about the ffmpeg-devel mailing list