Implement a RDT-specific SET_PARAMETER command that subscribes to the
authorRonald S. Bultje <rsbultje@gmail.com>
Sun, 7 Sep 2008 01:22:18 +0000 (01:22 +0000)
committerRonald S. Bultje <rsbultje@gmail.com>
Sun, 7 Sep 2008 01:22:18 +0000 (01:22 +0000)
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
libavformat/rdt.h
libavformat/rtsp.c

index e5a1f89..6ed0f19 100644 (file)
@@ -134,6 +134,18 @@ rdt_load_mdpr (rdt_data *rdt, AVStream *st, int rule_nr)
     return 0;
 }
 
     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)
 {
 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);
 
     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);
 
     } else if (av_strstart(p, "StartTime:integer;", &p))
         stream->first_dts = atoi(p);
 
index 5da9a78..37b1928 100644 (file)
@@ -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);
 
  */
 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 */
 #endif /* AVFORMAT_RDT_H */
index 98f868e..20e7062 100644 (file)
@@ -65,6 +65,7 @@ typedef struct RTSPState {
     enum RTSPServerType server_type;
     char last_reply[2048]; /* XXX: allocate ? */
     RTPDemuxContext *cur_rtp;
     enum RTSPServerType server_type;
     char last_reply[2048]; /* XXX: allocate ? */
     RTPDemuxContext *cur_rtp;
+    int need_subscription;
 } RTSPState;
 
 typedef struct RTSPStream {
 } 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:
     return 0;
 
 fail:
@@ -1295,6 +1299,31 @@ static int rtsp_read_packet(AVFormatContext *s,
     int ret, len;
     uint8_t buf[RTP_MAX_PACKET_LENGTH];
 
     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);
     /* 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);
 
 
     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",
     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;
     }
     if (reply->status_code != RTSP_STATUS_OK) {
         return -1;
     }
+    }
     rt->state = RTSP_STATE_PLAYING;
     return 0;
 }
     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;
 
     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);
     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;
     }
     if (reply->status_code != RTSP_STATUS_OK) {
         return -1;
     }
+    }
     rt->state = RTSP_STATE_PAUSED;
     return 0;
 }
     rt->state = RTSP_STATE_PAUSED;
     return 0;
 }