diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2013-01-04 13:23:19 +0100 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2013-01-04 13:23:19 +0100 |
commit | 8d0b2aae71f01904e4a7ac0e8795592da5a0bd89 (patch) | |
tree | e0bfc884210a851e22fd1acabb6b9e873cef5bb4 | |
parent | ea96feddb7bb813c1e0c9befe9c96bf73996f841 (diff) | |
parent | e96406eda4f143f101bd44372f7b2d542183000a (diff) | |
download | ffmpeg-8d0b2aae71f01904e4a7ac0e8795592da5a0bd89.tar.gz |
Merge commit 'e96406eda4f143f101bd44372f7b2d542183000a'
* commit 'e96406eda4f143f101bd44372f7b2d542183000a':
rtsp: Add support for depacketizing RTP data via custom IO
Conflicts:
libavformat/version.h
Merged-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r-- | libavformat/rtpdec.c | 11 | ||||
-rw-r--r-- | libavformat/rtpdec.h | 5 | ||||
-rw-r--r-- | libavformat/rtsp.c | 79 | ||||
-rw-r--r-- | libavformat/rtsp.h | 5 | ||||
-rw-r--r-- | libavformat/version.h | 2 |
5 files changed, 84 insertions, 18 deletions
diff --git a/libavformat/rtpdec.c b/libavformat/rtpdec.c index 5412e6735b..31c033a882 100644 --- a/libavformat/rtpdec.c +++ b/libavformat/rtpdec.c @@ -226,7 +226,8 @@ static int rtp_valid_packet_in_sequence(RTPStatistics *s, uint16_t seq) return 1; } -int ff_rtp_check_and_send_back_rr(RTPDemuxContext *s, URLContext *fd, int count) +int ff_rtp_check_and_send_back_rr(RTPDemuxContext *s, URLContext *fd, + AVIOContext *avio, int count) { AVIOContext *pb; uint8_t *buf; @@ -242,7 +243,7 @@ int ff_rtp_check_and_send_back_rr(RTPDemuxContext *s, URLContext *fd, int count) uint32_t fraction; uint64_t ntp_time = s->last_rtcp_ntp_time; // TODO: Get local ntp time? - if (!fd || (count < 1)) + if ((!fd && !avio) || (count < 1)) return -1; /* TODO: I think this is way too often; RFC 1889 has algorithm for this */ @@ -255,7 +256,9 @@ int ff_rtp_check_and_send_back_rr(RTPDemuxContext *s, URLContext *fd, int count) return -1; s->last_octet_count = s->octet_count; - if (avio_open_dyn_buf(&pb) < 0) + if (!fd) + pb = avio; + else if (avio_open_dyn_buf(&pb) < 0) return -1; // Receiver Report @@ -312,6 +315,8 @@ int ff_rtp_check_and_send_back_rr(RTPDemuxContext *s, URLContext *fd, int count) avio_w8(pb, 0); avio_flush(pb); + if (!fd) + return 0; len = avio_close_dyn_buf(pb, &buf); if ((len > 0) && buf) { int av_unused result; diff --git a/libavformat/rtpdec.h b/libavformat/rtpdec.h index 407c6d005d..d7ade3bb41 100644 --- a/libavformat/rtpdec.h +++ b/libavformat/rtpdec.h @@ -68,10 +68,11 @@ void ff_rtp_send_punch_packets(URLContext* rtp_handle); /** * some rtp servers assume client is dead if they don't hear from them... - * so we send a Receiver Report to the provided URLContext + * so we send a Receiver Report to the provided URLContext or AVIOContext * (we don't have access to the rtcp handle from here) */ -int ff_rtp_check_and_send_back_rr(RTPDemuxContext *s, URLContext *fd, int count); +int ff_rtp_check_and_send_back_rr(RTPDemuxContext *s, URLContext *fd, + AVIOContext *avio, int count); // these statistics are used for rtcp receiver reports... typedef struct RTPStatistics { diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index bac075295f..d1b6b422a2 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -97,6 +97,7 @@ const AVOption ff_rtsp_options[] = { static const AVOption sdp_options[] = { RTSP_FLAG_OPTS("sdp_flags", "SDP flags"), + { "custom_io", "Use custom IO", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_CUSTOM_IO}, 0, 0, DEC, "rtsp_flags" }, RTSP_MEDIATYPE_OPTS("allowed_media_types", "Media types to accept from the server"), RTSP_REORDERING_OPTS(), { NULL }, @@ -1785,6 +1786,50 @@ static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, } } +static int pick_stream(AVFormatContext *s, RTSPStream **rtsp_st, + const uint8_t *buf, int len) +{ + RTSPState *rt = s->priv_data; + int i; + if (len < 0) + return len; + if (rt->nb_rtsp_streams == 1) { + *rtsp_st = rt->rtsp_streams[0]; + return len; + } + if (len >= 8 && rt->transport == RTSP_TRANSPORT_RTP) { + if (RTP_PT_IS_RTCP(rt->recvbuf[1])) { + int no_ssrc = 0; + for (i = 0; i < rt->nb_rtsp_streams; i++) { + RTPDemuxContext *rtpctx = rt->rtsp_streams[i]->transport_priv; + if (!rtpctx) + continue; + if (rtpctx->ssrc == AV_RB32(&buf[4])) { + *rtsp_st = rt->rtsp_streams[i]; + return len; + } + if (!rtpctx->ssrc) + no_ssrc = 1; + } + if (no_ssrc) { + av_log(s, AV_LOG_WARNING, + "Unable to pick stream for packet - SSRC not known for " + "all streams\n"); + return AVERROR(EAGAIN); + } + } else { + for (i = 0; i < rt->nb_rtsp_streams; i++) { + if ((buf[1] & 0x7f) == rt->rtsp_streams[i]->sdp_payload_type) { + *rtsp_st = rt->rtsp_streams[i]; + return len; + } + } + } + } + av_log(s, AV_LOG_WARNING, "Unable to pick stream for packet\n"); + return AVERROR(EAGAIN); +} + int ff_rtsp_fetch_packet(AVFormatContext *s, AVPacket *pkt) { RTSPState *rt = s->priv_data; @@ -1856,7 +1901,13 @@ int ff_rtsp_fetch_packet(AVFormatContext *s, AVPacket *pkt) case RTSP_LOWER_TRANSPORT_UDP_MULTICAST: len = udp_read_packet(s, &rtsp_st, rt->recvbuf, RECVBUF_SIZE, wait_end); if (len > 0 && rtsp_st->transport_priv && rt->transport == RTSP_TRANSPORT_RTP) - ff_rtp_check_and_send_back_rr(rtsp_st->transport_priv, rtsp_st->rtp_handle, len); + ff_rtp_check_and_send_back_rr(rtsp_st->transport_priv, rtsp_st->rtp_handle, NULL, len); + break; + case RTSP_LOWER_TRANSPORT_CUSTOM: + len = ffio_read_partial(s->pb, rt->recvbuf, RECVBUF_SIZE); + len = pick_stream(s, &rtsp_st, rt->recvbuf, len); + if (len > 0 && rtsp_st->transport_priv && rt->transport == RTSP_TRANSPORT_RTP) + ff_rtp_check_and_send_back_rr(rtsp_st->transport_priv, NULL, s->pb, len); break; } if (len == AVERROR(EAGAIN) && first_queue_st && @@ -1969,6 +2020,8 @@ static int sdp_read_header(AVFormatContext *s) if (s->max_delay < 0) /* Not set by the caller */ s->max_delay = DEFAULT_REORDERING_DELAY; + if (rt->rtsp_flags & RTSP_FLAG_CUSTOM_IO) + rt->lower_transport = RTSP_LOWER_TRANSPORT_CUSTOM; /* read the whole sdp file */ /* XXX: better loading */ @@ -1989,17 +2042,19 @@ static int sdp_read_header(AVFormatContext *s) char namebuf[50]; rtsp_st = rt->rtsp_streams[i]; - getnameinfo((struct sockaddr*) &rtsp_st->sdp_ip, sizeof(rtsp_st->sdp_ip), - namebuf, sizeof(namebuf), NULL, 0, NI_NUMERICHOST); - ff_url_join(url, sizeof(url), "rtp", NULL, - namebuf, rtsp_st->sdp_port, - "?localport=%d&ttl=%d&connect=%d", rtsp_st->sdp_port, - rtsp_st->sdp_ttl, - rt->rtsp_flags & RTSP_FLAG_FILTER_SRC ? 1 : 0); - if (ffurl_open(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE, - &s->interrupt_callback, NULL) < 0) { - err = AVERROR_INVALIDDATA; - goto fail; + if (!(rt->rtsp_flags & RTSP_FLAG_CUSTOM_IO)) { + getnameinfo((struct sockaddr*) &rtsp_st->sdp_ip, sizeof(rtsp_st->sdp_ip), + namebuf, sizeof(namebuf), NULL, 0, NI_NUMERICHOST); + ff_url_join(url, sizeof(url), "rtp", NULL, + namebuf, rtsp_st->sdp_port, + "?localport=%d&ttl=%d&connect=%d", rtsp_st->sdp_port, + rtsp_st->sdp_ttl, + rt->rtsp_flags & RTSP_FLAG_FILTER_SRC ? 1 : 0); + if (ffurl_open(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE, + &s->interrupt_callback, NULL) < 0) { + err = AVERROR_INVALIDDATA; + goto fail; + } } if ((err = ff_rtsp_open_transport_ctx(s, rtsp_st))) goto fail; diff --git a/libavformat/rtsp.h b/libavformat/rtsp.h index 3a5ad7117f..7ca8f64569 100644 --- a/libavformat/rtsp.h +++ b/libavformat/rtsp.h @@ -42,6 +42,10 @@ enum RTSPLowerTransport { RTSP_LOWER_TRANSPORT_HTTP = 8, /**< HTTP tunneled - not a proper transport mode as such, only for use via AVOptions */ + RTSP_LOWER_TRANSPORT_CUSTOM = 16, /**< Custom IO - not a public + option for lower_transport_mask, + but set in the SDP demuxer based + on a flag. */ }; /** @@ -396,6 +400,7 @@ typedef struct RTSPState { receive packets only from the right source address and port. */ #define RTSP_FLAG_LISTEN 0x2 /**< Wait for incoming connections. */ +#define RTSP_FLAG_CUSTOM_IO 0x4 /**< Do all IO via the AVIOContext. */ /** * Describe a single stream, as identified by a single m= line block in the diff --git a/libavformat/version.h b/libavformat/version.h index 890d8ef7e4..3b760bb311 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -31,7 +31,7 @@ #define LIBAVFORMAT_VERSION_MAJOR 54 #define LIBAVFORMAT_VERSION_MINOR 59 -#define LIBAVFORMAT_VERSION_MICRO 102 +#define LIBAVFORMAT_VERSION_MICRO 103 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ |