From 007aedeebf3f42ba44ba5201be77be71ae4d09f6 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 3 Jun 2012 10:07:54 +0200 Subject: librtmp: add rtmp_app and rtmp_playpath private options. This makes it easier to switch between native rtmp and librtmp. --- libavformat/librtmp.c | 95 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 80 insertions(+), 15 deletions(-) (limited to 'libavformat/librtmp.c') diff --git a/libavformat/librtmp.c b/libavformat/librtmp.c index 8883bbc65f..4641c5d21e 100644 --- a/libavformat/librtmp.c +++ b/libavformat/librtmp.c @@ -24,13 +24,22 @@ * RTMP protocol based on http://rtmpdump.mplayerhq.hu/ librtmp */ +#include "libavutil/avstring.h" #include "libavutil/mathematics.h" +#include "libavutil/opt.h" #include "avformat.h" #include "url.h" #include #include +typedef struct LibRTMPContext { + const AVClass *class; + RTMP rtmp; + char *app; + char *playpath; +} LibRTMPContext; + static void rtmp_log(int level, const char *fmt, va_list args) { switch (level) { @@ -49,7 +58,8 @@ static void rtmp_log(int level, const char *fmt, va_list args) static int rtmp_close(URLContext *s) { - RTMP *r = s->priv_data; + LibRTMPContext *ctx = s->priv_data; + RTMP *r = &ctx->rtmp; RTMP_Close(r); return 0; @@ -69,8 +79,10 @@ static int rtmp_close(URLContext *s) */ static int rtmp_open(URLContext *s, const char *uri, int flags) { - RTMP *r = s->priv_data; - int rc; + LibRTMPContext *ctx = s->priv_data; + RTMP *r = &ctx->rtmp; + int rc = 0; + char *filename = s->filename; switch (av_log_get_level()) { default: @@ -84,8 +96,27 @@ static int rtmp_open(URLContext *s, const char *uri, int flags) RTMP_LogSetLevel(rc); RTMP_LogSetCallback(rtmp_log); + if (ctx->app || ctx->playpath) { + int len = strlen(s->filename) + 1; + if (ctx->app) len += strlen(ctx->app) + sizeof(" app="); + if (ctx->playpath) len += strlen(ctx->playpath) + sizeof(" playpath="); + + if (!(filename = av_malloc(len))) + return AVERROR(ENOMEM); + + av_strlcpy(filename, s->filename, len); + if (ctx->app) { + av_strlcat(filename, " app=", len); + av_strlcat(filename, ctx->app, len); + } + if (ctx->playpath) { + av_strlcat(filename, " playpath=", len); + av_strlcat(filename, ctx->playpath, len); + } + } + RTMP_Init(r); - if (!RTMP_SetupURL(r, s->filename)) { + if (!RTMP_SetupURL(r, filename)) { rc = -1; goto fail; } @@ -99,28 +130,33 @@ static int rtmp_open(URLContext *s, const char *uri, int flags) } s->is_streamed = 1; - return 0; + rc = 0; fail: + if (filename != s->filename) + av_freep(&filename); return rc; } static int rtmp_write(URLContext *s, const uint8_t *buf, int size) { - RTMP *r = s->priv_data; + LibRTMPContext *ctx = s->priv_data; + RTMP *r = &ctx->rtmp; return RTMP_Write(r, buf, size); } static int rtmp_read(URLContext *s, uint8_t *buf, int size) { - RTMP *r = s->priv_data; + LibRTMPContext *ctx = s->priv_data; + RTMP *r = &ctx->rtmp; return RTMP_Read(r, buf, size); } static int rtmp_read_pause(URLContext *s, int pause) { - RTMP *r = s->priv_data; + LibRTMPContext *ctx = s->priv_data; + RTMP *r = &ctx->rtmp; if (!RTMP_Pause(r, pause)) return -1; @@ -130,7 +166,8 @@ static int rtmp_read_pause(URLContext *s, int pause) static int64_t rtmp_read_seek(URLContext *s, int stream_index, int64_t timestamp, int flags) { - RTMP *r = s->priv_data; + LibRTMPContext *ctx = s->priv_data; + RTMP *r = &ctx->rtmp; if (flags & AVSEEK_FLAG_BYTE) return AVERROR(ENOSYS); @@ -147,11 +184,30 @@ static int64_t rtmp_read_seek(URLContext *s, int stream_index, static int rtmp_get_file_handle(URLContext *s) { - RTMP *r = s->priv_data; + LibRTMPContext *ctx = s->priv_data; + RTMP *r = &ctx->rtmp; return RTMP_Socket(r); } +#define OFFSET(x) offsetof(LibRTMPContext, x) +#define DEC AV_OPT_FLAG_DECODING_PARAM +#define ENC AV_OPT_FLAG_ENCODING_PARAM +static const AVOption 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}, + {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC}, + { NULL }, +}; + +#define RTMP_CLASS(flavor)\ +static const AVClass lib ## flavor ## _class = {\ + .class_name = "lib" #flavor " protocol",\ + .item_name = av_default_item_name,\ + .option = options,\ + .version = LIBAVUTIL_VERSION_INT,\ +}; + +RTMP_CLASS(rtmp) URLProtocol ff_librtmp_protocol = { .name = "rtmp", .url_open = rtmp_open, @@ -161,10 +217,12 @@ URLProtocol ff_librtmp_protocol = { .url_read_pause = rtmp_read_pause, .url_read_seek = rtmp_read_seek, .url_get_file_handle = rtmp_get_file_handle, - .priv_data_size = sizeof(RTMP), + .priv_data_size = sizeof(LibRTMPContext), + .priv_data_class = &librtmp_class, .flags = URL_PROTOCOL_FLAG_NETWORK, }; +RTMP_CLASS(rtmpt) URLProtocol ff_librtmpt_protocol = { .name = "rtmpt", .url_open = rtmp_open, @@ -174,10 +232,12 @@ URLProtocol ff_librtmpt_protocol = { .url_read_pause = rtmp_read_pause, .url_read_seek = rtmp_read_seek, .url_get_file_handle = rtmp_get_file_handle, - .priv_data_size = sizeof(RTMP), + .priv_data_size = sizeof(LibRTMPContext), + .priv_data_class = &librtmpt_class, .flags = URL_PROTOCOL_FLAG_NETWORK, }; +RTMP_CLASS(rtmpe) URLProtocol ff_librtmpe_protocol = { .name = "rtmpe", .url_open = rtmp_open, @@ -187,10 +247,12 @@ URLProtocol ff_librtmpe_protocol = { .url_read_pause = rtmp_read_pause, .url_read_seek = rtmp_read_seek, .url_get_file_handle = rtmp_get_file_handle, - .priv_data_size = sizeof(RTMP), + .priv_data_size = sizeof(LibRTMPContext), + .priv_data_class = &librtmpe_class, .flags = URL_PROTOCOL_FLAG_NETWORK, }; +RTMP_CLASS(rtmpte) URLProtocol ff_librtmpte_protocol = { .name = "rtmpte", .url_open = rtmp_open, @@ -200,10 +262,12 @@ URLProtocol ff_librtmpte_protocol = { .url_read_pause = rtmp_read_pause, .url_read_seek = rtmp_read_seek, .url_get_file_handle = rtmp_get_file_handle, - .priv_data_size = sizeof(RTMP), + .priv_data_size = sizeof(LibRTMPContext), + .priv_data_class = &librtmpte_class, .flags = URL_PROTOCOL_FLAG_NETWORK, }; +RTMP_CLASS(rtmps) URLProtocol ff_librtmps_protocol = { .name = "rtmps", .url_open = rtmp_open, @@ -213,6 +277,7 @@ URLProtocol ff_librtmps_protocol = { .url_read_pause = rtmp_read_pause, .url_read_seek = rtmp_read_seek, .url_get_file_handle = rtmp_get_file_handle, - .priv_data_size = sizeof(RTMP), + .priv_data_size = sizeof(LibRTMPContext), + .priv_data_class = &librtmps_class, .flags = URL_PROTOCOL_FLAG_NETWORK, }; -- cgit v1.2.3