X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fffmenc.c;h=ef7dc3a03113a3c5fe17245b62613a1b00d32f62;hb=566bfd59c963938e183d523be9216b3f95ad8a09;hp=221f0a2cfdc5f3daefd122a792f09559e3dade7c;hpb=c06d4f2cedb76f2a38732ff45d12b584d2900c19;p=ffmpeg diff --git a/libavformat/ffmenc.c b/libavformat/ffmenc.c index 221f0a2cfdc..ef7dc3a0311 100644 --- a/libavformat/ffmenc.c +++ b/libavformat/ffmenc.c @@ -95,11 +95,12 @@ static void write_header_chunk(AVIOContext *pb, AVIOContext *dpb, unsigned id) av_free(dyn_buf); } -static int ffm_write_header_codec_ctx(AVIOContext *pb, AVCodecContext *ctx, unsigned tag, int type) +static int ffm_write_header_codec_ctx(AVIOContext *pb, AVCodecParameters *ctxpar, unsigned tag, int type) { AVIOContext *tmp; char *buf = NULL; int ret, need_coma = 0; + AVCodecContext *ctx = NULL; #define SKIP_DEFAULTS AV_OPT_SERIALIZE_SKIP_DEFAULTS #define OPT_FLAGS_EXACT AV_OPT_SERIALIZE_OPT_FLAGS_EXACT @@ -107,6 +108,16 @@ static int ffm_write_header_codec_ctx(AVIOContext *pb, AVCodecContext *ctx, unsi if (avio_open_dyn_buf(&tmp) < 0) return AVERROR(ENOMEM); + + // AVCodecParameters does not suport AVOptions, we thus must copy it over to a context that does + // otherwise it could be used directly and this would be much simpler + ctx = avcodec_alloc_context3(NULL); + if (!ctx) { + ret = AVERROR(ENOMEM); + goto fail; + } + avcodec_parameters_to_context(ctx, ctxpar); + if ((ret = av_opt_serialize(ctx, ENC | type, SKIP_DEFAULTS, &buf, '=', ',')) < 0) goto fail; if (buf && strlen(buf)) { @@ -124,10 +135,12 @@ static int ffm_write_header_codec_ctx(AVIOContext *pb, AVCodecContext *ctx, unsi av_freep(&buf); avio_w8(tmp, 0); write_header_chunk(pb, tmp, tag); + avcodec_free_context(&ctx); return 0; fail: av_free(buf); ffio_free_dyn_buf(&tmp); + avcodec_free_context(&ctx); return ret; #undef SKIP_DEFAULTS @@ -135,11 +148,11 @@ static int ffm_write_header_codec_ctx(AVIOContext *pb, AVCodecContext *ctx, unsi #undef ENC } -static int ffm_write_recommended_config(AVIOContext *pb, AVCodecContext *ctx, unsigned tag, +static int ffm_write_recommended_config(AVIOContext *pb, AVCodecParameters *codecpar, unsigned tag, const char *configuration) { int ret; - const AVCodec *enc = ctx->codec ? ctx->codec : avcodec_find_encoder(ctx->codec_id); + const AVCodec *enc = avcodec_find_encoder(codecpar->codec_id); AVIOContext *tmp; AVDictionaryEntry *t = NULL; AVDictionary *all = NULL, *comm = NULL, *prv = NULL; @@ -194,7 +207,6 @@ static int ffm_write_header(AVFormatContext *s) FFMContext *ffm = s->priv_data; AVStream *st; AVIOContext *pb = s->pb; - AVCodecContext *codec; AVCodecParameters *codecpar; int bit_rate, i, ret; @@ -223,18 +235,27 @@ static int ffm_write_header(AVFormatContext *s) /* list of streams */ for(i=0;inb_streams;i++) { + int flags = 0; st = s->streams[i]; avpriv_set_pts_info(st, 64, 1, 1000000); if(avio_open_dyn_buf(&pb) < 0) return AVERROR(ENOMEM); - codec = st->codec; codecpar = st->codecpar; /* generic info */ avio_wb32(pb, codecpar->codec_id); avio_w8(pb, codecpar->codec_type); avio_wb32(pb, codecpar->bit_rate); - avio_wb32(pb, codecpar->extradata_size ? AV_CODEC_FLAG_GLOBAL_HEADER : 0); + if (codecpar->extradata_size) + flags |= AV_CODEC_FLAG_GLOBAL_HEADER; + + // If the user is not providing us with a configuration we have to fill it in as we cannot access the encoder + if (!st->recommended_encoder_configuration) { + if (s->flags & AVFMT_FLAG_BITEXACT) + flags |= AV_CODEC_FLAG_BITEXACT; + } + + avio_wb32(pb, flags); avio_wb32(pb, 0); // flags2 avio_wb32(pb, 0); // debug if (codecpar->extradata_size) { @@ -248,20 +269,20 @@ static int ffm_write_header(AVFormatContext *s) if (st->recommended_encoder_configuration) { av_log(NULL, AV_LOG_DEBUG, "writing recommended configuration: %s\n", st->recommended_encoder_configuration); - if ((ret = ffm_write_recommended_config(s->pb, codec, MKBETAG('S', '2', 'V', 'I'), + if ((ret = ffm_write_recommended_config(s->pb, codecpar, MKBETAG('S', '2', 'V', 'I'), st->recommended_encoder_configuration)) < 0) return ret; - } else if ((ret = ffm_write_header_codec_ctx(s->pb, codec, MKBETAG('S', '2', 'V', 'I'), AV_OPT_FLAG_VIDEO_PARAM)) < 0) + } else if ((ret = ffm_write_header_codec_ctx(s->pb, codecpar, MKBETAG('S', '2', 'V', 'I'), AV_OPT_FLAG_VIDEO_PARAM)) < 0) return ret; break; case AVMEDIA_TYPE_AUDIO: if (st->recommended_encoder_configuration) { av_log(NULL, AV_LOG_DEBUG, "writing recommended configuration: %s\n", st->recommended_encoder_configuration); - if ((ret = ffm_write_recommended_config(s->pb, codec, MKBETAG('S', '2', 'A', 'U'), + if ((ret = ffm_write_recommended_config(s->pb, codecpar, MKBETAG('S', '2', 'A', 'U'), st->recommended_encoder_configuration)) < 0) return ret; - } else if ((ret = ffm_write_header_codec_ctx(s->pb, codec, MKBETAG('S', '2', 'A', 'U'), AV_OPT_FLAG_AUDIO_PARAM)) < 0) + } else if ((ret = ffm_write_header_codec_ctx(s->pb, codecpar, MKBETAG('S', '2', 'A', 'U'), AV_OPT_FLAG_AUDIO_PARAM)) < 0) return ret; break; default: