Browse code

RTMPTS protocol support

Signed-off-by: Martin Storsjö <martin@martin.st>

Samuel Pitoiset authored on 2012/07/17 19:02:43
Showing 9 changed files
... ...
@@ -36,6 +36,7 @@ version <next>:
36 36
 - AAC encoding via libfdk-aac
37 37
 - Microsoft Expression Encoder Screen decoder
38 38
 - RTMPS protocol support
39
+- RTMPTS protocol support
39 40
 
40 41
 
41 42
 version 0.8:
... ...
@@ -1547,6 +1547,8 @@ rtmps_protocol_deps="!librtmp_protocol"
1547 1547
 rtmps_protocol_select="tls_protocol"
1548 1548
 rtmpt_protocol_deps="!librtmp_protocol"
1549 1549
 rtmpt_protocol_select="ffrtmphttp_protocol"
1550
+rtmpts_protocol_deps="!librtmp_protocol"
1551
+rtmpts_protocol_select="ffrtmphttp_protocol"
1550 1552
 rtp_protocol_select="udp_protocol"
1551 1553
 sctp_protocol_deps="network netinet_sctp_h"
1552 1554
 tcp_protocol_deps="network"
... ...
@@ -847,6 +847,7 @@ performance on systems without hardware floating point support).
847 847
 @item RTMPS        @tab X
848 848
 @item RTMPT        @tab X
849 849
 @item RTMPTE       @tab E
850
+@item RTMPTS       @tab X
850 851
 @item RTP          @tab X
851 852
 @item SCTP         @tab X
852 853
 @item TCP          @tab X
... ...
@@ -262,6 +262,14 @@ The Real-Time Messaging Protocol tunneled through HTTP (RTMPT) is used
262 262
 for streaming multimedia content within HTTP requests to traverse
263 263
 firewalls.
264 264
 
265
+@section rtmpts
266
+
267
+Real-Time Messaging Protocol tunneled through HTTPS.
268
+
269
+The Real-Time Messaging Protocol tunneled through HTTPS (RTMPTS) is used
270
+for streaming multimedia content within HTTPS requests to traverse
271
+firewalls.
272
+
265 273
 @section rtmp, rtmpe, rtmps, rtmpt, rtmpte
266 274
 
267 275
 Real-Time Messaging Protocol and its variants supported through
... ...
@@ -354,6 +354,7 @@ OBJS-$(CONFIG_PIPE_PROTOCOL)             += file.o
354 354
 OBJS-$(CONFIG_RTMP_PROTOCOL)             += rtmpproto.o rtmppkt.o
355 355
 OBJS-$(CONFIG_RTMPS_PROTOCOL)            += rtmpproto.o rtmppkt.o
356 356
 OBJS-$(CONFIG_RTMPT_PROTOCOL)            += rtmpproto.o rtmppkt.o
357
+OBJS-$(CONFIG_RTMPTS_PROTOCOL)           += rtmpproto.o rtmppkt.o
357 358
 OBJS-$(CONFIG_RTP_PROTOCOL)              += rtpproto.o
358 359
 OBJS-$(CONFIG_SCTP_PROTOCOL)             += sctp.o
359 360
 OBJS-$(CONFIG_TCP_PROTOCOL)              += tcp.o
... ...
@@ -260,6 +260,7 @@ void av_register_all(void)
260 260
     REGISTER_PROTOCOL (RTMP, rtmp);
261 261
     REGISTER_PROTOCOL (RTMPS, rtmps);
262 262
     REGISTER_PROTOCOL (RTMPT, rtmpt);
263
+    REGISTER_PROTOCOL (RTMPTS, rtmpts);
263 264
     REGISTER_PROTOCOL (RTP, rtp);
264 265
     REGISTER_PROTOCOL (SCTP, sctp);
265 266
     REGISTER_PROTOCOL (TCP, tcp);
... ...
@@ -30,11 +30,14 @@
30 30
 #include "libavutil/time.h"
