X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Frtsp.c;h=d574797199e6d58ca2cb098f39a0e864dff3cd6a;hb=8b2e9636c57b22582143467a8a06b509b47b92f9;hp=06269bd0e1411a33ffc0d85eb4092b2e198532a4;hpb=f797b134cad4d248b1c8955659997980d0668bc3;p=ffmpeg diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index 06269bd0e14..d574797199e 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -292,6 +292,9 @@ typedef struct SDPParseState { struct RTSPSource **default_include_source_addrs; /**< Source-specific multicast include source IP address (from SDP content) */ int nb_default_exclude_source_addrs; /**< Number of source-specific multicast exclude source IP address (from SDP content) */ struct RTSPSource **default_exclude_source_addrs; /**< Source-specific multicast exclude source IP address (from SDP content) */ + int seen_rtpmap; + int seen_fmtp; + char delayed_fmtp[2048]; } SDPParseState; static void copy_default_source_addrs(struct RTSPSource **addrs, int count, @@ -309,6 +312,22 @@ static void copy_default_source_addrs(struct RTSPSource **addrs, int count, } } +static void parse_fmtp(AVFormatContext *s, RTSPState *rt, + int payload_type, const char *line) +{ + int i; + + for (i = 0; i < rt->nb_rtsp_streams; i++) { + RTSPStream *rtsp_st = rt->rtsp_streams[i]; + if (rtsp_st->sdp_payload_type == payload_type && + rtsp_st->dynamic_handler && + rtsp_st->dynamic_handler->parse_sdp_a_line) { + rtsp_st->dynamic_handler->parse_sdp_a_line(s, i, + rtsp_st->dynamic_protocol_context, line); + } + } +} + static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, int letter, const char *buf) { @@ -316,7 +335,7 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, char buf1[64], st_type[64]; const char *p; enum AVMediaType codec_type; - int payload_type, i; + int payload_type; AVStream *st; RTSPStream *rtsp_st; RTSPSource *rtsp_src; @@ -365,7 +384,9 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, break; case 'm': /* new stream */ - s1->skip_media = 0; + s1->skip_media = 0; + s1->seen_fmtp = 0; + s1->seen_rtpmap = 0; codec_type = AVMEDIA_TYPE_UNKNOWN; get_word(st_type, sizeof(st_type), &p); if (!strcmp(st_type, "audio")) { @@ -488,19 +509,20 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, st = s->streams[rtsp_st->stream_index]; sdp_parse_rtpmap(s, st, rtsp_st, payload_type, p); } + s1->seen_rtpmap = 1; + if (s1->seen_fmtp) { + parse_fmtp(s, rt, payload_type, s1->delayed_fmtp); + } } else if (av_strstart(p, "fmtp:", &p) || av_strstart(p, "framesize:", &p)) { - /* NOTE: fmtp is only supported AFTER the 'a=rtpmap:xxx' tag */ // let dynamic protocol handlers have a stab at the line. get_word(buf1, sizeof(buf1), &p); payload_type = atoi(buf1); - for (i = 0; i < rt->nb_rtsp_streams; i++) { - rtsp_st = rt->rtsp_streams[i]; - if (rtsp_st->sdp_payload_type == payload_type && - rtsp_st->dynamic_handler && - rtsp_st->dynamic_handler->parse_sdp_a_line) - rtsp_st->dynamic_handler->parse_sdp_a_line(s, i, - rtsp_st->dynamic_protocol_context, buf); + if (s1->seen_rtpmap) { + parse_fmtp(s, rt, payload_type, buf); + } else { + s1->seen_fmtp = 1; + av_strlcpy(s1->delayed_fmtp, buf, sizeof(s1->delayed_fmtp)); } } else if (av_strstart(p, "range:", &p)) { int64_t start, end; @@ -1567,10 +1589,13 @@ void ff_rtsp_close_connections(AVFormatContext *s) int ff_rtsp_connect(AVFormatContext *s) { RTSPState *rt = s->priv_data; - char host[1024], path[1024], tcpname[1024], cmd[2048], auth[128]; + char proto[128], host[1024], path[1024]; + char tcpname[1024], cmd[2048], auth[128]; + const char *lower_rtsp_proto = "tcp"; int port, err, tcp_fd; RTSPMessageHeader reply1 = {0}, *reply = &reply1; int lower_transport_mask = 0; + int default_port = RTSP_DEFAULT_PORT; char real_challenge[64] = ""; struct sockaddr_storage peer; socklen_t peer_len = sizeof(peer); @@ -1597,15 +1622,23 @@ int ff_rtsp_connect(AVFormatContext *s) rt->lower_transport_mask &= (1 << RTSP_LOWER_TRANSPORT_NB) - 1; redirect: - lower_transport_mask = rt->lower_transport_mask; /* extract hostname and port */ - av_url_split(NULL, 0, auth, sizeof(auth), + av_url_split(proto, sizeof(proto), auth, sizeof(auth), host, sizeof(host), &port, path, sizeof(path), s->filename); + + if (!strcmp(proto, "rtsps")) { + lower_rtsp_proto = "tls"; + default_port = RTSPS_DEFAULT_PORT; + rt->lower_transport_mask = 1 << RTSP_LOWER_TRANSPORT_TCP; + } + if (*auth) { av_strlcpy(rt->auth, auth, sizeof(rt->auth)); } if (port < 0) - port = RTSP_DEFAULT_PORT; + port = default_port; + + lower_transport_mask = rt->lower_transport_mask; if (!lower_transport_mask) lower_transport_mask = (1 << RTSP_LOWER_TRANSPORT_NB) - 1; @@ -1625,7 +1658,7 @@ redirect: /* Construct the URI used in request; this is similar to s->filename, * but with authentication credentials removed and RTSP specific options * stripped out. */ - ff_url_join(rt->control_uri, sizeof(rt->control_uri), "rtsp", NULL, + ff_url_join(rt->control_uri, sizeof(rt->control_uri), proto, NULL, host, port, "%s", path); if (rt->control_transport == RTSP_MODE_TUNNEL) { @@ -1704,7 +1737,8 @@ redirect: } } else { /* open the tcp connection */ - ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, host, port, NULL); + ff_url_join(tcpname, sizeof(tcpname), lower_rtsp_proto, NULL, + host, port, NULL); if (ffurl_open(&rt->rtsp_hd, tcpname, AVIO_FLAG_READ_WRITE, &s->interrupt_callback, NULL) < 0) { err = AVERROR(EIO); @@ -1790,6 +1824,7 @@ redirect: ff_rtsp_close_connections(s); if (reply->status_code >=300 && reply->status_code < 400 && s->iformat) { av_strlcpy(s->filename, reply->location, sizeof(s->filename)); + rt->session_id[0] = '\0'; av_log(s, AV_LOG_INFO, "Status %d: Redirecting to %s\n", reply->status_code, s->filename);