#include "libavutil/pixdesc.h"
#include "libavutil/pixfmt.h"
+#define DEFAULT_PASS_LOGFILENAME_PREFIX "av2pass"
+
#define MATCH_PER_STREAM_OPT(name, type, outvar, fmtctx, st)\
{\
int i, ret;\
return ar;
}
+static int show_hwaccels(void *optctx, const char *opt, const char *arg)
+{
+ int i;
+
+ printf("Supported hardware acceleration:\n");
+ for (i = 0; i < FF_ARRAY_ELEMS(hwaccels) - 1; i++) {
+ printf("%s\n", hwaccels[i].name);
+ }
+ printf("\n");
+ return 0;
+}
+
static int opt_audio_codec(void *optctx, const char *opt, const char *arg)
{
OptionsContext *o = optctx;
MATCH_PER_STREAM_OPT(qscale, dbl, qscale, oc, st);
if (qscale >= 0) {
- ost->enc_ctx->flags |= CODEC_FLAG_QSCALE;
+ ost->enc_ctx->flags |= AV_CODEC_FLAG_QSCALE;
ost->enc_ctx->global_quality = FF_QP2LAMBDA * qscale;
}
if (oc->oformat->flags & AVFMT_GLOBALHEADER)
- ost->enc_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER;
+ ost->enc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
av_opt_get_int(o->g->sws_opts, "sws_flags", 0, &ost->sws_flags);
MATCH_PER_STREAM_OPT(pass, i, do_pass, oc, st);
if (do_pass) {
if (do_pass == 1) {
- video_enc->flags |= CODEC_FLAG_PASS1;
+ video_enc->flags |= AV_CODEC_FLAG_PASS1;
} else {
- video_enc->flags |= CODEC_FLAG_PASS2;
+ video_enc->flags |= AV_CODEC_FLAG_PASS2;
}
}
!(ost->logfile_prefix = av_strdup(ost->logfile_prefix)))
exit_program(1);
+ if (do_pass) {
+ char logfilename[1024];
+ FILE *f;
+
+ snprintf(logfilename, sizeof(logfilename), "%s-%d.log",
+ ost->logfile_prefix ? ost->logfile_prefix :
+ DEFAULT_PASS_LOGFILENAME_PREFIX,
+ i);
+ if (!strcmp(ost->enc->name, "libx264")) {
+ av_dict_set(&ost->encoder_opts, "stats", logfilename, AV_DICT_DONT_OVERWRITE);
+ } else {
+ if (video_enc->flags & AV_CODEC_FLAG_PASS1) {
+ f = fopen(logfilename, "wb");
+ if (!f) {
+ av_log(NULL, AV_LOG_FATAL, "Cannot write log file '%s' for pass-1 encoding: %s\n",
+ logfilename, strerror(errno));
+ exit_program(1);
+ }
+ ost->logfile = f;
+ } else {
+ char *logbuffer = read_file(logfilename);
+
+ if (!logbuffer) {
+ av_log(NULL, AV_LOG_FATAL, "Error reading log file '%s' for pass-2 encoding\n",
+ logfilename);
+ exit_program(1);
+ }
+ video_enc->stats_in = logbuffer;
+ }
+ }
+ }
+
MATCH_PER_STREAM_OPT(forced_key_frames, str, ost->forced_keyframes, oc, st);
if (ost->forced_keyframes)
ost->forced_keyframes = av_strdup(ost->forced_keyframes);
{
OutputStream *ost;
- switch (avfilter_pad_get_type(ofilter->out_tmp->filter_ctx->output_pads,
- ofilter->out_tmp->pad_idx)) {
+ switch (ofilter->type) {
case AVMEDIA_TYPE_VIDEO: ost = new_video_stream(o, oc); break;
case AVMEDIA_TYPE_AUDIO: ost = new_audio_stream(o, oc); break;
default:
exit_program(1);
}
- if (configure_output_filter(ofilter->graph, ofilter, ofilter->out_tmp) < 0) {
- av_log(NULL, AV_LOG_FATAL, "Error configuring filter.\n");
- exit_program(1);
- }
avfilter_inout_free(&ofilter->out_tmp);
}
+static int init_complex_filters(void)
+{
+ int i, ret = 0;
+
+ for (i = 0; i < nb_filtergraphs; i++) {
+ ret = init_complex_filtergraph(filtergraphs[i]);
+ if (ret < 0)
+ return ret;
+ }
+ return 0;
+}
+
static int configure_complex_filters(void)
{
int i, ret = 0;
AVDictionary *unused_opts = NULL;
AVDictionaryEntry *e = NULL;
- if (configure_complex_filters() < 0) {
- av_log(NULL, AV_LOG_FATAL, "Error configuring filters.\n");
- exit_program(1);
- }
-
GROW_ARRAY(output_files, nb_output_files);
of = av_mallocz(sizeof(*of));
if (!of)
if (!ofilter->out_tmp || ofilter->out_tmp->name)
continue;
- switch (avfilter_pad_get_type(ofilter->out_tmp->filter_ctx->output_pads,
- ofilter->out_tmp->pad_idx)) {
+ switch (ofilter->type) {
case AVMEDIA_TYPE_VIDEO: o->video_disable = 1; break;
case AVMEDIA_TYPE_AUDIO: o->audio_disable = 1; break;
case AVMEDIA_TYPE_SUBTITLE: o->subtitle_disable = 1; break;
avio_close(pb);
}
+ if (!oc->nb_streams && !(oc->oformat->flags & AVFMT_NOSTREAMS)) {
+ av_dump_format(oc, nb_output_files - 1, oc->filename, 1);
+ av_log(NULL, AV_LOG_ERROR, "Output file #%d does not contain any stream\n", nb_output_files - 1);
+ exit_program(1);
+ }
+
/* 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++) {
return 0;
}
+/* Search a class from a codec, format, or filter, named 'opt', in order
+ * to extract its private options. If the class type is specified, only
+ * the associated options are printed, otherwise all the ones matching
+ * the input name are shown. */
+static int show_help_specific(const char *opt)
+{
+ AVCodec *codec = NULL;
+ AVFilter *filter = NULL;
+ AVInputFormat *iformat = NULL;
+ AVOutputFormat *oformat = NULL;
+ int flags = AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM |
+ AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM;
+
+ char *kind = av_get_token(&opt, ":");
+ if (!kind)
+ return 0;
+ if (*opt)
+ opt = &opt[1]; // skip ':'
+
+ show_usage();
+
+ if (!strcmp(kind, "decoder") &&
+ (codec = avcodec_find_decoder_by_name(opt)) && codec->priv_class)
+ show_help_children(codec->priv_class, flags);
+ else if (!strcmp(kind, "encoder") &&
+ (codec = avcodec_find_encoder_by_name(opt)) && codec->priv_class)
+ show_help_children(codec->priv_class, flags);
+ else if (!strcmp(kind, "demuxer") &&
+ (iformat = av_find_input_format(opt)) && iformat->priv_class)
+ show_help_children(iformat->priv_class, flags);
+ else if (!strcmp(kind, "muxer") &&
+ (oformat = av_guess_format(opt, NULL, NULL)) && oformat->priv_class)
+ show_help_children(oformat->priv_class, flags);
+ else if (!strcmp(kind, "filter") &&
+ (filter = avfilter_get_by_name(opt)) && filter->priv_class)
+ show_help_children(filter->priv_class, flags);
+ else if (!opt)
+ av_log(NULL, AV_LOG_ERROR,
+ "Unknown class '%s', only 'decoder', 'encoder', 'demuxer', "
+ "'muxer', or 'filter' are valid specifiers.\n", kind);
+ else {
+ if ((codec = avcodec_find_decoder_by_name(kind)) && codec->priv_class)
+ show_help_children(codec->priv_class, flags);
+ if ((codec = avcodec_find_encoder_by_name(kind)) && codec->priv_class)
+ show_help_children(codec->priv_class, flags);
+ if ((iformat = av_find_input_format(kind)) && iformat->priv_class)
+ show_help_children(iformat->priv_class, flags);
+ if ((oformat = av_guess_format(kind, NULL, NULL)) && oformat->priv_class)
+ show_help_children(oformat->priv_class, flags);
+ if ((filter = avfilter_get_by_name(kind)) && filter->priv_class)
+ show_help_children(filter->priv_class, flags);
+ }
+ av_freep(&kind);
+
+ return codec || iformat || oformat || filter;
+}
+
void show_help_default(const char *opt, const char *arg)
{
/* per-file options have at least one of those set */
show_advanced = 1;
else if (!strcmp(opt, "full"))
show_advanced = show_avoptions = 1;
+ else if (show_help_specific(opt))
+ return;
else
av_log(NULL, AV_LOG_ERROR, "Unknown help option '%s'.\n", opt);
}
" -h -- print basic options\n"
" -h long -- print more options\n"
" -h full -- print all options (including all format and codec specific options, very long)\n"
+ " -h [type:]name -- print private options from a codec, format or filter named 'name' (set 'type' to print options from a single class)\n"
" See man %s for detailed description of the options.\n"
"\n", program_name);
goto fail;
}
+ /* create the complex filtergraphs */
+ ret = init_complex_filters();
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_FATAL, "Error initializing complex filters.\n");
+ goto fail;
+ }
+
/* open output files */
ret = open_files(&octx.groups[GROUP_OUTFILE], "output", open_output_file);
if (ret < 0) {
goto fail;
}
+ /* configure the complex filtergraphs */
+ ret = configure_complex_filters();
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_FATAL, "Error configuring complex filters.\n");
+ goto fail;
+ }
+
fail:
uninit_parse_context(&octx);
if (ret < 0) {
"use HW accelerated decoding", "hwaccel name" },
{ "hwaccel_device", OPT_VIDEO | OPT_STRING | HAS_ARG | OPT_EXPERT |
OPT_SPEC | OPT_INPUT, { .off = OFFSET(hwaccel_devices) },
- "select a device for HW acceleration" "devicename" },
+ "select a device for HW acceleration", "devicename" },
+ { "hwaccels", OPT_EXIT, { .func_arg = show_hwaccels },
+ "show available HW acceleration methods" },
{ "autorotate", HAS_ARG | OPT_BOOL | OPT_SPEC |
OPT_EXPERT | OPT_INPUT, { .off = OFFSET(autorotate) },
"automatically insert correct rotate filters" },