mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2025-12-24 07:50:11 +01:00
fftools/ffmpeg: rewrite checking whether codec AVOptions have been used
Share the code between encoding and decoding. Instead of checking every stream's options dictionary (which is also used for other purposes), track all used options in a dedicated dictionary.
This commit is contained in:
@@ -1160,7 +1160,8 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
|
||||
const char *enc_time_base = NULL;
|
||||
|
||||
ret = filter_codec_opts(o->g->codec_opts, enc->codec_id,
|
||||
oc, st, enc->codec, &ost->encoder_opts);
|
||||
oc, st, enc->codec, &ost->encoder_opts,
|
||||
&mux->enc_opts_used);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@@ -1265,7 +1266,8 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
|
||||
}
|
||||
} else {
|
||||
ret = filter_codec_opts(o->g->codec_opts, AV_CODEC_ID_NONE, oc, st,
|
||||
NULL, &ost->encoder_opts);
|
||||
NULL, &ost->encoder_opts,
|
||||
&mux->enc_opts_used);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
@@ -3118,53 +3120,6 @@ static int process_forced_keyframes(Muxer *mux, const OptionsContext *o)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int validate_enc_avopt(Muxer *mux, const AVDictionary *codec_avopt)
|
||||
{
|
||||
const AVClass *class = avcodec_get_class();
|
||||
const AVClass *fclass = avformat_get_class();
|
||||
const OutputFile *of = &mux->of;
|
||||
|
||||
AVDictionary *unused_opts;
|
||||
const AVDictionaryEntry *e;
|
||||
|
||||
unused_opts = strip_specifiers(codec_avopt);
|
||||
for (int i = 0; i < of->nb_streams; i++) {
|
||||
e = NULL;
|
||||
while ((e = av_dict_iterate(of->streams[i]->encoder_opts, e)))
|
||||
av_dict_set(&unused_opts, e->key, NULL, 0);
|
||||
}
|
||||
|
||||
e = NULL;
|
||||
while ((e = av_dict_iterate(unused_opts, e))) {
|
||||
const AVOption *option = av_opt_find(&class, e->key, NULL, 0,
|
||||
AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ);
|
||||
const AVOption *foption = av_opt_find(&fclass, e->key, NULL, 0,
|
||||
AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ);
|
||||
if (!option || foption)
|
||||
continue;
|
||||
|
||||
if (!(option->flags & AV_OPT_FLAG_ENCODING_PARAM)) {
|
||||
av_log(mux, AV_LOG_ERROR, "Codec AVOption %s (%s) is not an "
|
||||
"encoding option.\n", e->key, option->help ? option->help : "");
|
||||
av_dict_free(&unused_opts);
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
|
||||
// gop_timecode is injected by generic code but not always used
|
||||
if (!strcmp(e->key, "gop_timecode"))
|
||||
continue;
|
||||
|
||||
av_log(mux, AV_LOG_WARNING, "Codec AVOption %s (%s) has not been used "
|
||||
"for any stream. The most likely reason is either wrong type "
|
||||
"(e.g. a video option with no video streams) or that it is a "
|
||||
"private option of some encoder which was not actually used for "
|
||||
"any stream.\n", e->key, option->help ? option->help : "");
|
||||
}
|
||||
av_dict_free(&unused_opts);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *output_file_item_name(void *obj)
|
||||
{
|
||||
const Muxer *mux = obj;
|
||||
@@ -3272,7 +3227,8 @@ int of_open(const OptionsContext *o, const char *filename, Scheduler *sch)
|
||||
return err;
|
||||
|
||||
/* check if all codec options have been used */
|
||||
err = validate_enc_avopt(mux, o->g->codec_opts);
|
||||
err = check_avoptions_used(o->g->codec_opts, mux->enc_opts_used, mux, 0);
|
||||
av_dict_free(&mux->enc_opts_used);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user