Skip to content

Commit

Permalink
fftools/ffmpeg_mux_init: apply encoder options manually
Browse files Browse the repository at this point in the history
Do not pass an options dictionary to the avcodec_open2() in enc_open().

This is cleaner and more robust, as previously various bits of code
would try to interpret the contents of the options dictionary, with
varying degrees of correctness. Now they can just access the encoder
AVCodecContext directly.

Cf. 372c78d - analogous change for
decoding.

A non-progressive field order is now written on the container level in
interlaced ProRes encoding tests.
  • Loading branch information
elenril committed Jul 3, 2024
1 parent f1664aa commit 9a7686e
Show file tree
Hide file tree
Showing 10 changed files with 47 additions and 53 deletions.
18 changes: 4 additions & 14 deletions fftools/ffmpeg_enc.c
Original file line number Diff line number Diff line change
Expand Up @@ -307,16 +307,10 @@ int enc_open(void *opaque, const AVFrame *frame)
if (ost->bitexact)
enc_ctx->flags |= AV_CODEC_FLAG_BITEXACT;

if (!av_dict_get(ost->encoder_opts, "threads", NULL, 0))
av_dict_set(&ost->encoder_opts, "threads", "auto", 0);
if (enc->capabilities & AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE)
enc_ctx->flags |= AV_CODEC_FLAG_COPY_OPAQUE;

if (enc->capabilities & AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE) {
ret = av_dict_set(&ost->encoder_opts, "flags", "+copy_opaque", AV_DICT_MULTIKEY);
if (ret < 0)
return ret;
}

av_dict_set(&ost->encoder_opts, "flags", "+frame_duration", AV_DICT_MULTIKEY);
enc_ctx->flags |= AV_CODEC_FLAG_FRAME_DURATION;

ret = hw_device_setup_for_encode(ost, frame ? frame->hw_frames_ctx : NULL);
if (ret < 0) {
Expand All @@ -325,7 +319,7 @@ int enc_open(void *opaque, const AVFrame *frame)
return ret;
}

