[FFmpeg-devel] [RFC] Add a demuxer directly handling rtp:// URLs by inspecting their content
Martin Storsjo
martin
Sat Oct 9 16:55:05 CEST 2010
---
This is an initial attempt at creating a demuxer that is able to play back
some RTP streams without needing a SDP description of them. It works for
RTP payloads with a static, officially registered payload type, that need
no extra parameters passed in the SDP.
With this in place, one is simply able to do "ffplay rtp://224.0.0.255:10000"
to playback a RTP stream on that multicast address, if it happens to be
of such a type.
This proof of concept piggybacks on the SDP demuxer by wrapping its
read_header function in a function that receives one RTP packet, inspects it,
creates a minimal fake SDP description, and feeds that to sdp_read_header.
This way, it is not necessary to create a full chained demuxer and try to
keep the state of the chained demuxer synced with the main one.
This was requested in roundup issues 2277 and 2280.
configure | 1 +
doc/general.texi | 2 +-
libavformat/allformats.c | 2 +-
libavformat/rtsp.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 101 insertions(+), 2 deletions(-)
diff --git a/configure b/configure
index 400990a..ab2fbd7 100755
--- 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_muxer_select="rtp_muxer rtp_protocol"
diff --git a/doc/general.texi b/doc/general.texi
index aa4e480..8a646bf 100644
--- a/doc/general.texi
+++ b/doc/general.texi
@@ -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
- at item RTP @tab X @tab
+ at item RTP @tab X @tab X
@item RTSP @tab X @tab X
@item SAP @tab X @tab
@item SDP @tab @tab X
diff --git a/libavformat/allformats.c b/libavformat/allformats.c
index 66de933..7defd87 100644
--- a/libavformat/allformats.c
+++ b/libavformat/allformats.c
@@ -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_MUXER (SAP, sap);
REGISTER_DEMUXER (SDP, sdp);
diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c
index 6570c38..c75bf60 100644
--- a/libavformat/rtsp.c
+++ b/libavformat/rtsp.c
@@ -2104,3 +2104,101 @@ 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_WARNING, "Unrecognized payload type %d\n",
+ payload_type);
+ goto fail;
+ }
+
+ 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,
+};
+
--
1.7.3.1
More information about the ffmpeg-devel
mailing list