func: static int rtsp_read_header(AVFormatContext *s,
  
                              AVFormatParameters *ap)
  
  {
  
      RTSPState *rt = s->priv_data;
  
      char host[1024], path[1024], tcpname[1024], cmd[2048];
  
      URLContext *rtsp_hd;
  
      int port, i, ret, err;
  
      RTSPHeader reply1, *reply = &reply1;
  
      unsigned char *content = NULL;
  
      AVStream *st;
  
      RTSPStream *rtsp_st;
  
      int protocol_mask;
  
  
  
      rtsp_abort_req = 0;
  
      
  
      /* extract hostname and port */
  
      url_split(NULL, 0,
  
                host, sizeof(host), &port, path, sizeof(path), s->filename);
  
      if (port < 0)
  
          port = RTSP_DEFAULT_PORT;
  
  
  
      /* open the tcp connexion */
  
      snprintf(tcpname, sizeof(tcpname), "tcp://%s:%d", host, port);
  
      if (url_open(&rtsp_hd, tcpname, URL_RDWR) < 0)
  
          return AVERROR_IO;
  
      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;
  
      }
  
      
  
      protocol_mask = rtsp_default_protocols;
  
  
  
      /* for each stream, make the setup request */
  
      /* XXX: we assume the same server is used for the control of each
  
         RTSP stream */
  
      for(i=0;i<s->nb_streams;i++) {
  
          char transport[2048];
  
          AVInputFormat *fmt;
  
  
  
          st = s->streams[i];
  
          rtsp_st = st->priv_data;
  
  
  
          /* compute available transports */
  
          transport[0] = '\0';
  
  
  
          /* RTP/UDP */
  
          if (protocol_mask & (1 << RTSP_PROTOCOL_RTP_UDP)) {
  
              char buf[256];
  
              int j;
  
  
  
              /* first try in specified port range */
  
              if (rtsp_rtp_port_min != 0) {
  
                  for(j=rtsp_rtp_port_min;j<=rtsp_rtp_port_max;j++) {
  
                      snprintf(buf, sizeof(buf), "rtp://?localport=%d", j);
  
                      if (!av_open_input_file(&rtsp_st->ic, buf, 
  
                                              &rtp_demux, 0, NULL))
  
                          goto rtp_opened;
  
                  }
  
              }
  
  
  
              /* then try on any port */
  
              if (av_open_input_file(&rtsp_st->ic, "rtp://", 
  
                                         &rtp_demux, 0, NULL) < 0) {
  
                      err = AVERROR_INVALIDDATA;
  
                      goto fail;
  
              }
  
  
  
          rtp_opened:
  
              port = rtp_get_local_port(url_fileno(&rtsp_st->ic->pb));
  
              if (transport[0] != '\0')
  
                  pstrcat(transport, sizeof(transport), ",");
  
              snprintf(transport + strlen(transport), sizeof(transport) - strlen(transport) - 1,
  
                       "RTP/AVP/UDP;unicast;client_port=%d-%d",
  
                       port, port + 1);
  
          }
  
  
  
          /* RTP/TCP */
  
          if (protocol_mask & (1 << RTSP_PROTOCOL_RTP_TCP)) {
  
              if (transport[0] != '\0')
  
                  pstrcat(transport, sizeof(transport), ",");
  
              snprintf(transport + strlen(transport), sizeof(transport) - strlen(transport) - 1,
  
                       "RTP/AVP/TCP");
  
          }
  
  
  
          if (protocol_mask & (1 << RTSP_PROTOCOL_RTP_UDP_MULTICAST)) {
  
              if (transport[0] != '\0')
  
                  pstrcat(transport, sizeof(transport), ",");
  
              snprintf(transport + strlen(transport), 
  
                       sizeof(transport) - strlen(transport) - 1,
  
                       "RTP/AVP/UDP;multicast");
  
          }
  
          snprintf(cmd, sizeof(cmd), 
  
                   "SETUP %s RTSP/1.0\r\n"
  
                   "Transport: %s\r\n",
  
                   rtsp_st->control_url, transport);
  
          rtsp_send_cmd(s, cmd, reply, NULL);
  
          if (reply->status_code != RTSP_STATUS_OK ||
  
              reply->nb_transports != 1) {
  
              err = AVERROR_INVALIDDATA;
  
              goto fail;
  
          }
  
  
  
          /* XXX: same protocol for all streams is required */
  
          if (i > 0) {
  
              if (reply->transports[0].protocol != rt->protocol) {
  
                  err = AVERROR_INVALIDDATA;
  
                  goto fail;
  
              }
  
          } else {
  
              rt->protocol = reply->transports[0].protocol;
  
          }
  
  
  
          /* close RTP connection if not choosen */
  
          if (reply->transports[0].protocol != RTSP_PROTOCOL_RTP_UDP &&
  
              (protocol_mask & (1 << RTSP_PROTOCOL_RTP_UDP))) {
  
              av_close_input_file(rtsp_st->ic);
  
              rtsp_st->ic = NULL;
  
          }
  
  
  
          switch(reply->transports[0].protocol) {
  
          case RTSP_PROTOCOL_RTP_TCP:
  
              fmt = &rtp_demux;
  
              if (av_open_input_file(&rtsp_st->ic, "null", fmt, 0, NULL) < 0) {
  
                  err = AVERROR_INVALIDDATA;
  
                  goto fail;
  
              }
  
              rtsp_st->interleaved_min = reply->transports[0].interleaved_min;
  
              rtsp_st->interleaved_max = reply->transports[0].interleaved_max;
  
              break;
  
              
  
          case RTSP_PROTOCOL_RTP_UDP:
  
              {
  
                  char url[1024];
  
                  
  
                  /* XXX: also use address if specified */
  
                  snprintf(url, sizeof(url), "rtp://%s:%d", 
  
                           host, reply->transports[0].server_port_min);
  
                  if (rtp_set_remote_url(url_fileno(&rtsp_st->ic->pb), url) < 0) {
  
                      err = AVERROR_INVALIDDATA;
  
                      goto fail;
  
                  }
  
              }
  
              break;
  
          case RTSP_PROTOCOL_RTP_UDP_MULTICAST:
  
              {
  
                  char url[1024];
  
                  int ttl;
  
  
  
                  fmt = &rtp_demux;
  
                  ttl = reply->transports[0].ttl;
  
                  if (!ttl)
  
                      ttl = 16;
  
                  snprintf(url, sizeof(url), "rtp://%s:%d?multicast=1&ttl=%d", 
  
                           host, 
  
                           reply->transports[0].server_port_min,
  
                           ttl);
  
                  if (av_open_input_file(&rtsp_st->ic, url, fmt, 0, NULL) < 0) {
  
                      err = AVERROR_INVALIDDATA;
  
                      goto fail;
  
                  }
  
              }
  
              break;
  
          }
  
      }
  
  
  
      /* use callback if available to extend setup */
  
      if (ff_rtsp_callback) {
  
          if (ff_rtsp_callback(RTSP_ACTION_CLIENT_SETUP, rt->session_id, 
  
                               NULL, 0, rt->last_reply) < 0) {
  
              err = AVERROR_INVALIDDATA;
  
              goto fail;
  
          }
  
      }
  
                           
  
      /* start playing */
  
      snprintf(cmd, sizeof(cmd), 
  
               "PLAY %s RTSP/1.0\r\n"
  
               "Range: npt=0-\r\n",
  
               s->filename);
  
      rtsp_send_cmd(s, cmd, reply, NULL);
  
      if (reply->status_code != RTSP_STATUS_OK) {
  
          err = AVERROR_INVALIDDATA;
  
          goto fail;
  
      }
  
  
  
  #if 0
  
      /* open TCP with bufferized input */
  
      if (rt->protocol == RTSP_PROTOCOL_RTP_TCP) {
  
          if (url_fdopen(&rt->rtsp_gb, rt->rtsp_hd) < 0) {
  
              err = AVERROR_NOMEM;
  
              goto fail;
  
          }
  
      }
  
  #endif
  
  
  
      return 0;
  
   fail:
  
      for(i=0;i<s->nb_streams;i++) {
  
          st = s->streams[i];
  
          rtsp_st = st->priv_data;
  
          if (rtsp_st) {
  
              if (rtsp_st->ic)
  
                  av_close_input_file(rtsp_st->ic);
  
          }
  
          av_free(rtsp_st);
  
      }
  
      av_freep(&content);
  
      url_close(rt->rtsp_hd);
  
      return err;
  
  }
  