#define MAX_TIMEOUTS READ_PACKET_TIMEOUT_S * 1000 / POLL_TIMEOUT_MS
#define SDP_MAX_SIZE 16384
#define RECVBUF_SIZE 10 * RTP_MAX_PACKET_LENGTH
+#define DEFAULT_REORDERING_DELAY 100000
#define OFFSET(x) offsetof(RTSPState, x)
#define DEC AV_OPT_FLAG_DECODING_PARAM
static int get_sockaddr(const char *buf, struct sockaddr_storage *sock)
{
- struct addrinfo hints, *ai = NULL;
- memset(&hints, 0, sizeof(hints));
+ struct addrinfo hints = { 0 }, *ai = NULL;
hints.ai_flags = AI_NUMERICHOST;
if (getaddrinfo(buf, NULL, &hints, &ai))
return -1;
if (!strcmp(ff_rtp_enc_name(rtsp_st->sdp_payload_type), "MP2T")) {
/* no corresponding stream */
+ } else if (rt->server_type == RTSP_SERVER_WMS &&
+ codec_type == AVMEDIA_TYPE_DATA) {
+ /* RTX stream, a stream that carries all the other actual
+ * audio/video streams. Don't expose this to the callers. */
} else {
st = avformat_new_stream(s, NULL);
if (!st)
/* NOTE: rtpmap is only supported AFTER the 'm=' tag */
get_word(buf1, sizeof(buf1), &p);
payload_type = atoi(buf1);
- st = s->streams[s->nb_streams - 1];
rtsp_st = rt->rtsp_streams[rt->nb_rtsp_streams - 1];
- sdp_parse_rtpmap(s, st, rtsp_st, payload_type, p);
+ if (rtsp_st->stream_index >= 0) {
+ st = s->streams[rtsp_st->stream_index];
+ sdp_parse_rtpmap(s, st, rtsp_st, payload_type, p);
+ }
} else if (av_strstart(p, "fmtp:", &p) ||
av_strstart(p, "framesize:", &p)) {
/* NOTE: fmtp is only supported AFTER the 'a=rtpmap:xxx' tag */
if (rt->server_type == RTSP_SERVER_WMS)
ff_wms_parse_sdp_a_line(s, p);
if (s->nb_streams > 0) {
+ rtsp_st = rt->rtsp_streams[rt->nb_rtsp_streams - 1];
+
if (rt->server_type == RTSP_SERVER_REAL)
- ff_real_parse_sdp_a_line(s, s->nb_streams - 1, p);
+ ff_real_parse_sdp_a_line(s, rtsp_st->stream_index, p);
- rtsp_st = rt->rtsp_streams[rt->nb_rtsp_streams - 1];
if (rtsp_st->dynamic_handler &&
rtsp_st->dynamic_handler->parse_sdp_a_line)
rtsp_st->dynamic_handler->parse_sdp_a_line(s,
- s->nb_streams - 1,
+ rtsp_st->stream_index,
rtsp_st->dynamic_protocol_context, buf);
}
}
* The Vorbis FMTP line can be up to 16KB - see xiph_parse_sdp_line
* in rtpdec_xiph.c. */
char buf[16384], *q;
- SDPParseState sdp_parse_state, *s1 = &sdp_parse_state;
+ SDPParseState sdp_parse_state = { { 0 } }, *s1 = &sdp_parse_state;
- memset(s1, 0, sizeof(SDPParseState));
p = content;
for (;;) {
p += strspn(p, SPACE_CHARS);
#if CONFIG_RTSP_DEMUXER || CONFIG_RTSP_MUXER
static void rtsp_parse_range(int *min_ptr, int *max_ptr, const char **pp)
{
- const char *p;
+ const char *q;
+ char *p;
int v;
- p = *pp;
- p += strspn(p, SPACE_CHARS);
- v = strtol(p, (char **)&p, 10);
+ q = *pp;
+ q += strspn(q, SPACE_CHARS);
+ v = strtol(q, &p, 10);
if (*p == '-') {
p++;
*min_ptr = v;
- v = strtol(p, (char **)&p, 10);
+ v = strtol(p, &p, 10);
*max_ptr = v;
} else {
*min_ptr = v;
} else if (av_stristart(p, "x-Accept-Dynamic-Rate:", &p) && rt) {
p += strspn(p, SPACE_CHARS);
rt->accept_dynamic_rate = atoi(p);
+ } else if (av_stristart(p, "Content-Type:", &p)) {
+ p += strspn(p, SPACE_CHARS);
+ av_strlcpy(reply->content_type, p, sizeof(reply->content_type));
}
}
av_freep(content_ptr);
/* If method is set, this is called from ff_rtsp_send_cmd,
* where a reply to exactly this request is awaited. For
- * callers from within packet reciving, we just want to
+ * callers from within packet receiving, we just want to
* return to the caller and go back to receiving packets. */
if (method)
goto start;
{
RTSPState *rt = s->priv_data;
HTTPAuthType cur_auth_type;
- int ret;
+ int ret, attempts = 0;
retry:
cur_auth_type = rt->auth_state.auth_type;
if ((ret = ff_rtsp_read_reply(s, reply, content_ptr, 0, method) ) < 0)
return ret;
+ attempts++;
- if (reply->status_code == 401 && cur_auth_type == HTTP_AUTH_NONE &&
- rt->auth_state.auth_type != HTTP_AUTH_NONE)
+ if (reply->status_code == 401 &&
+ (cur_auth_type == HTTP_AUTH_NONE || rt->auth_state.stale) &&
+ rt->auth_state.auth_type != HTTP_AUTH_NONE && attempts < 2)
goto retry;
if (reply->status_code > 400){
* UDP. When trying to set it up for TCP streams, the server
* will return an error. Therefore, we skip those streams. */
if (rt->server_type == RTSP_SERVER_WMS &&
- s->streams[rtsp_st->stream_index]->codec->codec_type ==
- AVMEDIA_TYPE_DATA)
+ (rtsp_st->stream_index < 0 ||
+ s->streams[rtsp_st->stream_index]->codec->codec_type ==
+ AVMEDIA_TYPE_DATA))
continue;
snprintf(transport, sizeof(transport) - 1,
"%s/TCP;", trans_pref);
goto fail;
}
- if (reply->timeout > 0)
+ if (rt->nb_rtsp_streams && reply->timeout > 0)
rt->timeout = reply->timeout;
if (rt->server_type == RTSP_SERVER_REAL)
if (!ff_network_init())
return AVERROR(EIO);
+ if (s->max_delay < 0) /* Not set by the caller */
+ s->max_delay = s->iformat ? DEFAULT_REORDERING_DELAY : 0;
+
rt->control_transport = RTSP_MODE_PLAIN;
if (rt->lower_transport_mask & (1 << RTSP_LOWER_TRANSPORT_HTTP)) {
rt->lower_transport_mask = 1 << RTSP_LOWER_TRANSPORT_TCP;
if (!ff_network_init())
return AVERROR(EIO);
+ if (s->max_delay < 0) /* Not set by the caller */
+ s->max_delay = DEFAULT_REORDERING_DELAY;
+
/* read the whole sdp file */
/* XXX: better loading */
content = av_malloc(SDP_MAX_SIZE);
.read_header = sdp_read_header,
.read_packet = ff_rtsp_fetch_packet,
.read_close = sdp_read_close,
- .priv_class = &sdp_demuxer_class
+ .priv_class = &sdp_demuxer_class,
};
#endif /* CONFIG_SDP_DEMUXER */
int ret, port;
URLContext* in = NULL;
int payload_type;
- AVCodecContext codec;
+ AVCodecContext codec = { 0 };
struct sockaddr_storage addr;
AVIOContext pb;
socklen_t addrlen = sizeof(addr);
ffurl_close(in);
in = NULL;
- memset(&codec, 0, sizeof(codec));
if (ff_rtp_get_codec_info(&codec, payload_type)) {
av_log(s, AV_LOG_ERROR, "Unable to receive RTP payload type %d "
"without an SDP file describing it\n",
.read_header = rtp_read_header,
.read_packet = ff_rtsp_fetch_packet,
.read_close = sdp_read_close,
- .flags = AVFMT_NOFILE,
- .priv_class = &rtp_demuxer_class
+ .flags = AVFMT_NOFILE,
+ .priv_class = &rtp_demuxer_class,
};
#endif /* CONFIG_RTP_DEMUXER */