Merge remote-tracking branch 'qatar/master'

* qatar/master:
  librtmp: return AVERROR_UNKNOWN instead of -1.
  librtmp: don't abuse a variable for two unrelated things.
  librtmp: add rtmp_app and rtmp_playpath private options.
  bmv: add stricter checks for invalid decoded length
  avpacket: fix duplicating side data.
  flv: support stream text data as onTextData

Conflicts:
	libavcodec/bmv.c
	libavformat/flvdec.c
	libavformat/flvenc.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
Michael Niedermayer 2012-06-04 00:33:42 +02:00
commit 7d82020fcb
5 changed files with 252 additions and 74 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,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,17 +178,36 @@ 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);
}
#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,
};