Add a demuxer for receiving raw rtp:// URLs without an SDP description
authorMartin Storsjö <martin@martin.st>
Tue, 19 Oct 2010 07:38:53 +0000 (07:38 +0000)
committerMartin Storsjö <martin@martin.st>
Tue, 19 Oct 2010 07:38:53 +0000 (07:38 +0000)
The demuxer inspects the payload type of a received RTP packet and
handles the cases where the content is fully described by the payload type.

Originally committed as revision 25527 to svn://svn.ffmpeg.org/ffmpeg/trunk

Changelog
configure
doc/general.texi
libavformat/allformats.c
libavformat/avformat.h
libavformat/rtsp.c

index c1bf118..1289036 100644 (file)
--- a/Changelog
+++ b/Changelog
@@ -49,6 +49,7 @@ version <next>:
 - ffmpeg -crop* options removed
 - transpose filter added
 - ffmpeg -force_key_frames option added
+- demuxer for receiving raw rtp:// URLs without an SDP description
 
 
 version 0.6:
index 0e6e439..d725942 100755 (executable)
--- a/configure
+++ b/configure
@@ -1361,6 +1361,7 @@ mpegtsraw_demuxer_select="mpegts_demuxer"
 mxf_d10_muxer_select="mxf_muxer"
 ogg_demuxer_select="golomb"
 psp_muxer_select="mov_muxer"
+rtp_demuxer_select="sdp_demuxer"
 rtsp_demuxer_select="http_protocol sdp_demuxer"
 rtsp_muxer_select="rtp_muxer http_protocol sdp_demuxer"
 sap_demuxer_select="sdp_demuxer"
index 4f61b2b..f59258c 100644 (file)
@@ -215,7 +215,7 @@ library:
 @item Lego Mindstorms RSO       @tab X @tab X
 @item RTMP                      @tab X @tab X
     @tab Output is performed by publishing stream to RTMP server
-@item RTP                       @tab X @tab
+@item RTP                       @tab X @tab X
 @item RTSP                      @tab X @tab X
 @item SAP                       @tab X @tab X
 @item SDP                       @tab   @tab X
index 9769de9..9f33e31 100644 (file)
@@ -179,7 +179,7 @@ void av_register_all(void)
     REGISTER_MUXDEMUX (ROQ, roq);
     REGISTER_DEMUXER  (RPL, rpl);
     REGISTER_MUXDEMUX (RSO, rso);
-    REGISTER_MUXER    (RTP, rtp);
+    REGISTER_MUXDEMUX (RTP, rtp);
     REGISTER_MUXDEMUX (RTSP, rtsp);
     REGISTER_MUXDEMUX (SAP, sap);
     REGISTER_DEMUXER  (SDP, sdp);
index 62bf42b..a9cf174 100644 (file)
@@ -22,7 +22,7 @@
 #define AVFORMAT_AVFORMAT_H
 
 #define LIBAVFORMAT_VERSION_MAJOR 52
-#define LIBAVFORMAT_VERSION_MINOR 83
+#define LIBAVFORMAT_VERSION_MINOR 84
 #define LIBAVFORMAT_VERSION_MICRO  0
 
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
index 6570c38..aff745a 100644 (file)
@@ -2104,3 +2104,107 @@ AVInputFormat sdp_demuxer = {
     rtsp_fetch_packet,
     sdp_read_close,
 };
+
+static int rtp_probe(AVProbeData *p)
+{
+    if (av_strstart(p->filename, "rtp:", NULL))
+        return AVPROBE_SCORE_MAX;
+    return 0;
+}
+
+static int rtp_read_header(AVFormatContext *s,
+                           AVFormatParameters *ap)
+{
+    uint8_t recvbuf[1500];
+    char host[500], sdp[500];
+    int ret, port;
+    URLContext* in = NULL;
+    int payload_type;
+    AVCodecContext codec;
+    struct sockaddr_storage addr;
+    ByteIOContext pb;
+    socklen_t addrlen = sizeof(addr);
+
+    if (!ff_network_init())
+        return AVERROR(EIO);
+
+    ret = url_open(&in, s->filename, URL_RDONLY);
+    if (ret)
+        goto fail;
+
+    while (1) {
+        ret = url_read(in, recvbuf, sizeof(recvbuf));
+        if (ret == AVERROR(EAGAIN))
+            continue;
+        if (ret < 0)
+            goto fail;
+        if (ret < 12) {
+            av_log(s, AV_LOG_WARNING, "Received too short packet\n");
+            continue;
+        }
+
+        if ((recvbuf[0] & 0xc0) != 0x80) {
+            av_log(s, AV_LOG_WARNING, "Unsupported RTP version packet "
+                                      "received\n");
+            continue;
+        }
+
+        payload_type = recvbuf[1] & 0x7f;
+        break;
+    }
+    getsockname(url_get_file_handle(in), (struct sockaddr*) &addr, &addrlen);
+    url_close(in);
+    in = NULL;
+
+    memset(&codec, 0, sizeof(codec));
+    if (ff_rtp_get_codec_info(&codec, payload_type)) {
+        av_log(s, AV_LOG_ERROR, "Unable to receive RTP payload type %d "
+                                "without an SDP file describing it\n",
+                                 payload_type);
+        goto fail;
+    }
+    if (codec.codec_type != AVMEDIA_TYPE_DATA) {
+        av_log(s, AV_LOG_WARNING, "Guessing on RTP content - if not received "
+                                  "properly you need an SDP file "
+                                  "describing it\n");
+    }
+
+    av_url_split(NULL, 0, NULL, 0, host, sizeof(host), &port,
+                 NULL, 0, s->filename);
+
+    snprintf(sdp, sizeof(sdp),
+             "v=0\r\nc=IN IP%d %s\r\nm=%s %d RTP/AVP %d\r\n",
+             addr.ss_family == AF_INET ? 4 : 6, host,
+             codec.codec_type == AVMEDIA_TYPE_DATA  ? "application" :
+             codec.codec_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio",
+             port, payload_type);
+    av_log(s, AV_LOG_VERBOSE, "SDP:\n%s\n", sdp);
+
+    init_put_byte(&pb, sdp, strlen(sdp), 0, NULL, NULL, NULL, NULL);
+    s->pb = &pb;
+
+    /* sdp_read_header initializes this again */
+    ff_network_close();
+
+    ret = sdp_read_header(s, ap);
+    s->pb = NULL;
+    return ret;
+
+fail:
+    if (in)
+        url_close(in);
+    ff_network_close();
+    return ret;
+}
+
+AVInputFormat rtp_demuxer = {
+    "rtp",
+    NULL_IF_CONFIG_SMALL("RTP input format"),
+    sizeof(RTSPState),
+    rtp_probe,
+    rtp_read_header,
+    rtsp_fetch_packet,
+    sdp_read_close,
+    .flags = AVFMT_NOFILE,
+};
+