31 31
 #include "internal.h"
32 32
 #include "http.h"
33
+#include "rtmp.h"
33 34
 
34 35
 #define RTMPT_DEFAULT_PORT 80
36
+#define RTMPTS_DEFAULT_PORT RTMPS_DEFAULT_PORT
35 37
 
36 38
 /* protocol handler context */
37 39
 typedef struct RTMP_HTTPContext {
40
+    const AVClass *class;
38 41
     URLContext   *stream;           ///< HTTP stream
39 42
     char         host[256];         ///< hostname of the server
40 43
     int          port;              ///< port to connect (default is 80)
... ...
@@ -46,6 +49,7 @@ typedef struct RTMP_HTTPContext {
46 46
     int          initialized;       ///< flag indicating when the http context is initialized
47 47
     int          finishing;         ///< flag indicating when the client closes the connection
48 48
     int          nb_bytes_read;     ///< number of bytes read since the last request
49
+    int          tls;               ///< use Transport Security Layer (RTMPTS)
49 50
 } RTMP_HTTPContext;
50 51
 
51 52
 static int rtmp_http_send_cmd(URLContext *h, const char *cmd)
... ...
@@ -185,9 +189,6 @@ static int rtmp_http_open(URLContext *h, const char *uri, int flags)
185 185
     av_url_split(NULL, 0, NULL, 0, rt->host, sizeof(rt->host), &rt->port,
186 186
                  NULL, 0, uri);
187 187
 
188
-    if (rt->port < 0)
189
-        rt->port = RTMPT_DEFAULT_PORT;
190
-
191 188
     /* This is the first request that is sent to the server in order to
192 189
      * register a client on the server and start a new session. The server
193 190
      * replies with a unique id (usually a number) that is used by the client
... ...
@@ -195,7 +196,15 @@ static int rtmp_http_open(URLContext *h, const char *uri, int flags)
195 195
      * Note: the reply doesn't contain a value for the polling interval.
196 196
      * A successful connect resets the consecutive index that is used
197 197
      * in the URLs. */
198
-    ff_url_join(url, sizeof(url), "http", NULL, rt->host, rt->port, "/open/1");
198
+    if (rt->tls) {
199
+        if (rt->port < 0)
200
+            rt->port = RTMPTS_DEFAULT_PORT;
201
+        ff_url_join(url, sizeof(url), "https", NULL, rt->host, rt->port, "/open/1");
202
+    } else {
203
+        if (rt->port < 0)
204
+            rt->port = RTMPT_DEFAULT_PORT;
205
+        ff_url_join(url, sizeof(url), "http", NULL, rt->host, rt->port, "/open/1");
206
+    }
199 207
 
200 208
     /* alloc the http context */
201 209
     if ((ret = ffurl_alloc(&rt->stream, url, AVIO_FLAG_READ_WRITE, NULL)) < 0)
... ...
@@ -240,6 +249,21 @@ fail:
240 240
     return ret;
241 241
 }
242 242
 
