summaryrefslogtreecommitdiff
path: root/libavformat/librtmp.c
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2012-06-03 10:07:54 +0200
committerAnton Khirnov <anton@khirnov.net>2012-06-03 15:45:55 +0200
commit007aedeebf3f42ba44ba5201be77be71ae4d09f6 (patch)
treec76b01aa2157e61963f87b396d0832dc9583a464 /libavformat/librtmp.c
parent96fadfb1588b1bf4968af371693e6484ce3050f8 (diff)
librtmp: add rtmp_app and rtmp_playpath private options.
This makes it easier to switch between native rtmp and librtmp.
Diffstat (limited to 'libavformat/librtmp.c')
-rw-r--r--libavformat/librtmp.c95
1 files changed, 80 insertions, 15 deletions
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 <librtmp/rtmp.h>
#include <librtmp/log.h>
+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,
};