Commit 8d0b2aae authored by Michael Niedermayer's avatar Michael Niedermayer

Merge commit 'e96406ed'

* commit 'e96406ed':
  rtsp: Add support for depacketizing RTP data via custom IO

Conflicts:
	libavformat/version.h
Merged-by: 's avatarMichael Niedermayer <michaelni@gmx.at>
parents ea96fedd e96406ed
...@@ -226,7 +226,8 @@ static int rtp_valid_packet_in_sequence(RTPStatistics *s, uint16_t seq) ...@@ -226,7 +226,8 @@ static int rtp_valid_packet_in_sequence(RTPStatistics *s, uint16_t seq)
return 1; 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; AVIOContext *pb;
uint8_t *buf; uint8_t *buf;
...@@ -242,7 +243,7 @@ int ff_rtp_check_and_send_back_rr(RTPDemuxContext *s, URLContext *fd, int count) ...@@ -242,7 +243,7 @@ int ff_rtp_check_and_send_back_rr(RTPDemuxContext *s, URLContext *fd, int count)
uint32_t fraction; uint32_t fraction;
uint64_t ntp_time = s->last_rtcp_ntp_time; // TODO: Get local ntp time? 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; return -1;
/* TODO: I think this is way too often; RFC 1889 has algorithm for this */ /* 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) ...@@ -255,7 +256,9 @@ int ff_rtp_check_and_send_back_rr(RTPDemuxContext *s, URLContext *fd, int count)
return -1; return -1;
s->last_octet_count = s->octet_count; 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; return -1;
// Receiver Report // Receiver Report
...@@ -312,6 +315,8 @@ int ff_rtp_check_and_send_back_rr(RTPDemuxContext *s, URLContext *fd, int count) ...@@ -312,6 +315,8 @@ int ff_rtp_check_and_send_back_rr(RTPDemuxContext *s, URLContext *fd, int count)
avio_w8(pb, 0); avio_w8(pb, 0);
avio_flush(pb); avio_flush(pb);
if (!fd)
return 0;
len = avio_close_dyn_buf(pb, &buf); len = avio_close_dyn_buf(pb, &buf);
if ((len > 0) && buf) { if ((len > 0) && buf) {
int av_unused result; int av_unused result;
......
...@@ -68,10 +68,11 @@ void ff_rtp_send_punch_packets(URLContext* rtp_handle); ...@@ -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... * 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) * (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... // these statistics are used for rtcp receiver reports...
typedef struct RTPStatistics { typedef struct RTPStatistics {
......
...@@ -97,6 +97,7 @@ const AVOption ff_rtsp_options[] = { ...@@ -97,6 +97,7 @@ const AVOption ff_rtsp_options[] = {
static const AVOption sdp_options[] = { static const AVOption sdp_options[] = {
RTSP_FLAG_OPTS("sdp_flags", "SDP flags"), 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_MEDIATYPE_OPTS("allowed_media_types", "Media types to accept from the server"),
RTSP_REORDERING_OPTS(), RTSP_REORDERING_OPTS(),
{ NULL }, { NULL },
...@@ -1785,6 +1786,50 @@ static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, ...@@ -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) int ff_rtsp_fetch_packet(AVFormatContext *s, AVPacket *pkt)
{ {
RTSPState *rt = s->priv_data; RTSPState *rt = s->priv_data;
...@@ -1856,7 +1901,13 @@ int ff_rtsp_fetch_packet(AVFormatContext *s, AVPacket *pkt) ...@@ -1856,7 +1901,13 @@ int ff_rtsp_fetch_packet(AVFormatContext *s, AVPacket *pkt)
case RTSP_LOWER_TRANSPORT_UDP_MULTICAST: case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
len = udp_read_packet(s, &rtsp_st, rt->recvbuf, RECVBUF_SIZE, wait_end); 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) 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; break;
} }
if (len == AVERROR(EAGAIN) && first_queue_st && if (len == AVERROR(EAGAIN) && first_queue_st &&
...@@ -1969,6 +2020,8 @@ static int sdp_read_header(AVFormatContext *s) ...@@ -1969,6 +2020,8 @@ static int sdp_read_header(AVFormatContext *s)
if (s->max_delay < 0) /* Not set by the caller */ if (s->max_delay < 0) /* Not set by the caller */
s->max_delay = DEFAULT_REORDERING_DELAY; 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 */ /* read the whole sdp file */
/* XXX: better loading */ /* XXX: better loading */
...@@ -1989,6 +2042,7 @@ static int sdp_read_header(AVFormatContext *s) ...@@ -1989,6 +2042,7 @@ static int sdp_read_header(AVFormatContext *s)
char namebuf[50]; char namebuf[50];
rtsp_st = rt->rtsp_streams[i]; rtsp_st = rt->rtsp_streams[i];
if (!(rt->rtsp_flags & RTSP_FLAG_CUSTOM_IO)) {
getnameinfo((struct sockaddr*) &rtsp_st->sdp_ip, sizeof(rtsp_st->sdp_ip), getnameinfo((struct sockaddr*) &rtsp_st->sdp_ip, sizeof(rtsp_st->sdp_ip),
namebuf, sizeof(namebuf), NULL, 0, NI_NUMERICHOST); namebuf, sizeof(namebuf), NULL, 0, NI_NUMERICHOST);
ff_url_join(url, sizeof(url), "rtp", NULL, ff_url_join(url, sizeof(url), "rtp", NULL,
...@@ -2001,6 +2055,7 @@ static int sdp_read_header(AVFormatContext *s) ...@@ -2001,6 +2055,7 @@ static int sdp_read_header(AVFormatContext *s)
err = AVERROR_INVALIDDATA; err = AVERROR_INVALIDDATA;
goto fail; goto fail;
} }
}
if ((err = ff_rtsp_open_transport_ctx(s, rtsp_st))) if ((err = ff_rtsp_open_transport_ctx(s, rtsp_st)))
goto fail; goto fail;
} }
......
...@@ -42,6 +42,10 @@ enum RTSPLowerTransport { ...@@ -42,6 +42,10 @@ enum RTSPLowerTransport {
RTSP_LOWER_TRANSPORT_HTTP = 8, /**< HTTP tunneled - not a proper RTSP_LOWER_TRANSPORT_HTTP = 8, /**< HTTP tunneled - not a proper
transport mode as such, transport mode as such,
only for use via AVOptions */ 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 { ...@@ -396,6 +400,7 @@ typedef struct RTSPState {
receive packets only from the right receive packets only from the right
source address and port. */ source address and port. */
#define RTSP_FLAG_LISTEN 0x2 /**< Wait for incoming connections. */ #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 * Describe a single stream, as identified by a single m= line block in the
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
#define LIBAVFORMAT_VERSION_MAJOR 54 #define LIBAVFORMAT_VERSION_MAJOR 54
#define LIBAVFORMAT_VERSION_MINOR 59 #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, \ #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
LIBAVFORMAT_VERSION_MINOR, \ LIBAVFORMAT_VERSION_MINOR, \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment