ffmpeg | branch: master | Lukasz Marek <lukasz.m.lu...@gmail.com> | Mon Nov 10 23:22:59 2014 +0100| [6690d4c3f53bd46144f3c13afcc77bcca3f7bb0b] | committer: Lukasz Marek
lavf/ffm: store/restore private codec context Signed-off-by: Lukasz Marek <lukasz.m.lu...@gmail.com> > http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=6690d4c3f53bd46144f3c13afcc77bcca3f7bb0b --- doc/APIchanges | 3 +++ libavformat/avformat.h | 8 ++++++++ libavformat/ffmdec.c | 36 +++++++++++++++++++++++++++++++----- libavformat/ffmenc.c | 35 +++++++++++++++++++++++++++++++++-- libavformat/utils.c | 2 ++ libavformat/version.h | 4 ++-- 6 files changed, 79 insertions(+), 9 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index b4a3ed8..79cccd2 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,9 @@ libavutil: 2014-08-09 API changes, most recent first: +2014-11-16 - xxxxxxx - lavf 56.13.0 - avformat.h + Add AVStream.recommended_encoder_configuration with accessors. + 2014-11-16 - xxxxxxx - lavu 54.13.0 - opt.h Add av_opt_serialize(). diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 3733549..56ab4e1 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -1097,11 +1097,19 @@ typedef struct AVStream { */ int inject_global_side_data; + /** + * String containing paris of key and values describing recommended encoder configuration. + * Paris are separated by ','. + * Keys are separated from values by '='. + */ + char *recommended_encoder_configuration; } AVStream; AVRational av_stream_get_r_frame_rate(const AVStream *s); void av_stream_set_r_frame_rate(AVStream *s, AVRational r); struct AVCodecParserContext *av_stream_get_parser(const AVStream *s); +char* av_stream_get_recommended_encoder_configuration(const AVStream *s); +void av_stream_set_recommended_encoder_configuration(AVStream *s, char *configuration); /** * Returns the pts of the last muxed packet + its duration diff --git a/libavformat/ffmdec.c b/libavformat/ffmdec.c index 448762b..1c848b9 100644 --- a/libavformat/ffmdec.c +++ b/libavformat/ffmdec.c @@ -23,6 +23,7 @@ #include "libavutil/intreadwrite.h" #include "libavutil/intfloat.h" +#include "libavutil/opt.h" #include "avformat.h" #include "internal.h" #include "ffm.h" @@ -237,6 +238,8 @@ static int ffm2_read_header(AVFormatContext *s) AVIOContext *pb = s->pb; AVCodecContext *codec; int ret; + int f_main = 0, f_cprv, f_stvi, f_stau; + AVCodec *enc; ffm->packet_size = avio_rb32(pb); if (ffm->packet_size != FFM_PACKET_SIZE) { @@ -267,10 +270,15 @@ static int ffm2_read_header(AVFormatContext *s) switch(id) { case MKBETAG('M', 'A', 'I', 'N'): + if (f_main++) { + ret = AVERROR(EINVAL); + goto fail; + } avio_rb32(pb); /* nb_streams */ avio_rb32(pb); /* total bitrate */ break; case MKBETAG('C', 'O', 'M', 'M'): + f_cprv = f_stvi = f_stau = 0; st = avformat_new_stream(s, NULL); if (!st) { ret = AVERROR(ENOMEM); @@ -291,12 +299,13 @@ static int ffm2_read_header(AVFormatContext *s) if (ff_get_extradata(codec, pb, avio_rb32(pb)) < 0) return AVERROR(ENOMEM); } - avio_seek(pb, next, SEEK_SET); - id = avio_rb32(pb); - size = avio_rb32(pb); - next = avio_tell(pb) + size; - switch(id) { + break; + //TODO: reident case MKBETAG('S', 'T', 'V', 'I'): + if (f_stvi++) { + ret = AVERROR(EINVAL); + goto fail; + } codec->time_base.num = avio_rb32(pb); codec->time_base.den = avio_rb32(pb); codec->width = avio_rb16(pb); @@ -343,10 +352,27 @@ static int ffm2_read_header(AVFormatContext *s) codec->refs = avio_rb32(pb); break; case MKBETAG('S', 'T', 'A', 'U'): + if (f_stau++) { + ret = AVERROR(EINVAL); + goto fail; + } codec->sample_rate = avio_rb32(pb); codec->channels = avio_rl16(pb); codec->frame_size = avio_rl16(pb); break; + case MKBETAG('C', 'P', 'R', 'V'): + if (f_cprv++) { + ret = AVERROR(EINVAL); + goto fail; + } + enc = avcodec_find_encoder(codec->codec_id); + if (enc && enc->priv_data_size && enc->priv_class) { + st->recommended_encoder_configuration = av_malloc(size + 1); + if (!st->recommended_encoder_configuration) { + ret = AVERROR(ENOMEM); + goto fail; + } + avio_get_str(pb, size, st->recommended_encoder_configuration, size + 1); } break; } diff --git a/libavformat/ffmenc.c b/libavformat/ffmenc.c index eb809eb..e0885e7 100644 --- a/libavformat/ffmenc.c +++ b/libavformat/ffmenc.c @@ -23,6 +23,7 @@ #include "libavutil/intfloat.h" #include "libavutil/avassert.h" #include "libavutil/parseutils.h" +#include "libavutil/opt.h" #include "avformat.h" #include "internal.h" #include "ffm.h" @@ -93,6 +94,32 @@ static void write_header_chunk(AVIOContext *pb, AVIOContext *dpb, unsigned id) av_free(dyn_buf); } +static int ffm_write_header_codec_private_ctx(AVIOContext *pb, AVCodecContext *ctx, int type) +{ + AVIOContext *tmp; + char *buf = NULL; + int ret; + const AVCodec *enc = ctx->codec ? ctx->codec : avcodec_find_encoder(ctx->codec_id); + + if (!enc) + return AVERROR(EINVAL); + if (ctx->priv_data && enc->priv_class && enc->priv_data_size) { + if ((ret = av_opt_serialize(ctx->priv_data, AV_OPT_FLAG_ENCODING_PARAM | type, + AV_OPT_SERIALIZE_SKIP_DEFAULTS, &buf, '=', ',')) < 0) + return ret; + if (buf && strlen(buf)) { + if (avio_open_dyn_buf(&tmp) < 0) { + av_free(buf); + return AVERROR(ENOMEM); + } + avio_put_str(tmp, buf); + write_header_chunk(pb, tmp, MKBETAG('C', 'P', 'R', 'V')); + } + av_free(buf); + } + return 0; +} + static int ffm_write_header(AVFormatContext *s) { FFMContext *ffm = s->priv_data; @@ -100,10 +127,10 @@ static int ffm_write_header(AVFormatContext *s) AVStream *st; AVIOContext *pb = s->pb; AVCodecContext *codec; - int bit_rate, i; + int bit_rate, i, ret; if (t = av_dict_get(s->metadata, "creation_time", NULL, 0)) { - int ret = av_parse_time(&ffm->start_time, t->value, 0); + ret = av_parse_time(&ffm->start_time, t->value, 0); if (ret < 0) return ret; } @@ -197,12 +224,16 @@ static int ffm_write_header(AVFormatContext *s) avio_wb32(pb, codec->max_qdiff); avio_wb32(pb, codec->refs); write_header_chunk(s->pb, pb, MKBETAG('S', 'T', 'V', 'I')); + if ((ret = ffm_write_header_codec_private_ctx(s->pb, codec, AV_OPT_FLAG_VIDEO_PARAM)) < 0) + return ret; break; case AVMEDIA_TYPE_AUDIO: avio_wb32(pb, codec->sample_rate); avio_wl16(pb, codec->channels); avio_wl16(pb, codec->frame_size); write_header_chunk(s->pb, pb, MKBETAG('S', 'T', 'A', 'U')); + if ((ret = ffm_write_header_codec_private_ctx(s->pb, codec, AV_OPT_FLAG_AUDIO_PARAM)) < 0) + return ret; break; default: return -1; diff --git a/libavformat/utils.c b/libavformat/utils.c index 8da8db4..39851fc 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -103,6 +103,7 @@ static int64_t wrap_timestamp(AVStream *st, int64_t timestamp) } MAKE_ACCESSORS(AVStream, stream, AVRational, r_frame_rate) +MAKE_ACCESSORS(AVStream, stream, char *, recommended_encoder_configuration) MAKE_ACCESSORS(AVFormatContext, format, AVCodec *, video_codec) MAKE_ACCESSORS(AVFormatContext, format, AVCodec *, audio_codec) MAKE_ACCESSORS(AVFormatContext, format, AVCodec *, subtitle_codec) @@ -3537,6 +3538,7 @@ void ff_free_stream(AVFormatContext *s, AVStream *st) { if (st->info) av_freep(&st->info->duration_error); av_freep(&st->info); + av_freep(&st->recommended_encoder_configuration); av_freep(&s->streams[ --s->nb_streams ]); } diff --git a/libavformat/version.h b/libavformat/version.h index 4596175..27f2861 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -30,8 +30,8 @@ #include "libavutil/version.h" #define LIBAVFORMAT_VERSION_MAJOR 56 -#define LIBAVFORMAT_VERSION_MINOR 12 -#define LIBAVFORMAT_VERSION_MICRO 103 +#define LIBAVFORMAT_VERSION_MINOR 13 +#define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ _______________________________________________ ffmpeg-cvslog mailing list ffmpeg-cvslog@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-cvslog