243
+#define OFFSET(x) offsetof(RTMP_HTTPContext, x)
244
+#define DEC AV_OPT_FLAG_DECODING_PARAM
245
+
246
+static const AVOption ffrtmphttp_options[] = {
247
+    {"ffrtmphttp_tls", "Use a HTTPS tunneling connection (RTMPTS).", OFFSET(tls), AV_OPT_TYPE_INT, {0}, 0, 1, DEC},
248
+    { NULL },
249
+};
250
+
251
+static const AVClass ffrtmphttp_class = {
252
+    .class_name = "ffrtmphttp",
253
+    .item_name  = av_default_item_name,
254
+    .option     = ffrtmphttp_options,
255
+    .version    = LIBAVUTIL_VERSION_INT,
256
+};
257
+
243 258
 URLProtocol ff_ffrtmphttp_protocol = {
244 259
     .name           = "ffrtmphttp",
245 260
     .url_open       = rtmp_http_open,
... ...
@@ -248,4 +272,5 @@ URLProtocol ff_ffrtmphttp_protocol = {
248 248
     .url_close      = rtmp_http_close,
249 249
     .priv_data_size = sizeof(RTMP_HTTPContext),
250 250
     .flags          = URL_PROTOCOL_FLAG_NETWORK,
251
+    .priv_data_class= &ffrtmphttp_class,
251 252
 };
... ...
@@ -1111,6 +1111,7 @@ static int rtmp_open(URLContext *s, const char *uri, int flags)
1111 1111
     char *old_app;
1112 1112
     uint8_t buf[2048];
1113 1113
     int port;
1114
+    AVDictionary *opts = NULL;
1114 1115
     int ret;
1115 1116
 
1116 1117
     rt->is_input = !(flags & AVIO_FLAG_WRITE);
... ...
@@ -1118,7 +1119,10 @@ static int rtmp_open(URLContext *s, const char *uri, int flags)
1118 1118
     av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port,
1119 1119
                  path, sizeof(path), s->filename);
1120 1120
 
1121
-    if (!strcmp(proto, "rtmpt")) {
1121
+    if (!strcmp(proto, "rtmpt") || !strcmp(proto, "rtmpts")) {
1122
+        if (!strcmp(proto, "rtmpts"))
1123
+            av_dict_set(&opts, "ffrtmphttp_tls", "1", 1);
1124
+
1122 1125
         /* open the http tunneling connection */
1123 1126
         ff_url_join(buf, sizeof(buf), "ffrtmphttp", NULL, hostname, port, NULL);
1124 1127
     } else if (!strcmp(proto, "rtmps")) {
... ...
@@ -1134,7 +1138,7 @@ static int rtmp_open(URLContext *s, const char *uri, int flags)
1134 1134
     }
1135 1135
 
1136 1136
     if ((ret = ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
1137
-                          &s->interrupt_callback, NULL)) < 0) {
1137
+                          &s->interrupt_callback, &opts)) < 0) {
1138 1138
         av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
1139 1139
         goto fail;
1140 1140
     }
... ...
@@ -1266,6 +1270,7 @@ static int rtmp_open(URLContext *s, const char *uri, int flags)
1266 1266
     return 0;
1267 1267
 
1268 1268
 fail:
1269
+    av_dict_free(&opts);
1269 1270
     rtmp_close(s);
1270 1271
     return ret;
1271 1272
 }
... ...
@@ -1484,3 +1489,21 @@ URLProtocol ff_rtmpt_protocol = {
1484 1484
     .flags           = URL_PROTOCOL_FLAG_NETWORK,
1485 1485
     .priv_data_class = &rtmpt_class,
1486 1486
 };
1487
+
1488
+static const AVClass rtmpts_class = {
1489
+    .class_name = "rtmpts",
1490
+    .item_name  = av_default_item_name,
1491
+    .option     = rtmp_options,
1492
+    .version    = LIBAVUTIL_VERSION_INT,
1493
+};
1494
+
1495
+URLProtocol ff_rtmpts_protocol = {
1496
+    .name            = "rtmpts",
1497
+    .url_open        = rtmp_open,
1498
+    .url_read        = rtmp_read,
1499
+    .url_write       = rtmp_write,
1500
+    .url_close       = rtmp_close,
1501
+    .priv_data_size  = sizeof(RTMPContext),
1502
+    .flags           = URL_PROTOCOL_FLAG_NETWORK,
1503
+    .priv_data_class = &rtmpts_class,
1504
+};
... ...
@@ -30,7 +30,7 @@
30 30
 #include "libavutil/avutil.h"
31 31
 
32 32
 #define LIBAVFORMAT_VERSION_MAJOR 54
33
-#define LIBAVFORMAT_VERSION_MINOR  8
33
+#define LIBAVFORMAT_VERSION_MINOR  9
34 34
 #define LIBAVFORMAT_VERSION_MICRO  0
35 35
 
36 36
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \