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
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)) {
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
#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;
FFMContext *ffm = s->priv_data;
AVStream *st;
AVIOContext *pb = s->pb;
- AVCodecContext *codec;
AVCodecParameters *codecpar;
int bit_rate, i, ret;
/* list of streams */
for(i=0;i<s->nb_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) {
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: