diff options
author | Ronald S. Bultje <rsbultje@gmail.com> | 2009-01-07 14:48:17 +0000 |
---|---|---|
committer | Ronald S. Bultje <rsbultje@gmail.com> | 2009-01-07 14:48:17 +0000 |
commit | 572c6a3814c7f08e9dca0cceaeb19265fcc57a6e (patch) | |
tree | a4d09f314e9967cb2f03b54c95b47fa9735cc8ed | |
parent | 7c68a17754ca1a42baccf8b90704a073f4514ece (diff) | |
download | ffmpeg-572c6a3814c7f08e9dca0cceaeb19265fcc57a6e.tar.gz |
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.
Originally committed as revision 16469 to svn://svn.ffmpeg.org/ffmpeg/trunk
-rw-r--r-- | libavformat/rtsp.c | 71 |
1 files changed, 56 insertions, 15 deletions
diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index 1e874ed5e1..f0c6e1b3ab 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -75,6 +75,8 @@ typedef struct RTSPState { 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 @@ static int rtsp_read_packet(AVFormatContext *s, 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->state == RTSP_STATE_PLAYING) - rtsp_read_play (s); + 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; + + 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 */ |