-#if CONFIG_RTSP_DEMUXER
-static int rtsp_read_header(AVFormatContext *s,
- AVFormatParameters *ap)
-{
- RTSPState *rt = s->priv_data;
- int ret;
-
- ret = ff_rtsp_connect(s);
- if (ret)
- return ret;
-
- rt->real_setup_cache = av_mallocz(2 * s->nb_streams * sizeof(*rt->real_setup_cache));
- if (!rt->real_setup_cache)
- return AVERROR(ENOMEM);
- rt->real_setup = rt->real_setup_cache + s->nb_streams * sizeof(*rt->real_setup);
-
- if (ap->initial_pause) {
- /* do not start immediately */
- } else {
- if (rtsp_read_play(s) < 0) {
- ff_rtsp_close_streams(s);
- ff_rtsp_close_connections(s);
- return AVERROR_INVALIDDATA;
- }
- }
-
- return 0;
-}
-
-static int tcp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
- uint8_t *buf, int buf_size)
-{
- RTSPState *rt = s->priv_data;
- int id, len, i, ret;
- RTSPStream *rtsp_st;
-
-#ifdef DEBUG_RTP_TCP
- dprintf(s, "tcp_read_packet:\n");
-#endif
-redo:
- for (;;) {
- RTSPMessageHeader reply;
-
- ret = ff_rtsp_read_reply(s, &reply, NULL, 1);
- if (ret < 0)
- return ret;
- if (ret == 1) /* received '$' */
- break;
- /* XXX: parse message */
- if (rt->state != RTSP_STATE_STREAMING)
- return 0;
- }
- ret = url_read_complete(rt->rtsp_hd, buf, 3);
- if (ret != 3)
- return -1;
- id = buf[0];
- len = AV_RB16(buf + 1);
-#ifdef DEBUG_RTP_TCP
- dprintf(s, "id=%d len=%d\n", id, len);
-#endif
- if (len > buf_size || len < 12)
- goto redo;
- /* get the data */
- ret = url_read_complete(rt->rtsp_hd, buf, len);
- if (ret != len)
- return -1;
- if (rt->transport == RTSP_TRANSPORT_RDT &&
- ff_rdt_parse_header(buf, len, &id, NULL, NULL, NULL, NULL) < 0)
- return -1;
-
- /* find the matching stream */
- for (i = 0; i < rt->nb_rtsp_streams; i++) {
- rtsp_st = rt->rtsp_streams[i];
- if (id >= rtsp_st->interleaved_min &&
- id <= rtsp_st->interleaved_max)
- goto found;
- }
- goto redo;
-found:
- *prtsp_st = rtsp_st;
- return len;
-}
-static int rtsp_read_packet(AVFormatContext *s, AVPacket *pkt)
-{
- RTSPState *rt = s->priv_data;
- int ret;
- RTSPMessageHeader reply1, *reply = &reply1;
- char cmd[1024];
-
- if (rt->server_type == RTSP_SERVER_REAL) {
- int i;
-
- for (i = 0; i < s->nb_streams; i++)
- rt->real_setup[i] = s->streams[i]->discard;
-
- if (!rt->need_subscription) {
- if (memcmp (rt->real_setup, rt->real_setup_cache,
- sizeof(enum AVDiscard) * s->nb_streams)) {
- snprintf(cmd, sizeof(cmd),
- "Unsubscribe: %s\r\n",
- rt->last_subscription);
- ff_rtsp_send_cmd(s, "SET_PARAMETER", rt->control_uri,
- cmd, reply, NULL);
- if (reply->status_code != RTSP_STATUS_OK)
- return AVERROR_INVALIDDATA;
- rt->need_subscription = 1;
- }
- }
-
- if (rt->need_subscription) {
- int r, rule_nr, first = 1;
-
- memcpy(rt->real_setup_cache, rt->real_setup,
- sizeof(enum AVDiscard) * s->nb_streams);
- rt->last_subscription[0] = 0;
-
- snprintf(cmd, sizeof(cmd),
- "Subscribe: ");
- for (i = 0; i < rt->nb_rtsp_streams; i++) {
- rule_nr = 0;
- for (r = 0; r < s->nb_streams; r++) {
- if (s->streams[r]->priv_data == rt->rtsp_streams[i]) {
- if (s->streams[r]->discard != AVDISCARD_ALL) {
- if (!first)
- av_strlcat(rt->last_subscription, ",",
- sizeof(rt->last_subscription));
- ff_rdt_subscribe_rule(
- rt->last_subscription,
- sizeof(rt->last_subscription), i, rule_nr);
- first = 0;
- }
- rule_nr++;
- }
- }
- }
- av_strlcatf(cmd, sizeof(cmd), "%s\r\n", rt->last_subscription);
- ff_rtsp_send_cmd(s, "SET_PARAMETER", rt->control_uri,
- cmd, reply, NULL);
- if (reply->status_code != RTSP_STATUS_OK)
- return AVERROR_INVALIDDATA;
- rt->need_subscription = 0;
-
- if (rt->state == RTSP_STATE_STREAMING)
- rtsp_read_play (s);
- }
- }
-
- ret = rtsp_fetch_packet(s, pkt);
- if (ret < 0)
- return ret;
-
- /* send dummy request to keep TCP connection alive */
- if ((av_gettime() - rt->last_cmd_time) / 1000000 >= rt->timeout / 2) {
- if (rt->server_type == RTSP_SERVER_WMS) {
- ff_rtsp_send_cmd_async(s, "GET_PARAMETER", rt->control_uri, NULL);
- } else {
- ff_rtsp_send_cmd_async(s, "OPTIONS", "*", NULL);
- }
- }
-
- return 0;
-}
-
-/* pause the stream */
-static int rtsp_read_pause(AVFormatContext *s)
-{
- RTSPState *rt = s->priv_data;
- RTSPMessageHeader reply1, *reply = &reply1;
-
- if (rt->state != RTSP_STATE_STREAMING)
- return 0;
- else if (!(rt->server_type == RTSP_SERVER_REAL && rt->need_subscription)) {
- ff_rtsp_send_cmd(s, "PAUSE", rt->control_uri, NULL, reply, NULL);
- if (reply->status_code != RTSP_STATUS_OK) {
- return -1;
- }
- }
- rt->state = RTSP_STATE_PAUSED;
- return 0;
-}
-
-static int rtsp_read_seek(AVFormatContext *s, int stream_index,
- int64_t timestamp, int flags)
-{
- RTSPState *rt = s->priv_data;
-
- rt->seek_timestamp = av_rescale_q(timestamp,
- s->streams[stream_index]->time_base,
- AV_TIME_BASE_Q);
- switch(rt->state) {
- default:
- case RTSP_STATE_IDLE:
- break;
- case RTSP_STATE_STREAMING:
- if (rtsp_read_pause(s) != 0)
- return -1;
- rt->state = RTSP_STATE_SEEKING;
- if (rtsp_read_play(s) != 0)
- return -1;
- break;
- case RTSP_STATE_PAUSED:
- rt->state = RTSP_STATE_IDLE;
- break;
- }
- return 0;
-}
-
-static int rtsp_read_close(AVFormatContext *s)
-{
- RTSPState *rt = s->priv_data;
-
-#if 0
- /* NOTE: it is valid to flush the buffer here */
- if (rt->lower_transport == RTSP_LOWER_TRANSPORT_TCP) {
- url_fclose(&rt->rtsp_gb);
- }
-#endif
- ff_rtsp_send_cmd_async(s, "TEARDOWN", rt->control_uri, NULL);
-
- ff_rtsp_close_streams(s);
- ff_rtsp_close_connections(s);
- ff_network_close();
- rt->real_setup = NULL;
- av_freep(&rt->real_setup_cache);
- return 0;
-}
-
-AVInputFormat rtsp_demuxer = {
- "rtsp",
- NULL_IF_CONFIG_SMALL("RTSP input format"),
- sizeof(RTSPState),
- rtsp_probe,
- rtsp_read_header,
- rtsp_read_packet,
- rtsp_read_close,
- rtsp_read_seek,
- .flags = AVFMT_NOFILE,
- .read_play = rtsp_read_play,
- .read_pause = rtsp_read_pause,
-};
-#endif /* CONFIG_RTSP_DEMUXER */
-