mirror of
https://github.com/nyanmisaka/ffmpeg-rockchip.git
synced 2025-10-14 04:54:54 +08:00
fftools/ffmpeg_mux_init: move validating codec avoptions to a separate function
This commit is contained in:
@@ -694,7 +694,7 @@ void assert_avoptions(AVDictionary *m);
|
|||||||
|
|
||||||
void assert_file_overwrite(const char *filename);
|
void assert_file_overwrite(const char *filename);
|
||||||
char *file_read(const char *filename);
|
char *file_read(const char *filename);
|
||||||
AVDictionary *strip_specifiers(AVDictionary *dict);
|
AVDictionary *strip_specifiers(const AVDictionary *dict);
|
||||||
const AVCodec *find_codec_or_die(const char *name, enum AVMediaType type, int encoder);
|
const AVCodec *find_codec_or_die(const char *name, enum AVMediaType type, int encoder);
|
||||||
int parse_and_set_vsync(const char *arg, int *vsync_var, int file_idx, int st_idx, int is_global);
|
int parse_and_set_vsync(const char *arg, int *vsync_var, int file_idx, int st_idx, int is_global);
|
||||||
|
|
||||||
|
@@ -1725,14 +1725,60 @@ static int set_dispositions(OutputFile *of, AVFormatContext *ctx)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void validate_enc_avopt(const Muxer *mux, const AVDictionary *codec_avopt)
|
||||||
|
{
|
||||||
|
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_get(of->streams[i]->encoder_opts, "", e,
|
||||||
|
AV_DICT_IGNORE_SUFFIX)))
|
||||||
|
av_dict_set(&unused_opts, e->key, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
e = NULL;
|
||||||
|
while ((e = av_dict_get(unused_opts, "", e, AV_DICT_IGNORE_SUFFIX))) {
|
||||||
|
const AVClass *class = avcodec_get_class();
|
||||||
|
const AVOption *option = av_opt_find(&class, e->key, NULL, 0,
|
||||||
|
AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ);
|
||||||
|
const AVClass *fclass = avformat_get_class();
|
||||||
|
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(NULL, AV_LOG_ERROR, "Codec AVOption %s (%s) specified for "
|
||||||
|
"output file #%d (%s) is not an encoding option.\n", e->key,
|
||||||
|
option->help ? option->help : "", nb_output_files - 1,
|
||||||
|
mux->fc->url);
|
||||||
|
exit_program(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// gop_timecode is injected by generic code but not always used
|
||||||
|
if (!strcmp(e->key, "gop_timecode"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
av_log(NULL, AV_LOG_WARNING, "Codec AVOption %s (%s) specified for "
|
||||||
|
"output file #%d (%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 : "", nb_output_files - 1, mux->fc->url);
|
||||||
|
}
|
||||||
|
av_dict_free(&unused_opts);
|
||||||
|
}
|
||||||
|
|
||||||
int of_open(const OptionsContext *o, const char *filename)
|
int of_open(const OptionsContext *o, const char *filename)
|
||||||
{
|
{
|
||||||
Muxer *mux;
|
Muxer *mux;
|
||||||
AVFormatContext *oc;
|
AVFormatContext *oc;
|
||||||
int err;
|
int err;
|
||||||
OutputFile *of;
|
OutputFile *of;
|
||||||
AVDictionary *unused_opts = NULL;
|
|
||||||
const AVDictionaryEntry *e = NULL;
|
|
||||||
|
|
||||||
int64_t recording_time = o->recording_time;
|
int64_t recording_time = o->recording_time;
|
||||||
int64_t stop_time = o->stop_time;
|
int64_t stop_time = o->stop_time;
|
||||||
@@ -1795,46 +1841,7 @@ int of_open(const OptionsContext *o, const char *filename)
|
|||||||
create_streams(mux, o);
|
create_streams(mux, o);
|
||||||
|
|
||||||
/* check if all codec options have been used */
|
/* check if all codec options have been used */
|
||||||
unused_opts = strip_specifiers(o->g->codec_opts);
|
validate_enc_avopt(mux, o->g->codec_opts);
|
||||||
for (int i = 0; i < of->nb_streams; i++) {
|
|
||||||
e = NULL;
|
|
||||||
while ((e = av_dict_get(of->streams[i]->encoder_opts, "", e,
|
|
||||||
AV_DICT_IGNORE_SUFFIX)))
|
|
||||||
av_dict_set(&unused_opts, e->key, NULL, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
e = NULL;
|
|
||||||
while ((e = av_dict_get(unused_opts, "", e, AV_DICT_IGNORE_SUFFIX))) {
|
|
||||||
const AVClass *class = avcodec_get_class();
|
|
||||||
const AVOption *option = av_opt_find(&class, e->key, NULL, 0,
|
|
||||||
AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ);
|
|
||||||
const AVClass *fclass = avformat_get_class();
|
|
||||||
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(NULL, AV_LOG_ERROR, "Codec AVOption %s (%s) specified for "
|
|
||||||
"output file #%d (%s) is not an encoding option.\n", e->key,
|
|
||||||
option->help ? option->help : "", nb_output_files - 1,
|
|
||||||
filename);
|
|
||||||
exit_program(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// gop_timecode is injected by generic code but not always used
|
|
||||||
if (!strcmp(e->key, "gop_timecode"))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
av_log(NULL, AV_LOG_WARNING, "Codec AVOption %s (%s) specified for "
|
|
||||||
"output file #%d (%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 : "", nb_output_files - 1, filename);
|
|
||||||
}
|
|
||||||
av_dict_free(&unused_opts);
|
|
||||||
|
|
||||||
/* set the decoding_needed flags and create simple filtergraphs */
|
/* set the decoding_needed flags and create simple filtergraphs */
|
||||||
for (int i = 0; i < of->nb_streams; i++) {
|
for (int i = 0; i < of->nb_streams; i++) {
|
||||||
|
@@ -165,7 +165,7 @@ static int show_hwaccels(void *optctx, const char *opt, const char *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* return a copy of the input with the stream specifiers removed from the keys */
|
/* return a copy of the input with the stream specifiers removed from the keys */
|
||||||
AVDictionary *strip_specifiers(AVDictionary *dict)
|
AVDictionary *strip_specifiers(const AVDictionary *dict)
|
||||||
{
|
{
|
||||||
const AVDictionaryEntry *e = NULL;
|
const AVDictionaryEntry *e = NULL;
|
||||||
AVDictionary *ret = NULL;
|
AVDictionary *ret = NULL;
|
||||||
|
Reference in New Issue
Block a user