|
|
|
@@ -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; |
|
|
|
|