if ((ret = avcodec_open2(ost->enc_ctx, enc, &ost->encoder_opts)) < 0) {
if ((ret = avcodec_open2(ost->enc_ctx, enc, NULL)) < 0) {
if (ret != AVERROR_EXPERIMENTAL)
av_log(ost, AV_LOG_ERROR, "Error while opening encoder - maybe "
"incorrect parameters such as bit_rate, rate, width or height.\n");
Expand All @@ -337,10 +331,6 @@ int enc_open(void *opaque, const AVFrame *frame)
if (ost->enc_ctx->frame_size)
frame_samples = ost->enc_ctx->frame_size;

ret = check_avoptions(ost->encoder_opts);
if (ret < 0)
return ret;

if (ost->enc_ctx->bit_rate && ost->enc_ctx->bit_rate < 1000 &&
ost->enc_ctx->codec_id != AV_CODEC_ID_CODEC2 /* don't complain about 700 bit/s modes */)
av_log(ost, AV_LOG_WARNING, "The bitrate parameter is set too low."
Expand Down
66 changes: 35 additions & 31 deletions fftools/ffmpeg_mux_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -711,14 +711,10 @@ static int new_stream_video(Muxer *mux, const OptionsContext *o,
/* two pass mode */
MATCH_PER_STREAM_OPT(pass, i, do_pass, oc, st);
if (do_pass) {
if (do_pass & 1) {
if (do_pass & 1)
video_enc->flags |= AV_CODEC_FLAG_PASS1;
av_dict_set(&ost->encoder_opts, "flags", "+pass1", AV_DICT_APPEND);
}
if (do_pass & 2) {
if (do_pass & 2)
video_enc->flags |= AV_CODEC_FLAG_PASS2;
av_dict_set(&ost->encoder_opts, "flags", "+pass2", AV_DICT_APPEND);
}
}

MATCH_PER_STREAM_OPT(passlogfiles, str, ost->logfile_prefix, oc, st);
Expand All @@ -740,7 +736,10 @@ static int new_stream_video(Muxer *mux, const OptionsContext *o,
DEFAULT_PASS_LOGFILENAME_PREFIX,
ost_idx);
if (!strcmp(ost->enc_ctx->codec->name, "libx264") || !strcmp(ost->enc_ctx->codec->name, "libvvenc")) {
av_dict_set(&ost->encoder_opts, "stats", logfilename, AV_DICT_DONT_OVERWRITE);
if (av_opt_is_set_to_default_by_name(ost->enc_ctx, "stats",
AV_OPT_SEARCH_CHILDREN) > 0)
av_opt_set(ost->enc_ctx, "stats", logfilename,
AV_OPT_SEARCH_CHILDREN);
} else {
if (video_enc->flags & AV_CODEC_FLAG_PASS2) {
char *logbuffer = file_read(logfilename);
Expand Down Expand Up @@ -1041,6 +1040,7 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
const AVCodec *enc;
AVStream *st;
int ret = 0, keep_pix_fmt = 0, autoscale = 1;
int threads_manual = 0;
AVRational enc_tb = { 0, 0 };
enum VideoSyncMethod vsync_method = VSYNC_AUTO;
const char *bsfs = NULL, *time_base = NULL;
Expand Down Expand Up @@ -1264,6 +1264,23 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,

enc_tb = q;
}

threads_manual = !!av_dict_get(ost->encoder_opts, "threads", NULL, 0);

ret = av_opt_set_dict2(ost->enc_ctx, &ost->encoder_opts, AV_OPT_SEARCH_CHILDREN);
if (ret < 0) {
av_log(ost, AV_LOG_ERROR, "Error applying encoder options: %s\n",
av_err2str(ret));
return ret;
}

ret = check_avoptions(ost->encoder_opts);
if (ret < 0)
return ret;

// default to automatic thread count
if (!threads_manual)
ost->enc_ctx->thread_count = 0;
} else {
ret = filter_codec_opts(o->g->codec_opts, AV_CODEC_ID_NONE, oc, st,
NULL, &ost->encoder_opts,
Expand All @@ -1276,8 +1293,7 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
if (o->bitexact) {
ost->bitexact = 1;
} else if (ost->enc_ctx) {
ost->bitexact = check_opt_bitexact(ost->enc_ctx, ost->encoder_opts, "flags",
AV_CODEC_FLAG_BITEXACT);
ost->bitexact = !!(ost->enc_ctx->flags & AV_CODEC_FLAG_BITEXACT);
}

MATCH_PER_STREAM_OPT(time_bases, str, time_base, oc, st);
Expand Down Expand Up @@ -1372,7 +1388,6 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,

if (ost->enc &&
(type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO)) {
const AVDictionaryEntry *e;
char name[16];
OutputFilterOptions opts = {
.enc = enc,
Expand All @@ -1398,10 +1413,6 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,

snprintf(name, sizeof(name), "#%d:%d", mux->of.index, ost->index);

e = av_dict_get(ost->encoder_opts, "threads", NULL, 0);
if (e)
opts.nb_threads = e->value;

// MJPEG encoder exports a full list of supported pixel formats,
// but the full-range ones are experimental-only.
// Restrict the auto-conversion list unless -strict experimental
Expand All @@ -1413,33 +1424,26 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
{ AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P,
AV_PIX_FMT_NONE };

const AVDictionaryEntry *strict = av_dict_get(ost->encoder_opts, "strict", NULL, 0);
int strict_val = ost->enc_ctx->strict_std_compliance;

if (strict) {
const AVOption *o = av_opt_find(ost->enc_ctx, strict->key, NULL, 0, 0);
av_assert0(o);
av_opt_eval_int(ost->enc_ctx, o, strict->value, &strict_val);
}

if (strict_val > FF_COMPLIANCE_UNOFFICIAL)
if (ost->enc_ctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL)
opts.pix_fmts = mjpeg_formats;
}

if (threads_manual) {
ret = av_opt_get(ost->enc_ctx, "threads", 0, (uint8_t**)&opts.nb_threads);
if (ret < 0)
return ret;
}

if (ofilter) {
ost->filter = ofilter;
ret = ofilter_bind_ost(ofilter, ost, ms->sch_idx_enc, &opts);
if (ret < 0)
return ret;
} else {
ret = init_simple_filtergraph(ost->ist, ost, filters,
mux->sch, ms->sch_idx_enc, &opts);
if (ret < 0) {
av_log(ost, AV_LOG_ERROR,
"Error initializing a simple filtergraph\n");
return ret;
}
}
av_freep(&opts.nb_threads);
if (ret < 0)
return ret;

ret = sch_connect(mux->sch, SCH_ENC(ms->sch_idx_enc),
SCH_MSTREAM(mux->sch_idx, ms->sch_idx));
Expand Down
2 changes: 1 addition & 1 deletion tests/ref/vsynth/vsynth1-prores_444_int
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
fd2a2f49c61817c2338f39d5736d5fd2 *tests/data/fate/vsynth1-prores_444_int.mov
bd1502671ce7144c106a6a460b2af404 *tests/data/fate/vsynth1-prores_444_int.mov
9940947 tests/data/fate/vsynth1-prores_444_int.mov
732ceeb6887524e0aee98762fe50578b *tests/data/fate/vsynth1-prores_444_int.out.rawvideo
stddev: 2.83 PSNR: 39.08 MAXDIFF: 45 bytes: 7603200/ 7603200
2 changes: 1 addition & 1 deletion tests/ref/vsynth/vsynth1-prores_int
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
1f1b246dfabe028f04c78887e5da51ed *tests/data/fate/vsynth1-prores_int.mov
842f92426e56cf6208cc94360d29fc69 *tests/data/fate/vsynth1-prores_int.mov
6308688 tests/data/fate/vsynth1-prores_int.mov
164a4ca890695cf594293d1acec9463c *tests/data/fate/vsynth1-prores_int.out.rawvideo
stddev: 2.66 PSNR: 39.62 MAXDIFF: 34 bytes: 7603200/ 7603200
2 changes: 1 addition & 1 deletion tests/ref/vsynth/vsynth2-prores_444_int
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
5ac517fc2380a6cf11b7d86d2fafee0a *tests/data/fate/vsynth2-prores_444_int.mov
6f5fa77609698fbed3a7eef1c91bb9ea *tests/data/fate/vsynth2-prores_444_int.mov
6420787 tests/data/fate/vsynth2-prores_444_int.mov
33a5db4f0423168d4ae4f1db3610928e *tests/data/fate/vsynth2-prores_444_int.out.rawvideo
stddev: 0.93 PSNR: 48.73 MAXDIFF: 14 bytes: 7603200/ 7603200
2 changes: 1 addition & 1 deletion tests/ref/vsynth/vsynth2-prores_int
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
4062c74196d95a64e642bd917377ed93 *tests/data/fate/vsynth2-prores_int.mov
a9a9812dd8944a58c2c2b3b0ce41247d *tests/data/fate/vsynth2-prores_int.mov
4070996 tests/data/fate/vsynth2-prores_int.mov
bef9e38387a1fbb1ce2e4401b6d41674 *tests/data/fate/vsynth2-prores_int.out.rawvideo
stddev: 1.54 PSNR: 44.37 MAXDIFF: 13 bytes: 7603200/ 7603200
2 changes: 1 addition & 1 deletion tests/ref/vsynth/vsynth3-prores_444_int
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
50db4bbc4674de3dfdd41f306af1cb17 *tests/data/fate/vsynth3-prores_444_int.mov
b61864cafb35ad8e592b4f899bdd84b6 *tests/data/fate/vsynth3-prores_444_int.mov
184397 tests/data/fate/vsynth3-prores_444_int.mov
a8852aa2841c2ce5f2aa86176ceda4ef *tests/data/fate/vsynth3-prores_444_int.out.rawvideo
stddev: 3.24 PSNR: 37.91 MAXDIFF: 41 bytes: 86700/ 86700
2 changes: 1 addition & 1 deletion tests/ref/vsynth/vsynth3-prores_int
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
24b765064b4aec754fdd0cc3658bba19 *tests/data/fate/vsynth3-prores_int.mov
2e89dfb5e2b5146337c1d65ccc4fe196 *tests/data/fate/vsynth3-prores_int.mov
120484 tests/data/fate/vsynth3-prores_int.mov
e5859ba47a99f9e53c1ddcaa68a8f8f8 *tests/data/fate/vsynth3-prores_int.out.rawvideo
stddev: 2.92 PSNR: 38.81 MAXDIFF: 29 bytes: 86700/ 86700
2 changes: 1 addition & 1 deletion tests/ref/vsynth/vsynth_lena-prores_444_int
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
09b5dffd1a484e2152a3b5a0bcceed32 *tests/data/fate/vsynth_lena-prores_444_int.mov
e76d98c772c65c7ac75f7d43484883d3 *tests/data/fate/vsynth_lena-prores_444_int.mov
5696258 tests/data/fate/vsynth_lena-prores_444_int.mov
466380156e4d2b811f4ffb9c5a8bca72 *tests/data/fate/vsynth_lena-prores_444_int.out.rawvideo
stddev: 0.88 PSNR: 49.23 MAXDIFF: 9 bytes: 7603200/ 7603200
2 changes: 1 addition & 1 deletion tests/ref/vsynth/vsynth_lena-prores_int
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
c7e9a61054f44fe372a3bce619b68ce9 *tests/data/fate/vsynth_lena-prores_int.mov
21d328216b194500a3c87c45afa5e927 *tests/data/fate/vsynth_lena-prores_int.mov
3532698 tests/data/fate/vsynth_lena-prores_int.mov
eb5caa9824ca294f403cd13f33c40f23 *tests/data/fate/vsynth_lena-prores_int.out.rawvideo
stddev: 1.47 PSNR: 44.78 MAXDIFF: 12 bytes: 7603200/ 7603200

0 comments on commit 9a7686e

Please sign in to comment.