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 },
}
}
+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;
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 &&
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 */
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;