X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=avconv_opt.c;h=8fe53e61682c91d2ebacd5a974d37e0f875a3f4d;hb=5e555f93009f0605db120eec78262d0fe337e645;hp=f8c524568ce2de17d49369f85971376cc41e818d;hpb=383136264ef40452efd86cafb2d7221cd3830b3d;p=ffmpeg diff --git a/avconv_opt.c b/avconv_opt.c index f8c524568ce..8fe53e61682 100644 --- a/avconv_opt.c +++ b/avconv_opt.c @@ -41,6 +41,8 @@ #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;\ @@ -62,6 +64,9 @@ const HWAccel hwaccels[] = { #endif #if CONFIG_VDA { "vda", vda_init, HWACCEL_VDA, AV_PIX_FMT_VDA }, +#endif +#if CONFIG_LIBMFX + { "qsv", qsv_init, HWACCEL_QSV, AV_PIX_FMT_QSV }, #endif { 0 }, }; @@ -175,6 +180,18 @@ static double parse_frame_aspect_ratio(const char *arg) 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; @@ -213,6 +230,8 @@ static int opt_map(void *optctx, const char *opt, const char *arg) arg++; } map = av_strdup(arg); + if (!map) + return AVERROR(ENOMEM); /* parse sync stream first, just pick first matching stream */ if (sync = strchr(map, ',')) { @@ -482,10 +501,16 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) ist->file_index = nb_input_files; ist->discard = 1; st->discard = AVDISCARD_ALL; + ist->nb_samples = 0; + ist->min_pts = INT64_MAX; + ist->max_pts = INT64_MIN; ist->ts_scale = 1.0; MATCH_PER_STREAM_OPT(ts_scale, dbl, ist->ts_scale, ic, st); + ist->autorotate = 1; + MATCH_PER_STREAM_OPT(autorotate, i, ist->autorotate, ic, st); + MATCH_PER_STREAM_OPT(codec_tags, str, codec_tag, ic, st); if (codec_tag) { uint32_t tag = strtol(codec_tag, &next, 0); @@ -587,7 +612,7 @@ static void assert_file_overwrite(const char *filename) } if (!file_overwrite && - (strchr(filename, ':') == NULL || filename[1] == ':' || + (!strchr(filename, ':') || filename[1] == ':' || av_strstart(filename, "file:", NULL))) { if (avio_check(filename, 0) == 0) { if (!using_stdin && !file_skip) { @@ -764,6 +789,9 @@ static int open_input_file(OptionsContext *o, const char *filename) f->nb_streams = ic->nb_streams; f->rate_emu = o->rate_emu; f->accurate_seek = o->accurate_seek; + f->loop = o->loop; + f->duration = 0; + f->time_base = (AVRational){ 1, 1 }; /* check if all codec options have been used */ unused_opts = strip_specifiers(o->g->codec_opts); @@ -977,12 +1005,12 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e 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); @@ -1134,6 +1162,10 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc) video_enc->rc_override = av_realloc(video_enc->rc_override, sizeof(RcOverride) * (i + 1)); + if (!video_enc->rc_override) { + av_log(NULL, AV_LOG_FATAL, "Could not (re)allocate memory for rc_override.\n"); + exit_program(1); + } video_enc->rc_override[i].start_frame = start; video_enc->rc_override[i].end_frame = end; if (q > 0) { @@ -1154,9 +1186,9 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc) 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; } } @@ -1165,6 +1197,38 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc) !(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); @@ -1324,8 +1388,7 @@ static void init_output_filter(OutputFilter *ofilter, OptionsContext *o, { 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: @@ -1346,13 +1409,21 @@ static void init_output_filter(OutputFilter *ofilter, OptionsContext *o, 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; @@ -1375,11 +1446,6 @@ static int open_output_file(OptionsContext *o, const char *filename) 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) @@ -1433,8 +1499,7 @@ static int open_output_file(OptionsContext *o, const char *filename) 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; @@ -1579,6 +1644,12 @@ loop_end: 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++) { @@ -1612,6 +1683,17 @@ loop_end: } av_dict_free(&unused_opts); + /* set the encoding/decoding_needed flags */ + for (i = of->ost_index; i < nb_output_streams; i++) { + OutputStream *ost = output_streams[i]; + + ost->encoding_needed = !ost->stream_copy; + if (ost->encoding_needed && ost->source_index >= 0) { + InputStream *ist = input_streams[ost->source_index]; + ist->decoding_needed = 1; + } + } + /* check filename in case of an image number is expected */ if (oc->oformat->flags & AVFMT_NEEDNUMBER) { if (!av_filename_number_test(oc->filename)) { @@ -1757,7 +1839,8 @@ static int opt_target(void *optctx, const char *opt, const char *arg) for (j = 0; j < nb_input_files; j++) { for (i = 0; i < input_files[j]->nb_streams; i++) { AVCodecContext *c = input_files[j]->ctx->streams[i]->codec; - if (c->codec_type != AVMEDIA_TYPE_VIDEO) + if (c->codec_type != AVMEDIA_TYPE_VIDEO || + !c->time_base.num) continue; fr = c->time_base.den * 1000 / c->time_base.num; if (fr == 25000) { @@ -1802,7 +1885,7 @@ static int opt_target(void *optctx, const char *opt, const char *arg) parse_option(o, "ac", "2", options); opt_default(NULL, "packetsize", "2324"); - opt_default(NULL, "muxrate", "1411200"); // 2352 * 75 * 8; + opt_default(NULL, "muxrate", "3528"); // 2352 * 75 / 50; /* We have to offset the PTS, so that it is consistent with the SCR. SCR starts at 36000, but the first two packs contain only padding @@ -1824,7 +1907,7 @@ static int opt_target(void *optctx, const char *opt, const char *arg) opt_default(NULL, "maxrate", "2516000"); opt_default(NULL, "minrate", "0"); // 1145000; opt_default(NULL, "bufsize", "1835008"); // 224*1024*8; - opt_default(NULL, "flags", "+scan_offset"); + opt_default(NULL, "scan_offset", "1"); opt_default(NULL, "b:a", "224000"); @@ -1848,7 +1931,7 @@ static int opt_target(void *optctx, const char *opt, const char *arg) opt_default(NULL, "bufsize", "1835008"); // 224*1024*8; opt_default(NULL, "packetsize", "2048"); // from www.mpucoder.com: DVD sectors contain 2048 bytes of data, this is also the size of one pack. - opt_default(NULL, "muxrate", "10080000"); // from mplex project: data_rate = 1260000. mux_rate = data_rate * 8 + opt_default(NULL, "muxrate", "25200"); // from mplex project: data_rate = 1260000. mux_rate = data_rate / 50 opt_default(NULL, "b:a", "448000"); parse_option(o, "ar", "48000", options); @@ -1869,6 +1952,10 @@ static int opt_target(void *optctx, const char *opt, const char *arg) av_log(NULL, AV_LOG_ERROR, "Unknown target: %s\n", arg); return AVERROR(EINVAL); } + + av_dict_copy(&o->g->codec_opts, codec_opts, 0); + av_dict_copy(&o->g->format_opts, format_opts, 0); + return 0; } @@ -1885,6 +1972,11 @@ static int opt_vstats(void *optctx, const char *opt, const char *arg) time_t today2 = time(NULL); struct tm *today = localtime(&today2); + if (!today) { // maybe tomorrow + av_log(NULL, AV_LOG_FATAL, "Unable to get current time.\n"); + exit_program(1); + } + snprintf(filename, sizeof(filename), "vstats_%02d%02d%02d.log", today->tm_hour, today->tm_min, today->tm_sec); return opt_vstats_file(NULL, opt, filename); @@ -2038,6 +2130,7 @@ void show_help_default(const char *opt, const char *arg) " -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 all options for the named decoder/encoder/demuxer/muxer/filter\n" " See man %s for detailed description of the options.\n" "\n", program_name); @@ -2162,6 +2255,13 @@ int avconv_parse_options(int argc, char **argv) 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) { @@ -2169,6 +2269,13 @@ int avconv_parse_options(int argc, char **argv) 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) { @@ -2293,6 +2400,8 @@ const OptionDef options[] = { { "dump_attachment", HAS_ARG | OPT_STRING | OPT_SPEC | OPT_EXPERT | OPT_INPUT, { .off = OFFSET(dump_attachment) }, "extract an attachment into a file", "filename" }, + { "loop", OPT_INT | HAS_ARG | OPT_EXPERT | OPT_INPUT | + OPT_OFFSET, { .off = OFFSET(loop) }, "set number of times input stream shall be looped", "loop count" }, /* video options */ { "vframes", OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_video_frames }, @@ -2360,7 +2469,12 @@ const OptionDef options[] = { "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" }, /* audio options */ { "aframes", OPT_AUDIO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_audio_frames },