aboutsummaryrefslogtreecommitdiffstats
path: root/fftools/ffmpeg.c
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2024-04-09 12:56:46 +0200
committerAnton Khirnov <anton@khirnov.net>2024-07-03 11:38:52 +0200
commitf1664aabb18b2d726c3c0c0b7fa8202f3b52b8da (patch)
treebcbff7ba11217d943ce7992c6fe47ce8ebe67622 /fftools/ffmpeg.c
parentfc446eea05b9bc7de9a3c6b56dae8255bb5c5b5d (diff)
downloadffmpeg-f1664aabb18b2d726c3c0c0b7fa8202f3b52b8da.tar.gz
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.
Diffstat (limited to 'fftools/ffmpeg.c')
-rw-r--r--fftools/ffmpeg.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 8674c4d250..00ab1cce51 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -474,6 +474,56 @@ const FrameData *packet_data_c(AVPacket *pkt)
return ret < 0 ? NULL : (const FrameData*)pkt->opaque_ref->data;
}
+int check_avoptions_used(const AVDictionary *opts, const AVDictionary *opts_used,
+ void *logctx, int decode)
+{
+ const AVClass *class = avcodec_get_class();
+ const AVClass *fclass = avformat_get_class();
+
+ const int flag = decode ? AV_OPT_FLAG_DECODING_PARAM :
+ AV_OPT_FLAG_ENCODING_PARAM;
+ const AVDictionaryEntry *e = NULL;
+
+ while ((e = av_dict_iterate(opts, e))) {
+ const AVOption *option, *foption;
+ char *optname, *p;
+
+ if (av_dict_get(opts_used, e->key, NULL, 0))
+ continue;
+
+ optname = av_strdup(e->key);
+ if (!optname)
+ return AVERROR(ENOMEM);
+
+ p = strchr(optname, ':');
+ if (p)
+ *p = 0;
+
+ option = av_opt_find(&class, optname, NULL, 0,
+ AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ);
+ foption = av_opt_find(&fclass, optname, NULL, 0,
+ AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ);
+ av_freep(&optname);
+ if (!option || foption)
+ continue;
+
+ if (!(option->flags & flag)) {
+ av_log(logctx, AV_LOG_ERROR, "Codec AVOption %s (%s) is not a %s "
+ "option.\n", e->key, option->help ? option->help : "",
+ decode ? "decoding" : "encoding");
+ return AVERROR(EINVAL);
+ }
+
+ av_log(logctx, 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 decoder which was not actually used "
+ "for any stream.\n", e->key, option->help ? option->help : "");
+ }
+
+ return 0;
+}
+
void update_benchmark(const char *fmt, ...)
{
if (do_benchmark_all) {