Browse code

Add a demuxer for receiving raw rtp:// URLs without an SDP description

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

Martin Storsjö authored on 2010/10/19 16:38:53
Showing 6 changed files
... ...
@@ -49,6 +49,7 @@ version <next>:
49 49
 - ffmpeg -crop* options removed
50 50
 - transpose filter added
51 51
 - ffmpeg -force_key_frames option added
52
+- demuxer for receiving raw rtp:// URLs without an SDP description
52 53
 
53 54
 
54 55
 version 0.6:
... ...
@@ -1361,6 +1361,7 @@ mpegtsraw_demuxer_select="mpegts_demuxer"
1361 1361
 mxf_d10_muxer_select="mxf_muxer"
1362 1362
 ogg_demuxer_select="golomb"
1363 1363
 psp_muxer_select="mov_muxer"
1364
+rtp_demuxer_select="sdp_demuxer"
1364 1365
 rtsp_demuxer_select="http_protocol sdp_demuxer"
1365 1366
 rtsp_muxer_select="rtp_muxer http_protocol sdp_demuxer"
1366 1367
 sap_demuxer_select="sdp_demuxer"
... ...
@@ -215,7 +215,7 @@ library:
215 215
 @item Lego Mindstorms RSO       @tab X @tab X
216 216
 @item RTMP                      @tab X @tab X
217 217
     @tab Output is performed by publishing stream to RTMP server
218
-@item RTP                       @tab X @tab
218
+@item RTP                       @tab X @tab X
219 219
 @item RTSP                      @tab X @tab X
220 220
 @item SAP                       @tab X @tab X
221 221
 @item SDP                       @tab   @tab X
... ...
@@ -179,7 +179,7 @@ void av_register_all(void)
179 179
     REGISTER_MUXDEMUX (ROQ, roq);
180 180
     REGISTER_DEMUXER  (RPL, rpl);
181 181
     REGISTER_MUXDEMUX (RSO, rso);
182
-    REGISTER_MUXER    (RTP, rtp);
182
+    REGISTER_MUXDEMUX (RTP, rtp);
183 183
     REGISTER_MUXDEMUX (RTSP, rtsp);
184 184
     REGISTER_MUXDEMUX (SAP, sap);
185 185
     REGISTER_DEMUXER  (SDP, sdp);
... ...
@@ -22,7 +22,7 @@
22 22
 #define AVFORMAT_AVFORMAT_H
23 23
 
24 24
 #define LIBAVFORMAT_VERSION_MAJOR 52
25
-#define LIBAVFORMAT_VERSION_MINOR 83
25
+#define LIBAVFORMAT_VERSION_MINOR 84
26 26
 #define LIBAVFORMAT_VERSION_MICRO  0
27 27
 
28 28
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
... ...
@@ -2104,3 +2104,107 @@ AVInputFormat sdp_demuxer = {
2104 2104
     rtsp_fetch_packet,
2105 2105
     sdp_read_close,
2106 2106
 };
2107
+
2108
+static int rtp_probe(AVProbeData *p)
2109
+{
2110
+    if (av_strstart(p->filename, "rtp:", NULL))
2111
+        return AVPROBE_SCORE_MAX;
2112
+    return 0;
2113
+}
2114
+
2115
+static int rtp_read_header(AVFormatContext *s,
2116
+                           AVFormatParameters *ap)
2117
+{
2118
+    uint8_t recvbuf[1500];
2119
+    char host[500], sdp[500];
2120
+    int ret, port;
2121
+    URLContext* in = NULL;
2122
+    int payload_type;
2123
+    AVCodecContext codec;
2124
+    struct sockaddr_storage addr;
2125
+    ByteIOContext pb;
2126
+    socklen_t addrlen = sizeof(addr);
2127
+
2128
+    if (!ff_network_init())
2129
+        return AVERROR(EIO);
2130
+
2131
+    ret = url_open(&in, s->filename, URL_RDONLY);
2132
+    if (ret)
2133
+        goto fail;
2134
+
2135
+    while (1) {
2136
+        ret = url_read(in, recvbuf, sizeof(recvbuf));
2137
+        if (ret == AVERROR(EAGAIN))
2138
+            continue;
2139
+        if (ret < 0)
2140
+            goto fail;
2141
+        if (ret < 12) {
2142
+            av_log(s, AV_LOG_WARNING, "Received too short packet\n");
2143
+            continue;
2144
+        }
2145
+
2146
+        if ((recvbuf[0] & 0xc0) != 0x80) {
2147
+            av_log(s, AV_LOG_WARNING, "Unsupported RTP version packet "
2148
+                                      "received\n");
2149
+            continue;
2150
+        }
2151
+
2152
+        payload_type = recvbuf[1] & 0x7f;
2153
+        break;
2154
+    }
2155
+    getsockname(url_get_file_handle(in), (struct sockaddr*) &addr, &addrlen);
2156
+    url_close(in);
2157
+    in = NULL;
2158
+
2159
+    memset(&codec, 0, sizeof(codec));
2160
+    if (ff_rtp_get_codec_info(&codec, payload_type)) {
2161
+        av_log(s, AV_LOG_ERROR, "Unable to receive RTP payload type %d "
2162
+                                "without an SDP file describing it\n",
2163
+                                 payload_type);
2164
+        goto fail;
2165
+    }
2166
+    if (codec.codec_type != AVMEDIA_TYPE_DATA) {
2167
+        av_log(s, AV_LOG_WARNING, "Guessing on RTP content - if not received "
2168
+                                  "properly you need an SDP file "
2169
+                                  "describing it\n");
2170
+    }
2171
+
2172
+    av_url_split(NULL, 0, NULL, 0, host, sizeof(host), &port,
2173
+                 NULL, 0, s->filename);
2174
+
2175
+    snprintf(sdp, sizeof(sdp),
2176
+             "v=0\r\nc=IN IP%d %s\r\nm=%s %d RTP/AVP %d\r\n",
2177
+             addr.ss_family == AF_INET ? 4 : 6, host,
2178
+             codec.codec_type == AVMEDIA_TYPE_DATA  ? "application" :
2179
+             codec.codec_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio",
2180
+             port, payload_type);
2181
+    av_log(s, AV_LOG_VERBOSE, "SDP:\n%s\n", sdp);
2182
+
2183
+    init_put_byte(&pb, sdp, strlen(sdp), 0, NULL, NULL, NULL, NULL);
2184
+    s->pb = &pb;
2185
+
2186
+    /* sdp_read_header initializes this again */
2187
+    ff_network_close();
2188
+
2189
+    ret = sdp_read_header(s, ap);
2190
+    s->pb = NULL;
2191
+    return ret;
2192
+
2193
+fail:
2194
+    if (in)
2195
+        url_close(in);
2196
+    ff_network_close();
2197
+    return ret;
2198
+}
2199
+
2200
+AVInputFormat rtp_demuxer = {
2201
+    "rtp",
2202
+    NULL_IF_CONFIG_SMALL("RTP input format"),
2203
+    sizeof(RTSPState),
2204
+    rtp_probe,
2205
+    rtp_read_header,
2206
+    rtsp_fetch_packet,
2207
+    sdp_read_close,
2208
+    .flags = AVFMT_NOFILE,
2209
+};
2210
+