On Tue, 3 Apr 2012, Samuel Pitoiset wrote:

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;
}

IIRC this shouldn't be needed, if you've declared it as an option, the normal option handling logic should free it (regardless if you've set it via an option or set by the protocol code itself).

@@ -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;

Please use av_strdup instead of plain strdup (otherwise you can't use av_free to free it).

+
+    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;
+    }
+

Hmm, this doesn't feel too nice, but I do see that we need to do the same parsing to find the playpath. Or should the full path be used as playpath if an app parameter is given? (How does rtmpdump/librtmp do it?)

    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

If you add a private class, you need to add const AVClass *class; as the first member of the RTMPContext struct - the framework code will assume the first member is such a class pointer.

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

Reply via email to