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