On Fri, 6 Apr 2012, Martin Storsjö wrote:

This avoids having to try to wait for data in
avformat_find_stream_info that we won't be able to decode anyway.
---
libavformat/rtsp.c |   28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)

diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c
index c94ef02..c9c366f 100644
--- a/libavformat/rtsp.c
+++ b/libavformat/rtsp.c
@@ -278,6 +278,32 @@ int ff_rtsp_next_attr_and_value(const char **p, char 
*attr, int attr_size,
    return 0;
}

+static void free_uninitialized_stream(AVFormatContext *s)
+{
+    RTSPState *rt = s->priv_data;
+    RTSPStream *rtsp_st;
+    AVStream *st;
+
+    if (rt->nb_rtsp_streams <= 0)
+        return;
+    rtsp_st = rt->rtsp_streams[rt->nb_rtsp_streams - 1];
+    if (rtsp_st->stream_index < 0)
+        return;
+    st = s->streams[rtsp_st->stream_index];
+    if (st->codec->codec_id != CODEC_ID_NONE)
+        return;
+    if (rtsp_st->dynamic_handler)
+        return;
+    /* Previous stream never got a codec id assigned, and isn't handled
+     * by any dynamic handler, thus don't expose it */
+    av_free(st->codec);
+    av_free(st->info);
+    av_free(st);
+    av_free(rtsp_st);
+    rt->nb_rtsp_streams--;
+    s->nb_streams--;
+}
+
typedef struct SDPParseState {
    /* SDP only */
    struct sockaddr_storage default_ip;
@@ -354,6 +380,7 @@ static void sdp_parse_line(AVFormatContext *s, 
SDPParseState *s1,
            s1->skip_media = 1;
            return;
        }
+        free_uninitialized_stream(s);
        rtsp_st = av_mallocz(sizeof(RTSPStream));
        if (!rtsp_st)
            return;
@@ -523,6 +550,7 @@ int ff_sdp_parse(AVFormatContext *s, const char *content)
        if (*p == '\n')
            p++;
    }
+    free_uninitialized_stream(s);
    rt->p = av_malloc(sizeof(struct pollfd)*2*(rt->nb_rtsp_streams+1));
    if (!rt->p) return AVERROR(ENOMEM);
    return 0;
--
1.7.9.4

Hmm, this still isn't totally right - for MS-RTSP/UDP, we need the data stream, since all the packets actually are sent over this connection, according to this code snippet:

        /*
         * WMS serves all UDP data over a single connection, the RTX, which
         * isn't necessarily the first in the SDP but has to be the first
         * to be set up, else the second/third SETUP will fail with a 461.
         */
        if (lower_transport == RTSP_LOWER_TRANSPORT_UDP &&
             rt->server_type == RTSP_SERVER_WMS) {
            if (i == 0) {
                /* rtx first */
                for (rtx = 0; rtx < rt->nb_rtsp_streams; rtx++) {
                    int len = strlen(rt->rtsp_streams[rtx]->control_url);
                    if (len >= 4 &&
                        !strcmp(rt->rtsp_streams[rtx]->control_url + len - 4,
                                "/rtx"))
                        break;
                }
                if (rtx == rt->nb_rtsp_streams)
                    return -1; /* no RTX found */
                rtsp_st = rt->rtsp_streams[rtx];
            } else
                rtsp_st = rt->rtsp_streams[i > rtx ? i : i - 1];
        } else
            rtsp_st = rt->rtsp_streams[i];

This stream of course doesn't have to be exposed to the caller. I'll see if there's a neater way of handling it...

// Martin
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to