Sometimes the URL parser cannot determine the app name automatically,
so it must be given explicitly using this option (ie. -app).
---
 libavformat/rtmpproto.c |   40 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 39 insertions(+), 1 deletion(-)

diff --git a/libavformat/rtmpproto.c b/libavformat/rtmpproto.c
index a6917ce..08bb86b 100644
--- a/libavformat/rtmpproto.c
+++ b/libavformat/rtmpproto.c
@@ -28,6 +28,7 @@
 #include "libavutil/avstring.h"
 #include "libavutil/intfloat.h"
 #include "libavutil/lfg.h"
+#include "libavutil/opt.h"
 #include "libavutil/sha.h"
 #include "avformat.h"
 #include "internal.h"
@@ -41,6 +42,8 @@
 
 //#define DEBUG
 
+#define APP_MAX_LENGTH 128
+
 /** RTMP protocol handler state */
 typedef enum {
     STATE_START,      ///< client has not done anything yet
@@ -61,7 +64,7 @@ typedef struct RTMPContext {
     int           chunk_size;                 ///< size of the chunks RTMP 
packets are divided into
     int           is_input;                   ///< input/output flag
     char          playpath[256];              ///< path to filename to play 
(with possible "mp4:" prefix)
-    char          app[128];                   ///< application
+    char          *app;                       ///< name of application
     ClientState   state;                      ///< current state
     int           main_channel_id;            ///< an additional channel ID 
which is used for some invocations
     uint8_t*      flv_data;                   ///< buffer with data for demuxer
@@ -789,6 +792,7 @@ static int rtmp_close(URLContext *h)
         gen_delete_stream(h, rt);
 
     av_freep(&rt->flv_data);
+    av_free(rt->app);
     ffurl_close(rt->stream);
     return 0;
 }
@@ -806,6 +810,7 @@ static int rtmp_open(URLContext *s, const char *uri, int 
flags)
 {
     RTMPContext *rt = s->priv_data;
     char proto[8], hostname[256], path[1024], *fname;
+    char *old_app;
     uint8_t buf[2048];
     int port;
     int ret;
@@ -831,6 +836,16 @@ static int rtmp_open(URLContext *s, const char *uri, int 
flags)
 
     rt->chunk_size = 128;
     rt->state = STATE_HANDSHAKED;
+
+    // Keep the application name when it has been defined by the user.
+    old_app = (rt->app) ? strdup(rt->app) : NULL;
+
+    rt->app = av_malloc(APP_MAX_LENGTH);
+    if (!rt->app) {
+        rtmp_close(s);
+        return AVERROR(ENOMEM);
+    }
+
     //extract "app" part from path
     if (!strncmp(path, "/ondemand/", 10)) {
         fname = path + 10;
@@ -852,6 +867,13 @@ static int rtmp_open(URLContext *s, const char *uri, int 
flags)
             }
         }
     }
+
+    if (old_app) {
+        // The name of application has been defined by the user, override it.
+        av_free(rt->app);
+        rt->app = old_app;
+    }
+
     if (!strchr(fname, ':') &&
         (!strcmp(fname + strlen(fname) - 4, ".f4v") ||
          !strcmp(fname + strlen(fname) - 4, ".mp4"))) {
@@ -997,6 +1019,21 @@ static int rtmp_write(URLContext *s, const uint8_t *buf, 
int size)
     return size;
 }
 
+#define OFFSET(x) offsetof(RTMPContext, x)
+#define DEC AV_OPT_FLAG_DECODING_PARAM
+
+static const AVOption rtmp_options[] = {
+    {"app", "Name of application to connect to on the RTMP server", 
OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
+    { NULL },
+};
+
+static const AVClass rtmp_class = {
+    .class_name = "rtmp",
+    .item_name  = av_default_item_name,
+    .option     = rtmp_options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
 URLProtocol ff_rtmp_protocol = {
     .name           = "rtmp",
     .url_open       = rtmp_open,
@@ -1005,4 +1042,5 @@ URLProtocol ff_rtmp_protocol = {
     .url_close      = rtmp_close,
     .priv_data_size = sizeof(RTMPContext),
     .flags          = URL_PROTOCOL_FLAG_NETWORK,
+    .priv_data_class= &rtmp_class,
 };
-- 
1.7.9.4

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to