diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 6e44a9068b..42eb57b76a 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -3112,6 +3112,13 @@ typedef struct AVCodecContext { */ uint8_t *dump_separator; + /** + * ',' seperated list of allowed decoders. + * If NULL then all are allowed + * - encoding: unused + * - decoding: set by user through AVOPtions (NO direct access) + */ + char *codec_whitelist; } AVCodecContext; AVRational av_codec_get_pkt_timebase (const AVCodecContext *avctx); diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h index 840d054edc..77841b55fe 100644 --- a/libavcodec/options_table.h +++ b/libavcodec/options_table.h @@ -487,6 +487,7 @@ static const AVOption avcodec_options[] = { {"tb", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AV_FIELD_TB }, 0, 0, V|D|E, "field_order" }, {"bt", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AV_FIELD_BT }, 0, 0, V|D|E, "field_order" }, {"dump_separator", "set information dump field separator", OFFSET(dump_separator), AV_OPT_TYPE_STRING, {.str = NULL}, CHAR_MIN, CHAR_MAX, A|V|S|D|E}, +{"codec_whitelist", "List of decoders that are allowed to be used", OFFSET(codec_whitelist), AV_OPT_TYPE_STRING, { .str = NULL }, CHAR_MIN, CHAR_MAX, D }, {NULL}, }; diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 93be575d27..36ba118e7f 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -1385,6 +1385,12 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code if ((ret = av_opt_set_dict(avctx, &tmp)) < 0) goto free_and_end; + if (avctx->codec_whitelist && av_match_list(codec->name, avctx->codec_whitelist, ',') <= 0) { + av_log(avctx, AV_LOG_ERROR, "Codec not on whitelist\n"); + ret = AVERROR(EINVAL); + goto free_and_end; + } + // only call ff_set_dimensions() for non H.264/VP6F codecs so as not to overwrite previously setup dimensions if (!(avctx->coded_width && avctx->coded_height && avctx->width && avctx->height && (avctx->codec_id == AV_CODEC_ID_H264 || avctx->codec_id == AV_CODEC_ID_VP6F))) {