From 1256d16b6cf937c180bb898a37e1c79a27b79922 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Sun, 7 Sep 2008 01:22:18 +0000 Subject: [PATCH] Implement a RDT-specific SET_PARAMETER command that subscribes to the first stream in a RTSP/RDT session. See discussion in "Realmedia patch" thread on ML. Originally committed as revision 15235 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavformat/rdt.c | 13 ++++++++++++- libavformat/rdt.h | 12 ++++++++++++ libavformat/rtsp.c | 34 +++++++++++++++++++++++++++++++++- 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/libavformat/rdt.c b/libavformat/rdt.c index e5a1f89c6d..6ed0f19417 100644 --- a/libavformat/rdt.c +++ b/libavformat/rdt.c @@ -134,6 +134,18 @@ rdt_load_mdpr (rdt_data *rdt, AVStream *st, int rule_nr) return 0; } +void +ff_rdt_subscribe_rule (RTPDemuxContext *s, char *cmd, int size, + int stream_nr, int rule_nr) +{ + rdt_data *rdt = s->dynamic_protocol_context; + + av_strlcatf(cmd, size, "stream=%d;rule=%d,stream=%d;rule=%d", + stream_nr, rule_nr, stream_nr, rule_nr + 1); + + rdt_load_mdpr(rdt, s->st, 0); +} + static unsigned char * rdt_parse_b64buf (unsigned int *target_len, const char *p) { @@ -157,7 +169,6 @@ rdt_parse_sdp_line (AVStream *stream, void *d, const char *line) if (av_strstart(p, "OpaqueData:buffer;", &p)) { rdt->mlti_data = rdt_parse_b64buf(&rdt->mlti_data_size, p); - rdt_load_mdpr(rdt, stream, 0); } else if (av_strstart(p, "StartTime:integer;", &p)) stream->first_dts = atoi(p); diff --git a/libavformat/rdt.h b/libavformat/rdt.h index 5da9a78628..37b1928570 100644 --- a/libavformat/rdt.h +++ b/libavformat/rdt.h @@ -42,4 +42,16 @@ void ff_rdt_calc_response_and_checksum(char response[41], char chksum[9], */ void av_register_rdt_dynamic_payload_handlers(void); +/** + * Add subscription information to Subscribe parameter string. + * + * @param s RDT context + * @param cmd string to write the subscription information into. + * @param size size of cmd. + * @param stream_nr stream number. + * @param rule_nr rule number to conform to. + */ +void ff_rdt_subscribe_rule(RTPDemuxContext *s, char *cmd, int size, + int stream_nr, int rule_nr); + #endif /* AVFORMAT_RDT_H */ diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index 98f868e8a7..20e706229b 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -65,6 +65,7 @@ typedef struct RTSPState { enum RTSPServerType server_type; char last_reply[2048]; /* XXX: allocate ? */ RTPDemuxContext *cur_rtp; + int need_subscription; } RTSPState; typedef struct RTSPStream { @@ -1034,6 +1035,9 @@ make_setup_request (AVFormatContext *s, const char *host, int port, } } + if (rt->server_type == RTSP_SERVER_RDT) + rt->need_subscription = 1; + return 0; fail: @@ -1295,6 +1299,31 @@ static int rtsp_read_packet(AVFormatContext *s, int ret, len; uint8_t buf[RTP_MAX_PACKET_LENGTH]; + if (rt->server_type == RTSP_SERVER_RDT && rt->need_subscription) { + int i; + RTSPHeader reply1, *reply = &reply1; + 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( + rt->rtsp_streams[i]->rtp_ctx, + cmd, sizeof(cmd), i, 0); + } + 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); + } + /* get next frames from the same RTP packet */ if (rt->cur_rtp) { ret = rtp_parse_packet(rt->cur_rtp, pkt, NULL, 0); @@ -1342,6 +1371,7 @@ static int rtsp_read_play(AVFormatContext *s) av_log(s, AV_LOG_DEBUG, "hello state=%d\n", rt->state); + if (!(rt->server_type == RTSP_SERVER_RDT && rt->need_subscription)) { if (rt->state == RTSP_STATE_PAUSED) { snprintf(cmd, sizeof(cmd), "PLAY %s RTSP/1.0\r\n", @@ -1357,6 +1387,7 @@ static int rtsp_read_play(AVFormatContext *s) if (reply->status_code != RTSP_STATUS_OK) { return -1; } + } rt->state = RTSP_STATE_PLAYING; return 0; } @@ -1372,7 +1403,7 @@ static int rtsp_read_pause(AVFormatContext *s) if (rt->state != RTSP_STATE_PLAYING) return 0; - + else if (!(rt->server_type == RTSP_SERVER_RDT && rt->need_subscription)) { snprintf(cmd, sizeof(cmd), "PAUSE %s RTSP/1.0\r\n", s->filename); @@ -1380,6 +1411,7 @@ static int rtsp_read_pause(AVFormatContext *s) if (reply->status_code != RTSP_STATUS_OK) { return -1; } + } rt->state = RTSP_STATE_PAUSED; return 0; }