static void rtsp_cmd_setup(HTTPContext *c, const char *url, 

                           RTSPHeader *h)

{

    FFStream *stream;

    int stream_index, port;

    char buf[1024];

    char path1[1024];

    const char *path;

    HTTPContext *rtp_c;

    RTSPTransportField *th;

    struct sockaddr_in dest_addr;

    RTSPActionServerSetup setup;

    

    /* find which url is asked */

    url_split(NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);

    path = path1;

    if (*path == '/')

        path++;



    /* now check each stream */

    for(stream = first_stream; stream != NULL; stream = stream->next) {

        if (!stream->is_feed && stream->fmt == &rtp_mux) {

            /* accept aggregate filenames only if single stream */

            if (!strcmp(path, stream->filename)) {

                if (stream->nb_streams != 1) {

                    rtsp_reply_error(c, RTSP_STATUS_AGGREGATE);

                    return;

                }

                stream_index = 0;

                goto found;

            }

                

            for(stream_index = 0; stream_index < stream->nb_streams;

                stream_index++) {

                snprintf(buf, sizeof(buf), "%s/streamid=%d", 

                         stream->filename, stream_index);

                if (!strcmp(path, buf))

                    goto found;

            }

        }

    }

    /* no stream found */

    rtsp_reply_error(c, RTSP_STATUS_SERVICE); /* XXX: right error ? */

    return;

 found:



    /* generate session id if needed */

    if (h->session_id[0] == '\0') {

        snprintf(h->session_id, sizeof(h->session_id), 

                 "%08x%08x", (int)random(), (int)random());

    }



    /* find rtp session, and create it if none found */

    rtp_c = find_rtp_session(h->session_id);

    if (!rtp_c) {

        /* always prefer UDP */

        th = find_transport(h, RTSP_PROTOCOL_RTP_UDP);

        if (!th) {

            th = find_transport(h, RTSP_PROTOCOL_RTP_TCP);

            if (!th) {

                rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);

                return;

            }

        }



        rtp_c = rtp_new_connection(&c->from_addr, stream, h->session_id,

                                   th->protocol);

        if (!rtp_c) {

            rtsp_reply_error(c, RTSP_STATUS_BANDWIDTH);

            return;

        }



        /* open input stream */

        if (open_input_stream(rtp_c, "") < 0) {

            rtsp_reply_error(c, RTSP_STATUS_INTERNAL);

            return;

        }

    }

    

    /* test if stream is OK (test needed because several SETUP needs

       to be done for a given file) */

    if (rtp_c->stream != stream) {

        rtsp_reply_error(c, RTSP_STATUS_SERVICE);

        return;

    }

    

    /* test if stream is already set up */

    if (rtp_c->rtp_ctx[stream_index]) {

        rtsp_reply_error(c, RTSP_STATUS_STATE);

        return;

    }



    /* check transport */

    th = find_transport(h, rtp_c->rtp_protocol);

    if (!th || (th->protocol == RTSP_PROTOCOL_RTP_UDP && 

                th->client_port_min <= 0)) {

        rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);

        return;

    }



    /* setup default options */

    setup.transport_option[0] = '\0';

    dest_addr = rtp_c->from_addr;

    dest_addr.sin_port = htons(th->client_port_min);

    

    /* add transport option if needed */

    if (ff_rtsp_callback) {

        setup.ipaddr = ntohl(dest_addr.sin_addr.s_addr);

        if (ff_rtsp_callback(RTSP_ACTION_SERVER_SETUP, rtp_c->session_id, 

                             (char *)&setup, sizeof(setup),

                             stream->rtsp_option) < 0) {

            rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);

            return;

        }

        dest_addr.sin_addr.s_addr = htonl(setup.ipaddr);

    }

    

    /* setup stream */

    if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, c) < 0) {

        rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);

        return;

    }



    /* now everything is OK, so we can send the connection parameters */

    rtsp_reply_header(c, RTSP_STATUS_OK);

    /* session ID */

    url_fprintf(c->pb, "Session: %s\r\n", rtp_c->session_id);



    switch(rtp_c->rtp_protocol) {

    case RTSP_PROTOCOL_RTP_UDP:

        port = rtp_get_local_port(rtp_c->rtp_handles[stream_index]);

        url_fprintf(c->pb, "Transport: RTP/AVP/UDP;unicast;"

                    "client_port=%d-%d;server_port=%d-%d",

                    th->client_port_min, th->client_port_min + 1,

                    port, port + 1);

        break;

    case RTSP_PROTOCOL_RTP_TCP:

        url_fprintf(c->pb, "Transport: RTP/AVP/TCP;interleaved=%d-%d",

                    stream_index * 2, stream_index * 2 + 1);

        break;

    default:

        break;

    }

    if (setup.transport_option[0] != '\0') {

        url_fprintf(c->pb, ";%s", setup.transport_option);

    }

    url_fprintf(c->pb, "\r\n");

    



    url_fprintf(c->pb, "\r\n");

}
