diff --git a/libavformat/rtmpproto.c b/libavformat/rtmpproto.c index 76835592d3..1d27c6f8e8 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 @@ -56,12 +59,13 @@ typedef enum { /** protocol handler context */ typedef struct RTMPContext { + const AVClass *class; URLContext* stream; ///< TCP stream used in interactions with RTMP server RTMPPacket prev_pkt[2][RTMP_CHANNELS]; ///< packet history used when reading and sending packets 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 @@ -822,6 +826,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; @@ -847,6 +852,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; + + 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; @@ -868,6 +883,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"))) { @@ -1013,6 +1035,22 @@ 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 +#define ENC AV_OPT_FLAG_ENCODING_PARAM + +static const AVOption rtmp_options[] = { + {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC}, + { 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, @@ -1021,4 +1059,5 @@ URLProtocol ff_rtmp_protocol = { .url_close = rtmp_close, .priv_data_size = sizeof(RTMPContext), .flags = URL_PROTOCOL_FLAG_NETWORK, + .priv_data_class= &rtmp_class, };