It appears that some Avigilion RTSP servers emit a malformed sdp file,
where the attributes come in out of order. The library handling of
sdp's doesn't expect the attributes out of order, and the result is that
extradata doesn't get passed correctly down the chain to the decoder.
The short term fix is to intercept the sdp before the library and
reorder it properly, or modify the library to account for this and wait
to apply the attributes until the time is right. The long term answer
is obviously for the manufacturer to release a fix, but existing systems
yada yada yada
Attached is a patch to recent trunk that keeps the a=fmtp line around
until after we detect an a=rtpmap line. The rtpmap line payload type
gets propagated down the library, and then after that, the fmtp line
gets applied to the correct streams. When the order is reversed, there
is a check in the fmtp propagation that check the stream to make sure it
is of the correct type, and only then applies the line. I just keep the
line around until such time.
The patch is most likely not safe for production use and is provided as
is, and is a proof of concept. There is also some logic that seems to
be in place that I didn't not understand and expect will need to be
redone if its desired to use this for real, and it could be made to be
more general, in the case that we expect to need to hang on to all
attributes until we can apply them properly, not just the one in question.
Cheers.
--
Joshua Kordani
LSA Autonomy
diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c
index 06269bd..6f03991 100644
--- a/libavformat/rtsp.c
+++ b/libavformat/rtsp.c
@@ -292,6 +292,12 @@ typedef struct SDPParseState {
struct RTSPSource **default_include_source_addrs; /**< Source-specific
multicast include source IP address (from SDP content) */
int nb_default_exclude_source_addrs; /**< Number of source-specific
multicast exclude source IP address (from SDP content) */
struct RTSPSource **default_exclude_source_addrs; /**< Source-specific
multicast exclude source IP address (from SDP content) */
+
+ /* used to handle buggy sdp, where a=fmtp comes before a=rtpmap */
+ int seen_rtpmap;
+ int delayedHandling;
+ char delayed_a_line[2048];
+
} SDPParseState;
static void copy_default_source_addrs(struct RTSPSource **addrs, int count,
@@ -488,19 +494,40 @@ static void sdp_parse_line(AVFormatContext *s,
SDPParseState *s1,
st = s->streams[rtsp_st->stream_index];
sdp_parse_rtpmap(s, st, rtsp_st, payload_type, p);
}
+ // used in case rtpmap comes after fmtp
+ s1->seen_rtpmap = 1;
+ if (s1->delayedHandling) {
+ for (i = 0; i < rt->nb_rtsp_streams; i++) {
+ rtsp_st = rt->rtsp_streams[i];
+ if (rtsp_st->sdp_payload_type == payload_type &&
+ rtsp_st->dynamic_handler &&
+ rtsp_st->dynamic_handler->parse_sdp_a_line)
+ rtsp_st->dynamic_handler->parse_sdp_a_line(s, i,
+ rtsp_st->dynamic_protocol_context, s1->delayed_a_line);
+ }
+ }
} else if (av_strstart(p, "fmtp:", &p) ||
av_strstart(p, "framesize:", &p)) {
/* NOTE: fmtp is only supported AFTER the 'a=rtpmap:xxx' tag */
// let dynamic protocol handlers have a stab at the line.
get_word(buf1, sizeof(buf1), &p);
payload_type = atoi(buf1);
- for (i = 0; i < rt->nb_rtsp_streams; i++) {
+ if (!s1->seen_rtpmap) {
+ // need to store the fmtp line for later, since we haven't seen
the rtpmap line yet.
+ s1->delayedHandling = 1;
+ // store the line somewhere
+ strncpy(s1->delayed_a_line, buf, 2048);
+ //only handles last line found...
+ } else {
+ //business as usual
+ for (i = 0; i < rt->nb_rtsp_streams; i++) {
rtsp_st = rt->rtsp_streams[i];
if (rtsp_st->sdp_payload_type == payload_type &&
rtsp_st->dynamic_handler &&
rtsp_st->dynamic_handler->parse_sdp_a_line)
- rtsp_st->dynamic_handler->parse_sdp_a_line(s, i,
- rtsp_st->dynamic_protocol_context, buf);
+ rtsp_st->dynamic_handler->parse_sdp_a_line(s, i,
+
rtsp_st->dynamic_protocol_context, buf);
+ }
}
} else if (av_strstart(p, "range:", &p)) {
int64_t start, end;
@@ -578,7 +605,7 @@ static void sdp_parse_line(AVFormatContext *s,
SDPParseState *s1,
rtsp_st->stream_index,
rtsp_st->dynamic_protocol_context, buf);
}
- }
+ }
break;
}
}
_______________________________________________
libav-api mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-api