# HG changeset patch # User rbultje # Date 1231339697 0 # Node ID 1dbda91eaebd5d7cbff61cc817a5aa43b3f38bf2 # Parent 8b294ed0bd6570e718720137f1feaa80e7271875 Allow subscription to any of the streams, not just the first, available in this RTSP/RDT session. This basically implies full RDT support, including stream selection in ffmpeg and multi-stream backupping in ffmpeg (by mapping each stream to an output). See "[PATCH] RTSP/RDT: subscriptions" thread on mailinglist. diff -r 8b294ed0bd65 -r 1dbda91eaebd rtsp.c --- a/rtsp.c Wed Jan 07 14:45:13 2009 +0000 +++ b/rtsp.c Wed Jan 07 14:48:17 2009 +0000 @@ -75,6 +75,8 @@ char last_reply[2048]; /* XXX: allocate ? */ void *cur_tx; int need_subscription; + enum AVDiscard real_setup_cache[MAX_STREAMS]; + char last_subscription[1024]; } RTSPState; typedef struct RTSPStream { @@ -1352,27 +1354,66 @@ int ret, len; uint8_t buf[RTP_MAX_PACKET_LENGTH]; - if (rt->server_type == RTSP_SERVER_REAL && rt->need_subscription) { + if (rt->server_type == RTSP_SERVER_REAL) { int i; RTSPHeader reply1, *reply = &reply1; + enum AVDiscard cache[MAX_STREAMS]; char cmd[1024]; - snprintf(cmd, sizeof(cmd), - "SET_PARAMETER %s RTSP/1.0\r\n" - "Subscribe: ", - s->filename); - for (i = 0; i < rt->nb_rtsp_streams; i++) { - if (i != 0) av_strlcat(cmd, ",", sizeof(cmd)); - ff_rdt_subscribe_rule(cmd, sizeof(cmd), i, 0); + for (i = 0; i < s->nb_streams; i++) + cache[i] = s->streams[i]->discard; + + if (!rt->need_subscription) { + if (memcmp (cache, rt->real_setup_cache, + sizeof(enum AVDiscard) * s->nb_streams)) { + av_strlcatf(cmd, sizeof(cmd), + "SET_PARAMETER %s RTSP/1.0\r\n" + "Unsubscribe: %s\r\n", + s->filename, rt->last_subscription); + rtsp_send_cmd(s, cmd, reply, NULL); + if (reply->status_code != RTSP_STATUS_OK) + return AVERROR_INVALIDDATA; + rt->need_subscription = 1; + } } - av_strlcat(cmd, "\r\n", sizeof(cmd)); - rtsp_send_cmd(s, cmd, reply, NULL); - if (reply->status_code != RTSP_STATUS_OK) - return AVERROR_INVALIDDATA; - rt->need_subscription = 0; + + if (rt->need_subscription) { + int r, rule_nr, first = 1; + + memcpy(rt->real_setup_cache, cache, + sizeof(enum AVDiscard) * s->nb_streams); + rt->last_subscription[0] = 0; - if (rt->state == RTSP_STATE_PLAYING) - rtsp_read_play (s); + snprintf(cmd, sizeof(cmd), + "SET_PARAMETER %s RTSP/1.0\r\n" + "Subscribe: ", + s->filename); + 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); + rtsp_send_cmd(s, cmd, reply, NULL); + if (reply->status_code != RTSP_STATUS_OK) + return AVERROR_INVALIDDATA; + rt->need_subscription = 0; + + if (rt->state == RTSP_STATE_PLAYING) + rtsp_read_play (s); + } } /* get next frames from the same RTP packet */