o->chapters_input_file = INT_MAX;
}
+/* return a copy of the input with the stream specifiers removed from the keys */
+static AVDictionary *strip_specifiers(AVDictionary *dict)
+{
+ AVDictionaryEntry *e = NULL;
+ AVDictionary *ret = NULL;
+
+ while ((e = av_dict_get(dict, "", e, AV_DICT_IGNORE_SUFFIX))) {
+ char *p = strchr(e->key, ':');
+
+ if (p)
+ *p = 0;
+ av_dict_set(&ret, e->key, e->value, 0);
+ if (p)
+ *p = ':';
+ }
+ return ret;
+}
+
static double parse_frame_aspect_ratio(const char *arg)
{
int x = 0, y = 0;
static int open_input_file(OptionsContext *o, const char *filename)
{
+ InputFile *f;
AVFormatContext *ic;
AVInputFormat *file_iformat = NULL;
int err, i, ret;
int64_t timestamp;
uint8_t buf[128];
AVDictionary **opts;
+ AVDictionary *unused_opts = NULL;
+ AVDictionaryEntry *e = NULL;
int orig_nb_streams; // number of streams before avformat_find_stream_info
if (o->format) {
av_dump_format(ic, nb_input_files, filename, 0);
GROW_ARRAY(input_files, nb_input_files);
- if (!(input_files[nb_input_files - 1] = av_mallocz(sizeof(*input_files[0]))))
+ f = av_mallocz(sizeof(*f));
+ if (!f)
exit(1);
+ input_files[nb_input_files - 1] = f;
+
+ f->ctx = ic;
+ f->ist_index = nb_input_streams - ic->nb_streams;
+ f->ts_offset = o->input_ts_offset - (copy_ts ? 0 : timestamp);
+ f->nb_streams = ic->nb_streams;
+ f->rate_emu = o->rate_emu;
+
+ /* check if all codec options have been used */
+ unused_opts = strip_specifiers(o->g->codec_opts);
+ for (i = f->ist_index; i < nb_input_streams; i++) {
+ e = NULL;
+ while ((e = av_dict_get(input_streams[i]->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);
+ if (!option)
+ continue;
+ if (!(option->flags & AV_OPT_FLAG_DECODING_PARAM)) {
+ av_log(NULL, AV_LOG_ERROR, "Codec AVOption %s (%s) specified for "
+ "input file #%d (%s) is not a decoding option.\n", e->key,
+ option->help ? option->help : "", nb_input_files - 1,
+ filename);
+ exit(1);
+ }
- input_files[nb_input_files - 1]->ctx = ic;
- input_files[nb_input_files - 1]->ist_index = nb_input_streams - ic->nb_streams;
- input_files[nb_input_files - 1]->ts_offset = o->input_ts_offset - (copy_ts ? 0 : timestamp);
- input_files[nb_input_files - 1]->nb_streams = ic->nb_streams;
- input_files[nb_input_files - 1]->rate_emu = o->rate_emu;
+ av_log(NULL, AV_LOG_WARNING, "Codec AVOption %s (%s) specified for "
+ "input 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 decoder "
+ "which was not actually used for any stream.\n", e->key,
+ option->help ? option->help : "", nb_input_files - 1, filename);
+ }
+ av_dict_free(&unused_opts);
for (i = 0; i < o->nb_dump_attachment; i++) {
int j;
{
OutputStream *ost = new_output_stream(o, oc, AVMEDIA_TYPE_ATTACHMENT);
ost->stream_copy = 1;
+ ost->finished = 1;
return ost;
}
AVFormatContext *oc;
int i, j, err;
AVOutputFormat *file_oformat;
+ OutputFile *of;
OutputStream *ost;
InputStream *ist;
+ AVDictionary *unused_opts = NULL;
+ AVDictionaryEntry *e = NULL;
if (configure_complex_filters() < 0) {
av_log(NULL, AV_LOG_FATAL, "Error configuring filters.\n");
}
GROW_ARRAY(output_files, nb_output_files);
- if (!(output_files[nb_output_files - 1] = av_mallocz(sizeof(*output_files[0]))))
+ of = av_mallocz(sizeof(*of));
+ if (!of)
exit(1);
+ output_files[nb_output_files - 1] = of;
- output_files[nb_output_files - 1]->ctx = oc;
- output_files[nb_output_files - 1]->ost_index = nb_output_streams - oc->nb_streams;
- output_files[nb_output_files - 1]->recording_time = o->recording_time;
+ of->ctx = oc;
+ of->ost_index = nb_output_streams - oc->nb_streams;
+ of->recording_time = o->recording_time;
if (o->recording_time != INT64_MAX)
oc->duration = o->recording_time;
- output_files[nb_output_files - 1]->start_time = o->start_time;
- output_files[nb_output_files - 1]->limit_filesize = o->limit_filesize;
- output_files[nb_output_files - 1]->shortest = o->shortest;
- av_dict_copy(&output_files[nb_output_files - 1]->opts, o->g->format_opts, 0);
+ of->start_time = o->start_time;
+ of->limit_filesize = o->limit_filesize;
+ of->shortest = o->shortest;
+ av_dict_copy(&of->opts, o->g->format_opts, 0);
+
+
+ /* check if all codec options have been used */
+ unused_opts = strip_specifiers(o->g->codec_opts);
+ for (i = of->ost_index; i < nb_output_streams; i++) {
+ e = NULL;
+ while ((e = av_dict_get(output_streams[i]->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);
+ if (!option)
+ 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(1);
+ }
+
+ 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);
/* check filename in case of an image number is expected */
if (oc->oformat->flags & AVFMT_NEEDNUMBER) {
/* open the file */
if ((err = avio_open2(&oc->pb, filename, AVIO_FLAG_WRITE,
&oc->interrupt_callback,
- &output_files[nb_output_files - 1]->opts)) < 0) {
+ &of->opts)) < 0) {
print_error(filename, err);
exit(1);
}
if (o->mux_preload) {
uint8_t buf[64];
snprintf(buf, sizeof(buf), "%d", (int)(o->mux_preload*AV_TIME_BASE));
- av_dict_set(&output_files[nb_output_files - 1]->opts, "preload", buf, 0);
+ av_dict_set(&of->opts, "preload", buf, 0);
}
oc->max_delay = (int)(o->mux_max_delay * AV_TIME_BASE);
oc->flags |= AVFMT_FLAG_NONBLOCK;
}
}
if (o->chapters_input_file >= 0)
- copy_chapters(input_files[o->chapters_input_file], output_files[nb_output_files - 1],
+ copy_chapters(input_files[o->chapters_input_file], of,
!o->metadata_chapters_manual);
/* copy global metadata by default */
av_dict_copy(&oc->metadata, input_files[0]->ctx->metadata,
AV_DICT_DONT_OVERWRITE);
if (!o->metadata_streams_manual)
- for (i = output_files[nb_output_files - 1]->ost_index; i < nb_output_streams; i++) {
+ for (i = of->ost_index; i < nb_output_streams; i++) {
InputStream *ist;
if (output_streams[i]->source_index < 0) /* this is true e.g. for attached files */
continue;
inout, g->arg);
return ret;
}
- av_log(NULL, AV_LOG_DEBUG, "Successfully openened the file.\n");
+ av_log(NULL, AV_LOG_DEBUG, "Successfully opened the file.\n");
}
return 0;