+ return 0;
+
+fail:
+ for (i=0; i<rt->nb_rtsp_streams; i++) {
+ if (rt->rtsp_streams[i]->rtp_handle) {
+ url_close(rt->rtsp_streams[i]->rtp_handle);
+ rt->rtsp_streams[i]->rtp_handle = NULL;
+ }
+ }
+ return err;
+}
+
+static int rtsp_read_header(AVFormatContext *s,
+ AVFormatParameters *ap)
+{
+ RTSPState *rt = s->priv_data;
+ char host[1024], path[1024], tcpname[1024], cmd[2048], *option_list, *option;
+ URLContext *rtsp_hd;
+ int port, ret, err;
+ RTSPHeader reply1, *reply = &reply1;
+ unsigned char *content = NULL;
+ int protocol_mask = 0;
+
+ /* extract hostname and port */
+ url_split(NULL, 0, NULL, 0,
+ host, sizeof(host), &port, path, sizeof(path), s->filename);
+ if (port < 0)
+ port = RTSP_DEFAULT_PORT;
+
+ /* search for options */
+ option_list = strchr(path, '?');
+ if (option_list) {
+ /* remove the options from the path */
+ *option_list++ = 0;
+ while(option_list) {
+ /* move the option pointer */
+ option = option_list;
+ option_list = strchr(option_list, '&');
+ if (option_list)
+ *(option_list++) = 0;
+ /* handle the options */
+ if (strcmp(option, "udp") == 0)
+ protocol_mask = (1<< RTSP_PROTOCOL_RTP_UDP);
+ else if (strcmp(option, "multicast") == 0)
+ protocol_mask = (1<< RTSP_PROTOCOL_RTP_UDP_MULTICAST);
+ else if (strcmp(option, "tcp") == 0)
+ protocol_mask = (1<< RTSP_PROTOCOL_RTP_TCP);
+ }
+ }
+
+ if (!protocol_mask)
+ protocol_mask = (1 << RTSP_PROTOCOL_RTP_LAST) - 1;
+
+ /* open the tcp connexion */
+ snprintf(tcpname, sizeof(tcpname), "tcp://%s:%d", host, port);
+ if (url_open(&rtsp_hd, tcpname, URL_RDWR) < 0)
+ return AVERROR(EIO);
+ rt->rtsp_hd = rtsp_hd;
+ rt->seq = 0;
+
+ /* describe the stream */
+ snprintf(cmd, sizeof(cmd),
+ "DESCRIBE %s RTSP/1.0\r\n"
+ "Accept: application/sdp\r\n",
+ s->filename);
+ rtsp_send_cmd(s, cmd, reply, &content);
+ if (!content) {
+ err = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+ if (reply->status_code != RTSP_STATUS_OK) {
+ err = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+
+ /* now we got the SDP description, we parse it */
+ ret = sdp_parse(s, (const char *)content);
+ av_freep(&content);
+ if (ret < 0) {
+ err = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+
+ do {
+ int protocol = ff_log2_tab[protocol_mask & ~(protocol_mask - 1)];
+
+ err = make_setup_request(s, host, port, protocol);
+ if (err < 0)
+ goto fail;
+ protocol_mask &= ~(1 << protocol);
+ if (protocol_mask == 0 && err == 1) {
+ err = AVERROR(FF_NETERROR(EPROTONOSUPPORT));
+ goto fail;
+ }
+ } while (err);
+