#include "rtpenc.h"
#include "mpegts.h"
-//#define DEBUG
-
/* Timeout values for socket poll, in ms,
* and read_packet(), in seconds */
#define POLL_TIMEOUT_MS 100
#define ENC AV_OPT_FLAG_ENCODING_PARAM
#define RTSP_FLAG_OPTS(name, longname) \
- { name, longname, OFFSET(rtsp_flags), AV_OPT_TYPE_FLAGS, {0}, INT_MIN, INT_MAX, DEC, "rtsp_flags" }, \
- { "filter_src", "Only receive packets from the negotiated peer IP", 0, AV_OPT_TYPE_CONST, {RTSP_FLAG_FILTER_SRC}, 0, 0, DEC, "rtsp_flags" }, \
- { "listen", "Wait for incoming connections", 0, AV_OPT_TYPE_CONST, {RTSP_FLAG_LISTEN}, 0, 0, DEC, "rtsp_flags" }
+ { name, longname, OFFSET(rtsp_flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtsp_flags" }, \
+ { "filter_src", "Only receive packets from the negotiated peer IP", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_FILTER_SRC}, 0, 0, DEC, "rtsp_flags" }, \
+ { "listen", "Wait for incoming connections", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_LISTEN}, 0, 0, DEC, "rtsp_flags" }
#define RTSP_MEDIATYPE_OPTS(name, longname) \
- { name, longname, OFFSET(media_type_mask), AV_OPT_TYPE_FLAGS, { (1 << (AVMEDIA_TYPE_DATA+1)) - 1 }, INT_MIN, INT_MAX, DEC, "allowed_media_types" }, \
- { "video", "Video", 0, AV_OPT_TYPE_CONST, {1 << AVMEDIA_TYPE_VIDEO}, 0, 0, DEC, "allowed_media_types" }, \
- { "audio", "Audio", 0, AV_OPT_TYPE_CONST, {1 << AVMEDIA_TYPE_AUDIO}, 0, 0, DEC, "allowed_media_types" }, \
- { "data", "Data", 0, AV_OPT_TYPE_CONST, {1 << AVMEDIA_TYPE_DATA}, 0, 0, DEC, "allowed_media_types" }
+ { name, longname, OFFSET(media_type_mask), AV_OPT_TYPE_FLAGS, { .i64 = (1 << (AVMEDIA_TYPE_DATA+1)) - 1 }, INT_MIN, INT_MAX, DEC, "allowed_media_types" }, \
+ { "video", "Video", 0, AV_OPT_TYPE_CONST, {.i64 = 1 << AVMEDIA_TYPE_VIDEO}, 0, 0, DEC, "allowed_media_types" }, \
+ { "audio", "Audio", 0, AV_OPT_TYPE_CONST, {.i64 = 1 << AVMEDIA_TYPE_AUDIO}, 0, 0, DEC, "allowed_media_types" }, \
+ { "data", "Data", 0, AV_OPT_TYPE_CONST, {.i64 = 1 << AVMEDIA_TYPE_DATA}, 0, 0, DEC, "allowed_media_types" }
+
+#define RTSP_REORDERING_OPTS() \
+ { "reorder_queue_size", "Number of packets to buffer for handling of reordered packets", OFFSET(reordering_queue_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, DEC }
const AVOption ff_rtsp_options[] = {
- { "initial_pause", "Don't start playing the stream immediately", OFFSET(initial_pause), AV_OPT_TYPE_INT, {0}, 0, 1, DEC },
+ { "initial_pause", "Don't start playing the stream immediately", OFFSET(initial_pause), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, DEC },
FF_RTP_FLAG_OPTS(RTSPState, rtp_muxer_flags),
- { "rtsp_transport", "RTSP transport protocols", OFFSET(lower_transport_mask), AV_OPT_TYPE_FLAGS, {0}, INT_MIN, INT_MAX, DEC|ENC, "rtsp_transport" }, \
- { "udp", "UDP", 0, AV_OPT_TYPE_CONST, {1 << RTSP_LOWER_TRANSPORT_UDP}, 0, 0, DEC|ENC, "rtsp_transport" }, \
- { "tcp", "TCP", 0, AV_OPT_TYPE_CONST, {1 << RTSP_LOWER_TRANSPORT_TCP}, 0, 0, DEC|ENC, "rtsp_transport" }, \
- { "udp_multicast", "UDP multicast", 0, AV_OPT_TYPE_CONST, {1 << RTSP_LOWER_TRANSPORT_UDP_MULTICAST}, 0, 0, DEC, "rtsp_transport" },
- { "http", "HTTP tunneling", 0, AV_OPT_TYPE_CONST, {(1 << RTSP_LOWER_TRANSPORT_HTTP)}, 0, 0, DEC, "rtsp_transport" },
+ { "rtsp_transport", "RTSP transport protocols", OFFSET(lower_transport_mask), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, DEC|ENC, "rtsp_transport" }, \
+ { "udp", "UDP", 0, AV_OPT_TYPE_CONST, {.i64 = 1 << RTSP_LOWER_TRANSPORT_UDP}, 0, 0, DEC|ENC, "rtsp_transport" }, \
+ { "tcp", "TCP", 0, AV_OPT_TYPE_CONST, {.i64 = 1 << RTSP_LOWER_TRANSPORT_TCP}, 0, 0, DEC|ENC, "rtsp_transport" }, \
+ { "udp_multicast", "UDP multicast", 0, AV_OPT_TYPE_CONST, {.i64 = 1 << RTSP_LOWER_TRANSPORT_UDP_MULTICAST}, 0, 0, DEC, "rtsp_transport" },
+ { "http", "HTTP tunneling", 0, AV_OPT_TYPE_CONST, {.i64 = (1 << RTSP_LOWER_TRANSPORT_HTTP)}, 0, 0, DEC, "rtsp_transport" },
RTSP_FLAG_OPTS("rtsp_flags", "RTSP flags"),
RTSP_MEDIATYPE_OPTS("allowed_media_types", "Media types to accept from the server"),
- { "min_port", "Minimum local UDP port", OFFSET(rtp_port_min), AV_OPT_TYPE_INT, {RTSP_RTP_PORT_MIN}, 0, 65535, DEC|ENC },
- { "max_port", "Maximum local UDP port", OFFSET(rtp_port_max), AV_OPT_TYPE_INT, {RTSP_RTP_PORT_MAX}, 0, 65535, DEC|ENC },
- { "timeout", "Maximum timeout (in seconds) to wait for incoming connections. -1 is infinite. Implies flag listen", OFFSET(initial_timeout), AV_OPT_TYPE_INT, {-1}, INT_MIN, INT_MAX, DEC },
+ { "min_port", "Minimum local UDP port", OFFSET(rtp_port_min), AV_OPT_TYPE_INT, {.i64 = RTSP_RTP_PORT_MIN}, 0, 65535, DEC|ENC },
+ { "max_port", "Maximum local UDP port", OFFSET(rtp_port_max), AV_OPT_TYPE_INT, {.i64 = RTSP_RTP_PORT_MAX}, 0, 65535, DEC|ENC },
+ { "timeout", "Maximum timeout (in seconds) to wait for incoming connections. -1 is infinite. Implies flag listen", OFFSET(initial_timeout), AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX, DEC },
+ RTSP_REORDERING_OPTS(),
{ NULL },
};
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 const AVOption rtp_options[] = {
RTSP_FLAG_OPTS("rtp_flags", "RTP flags"),
+ RTSP_REORDERING_OPTS(),
{ NULL },
};
get_word_sep(buf, sizeof(buf), "-", &p);
av_parse_time(end, buf, 1);
}
-// av_log(NULL, AV_LOG_DEBUG, "Range Start: %lld\n", *start);
-// av_log(NULL, AV_LOG_DEBUG, "Range End: %lld\n", *end);
}
static int get_sockaddr(const char *buf, struct sockaddr_storage *sock)
{
if (!handler)
return;
- codec->codec_id = handler->codec_id;
+ if (codec)
+ codec->codec_id = handler->codec_id;
rtsp_st->dynamic_handler = handler;
if (handler->alloc) {
rtsp_st->dynamic_protocol_context = handler->alloc();
AVCodec *c;
const char *c_name;
- /* Loop into AVRtpDynamicPayloadTypes[] and AVRtpPayloadTypes[] and
- * see if we can handle this kind of payload.
+ /* See if we can handle this kind of payload.
* The space should normally not be there but some Real streams or
* particular servers ("RealServer Version 6.1.3.970", see issue 1658)
* have a trailing space. */
if (payload_type < RTP_PT_PRIVATE) {
/* We are in a standard case
* (from http://www.iana.org/assignments/rtp-parameters). */
- /* search into AVRtpPayloadTypes[] */
codec->codec_id = ff_rtp_codec_id(buf, codec->codec_type);
}
i = atoi(buf);
if (i > 0)
codec->channels = i;
- // TODO: there is a bug here; if it is a mono stream, and
- // less than 22000Hz, faad upconverts to stereo and twice
- // the frequency. No problem, but the sample rate is being
- // set here by the sdp line. Patch on its way. (rdm)
}
av_log(s, AV_LOG_DEBUG, "audio samplerate set to: %i\n",
codec->sample_rate);
get_word(buf1, sizeof(buf1), &p); /* protocol */
if (!strcmp(buf1, "udp"))
rt->transport = RTSP_TRANSPORT_RAW;
+ else if (strstr(buf1, "/AVPF") || strstr(buf1, "/SAVPF"))
+ rtsp_st->feedback = 1;
/* XXX: handle list of formats */
get_word(buf1, sizeof(buf1), &p); /* format list */
if (!strcmp(ff_rtp_enc_name(rtsp_st->sdp_payload_type), "MP2T")) {
/* no corresponding stream */
- if (rt->transport == RTSP_TRANSPORT_RAW && !rt->ts && CONFIG_RTPDEC)
- rt->ts = ff_mpegts_parse_open(s);
+ if (rt->transport == RTSP_TRANSPORT_RAW) {
+ if (!rt->ts && CONFIG_RTPDEC)
+ rt->ts = ff_mpegts_parse_open(s);
+ } else {
+ RTPDynamicProtocolHandler *handler;
+ handler = ff_rtp_handler_find_by_id(
+ rtsp_st->sdp_payload_type, AVMEDIA_TYPE_DATA);
+ init_rtp_handler(handler, rtsp_st, NULL);
+ if (handler && handler->init)
+ handler->init(s, -1, rtsp_st->dynamic_protocol_context);
+ }
} else if (rt->server_type == RTSP_SERVER_WMS &&
codec_type == AVMEDIA_TYPE_DATA) {
/* RTX stream, a stream that carries all the other actual
s->nb_streams > 0) {
st = s->streams[s->nb_streams - 1];
st->codec->sample_rate = atoi(p);
+ } else if (av_strstart(p, "crypto:", &p) && s->nb_streams > 0) {
+ // RFC 4568
+ rtsp_st = rt->rtsp_streams[rt->nb_rtsp_streams - 1];
+ get_word(buf1, sizeof(buf1), &p); // ignore tag
+ get_word(rtsp_st->crypto_suite, sizeof(rtsp_st->crypto_suite), &p);
+ p += strspn(p, SPACE_CHARS);
+ if (av_strstart(p, "inline:", &p))
+ get_word(rtsp_st->crypto_params, sizeof(rtsp_st->crypto_params), &p);
} else {
if (rt->server_type == RTSP_SERVER_WMS)
ff_wms_parse_sdp_a_line(s, p);
avformat_free_context(rtpctx);
} else if (rt->transport == RTSP_TRANSPORT_RDT && CONFIG_RTPDEC)
ff_rdt_parse_close(rtsp_st->transport_priv);
- else if (rt->transport == RTSP_TRANSPORT_RAW && CONFIG_RTPDEC)
+ else if (rt->transport == RTSP_TRANSPORT_RTP && CONFIG_RTPDEC)
ff_rtp_parse_close(rtsp_st->transport_priv);
}
rtsp_st->transport_priv = NULL;
{
RTSPState *rt = s->priv_data;
AVStream *st = NULL;
+ int reordering_queue_size = rt->reordering_queue_size;
+ if (reordering_queue_size < 0) {
+ if (rt->lower_transport == RTSP_LOWER_TRANSPORT_TCP || !s->max_delay)
+ reordering_queue_size = 0;
+ else
+ reordering_queue_size = RTP_REORDER_QUEUE_DEFAULT_SIZE;
+ }
/* open the RTP context */
if (rtsp_st->stream_index >= 0)
if (s->oformat && CONFIG_RTSP_MUXER) {
int ret = ff_rtp_chain_mux_open(&rtsp_st->transport_priv, s, st,
rtsp_st->rtp_handle,
- RTSP_TCP_MAX_PACKET_SIZE);
+ RTSP_TCP_MAX_PACKET_SIZE,
+ rtsp_st->stream_index);
/* Ownership of rtp_handle is passed to the rtp mux context */
rtsp_st->rtp_handle = NULL;
if (ret < 0)
rtsp_st->dynamic_protocol_context,
rtsp_st->dynamic_handler);
else if (CONFIG_RTPDEC)
- rtsp_st->transport_priv = ff_rtp_parse_open(s, st, rtsp_st->rtp_handle,
+ rtsp_st->transport_priv = ff_rtp_parse_open(s, st,
rtsp_st->sdp_payload_type,
- (rt->lower_transport == RTSP_LOWER_TRANSPORT_TCP || !s->max_delay)
- ? 0 : RTP_REORDER_QUEUE_DEFAULT_SIZE);
+ reordering_queue_size);
if (!rtsp_st->transport_priv) {
return AVERROR(ENOMEM);
rtsp_st->dynamic_protocol_context,
rtsp_st->dynamic_handler);
}
+ if (rtsp_st->crypto_suite[0])
+ ff_rtp_parse_set_crypto(rtsp_st->transport_priv,
+ rtsp_st->crypto_suite,
+ rtsp_st->crypto_params);
}
return 0;
th->lower_transport = RTSP_LOWER_TRANSPORT_UDP_MULTICAST;
} else if (!strcmp(parameter, "ttl")) {
if (*p == '=') {
+ char *end;
p++;
- th->ttl = strtol(p, (char **)&p, 10);
+ th->ttl = strtol(p, &end, 10);
+ p = end;
}
} else if (!strcmp(parameter, "destination")) {
if (*p == '=') {
*
* @return zero if success, nonzero otherwise
*/
-static int ff_rtsp_send_cmd_with_content_async(AVFormatContext *s,
- const char *method, const char *url,
- const char *headers,
- const unsigned char *send_content,
- int send_content_length)
+static int rtsp_send_cmd_with_content_async(AVFormatContext *s,
+ const char *method, const char *url,
+ const char *headers,
+ const unsigned char *send_content,
+ int send_content_length)
{
RTSPState *rt = s->priv_data;
char buf[4096], *out_buf;
int ff_rtsp_send_cmd_async(AVFormatContext *s, const char *method,
const char *url, const char *headers)
{
- return ff_rtsp_send_cmd_with_content_async(s, method, url, headers, NULL, 0);
+ return rtsp_send_cmd_with_content_async(s, method, url, headers, NULL, 0);
}
int ff_rtsp_send_cmd(AVFormatContext *s, const char *method, const char *url,
retry:
cur_auth_type = rt->auth_state.auth_type;
- if ((ret = ff_rtsp_send_cmd_with_content_async(s, method, url, header,
- send_content,
- send_content_length)))
+ if ((ret = rtsp_send_cmd_with_content_async(s, method, url, header,
+ send_content,
+ send_content_length)))
return ret;
if ((ret = ff_rtsp_read_reply(s, reply, content_ptr, 0, method) ) < 0)
int n, i, ret, tcp_fd, timeout_cnt = 0;
int max_p = 0;
struct pollfd *p = rt->p;
+ int *fds = NULL, fdsnum, fdsidx;
for (;;) {
if (ff_check_interrupt(&s->interrupt_callback))
for (i = 0; i < rt->nb_rtsp_streams; i++) {
rtsp_st = rt->rtsp_streams[i];
if (rtsp_st->rtp_handle) {
- p[max_p].fd = ffurl_get_file_handle(rtsp_st->rtp_handle);
- p[max_p++].events = POLLIN;
- p[max_p].fd = ff_rtp_get_rtcp_file_handle(rtsp_st->rtp_handle);
- p[max_p++].events = POLLIN;
+ if (ret = ffurl_get_multi_file_handle(rtsp_st->rtp_handle,
+ &fds, &fdsnum)) {
+ av_log(s, AV_LOG_ERROR, "Unable to recover rtp ports\n");
+ return ret;
+ }
+ if (fdsnum != 2) {
+ av_log(s, AV_LOG_ERROR,
+ "Number of fds %d not supported\n", fdsnum);
+ return AVERROR_INVALIDDATA;
+ }
+ for (fdsidx = 0; fdsidx < fdsnum; fdsidx++) {
+ p[max_p].fd = fds[fdsidx];
+ p[max_p++].events = POLLIN;
+ }
+ av_free(fds);
}
}
n = poll(p, max_p, POLL_TIMEOUT_MS);
}
}
+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;
rt->recvbuf_pos += ret;
ret = rt->recvbuf_pos < rt->recvbuf_len;
}
- }
+ } else
+ ret = -1;
if (ret == 0) {
rt->cur_transport_priv = NULL;
return 0;
rt->cur_transport_priv = NULL;
}
+redo:
if (rt->transport == RTSP_TRANSPORT_RTP) {
int i;
int64_t first_queue_time = 0;
first_queue_st = rt->rtsp_streams[i];
}
}
- if (first_queue_time)
+ if (first_queue_time) {
wait_end = first_queue_time + s->max_delay;
+ } else {
+ wait_end = 0;
+ first_queue_st = NULL;
+ }
}
/* read next RTP packet */
- redo:
if (!rt->recvbuf) {
rt->recvbuf = av_malloc(RECVBUF_SIZE);
if (!rt->recvbuf)
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, len);
+ ff_rtp_check_and_send_back_rr(rtsp_st->transport_priv, rtsp_st->rtp_handle, NULL, len);
+ break;
+ case RTSP_LOWER_TRANSPORT_CUSTOM:
+ if (first_queue_st && rt->transport == RTSP_TRANSPORT_RTP &&
+ wait_end && wait_end < av_gettime())
+ len = AVERROR(EAGAIN);
+ else
+ 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 &&
ret = ff_rdt_parse_packet(rtsp_st->transport_priv, pkt, &rt->recvbuf, len);
} else if (rt->transport == RTSP_TRANSPORT_RTP) {
ret = ff_rtp_parse_packet(rtsp_st->transport_priv, pkt, &rt->recvbuf, len);
+ if (rtsp_st->feedback) {
+ AVIOContext *pb = NULL;
+ if (rt->lower_transport == RTSP_LOWER_TRANSPORT_CUSTOM)
+ pb = s->pb;
+ ff_rtp_send_rtcp_feedback(rtsp_st->transport_priv, rtsp_st->rtp_handle, pb);
+ }
if (ret < 0) {
/* Either bad packet, or a RTCP packet. Check if the
* first_rtcp_ntp_time field was initialized. */
while (p < p_end && *p != '\0') {
if (p + sizeof("c=IN IP") - 1 < p_end &&
av_strstart(p, "c=IN IP", NULL))
- return AVPROBE_SCORE_MAX / 2;
+ return AVPROBE_SCORE_EXTENSION;
while (p < p_end - 1 && *p != '\n') p++;
if (++p >= p_end)
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;
static int rtp_read_header(AVFormatContext *s)
{
- uint8_t recvbuf[1500];
+ uint8_t recvbuf[RTP_MAX_PACKET_LENGTH];
char host[500], sdp[500];
int ret, port;
URLContext* in = NULL;