From 44594cc7980a4651aba8ac40c59192c283634748 Mon Sep 17 00:00:00 2001 From: Martin Storsjö Date: Tue, 19 Oct 2010 07:38:53 +0000 Subject: 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 --- Changelog | 1 + configure | 1 + doc/general.texi | 2 +- libavformat/allformats.c | 2 +- libavformat/avformat.h | 2 +- libavformat/rtsp.c | 104 +++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 109 insertions(+), 3 deletions(-) diff --git a/Changelog b/Changelog index c1bf118b95..1289036a55 100644 --- a/Changelog +++ b/Changelog @@ -49,6 +49,7 @@ version : - 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: diff --git a/configure b/configure index 0e6e4394bf..d725942ee8 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_demuxer_select="sdp_demuxer" diff --git a/doc/general.texi b/doc/general.texi index 4f61b2bac3..f59258c8e1 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 -@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 diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 9769de9f0f..9f33e31822 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_MUXDEMUX (SAP, sap); REGISTER_DEMUXER (SDP, sdp); diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 62bf42b968..a9cf174af9 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -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, \ diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index 6570c3880b..aff745a370 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -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, +}; + -- cgit v1.2.3