librtmp: add rtmp_app and rtmp_playpath private options.

This makes it easier to switch between native rtmp and librtmp.
This commit is contained in:
Anton Khirnov 2012-06-03 10:07:54 +02:00
parent 96fadfb158
commit 007aedeebf
1 changed files with 80 additions and 15 deletions

View File

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