aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexandra Khirnova <alexandra@khirnov.net>2011-10-10 11:52:13 +0100
committerAnton Khirnov <anton@khirnov.net>2011-10-17 22:24:17 +0200
commit3ec344626c4ec2f515169f89bffe95dea92a5982 (patch)
treeccd69faec86d89d759e9742b8583644e93102ed8
parent51369f2891f756bcca4d7283d5a24c0529c1d6e1 (diff)
downloadffmpeg-3ec344626c4ec2f515169f89bffe95dea92a5982.tar.gz
avconv: add presets
Signed-off-by: Anton Khirnov <anton@khirnov.net>
-rw-r--r--avconv.c77
-rw-r--r--doc/avconv.texi17
2 files changed, 93 insertions, 1 deletions
diff --git a/avconv.c b/avconv.c
index 44bc59f0cb..3c68ffc10b 100644
--- a/avconv.c
+++ b/avconv.c
@@ -326,6 +326,8 @@ typedef struct OptionsContext {
int nb_inter_matrices;
SpecifierOpt *top_field_first;
int nb_top_field_first;
+ SpecifierOpt *presets;
+ int nb_presets;
#if CONFIG_AVFILTER
SpecifierOpt *filters;
int nb_filters;
@@ -2966,15 +2968,62 @@ static void parse_forced_key_frames(char *kf, OutputStream *ost,
}
}
+static uint8_t *get_line(AVIOContext *s)
+{
+ AVIOContext *line;
+ uint8_t *buf;
+ char c;
+
+ if (avio_open_dyn_buf(&line) < 0) {
+ av_log(NULL, AV_LOG_FATAL, "Could not alloc buffer for reading preset.\n");
+ exit_program(1);
+ }
+
+ while ((c = avio_r8(s)) && c != '\n')
+ avio_w8(line, c);
+ avio_w8(line, 0);
+ avio_close_dyn_buf(line, &buf);
+
+ return buf;
+}
+
+static int get_preset_file_2(const char *preset_name, const char *codec_name, AVIOContext **s)
+{
+ int i, ret = 1;
+ char filename[1000];
+ const char *base[3] = { getenv("AVCONV_DATADIR"),
+ getenv("HOME"),
+ AVCONV_DATADIR,
+ };
+
+ for (i = 0; i < FF_ARRAY_ELEMS(base) && ret; i++) {
+ if (!base[i])
+ continue;
+ if (codec_name) {
+ snprintf(filename, sizeof(filename), "%s%s/%s-%s.avpreset", base[i],
+ i != 1 ? "" : "/.avconv", codec_name, preset_name);
+ ret = avio_open(s, filename, AVIO_FLAG_READ);
+ }
+ if (ret) {
+ snprintf(filename, sizeof(filename), "%s%s/%s.avpreset", base[i],
+ i != 1 ? "" : "/.avconv", preset_name);
+ ret = avio_open(s, filename, AVIO_FLAG_READ);
+ }
+ }
+ return ret;
+}
+
static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, enum AVMediaType type)
{
OutputStream *ost;
AVStream *st = av_new_stream(oc, oc->nb_streams < o->nb_streamid_map ? o->streamid_map[oc->nb_streams] : 0);
- int idx = oc->nb_streams - 1;
+ int idx = oc->nb_streams - 1, ret = 0;
int64_t max_frames = INT64_MAX;
char *bsf = NULL, *next, *codec_tag = NULL;
AVBitStreamFilterContext *bsfc, *bsfc_prev = NULL;
double qscale = -1;
+ char *buf = NULL, *arg = NULL, *preset = NULL;
+ AVIOContext *s = NULL;
if (!st) {
av_log(NULL, AV_LOG_FATAL, "Could not alloc stream.\n");
@@ -2996,6 +3045,31 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e
avcodec_get_context_defaults3(st->codec, ost->enc);
st->codec->codec_type = type; // XXX hack, avcodec_get_context_defaults2() sets type to unknown for stream copy
+ MATCH_PER_STREAM_OPT(presets, str, preset, oc, st);
+ if (preset && (!(ret = get_preset_file_2(preset, ost->enc->name, &s)))) {
+ do {
+ buf = get_line(s);
+ if (!buf[0] || buf[0] == '#') {
+ av_free(buf);
+ continue;
+ }
+ if (!(arg = strchr(buf, '='))) {
+ av_log(NULL, AV_LOG_FATAL, "Invalid line found in the preset file.\n");
+ exit_program(1);
+ }
+ *arg++ = 0;
+ av_dict_set(&ost->opts, buf, arg, AV_DICT_DONT_OVERWRITE);
+ av_free(buf);
+ } while (!s->eof_reached);
+ avio_close(s);
+ }
+ if (ret) {
+ av_log(NULL, AV_LOG_FATAL,
+ "Preset %s specified for stream %d:%d, but could not be opened.\n",
+ preset, ost->file_index, ost->index);
+ exit_program(1);
+ }
+
MATCH_PER_STREAM_OPT(max_frames, i64, max_frames, oc, st);
ost->max_frames = max_frames;
@@ -3906,6 +3980,7 @@ static const OptionDef options[] = {
{ "y", OPT_BOOL, {(void*)&file_overwrite}, "overwrite output files" },
{ "c", HAS_ARG | OPT_STRING | OPT_SPEC, {.off = OFFSET(codec_names)}, "codec name", "codec" },
{ "codec", HAS_ARG | OPT_STRING | OPT_SPEC, {.off = OFFSET(codec_names)}, "codec name", "codec" },
+ { "pre", HAS_ARG | OPT_STRING | OPT_SPEC, {.off = OFFSET(presets)}, "preset name", "preset" },
{ "map", HAS_ARG | OPT_EXPERT | OPT_FUNC2, {(void*)opt_map}, "set input stream mapping", "file.stream[:syncfile.syncstream]" },
{ "map_metadata", HAS_ARG | OPT_EXPERT | OPT_FUNC2, {(void*)opt_map_metadata}, "set metadata information of outfile from infile",
"outfile[,metadata]:infile[,metadata]" },
diff --git a/doc/avconv.texi b/doc/avconv.texi
index 9faaee630d..6e38a47b78 100644
--- a/doc/avconv.texi
+++ b/doc/avconv.texi
@@ -186,6 +186,8 @@ codec-dependent.
@var{filter_graph} is a description of the filter graph to apply to
the stream. Use @code{-filters} to show all the available filters
(including also sources and sinks).
+@item -pre[:@var{stream_specifier}] @var{preset_name} (@emph{output,per-stream})
+Specify the preset for matching stream(s).
@item -stats (@emph{global})
Print encoding progress/statistics. On by default.
@@ -770,6 +772,21 @@ quality).
@chapter Examples
@c man begin EXAMPLES
+@section Preset files
+
+A preset file contains a sequence of @var{option=value} pairs, one for
+each line, specifying a sequence of options which can be specified also on
+the command line. Lines starting with the hash ('#') character are ignored and
+are used to provide comments. Empty lines are also ignored. Check the
+@file{ffpresets} directory in the Libav source tree for examples.
+
+Preset files are specified with the @code{pre} option, this option takes a
+preset name as input. Avconv searches for a file named @var{preset_name}.avpreset in
+the directories @file{$AVCONV_DATADIR} (if set), and @file{$HOME/.avconv}, and in
+the data directory defined at configuration time (usually @file{$PREFIX/share/avconv})
+in that order. For example, if the argument is @code{libx264-max}, it will
+search for the file @file{libx264-max.avpreset}.
+
@section Video and Audio grabbing
If you specify the input format and device then avconv can grab video