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

Reply via email to