[libav-api] Patch for use with Avigilon IP camera systems

Joshua Kordani jkordani at lsa2.com
Fri Jun 13 21:04:18 CEST 2014


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

-------------- next part --------------
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;
     }
 }


More information about the libav-api mailing list