X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Flibrtmp.c;h=7133bd655b7e5762c63a2600b4b2bd26ecf20581;hb=3b1c9eb0ffb680174ffaebb47b773a4628a2be6a;hp=c04c833c01b673c0cf304d3f9235b856f9a9b76f;hpb=7e58050590c556643869a1cc57215026ff88b0db;p=ffmpeg diff --git a/libavformat/librtmp.c b/libavformat/librtmp.c index c04c833c01b..7133bd655b7 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,24 +79,45 @@ 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, level; + char *filename = s->filename; switch (av_log_get_level()) { default: - case AV_LOG_FATAL: rc = RTMP_LOGCRIT; break; - case AV_LOG_ERROR: rc = RTMP_LOGERROR; break; - case AV_LOG_WARNING: rc = RTMP_LOGWARNING; break; - case AV_LOG_INFO: rc = RTMP_LOGINFO; break; - case AV_LOG_VERBOSE: rc = RTMP_LOGDEBUG; break; - case AV_LOG_DEBUG: rc = RTMP_LOGDEBUG2; break; + case AV_LOG_FATAL: level = RTMP_LOGCRIT; break; + case AV_LOG_ERROR: level = RTMP_LOGERROR; break; + case AV_LOG_WARNING: level = RTMP_LOGWARNING; break; + case AV_LOG_INFO: level = RTMP_LOGINFO; break; + case AV_LOG_VERBOSE: level = RTMP_LOGDEBUG; break; + case AV_LOG_DEBUG: level = RTMP_LOGDEBUG2; break; } - RTMP_LogSetLevel(rc); + RTMP_LogSetLevel(level); 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)) { - rc = -1; + if (!RTMP_SetupURL(r, filename)) { + rc = AVERROR_UNKNOWN; goto fail; } @@ -94,43 +125,49 @@ static int rtmp_open(URLContext *s, const char *uri, int flags) RTMP_EnableWrite(r); if (!RTMP_Connect(r, NULL) || !RTMP_ConnectStream(r, 0)) { - rc = -1; + rc = AVERROR_UNKNOWN; goto fail; } 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; + return AVERROR_UNKNOWN; return 0; } 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); @@ -141,18 +178,37 @@ static int64_t rtmp_read_seek(URLContext *s, int stream_index, flags & AVSEEK_FLAG_BACKWARD ? AV_ROUND_DOWN : AV_ROUND_UP); if (!RTMP_SendSeek(r, timestamp)) - return -1; + return AVERROR_UNKNOWN; return timestamp; } 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); } -URLProtocol ff_rtmp_protocol = { +#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, .url_read = rtmp_read, @@ -161,10 +217,13 @@ URLProtocol ff_rtmp_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, }; -URLProtocol ff_rtmpt_protocol = { +RTMP_CLASS(rtmpt) +URLProtocol ff_librtmpt_protocol = { .name = "rtmpt", .url_open = rtmp_open, .url_read = rtmp_read, @@ -173,10 +232,13 @@ URLProtocol ff_rtmpt_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, }; -URLProtocol ff_rtmpe_protocol = { +RTMP_CLASS(rtmpe) +URLProtocol ff_librtmpe_protocol = { .name = "rtmpe", .url_open = rtmp_open, .url_read = rtmp_read, @@ -185,10 +247,13 @@ URLProtocol ff_rtmpe_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, }; -URLProtocol ff_rtmpte_protocol = { +RTMP_CLASS(rtmpte) +URLProtocol ff_librtmpte_protocol = { .name = "rtmpte", .url_open = rtmp_open, .url_read = rtmp_read, @@ -197,10 +262,13 @@ URLProtocol ff_rtmpte_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, }; -URLProtocol ff_rtmps_protocol = { +RTMP_CLASS(rtmps) +URLProtocol ff_librtmps_protocol = { .name = "rtmps", .url_open = rtmp_open, .url_read = rtmp_read, @@ -209,5 +277,7 @@ URLProtocol ff_rtmps_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, };