static int exit_on_error = 0;
static int using_stdin = 0;
static int run_as_daemon = 0;
-static int q_pressed = 0;
+static volatile int received_nb_signals = 0;
static int64_t video_size = 0;
static int64_t audio_size = 0;
static int64_t extra_size = 0;
static float dts_delta_threshold = 10;
+static int print_stats = 1;
+
static uint8_t *audio_buf;
static uint8_t *audio_out;
static unsigned int allocated_audio_out_size, allocated_audio_buf_size;
typedef struct InputFile {
AVFormatContext *ctx;
int eof_reached; /* true if eof reached */
- int ist_index; /* index of first stream in ist_table */
+ int ist_index; /* index of first stream in input_streams */
int buffer_size; /* current total buffer size */
int64_t ts_offset;
- int nb_streams; /* number of stream that avconv is aware of; may be different
+ int nb_streams; /* number of stream that ffmpeg is aware of; may be different
from ctx.nb_streams if new streams appear during av_read_frame() */
int rate_emu;
} InputFile;
AVFilterGraph *graph;
#endif
- int sws_flags;
+ int64_t sws_flags;
AVDictionary *opts;
int is_past_recording_time;
} OutputStream;
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;
snprintf(args, 255, "%d:%d:flags=0x%X",
codec->width,
codec->height,
- ost->sws_flags);
+ (unsigned)ost->sws_flags);
if ((ret = avfilter_graph_create_filter(&filter, avfilter_get_by_name("scale"),
NULL, args, NULL, ost->graph)) < 0)
return ret;
last_filter = filter;
}
- snprintf(args, sizeof(args), "flags=0x%X", ost->sws_flags);
+ snprintf(args, sizeof(args), "flags=0x%X", (unsigned)ost->sws_flags);
ost->graph->scale_sws_opts = av_strdup(args);
if (ost->avfilter) {
static void sigterm_handler(int sig)
{
received_sigterm = sig;
- q_pressed++;
+ received_nb_signals++;
term_exit();
}
struct timeval tv;
fd_set rfds;
- if(run_as_daemon)
- return -1;
-
FD_ZERO(&rfds);
FD_SET(0, &rfds);
tv.tv_sec = 0;
static int decode_interrupt_cb(void)
{
- q_pressed += read_key() == 'q';
- return q_pressed > 1;
+ return received_nb_signals > 1;
}
void exit_program(int ret)
static void print_report(OutputFile *output_files,
OutputStream *ost_table, int nb_ostreams,
- int is_last_report, int64_t timer_start)
+ int is_last_report, int64_t timer_start, int64_t cur_time)
{
char buf[1024];
OutputStream *ost;
static int qp_histogram[52];
int hours, mins, secs, us;
+ if (!print_stats && !is_last_report)
+ return;
+
if (!is_last_report) {
- int64_t cur_time;
- /* display the report every 0.5 seconds */
- cur_time = av_gettime();
if (last_time == -1) {
last_time = cur_time;
return;
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "q=%2.1f ", q);
}
if (!vid && enc->codec_type == AVMEDIA_TYPE_VIDEO) {
- float t = (av_gettime()-timer_start) / 1000000.0;
+ float t = (cur_time-timer_start) / 1000000.0;
frame_number = ost->frame_number;
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "frame=%5d fps=%3d q=%3.1f ",
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " dup=%d drop=%d",
nb_frames_dup, nb_frames_drop);
- av_log(NULL, is_last_report ? AV_LOG_WARNING : AV_LOG_INFO, "%s \r", buf);
+ av_log(NULL, AV_LOG_INFO, "%s \r", buf);
fflush(stderr);
(ist->st->codec->sample_rate * ist->st->codec->channels);
break;}
case AVMEDIA_TYPE_VIDEO:
- decoded_data_size = (ist->st->codec->width * ist->st->codec->height * 3) / 2;
if (!(decoded_frame = avcodec_alloc_frame()))
return AVERROR(ENOMEM);
avpkt.pts = pkt_pts;
} else {
if (!ost->enc)
ost->enc = avcodec_find_encoder(ost->st->codec->codec_id);
+ ist->decoding_needed = 1;
+ ost->encoding_needed = 1;
switch(codec->codec_type) {
case AVMEDIA_TYPE_AUDIO:
ost->fifo= av_fifo_alloc(1024);
ost->audio_resample |= codec->sample_fmt != icodec->sample_fmt
|| codec->channel_layout != icodec->channel_layout;
icodec->request_channels = codec->channels;
- ist->decoding_needed = 1;
- ost->encoding_needed = 1;
ost->resample_sample_fmt = icodec->sample_fmt;
ost->resample_sample_rate = icodec->sample_rate;
ost->resample_channels = icodec->channels;
ost->resample_height = icodec->height;
ost->resample_width = icodec->width;
ost->resample_pix_fmt= icodec->pix_fmt;
- ost->encoding_needed = 1;
- ist->decoding_needed = 1;
if (!ost->frame_rate.num)
ost->frame_rate = ist->st->r_frame_rate.num ? ist->st->r_frame_rate : (AVRational){25,1};
#endif
break;
case AVMEDIA_TYPE_SUBTITLE:
- ost->encoding_needed = 1;
- ist->decoding_needed = 1;
break;
default:
abort();
break;
}
/* two pass mode */
- if (ost->encoding_needed && codec->codec_id != CODEC_ID_H264 &&
+ if (codec->codec_id != CODEC_ID_H264 &&
(codec->flags & (CODEC_FLAG_PASS1 | CODEC_FLAG_PASS2))) {
char logfilename[1024];
FILE *f;
assert_avoptions(ost->opts);
if (ost->st->codec->bit_rate && ost->st->codec->bit_rate < 1000)
av_log(NULL, AV_LOG_WARNING, "The bitrate parameter is set too low."
- "It takes bits/s as argument, not kbits/s\n");
+ " It takes bits/s as argument, not kbits/s\n");
extra_size += ost->st->codec->extradata_size;
if (ost->st->codec->me_threshold)
av_log(NULL, AV_LOG_INFO, "Press [q] to stop, [?] for help\n");
avio_set_interrupt_cb(decode_interrupt_cb);
}
- term_init();
timer_start = av_gettime();
AVPacket pkt;
int64_t ipts_min;
double opts_min;
+ int64_t cur_time= av_gettime();
ipts_min= INT64_MAX;
opts_min= 1e100;
/* if 'q' pressed, exits */
if (!using_stdin) {
- if (q_pressed)
+ static int64_t last_time;
+ if (received_nb_signals)
break;
/* read_key() returns 0 on EOF */
- key = read_key();
+ if(cur_time - last_time >= 100000 && !run_as_daemon){
+ key = read_key();
+ last_time = cur_time;
+ }else
+ key = -1;
if (key == 'q')
break;
if (key == '+') av_log_set_level(av_log_get_level()+10);
av_free_packet(&pkt);
/* dump report by using the output first video and audio streams */
- print_report(output_files, output_streams, nb_output_streams, 0, timer_start);
+ print_report(output_files, output_streams, nb_output_streams, 0, timer_start, cur_time);
}
/* at the end of stream, we must flush the decoder buffers */
}
/* dump report by using the first video and audio streams */
- print_report(output_files, output_streams, nb_output_streams, 1, timer_start);
+ print_report(output_files, output_streams, nb_output_streams, 1, timer_start, av_gettime());
/* close each encoder */
for (i = 0; i < nb_output_streams; i++) {
return ret;
}
-static int opt_verbose(const char *opt, const char *arg)
-{
- av_log(NULL, AV_LOG_WARNING, "-%s is deprecated, use -loglevel\n", opt);
- return 0;
-}
-
static int opt_frame_crop(const char *opt, const char *arg)
{
av_log(NULL, AV_LOG_FATAL, "Option '%s' has been removed, use the crop filter instead\n", opt);
static void add_input_streams(OptionsContext *o, AVFormatContext *ic)
{
int i, rfps, rfps_base;
+ char *next, *codec_tag = NULL;
for (i = 0; i < ic->nb_streams; i++) {
AVStream *st = ic->streams[i];
MATCH_PER_STREAM_OPT(ts_scale, dbl, scale, ic, st);
ist->ts_scale = scale;
+ MATCH_PER_STREAM_OPT(codec_tags, str, codec_tag, ic, st);
+ if (codec_tag) {
+ uint32_t tag = strtol(codec_tag, &next, 0);
+ if (*next)
+ tag = AV_RL32(codec_tag);
+ st->codec->codec_tag = tag;
+ }
+
ist->dec = choose_codec(o, ic, st, dec->codec_type);
if (!ist->dec)
ist->dec = avcodec_find_decoder(dec->codec_id);
if (o->nb_frame_pix_fmts)
av_dict_set(&format_opts, "pixel_format", o->frame_pix_fmts[o->nb_frame_pix_fmts - 1].u.str, 0);
+ ic->video_codec_id =
+ find_codec_or_die(video_codec_name , AVMEDIA_TYPE_VIDEO , 0);
+ ic->audio_codec_id =
+ find_codec_or_die(audio_codec_name , AVMEDIA_TYPE_AUDIO , 0);
+ ic->subtitle_codec_id=
+ find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 0);
ic->flags |= AVFMT_FLAG_NONBLOCK;
if (loop_input) {
}
}
+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;
+ AVStream *st = avformat_new_stream(oc, NULL);
+ 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");
exit_program(1);
}
+ if (oc->nb_streams - 1 < o->nb_streamid_map)
+ st->id = o->streamid_map[oc->nb_streams - 1];
+
output_streams = grow_array(output_streams, sizeof(*output_streams), &nb_output_streams,
nb_output_streams + 1);
ost = &output_streams[nb_output_streams - 1];
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;
if (oc->oformat->flags & AVFMT_GLOBALHEADER)
st->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
- ost->sws_flags = av_get_int(sws_opts, "sws_flags", NULL);
+ av_opt_get_int(sws_opts, "sws_flags", 0, &ost->sws_flags);
return ost;
}
if (!using_stdin) {
fprintf(stderr,"File '%s' already exists. Overwrite ? [y/N] ", filename);
fflush(stderr);
+ term_exit();
if (!read_yesno()) {
av_log(0, AV_LOG_FATAL, "Not overwriting - exiting\n");
exit_program(1);
}
+ term_init();
}
else {
av_log(0, AV_LOG_FATAL,"File '%s' already exists. Exiting.\n", filename);
static int opt_help(const char *opt, const char *arg)
{
- AVCodec *c;
- AVOutputFormat *oformat = NULL;
- AVInputFormat *iformat = NULL;
- const AVClass *class;
-
+ int flags = AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_ENCODING_PARAM;
av_log_set_callback(log_callback_help);
show_usage();
show_help_options(options, "Main options:\n",
OPT_GRAB,
OPT_GRAB);
printf("\n");
- class = avcodec_get_class();
- av_opt_show2(&class, NULL, AV_OPT_FLAG_ENCODING_PARAM|AV_OPT_FLAG_DECODING_PARAM, 0);
- printf("\n");
+ show_help_children(avcodec_get_class(), flags);
+ show_help_children(avformat_get_class(), flags);
+ show_help_children(sws_get_class(), flags);
- /* individual codec options */
- c = NULL;
- while ((c = av_codec_next(c))) {
- if (c->priv_class) {
- av_opt_show2(&c->priv_class, NULL, AV_OPT_FLAG_ENCODING_PARAM|AV_OPT_FLAG_DECODING_PARAM, 0);
- printf("\n");
- }
- }
-
- class = avformat_get_class();
- av_opt_show2(&class, NULL, AV_OPT_FLAG_ENCODING_PARAM|AV_OPT_FLAG_DECODING_PARAM, 0);
- printf("\n");
-
- /* individual muxer options */
- while ((oformat = av_oformat_next(oformat))) {
- if (oformat->priv_class) {
- av_opt_show2(&oformat->priv_class, NULL, AV_OPT_FLAG_ENCODING_PARAM, 0);
- printf("\n");
- }
- }
-
- /* individual demuxer options */
- while ((iformat = av_iformat_next(iformat))) {
- if (iformat->priv_class) {
- av_opt_show2(&iformat->priv_class, NULL, AV_OPT_FLAG_DECODING_PARAM, 0);
- printf("\n");
- }
- }
-
- class = sws_get_class();
- av_opt_show2(&class, NULL, AV_OPT_FLAG_ENCODING_PARAM|AV_OPT_FLAG_DECODING_PARAM, 0);
return 0;
}
{ "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_meta_data", HAS_ARG | OPT_EXPERT | OPT_FUNC2, {(void*)opt_map_meta_data}, "DEPRECATED set meta data information of outfile from infile",
"outfile[,metadata]:infile[,metadata]" },
{ "re", OPT_BOOL | OPT_EXPERT | OPT_OFFSET, {.off = OFFSET(rate_emu)}, "read input at native frame rate", "" },
{ "loop_input", OPT_BOOL | OPT_EXPERT, {(void*)&loop_input}, "deprecated, use -loop" },
{ "loop_output", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&loop_output}, "deprecated, use -loop", "" },
- { "v", HAS_ARG, {(void*)opt_verbose}, "deprecated, use -loglevel instead", "number" },
{ "target", HAS_ARG | OPT_FUNC2, {(void*)opt_target}, "specify target file type (\"vcd\", \"svcd\", \"dvd\", \"dv\", \"dv50\", \"pal-vcd\", \"ntsc-svcd\", ...)", "type" },
{ "vsync", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&video_sync_method}, "video sync method", "" },
{ "async", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&audio_sync_method}, "audio sync method", "" },
#if CONFIG_AVFILTER
{ "filter", HAS_ARG | OPT_STRING | OPT_SPEC, {.off = OFFSET(filters)}, "set stream filterchain", "filter_list" },
#endif
+ { "stats", OPT_BOOL, {&print_stats}, "print progress report during encoding", },
/* video options */
{ "vframes", HAS_ARG | OPT_VIDEO | OPT_FUNC2, {(void*)opt_video_frames}, "set the number of video frames to record", "number" },
show_banner();
+ term_init();
+
/* parse options */
parse_options(&o, argc, argv, options, opt_output_file);