diff options
Diffstat (limited to 'ffmpeg/ffmpeg_opt.c')
| -rw-r--r-- | ffmpeg/ffmpeg_opt.c | 592 |
1 files changed, 391 insertions, 201 deletions
diff --git a/ffmpeg/ffmpeg_opt.c b/ffmpeg/ffmpeg_opt.c index 4b2cfeb..d267c6d 100644 --- a/ffmpeg/ffmpeg_opt.c +++ b/ffmpeg/ffmpeg_opt.c @@ -28,7 +28,6 @@ #include "libavcodec/avcodec.h" #include "libavfilter/avfilter.h" -#include "libavfilter/avfiltergraph.h" #include "libavutil/avassert.h" #include "libavutil/avstring.h" @@ -50,7 +49,7 @@ if ((ret = check_stream_specifier(fmtctx, st, spec)) > 0)\ outvar = o->name[i].u.type;\ else if (ret < 0)\ - exit(1);\ + exit_program(1);\ }\ } @@ -63,6 +62,14 @@ outvar = o->name[i].u.type;\ }\ } + +const HWAccel hwaccels[] = { +#if HAVE_VDPAU_X11 + { "vdpau", vdpau_init, HWACCEL_VDPAU, AV_PIX_FMT_VDPAU }, +#endif + { 0 }, +}; + char *vstats_filename; float audio_drift_threshold = 0.1; @@ -85,6 +92,7 @@ int print_stats = -1; int qp_hist = 0; int stdin_interaction = 1; int frame_bits_per_raw_sample = 0; +float max_error_rate = 2.0/3; static int intra_only = 0; @@ -94,10 +102,9 @@ static int video_discard = 0; static int intra_dc_precision = 8; static int do_psnr = 0; static int input_sync; +static int override_ffserver = 0; -static int64_t recording_time = INT64_MAX; - -static void uninit_options(OptionsContext *o, int is_input) +static void uninit_options(OptionsContext *o) { const OptionDef *po = options; int i; @@ -127,28 +134,19 @@ static void uninit_options(OptionsContext *o, int is_input) av_freep(&o->audio_channel_maps); av_freep(&o->streamid_map); av_freep(&o->attachments); - - if (is_input) - recording_time = o->recording_time; - else - recording_time = INT64_MAX; } -static void init_options(OptionsContext *o, int is_input) +static void init_options(OptionsContext *o) { memset(o, 0, sizeof(*o)); - if (!is_input && recording_time != INT64_MAX) { - o->recording_time = recording_time; - av_log(NULL, AV_LOG_WARNING, - "-t is not an input option, keeping it for the next output;" - " consider fixing your command line.\n"); - } else - o->recording_time = INT64_MAX; o->stop_time = INT64_MAX; o->mux_max_delay = 0.7; + o->start_time = AV_NOPTS_VALUE; + o->recording_time = INT64_MAX; o->limit_filesize = UINT64_MAX; o->chapters_input_file = INT_MAX; + o->accurate_seek = 1; } /* return a copy of the input with the stream specifiers removed from the keys */ @@ -235,7 +233,7 @@ static int opt_map(void *optctx, const char *opt, const char *arg) sync_file_idx = strtol(sync + 1, &sync, 0); if (sync_file_idx >= nb_input_files || sync_file_idx < 0) { av_log(NULL, AV_LOG_FATAL, "Invalid sync file index: %d.\n", sync_file_idx); - exit(1); + exit_program(1); } if (*sync) sync++; @@ -248,7 +246,7 @@ static int opt_map(void *optctx, const char *opt, const char *arg) if (i == input_files[sync_file_idx]->nb_streams) { av_log(NULL, AV_LOG_FATAL, "Sync stream specification in map %s does not " "match any streams.\n", arg); - exit(1); + exit_program(1); } } @@ -261,13 +259,13 @@ static int opt_map(void *optctx, const char *opt, const char *arg) m->linklabel = av_get_token(&c, "]"); if (!m->linklabel) { av_log(NULL, AV_LOG_ERROR, "Invalid output link label: %s.\n", map); - exit(1); + exit_program(1); } } else { file_idx = strtol(map, &p, 0); if (file_idx >= nb_input_files || file_idx < 0) { av_log(NULL, AV_LOG_FATAL, "Invalid input file index: %d.\n", file_idx); - exit(1); + exit_program(1); } if (negative) /* disable some already defined maps */ @@ -302,7 +300,7 @@ static int opt_map(void *optctx, const char *opt, const char *arg) if (!m) { av_log(NULL, AV_LOG_FATAL, "Stream map '%s' matches no streams.\n", arg); - exit(1); + exit_program(1); } av_freep(&map); @@ -344,7 +342,7 @@ static int opt_map_channel(void *optctx, const char *opt, const char *arg) if (n != 3 && n != 5) { av_log(NULL, AV_LOG_FATAL, "Syntax error, mapchan usage: " "[file.stream.channel|-1][:syncfile:syncstream]\n"); - exit(1); + exit_program(1); } if (n != 5) // only file.stream.channel specified @@ -354,24 +352,24 @@ static int opt_map_channel(void *optctx, const char *opt, const char *arg) if (m->file_idx < 0 || m->file_idx >= nb_input_files) { av_log(NULL, AV_LOG_FATAL, "mapchan: invalid input file index: %d\n", m->file_idx); - exit(1); + exit_program(1); } if (m->stream_idx < 0 || m->stream_idx >= input_files[m->file_idx]->nb_streams) { av_log(NULL, AV_LOG_FATAL, "mapchan: invalid input file stream index #%d.%d\n", m->file_idx, m->stream_idx); - exit(1); + exit_program(1); } st = input_files[m->file_idx]->ctx->streams[m->stream_idx]; if (st->codec->codec_type != AVMEDIA_TYPE_AUDIO) { av_log(NULL, AV_LOG_FATAL, "mapchan: stream #%d.%d is not an audio stream.\n", m->file_idx, m->stream_idx); - exit(1); + exit_program(1); } if (m->channel_idx < 0 || m->channel_idx >= st->codec->channels) { av_log(NULL, AV_LOG_FATAL, "mapchan: invalid audio channel #%d.%d.%d\n", m->file_idx, m->stream_idx, m->channel_idx); - exit(1); + exit_program(1); } return 0; } @@ -393,7 +391,7 @@ static void parse_meta_type(char *arg, char *type, int *index, const char **stre case 's': if (*(++arg) && *arg != ':') { av_log(NULL, AV_LOG_FATAL, "Invalid metadata specifier %s.\n", arg); - exit(1); + exit_program(1); } *stream_spec = *arg == ':' ? arg + 1 : ""; break; @@ -404,7 +402,7 @@ static void parse_meta_type(char *arg, char *type, int *index, const char **stre break; default: av_log(NULL, AV_LOG_FATAL, "Invalid metadata type %c.\n", *arg); - exit(1); + exit_program(1); } } else *type = 'g'; @@ -447,7 +445,7 @@ static int copy_metadata(char *outspec, char *inspec, AVFormatContext *oc, AVFor if ((index) < 0 || (index) >= (nb_elems)) {\ av_log(NULL, AV_LOG_FATAL, "Invalid %s index %d while processing metadata maps.\n",\ (desc), (index));\ - exit(1);\ + exit_program(1);\ } #define SET_DICT(type, meta, context, index)\ @@ -478,11 +476,11 @@ static int copy_metadata(char *outspec, char *inspec, AVFormatContext *oc, AVFor meta_in = &ic->streams[i]->metadata; break; } else if (ret < 0) - exit(1); + exit_program(1); } if (!meta_in) { av_log(NULL, AV_LOG_FATAL, "Stream specifier %s does not match any streams.\n", istream_spec); - exit(1); + exit_program(1); } } @@ -492,7 +490,7 @@ static int copy_metadata(char *outspec, char *inspec, AVFormatContext *oc, AVFor meta_out = &oc->streams[i]->metadata; av_dict_copy(meta_out, *meta_in, AV_DICT_DONT_OVERWRITE); } else if (ret < 0) - exit(1); + exit_program(1); } } else av_dict_copy(meta_out, *meta_in, AV_DICT_DONT_OVERWRITE); @@ -534,11 +532,11 @@ static AVCodec *find_codec_or_die(const char *name, enum AVMediaType type, int e if (!codec) { av_log(NULL, AV_LOG_FATAL, "Unknown %s '%s'\n", codec_string, name); - exit(1); + exit_program(1); } if (codec->type != type) { av_log(NULL, AV_LOG_FATAL, "Invalid %s type '%s'\n", codec_string, name); - exit(1); + exit_program(1); } return codec; } @@ -567,10 +565,10 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) AVStream *st = ic->streams[i]; AVCodecContext *dec = st->codec; InputStream *ist = av_mallocz(sizeof(*ist)); - char *framerate = NULL; + char *framerate = NULL, *hwaccel = NULL, *hwaccel_device = NULL; if (!ist) - exit(1); + exit_program(1); GROW_ARRAY(input_streams, nb_input_streams); input_streams[nb_input_streams - 1] = ist; @@ -603,7 +601,7 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) case AVMEDIA_TYPE_VIDEO: if(!ist->dec) ist->dec = avcodec_find_decoder(dec->codec_id); - if (dec->lowres) { + if (av_codec_get_lowres(dec)) { dec->flags |= CODEC_FLAG_EMU_EDGE; } @@ -616,12 +614,47 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) framerate) < 0) { av_log(NULL, AV_LOG_ERROR, "Error parsing framerate %s.\n", framerate); - exit(1); + exit_program(1); } ist->top_field_first = -1; MATCH_PER_STREAM_OPT(top_field_first, i, ist->top_field_first, ic, st); + MATCH_PER_STREAM_OPT(hwaccels, str, hwaccel, ic, st); + if (hwaccel) { + if (!strcmp(hwaccel, "none")) + ist->hwaccel_id = HWACCEL_NONE; + else if (!strcmp(hwaccel, "auto")) + ist->hwaccel_id = HWACCEL_AUTO; + else { + int i; + for (i = 0; hwaccels[i].name; i++) { + if (!strcmp(hwaccels[i].name, hwaccel)) { + ist->hwaccel_id = hwaccels[i].id; + break; + } + } + + if (!ist->hwaccel_id) { + av_log(NULL, AV_LOG_FATAL, "Unrecognized hwaccel: %s.\n", + hwaccel); + av_log(NULL, AV_LOG_FATAL, "Supported hwaccels: "); + for (i = 0; hwaccels[i].name; i++) + av_log(NULL, AV_LOG_FATAL, "%s ", hwaccels[i].name); + av_log(NULL, AV_LOG_FATAL, "\n"); + exit_program(1); + } + } + } + + MATCH_PER_STREAM_OPT(hwaccel_devices, str, hwaccel_device, ic, st); + if (hwaccel_device) { + ist->hwaccel_device = av_strdup(hwaccel_device); + if (!ist->hwaccel_device) + exit_program(1); + } + ist->hwaccel_pix_fmt = AV_PIX_FMT_NONE; + break; case AVMEDIA_TYPE_AUDIO: ist->guess_layout_max = INT_MAX; @@ -644,7 +677,7 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) if (canvas_size && av_parse_video_size(&dec->width, &dec->height, canvas_size) < 0) { av_log(NULL, AV_LOG_FATAL, "Invalid canvas size: %s.\n", canvas_size); - exit(1); + exit_program(1); } break; } @@ -659,24 +692,29 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) static void assert_file_overwrite(const char *filename) { - if ((!file_overwrite || no_file_overwrite) && + if (file_overwrite && no_file_overwrite) { + fprintf(stderr, "Error, both -y and -n supplied. Exiting.\n"); + exit_program(1); + } + + if (!file_overwrite && (strchr(filename, ':') == NULL || filename[1] == ':' || av_strstart(filename, "file:", NULL))) { if (avio_check(filename, 0) == 0) { - if (stdin_interaction && (!no_file_overwrite || file_overwrite)) { + if (stdin_interaction && !no_file_overwrite) { fprintf(stderr,"File '%s' already exists. Overwrite ? [y/N] ", filename); fflush(stderr); term_exit(); signal(SIGINT, SIG_DFL); if (!read_yesno()) { av_log(NULL, AV_LOG_FATAL, "Not overwriting - exiting\n"); - exit(1); + exit_program(1); } term_init(); } else { av_log(NULL, AV_LOG_FATAL, "File '%s' already exists. Exiting.\n", filename); - exit(1); + exit_program(1); } } } @@ -698,7 +736,7 @@ static void dump_attachment(AVStream *st, const char *filename) if (!*filename) { av_log(NULL, AV_LOG_FATAL, "No filename specified and no 'filename' tag" "in stream #%d:%d.\n", nb_input_files - 1, st->index); - exit(1); + exit_program(1); } assert_file_overwrite(filename); @@ -706,7 +744,7 @@ static void dump_attachment(AVStream *st, const char *filename) if ((ret = avio_open2(&out, filename, AVIO_FLAG_WRITE, &int_cb, NULL)) < 0) { av_log(NULL, AV_LOG_FATAL, "Could not open file %s for writing.\n", filename); - exit(1); + exit_program(1); } avio_write(out, st->codec->extradata, st->codec->extradata_size); @@ -733,7 +771,7 @@ static int open_input_file(OptionsContext *o, const char *filename) if (o->format) { if (!(file_iformat = av_find_input_format(o->format))) { av_log(NULL, AV_LOG_FATAL, "Unknown input format: '%s'\n", o->format); - exit(1); + exit_program(1); } } @@ -747,7 +785,7 @@ static int open_input_file(OptionsContext *o, const char *filename) ic = avformat_alloc_context(); if (!ic) { print_error(filename, AVERROR(ENOMEM)); - exit(1); + exit_program(1); } if (o->nb_audio_sample_rate) { snprintf(buf, sizeof(buf), "%d", o->audio_sample_rate[o->nb_audio_sample_rate - 1].u.i); @@ -791,6 +829,14 @@ static int open_input_file(OptionsContext *o, const char *filename) find_codec_or_die(audio_codec_name , AVMEDIA_TYPE_AUDIO , 0)->id : AV_CODEC_ID_NONE; ic->subtitle_codec_id= subtitle_codec_name ? find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 0)->id : AV_CODEC_ID_NONE; + + if (video_codec_name) + av_format_set_video_codec (ic, find_codec_or_die(video_codec_name , AVMEDIA_TYPE_VIDEO , 0)); + if (audio_codec_name) + av_format_set_audio_codec (ic, find_codec_or_die(audio_codec_name , AVMEDIA_TYPE_AUDIO , 0)); + if (subtitle_codec_name) + av_format_set_subtitle_codec(ic, find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 0)); + ic->flags |= AVFMT_FLAG_NONBLOCK; ic->interrupt_callback = int_cb; @@ -798,7 +844,7 @@ static int open_input_file(OptionsContext *o, const char *filename) err = avformat_open_input(&ic, filename, file_iformat, &o->g->format_opts); if (err < 0) { print_error(filename, err); - exit(1); + exit_program(1); } assert_avoptions(o->g->format_opts); @@ -816,16 +862,16 @@ static int open_input_file(OptionsContext *o, const char *filename) if (ret < 0) { av_log(NULL, AV_LOG_FATAL, "%s: could not find codec parameters\n", filename); avformat_close_input(&ic); - exit(1); + exit_program(1); } - timestamp = o->start_time; + timestamp = (o->start_time == AV_NOPTS_VALUE) ? 0 : o->start_time; /* add the stream start time */ if (ic->start_time != AV_NOPTS_VALUE) timestamp += ic->start_time; /* if seeking requested, we execute it */ - if (o->start_time != 0) { + if (o->start_time != AV_NOPTS_VALUE) { ret = avformat_seek_file(ic, -1, INT64_MIN, timestamp, timestamp, 0); if (ret < 0) { av_log(NULL, AV_LOG_WARNING, "%s: could not seek to position %0.3f\n", @@ -842,14 +888,18 @@ static int open_input_file(OptionsContext *o, const char *filename) GROW_ARRAY(input_files, nb_input_files); f = av_mallocz(sizeof(*f)); if (!f) - exit(1); + exit_program(1); input_files[nb_input_files - 1] = f; f->ctx = ic; f->ist_index = nb_input_streams - ic->nb_streams; + f->start_time = o->start_time; + f->recording_time = o->recording_time; + f->input_ts_offset = o->input_ts_offset; f->ts_offset = o->input_ts_offset - (copy_ts ? 0 : timestamp); f->nb_streams = ic->nb_streams; f->rate_emu = o->rate_emu; + f->accurate_seek = o->accurate_seek; /* check if all codec options have been used */ unused_opts = strip_specifiers(o->g->codec_opts); @@ -872,7 +922,7 @@ static int open_input_file(OptionsContext *o, const char *filename) "input file #%d (%s) is not a decoding option.\n", e->key, option->help ? option->help : "", nb_input_files - 1, filename); - exit(1); + exit_program(1); } av_log(NULL, AV_LOG_WARNING, "Codec AVOption %s (%s) specified for " @@ -910,7 +960,7 @@ static uint8_t *get_line(AVIOContext *s) if (avio_open_dyn_buf(&line) < 0) { av_log(NULL, AV_LOG_FATAL, "Could not alloc buffer for reading preset.\n"); - exit(1); + exit_program(1); } while ((c = avio_r8(s)) && c != '\n') @@ -972,10 +1022,11 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e char *bsf = NULL, *next, *codec_tag = NULL; AVBitStreamFilterContext *bsfc, *bsfc_prev = NULL; double qscale = -1; + int i; if (!st) { av_log(NULL, AV_LOG_FATAL, "Could not alloc stream.\n"); - exit(1); + exit_program(1); } if (oc->nb_streams - 1 < o->nb_streamid_map) @@ -983,10 +1034,10 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e GROW_ARRAY(output_streams, nb_output_streams); if (!(ost = av_mallocz(sizeof(*ost)))) - exit(1); + exit_program(1); output_streams[nb_output_streams - 1] = ost; - ost->file_index = nb_output_files; + ost->file_index = nb_output_files - 1; ost->index = idx; ost->st = st; st->codec->codec_type = type; @@ -1007,7 +1058,7 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e } if (!(arg = strchr(buf, '='))) { av_log(NULL, AV_LOG_FATAL, "Invalid line found in the preset file.\n"); - exit(1); + exit_program(1); } *arg++ = 0; av_dict_set(&ost->opts, buf, arg, AV_DICT_DONT_OVERWRITE); @@ -1019,7 +1070,7 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e 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(1); + exit_program(1); } } else { ost->opts = filter_codec_opts(o->g->codec_opts, AV_CODEC_ID_NONE, oc, st, NULL); @@ -1030,6 +1081,13 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e ost->max_frames = INT64_MAX; MATCH_PER_STREAM_OPT(max_frames, i64, ost->max_frames, oc, st); + for (i = 0; i<o->nb_max_frames; i++) { + char *p = o->max_frames[i].specifier; + if (!*p && type != AVMEDIA_TYPE_VIDEO) { + av_log(NULL, AV_LOG_WARNING, "Applying unspecific -frames to non video streams, maybe you meant -vframes ?\n"); + break; + } + } ost->copy_prior_start = -1; MATCH_PER_STREAM_OPT(copy_prior_start, i, ost->copy_prior_start, oc ,st); @@ -1040,7 +1098,7 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e *next++ = 0; if (!(bsfc = av_bitstream_filter_init(bsf))) { av_log(NULL, AV_LOG_FATAL, "Unknown bitstream filter %s\n", bsf); - exit(1); + exit_program(1); } if (bsfc_prev) bsfc_prev->next = bsfc; @@ -1082,6 +1140,7 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e input_streams[source_index]->discard = 0; input_streams[source_index]->st->discard = AVDISCARD_NONE; } + ost->last_mux_dts = AV_NOPTS_VALUE; return ost; } @@ -1097,18 +1156,81 @@ static void parse_matrix_coeffs(uint16_t *dest, const char *str) p = strchr(p, ','); if (!p) { av_log(NULL, AV_LOG_FATAL, "Syntax error in matrix \"%s\" at coeff %d\n", str, i); - exit(1); + exit_program(1); } p++; } } +/* read file contents into a string */ +static uint8_t *read_file(const char *filename) +{ + AVIOContext *pb = NULL; + AVIOContext *dyn_buf = NULL; + int ret = avio_open(&pb, filename, AVIO_FLAG_READ); + uint8_t buf[1024], *str; + + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Error opening file %s.\n", filename); + return NULL; + } + + ret = avio_open_dyn_buf(&dyn_buf); + if (ret < 0) { + avio_closep(&pb); + return NULL; + } + while ((ret = avio_read(pb, buf, sizeof(buf))) > 0) + avio_write(dyn_buf, buf, ret); + avio_w8(dyn_buf, 0); + avio_closep(&pb); + + ret = avio_close_dyn_buf(dyn_buf, &str); + if (ret < 0) + return NULL; + return str; +} + +static char *get_ost_filters(OptionsContext *o, AVFormatContext *oc, + OutputStream *ost) +{ + AVStream *st = ost->st; + + if (ost->filters_script && ost->filters) { + av_log(NULL, AV_LOG_ERROR, "Both -filter and -filter_script set for " + "output stream #%d:%d.\n", nb_output_files, st->index); + exit_program(1); + } + + if (ost->filters_script) + return read_file(ost->filters_script); + else if (ost->filters) + return av_strdup(ost->filters); + + return av_strdup(st->codec->codec_type == AVMEDIA_TYPE_VIDEO ? + "null" : "anull"); +} + +static void check_streamcopy_filters(OptionsContext *o, AVFormatContext *oc, + const OutputStream *ost, enum AVMediaType type) +{ + if (ost->filters_script || ost->filters) { + av_log(NULL, AV_LOG_ERROR, + "%s '%s' was defined for %s output stream %d:%d but codec copy was selected.\n" + "Filtering and streamcopy cannot be used together.\n", + ost->filters ? "Filtergraph" : "Filtergraph script", + ost->filters ? ost->filters : ost->filters_script, + av_get_media_type_string(type), ost->file_index, ost->index); + exit_program(1); + } +} + static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, int source_index) { AVStream *st; OutputStream *ost; AVCodecContext *video_enc; - char *frame_rate = NULL; + char *frame_rate = NULL, *frame_aspect_ratio = NULL; ost = new_output_stream(o, oc, AVMEDIA_TYPE_VIDEO, source_index); st = ost->st; @@ -1117,33 +1239,35 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in MATCH_PER_STREAM_OPT(frame_rates, str, frame_rate, oc, st); if (frame_rate && av_parse_video_rate(&ost->frame_rate, frame_rate) < 0) { av_log(NULL, AV_LOG_FATAL, "Invalid framerate value: %s\n", frame_rate); - exit(1); + exit_program(1); } + MATCH_PER_STREAM_OPT(frame_aspect_ratios, str, frame_aspect_ratio, oc, st); + if (frame_aspect_ratio) { + AVRational q; + if (av_parse_ratio(&q, frame_aspect_ratio, 255, 0, NULL) < 0 || + q.num <= 0 || q.den <= 0) { + av_log(NULL, AV_LOG_FATAL, "Invalid aspect ratio: %s\n", frame_aspect_ratio); + exit_program(1); + } + ost->frame_aspect_ratio = q; + } + + MATCH_PER_STREAM_OPT(filter_scripts, str, ost->filters_script, oc, st); + MATCH_PER_STREAM_OPT(filters, str, ost->filters, oc, st); + if (!ost->stream_copy) { const char *p = NULL; char *frame_size = NULL; - char *frame_aspect_ratio = NULL, *frame_pix_fmt = NULL; + char *frame_pix_fmt = NULL; char *intra_matrix = NULL, *inter_matrix = NULL; - const char *filters = "null"; int do_pass = 0; int i; MATCH_PER_STREAM_OPT(frame_sizes, str, frame_size, oc, st); if (frame_size && av_parse_video_size(&video_enc->width, &video_enc->height, frame_size) < 0) { av_log(NULL, AV_LOG_FATAL, "Invalid frame size: %s.\n", frame_size); - exit(1); - } - - MATCH_PER_STREAM_OPT(frame_aspect_ratios, str, frame_aspect_ratio, oc, st); - if (frame_aspect_ratio) { - AVRational q; - if (av_parse_ratio(&q, frame_aspect_ratio, 255, 0, NULL) < 0 || - q.num <= 0 || q.den <= 0) { - av_log(NULL, AV_LOG_FATAL, "Invalid aspect ratio: %s\n", frame_aspect_ratio); - exit(1); - } - ost->frame_aspect_ratio = av_q2d(q); + exit_program(1); } video_enc->bits_per_raw_sample = frame_bits_per_raw_sample; @@ -1155,7 +1279,7 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in } if (frame_pix_fmt && (video_enc->pix_fmt = av_get_pix_fmt(frame_pix_fmt)) == AV_PIX_FMT_NONE) { av_log(NULL, AV_LOG_FATAL, "Unknown pixel format requested: %s.\n", frame_pix_fmt); - exit(1); + exit_program(1); } st->sample_aspect_ratio = video_enc->sample_aspect_ratio; @@ -1165,7 +1289,7 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in if (intra_matrix) { if (!(video_enc->intra_matrix = av_mallocz(sizeof(*video_enc->intra_matrix) * 64))) { av_log(NULL, AV_LOG_FATAL, "Could not allocate memory for intra matrix.\n"); - exit(1); + exit_program(1); } parse_matrix_coeffs(video_enc->intra_matrix, intra_matrix); } @@ -1173,7 +1297,7 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in if (inter_matrix) { if (!(video_enc->inter_matrix = av_mallocz(sizeof(*video_enc->inter_matrix) * 64))) { av_log(NULL, AV_LOG_FATAL, "Could not allocate memory for inter matrix.\n"); - exit(1); + exit_program(1); } parse_matrix_coeffs(video_enc->inter_matrix, inter_matrix); } @@ -1184,7 +1308,7 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in int e = sscanf(p, "%d,%d,%d", &start, &end, &q); if (e != 3) { av_log(NULL, AV_LOG_FATAL, "error parsing rc_override\n"); - exit(1); + exit_program(1); } /* FIXME realloc failure */ video_enc->rc_override = @@ -1225,7 +1349,7 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in MATCH_PER_STREAM_OPT(passlogfiles, str, ost->logfile_prefix, oc, st); if (ost->logfile_prefix && !(ost->logfile_prefix = av_strdup(ost->logfile_prefix))) - exit(1); + exit_program(1); MATCH_PER_STREAM_OPT(forced_key_frames, str, ost->forced_keyframes, oc, st); if (ost->forced_keyframes) @@ -1236,12 +1360,17 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in ost->top_field_first = -1; MATCH_PER_STREAM_OPT(top_field_first, i, ost->top_field_first, oc, st); - MATCH_PER_STREAM_OPT(filters, str, filters, oc, st); - ost->avfilter = av_strdup(filters); + + ost->avfilter = get_ost_filters(o, oc, ost); + if (!ost->avfilter) + exit_program(1); } else { MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i, ost->copy_initial_nonkeyframes, oc ,st); } + if (ost->stream_copy) + check_streamcopy_filters(o, oc, ost, AVMEDIA_TYPE_VIDEO); + return ost; } @@ -1258,9 +1387,11 @@ static OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext *oc, in audio_enc = st->codec; audio_enc->codec_type = AVMEDIA_TYPE_AUDIO; + MATCH_PER_STREAM_OPT(filter_scripts, str, ost->filters_script, oc, st); + MATCH_PER_STREAM_OPT(filters, str, ost->filters, oc, st); + if (!ost->stream_copy) { char *sample_fmt = NULL; - const char *filters = "anull"; MATCH_PER_STREAM_OPT(audio_channels, i, audio_enc->channels, oc, st); @@ -1268,15 +1399,17 @@ static OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext *oc, in if (sample_fmt && (audio_enc->sample_fmt = av_get_sample_fmt(sample_fmt)) == AV_SAMPLE_FMT_NONE) { av_log(NULL, AV_LOG_FATAL, "Invalid sample format '%s'\n", sample_fmt); - exit(1); + exit_program(1); } MATCH_PER_STREAM_OPT(audio_sample_rate, i, audio_enc->sample_rate, oc, st); - MATCH_PER_STREAM_OPT(filters, str, filters, oc, st); + MATCH_PER_STREAM_OPT(apad, str, ost->apad, oc, st); + ost->apad = av_strdup(ost->apad); - av_assert1(filters); - ost->avfilter = av_strdup(filters); + ost->avfilter = get_ost_filters(o, oc, ost); + if (!ost->avfilter) + exit_program(1); /* check for channel mapping for this audio stream */ for (n = 0; n < o->nb_audio_channel_maps; n++) { @@ -1294,6 +1427,9 @@ static OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext *oc, in } } + if (ost->stream_copy) + check_streamcopy_filters(o, oc, ost, AVMEDIA_TYPE_AUDIO); + return ost; } @@ -1304,7 +1440,7 @@ static OutputStream *new_data_stream(OptionsContext *o, AVFormatContext *oc, int ost = new_output_stream(o, oc, AVMEDIA_TYPE_DATA, source_index); if (!ost->stream_copy) { av_log(NULL, AV_LOG_FATAL, "Data stream encoding not supported yet (only streamcopy)\n"); - exit(1); + exit_program(1); } return ost; @@ -1338,7 +1474,7 @@ static OutputStream *new_subtitle_stream(OptionsContext *o, AVFormatContext *oc, MATCH_PER_STREAM_OPT(frame_sizes, str, frame_size, oc, st); if (frame_size && av_parse_video_size(&subtitle_enc->width, &subtitle_enc->height, frame_size) < 0) { av_log(NULL, AV_LOG_FATAL, "Invalid frame size: %s.\n", frame_size); - exit(1); + exit_program(1); } } @@ -1359,7 +1495,7 @@ static int opt_streamid(void *optctx, const char *opt, const char *arg) av_log(NULL, AV_LOG_FATAL, "Invalid value '%s' for option '%s', required syntax is 'index:value'\n", arg, opt); - exit(1); + exit_program(1); } *p++ = '\0'; idx = parse_number_or_die(opt, idx_str, OPT_INT, 0, MAX_STREAMS-1); @@ -1382,7 +1518,8 @@ static int copy_chapters(InputFile *ifile, OutputFile *ofile, int copy_metadata) for (i = 0; i < is->nb_chapters; i++) { AVChapter *in_ch = is->chapters[i], *out_ch; - int64_t ts_off = av_rescale_q(ofile->start_time - ifile->ts_offset, + int64_t start_time = (ofile->start_time == AV_NOPTS_VALUE) ? 0 : ofile->start_time; + int64_t ts_off = av_rescale_q(start_time - ifile->ts_offset, AV_TIME_BASE_Q, in_ch->time_base); int64_t rt = (ofile->recording_time == INT64_MAX) ? INT64_MAX : av_rescale_q(ofile->recording_time, AV_TIME_BASE_Q, in_ch->time_base); @@ -1446,9 +1583,6 @@ static int read_ffserver_streams(OptionsContext *o, AVFormatContext *s, const ch choose_pixel_fmt(st, codec, st->codec->pix_fmt); } - /* ffserver seeking with date=... needs a date reference */ - err = parse_option(o, "metadata", "creation_time=now", options); - avformat_close_input(&ic); return err; } @@ -1465,7 +1599,7 @@ static void init_output_filter(OutputFilter *ofilter, OptionsContext *o, default: av_log(NULL, AV_LOG_FATAL, "Only video and audio filters are supported " "currently.\n"); - exit(1); + exit_program(1); } ost->source_index = -1; @@ -1477,12 +1611,24 @@ static void init_output_filter(OutputFilter *ofilter, OptionsContext *o, av_log(NULL, AV_LOG_ERROR, "Streamcopy requested for output stream %d:%d, " "which is fed from a complex filtergraph. Filtering and streamcopy " "cannot be used together.\n", ost->file_index, ost->index); - exit(1); + exit_program(1); + } + + if (ost->avfilter && (ost->filters || ost->filters_script)) { + const char *opt = ost->filters ? "-vf/-af/-filter" : "-filter_script"; + av_log(NULL, AV_LOG_ERROR, + "%s '%s' was specified through the %s option " + "for output stream %d:%d, which is fed from a complex filtergraph.\n" + "%s and -filter_complex cannot be used together for the same stream.\n", + ost->filters ? "Filtergraph" : "Filtergraph script", + ost->filters ? ost->filters : ost->filters_script, + opt, ost->file_index, ost->index, opt); + 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(1); + exit_program(1); } avfilter_inout_free(&ofilter->out_tmp); } @@ -1511,17 +1657,50 @@ static int open_output_file(OptionsContext *o, const char *filename) if (configure_complex_filters() < 0) { av_log(NULL, AV_LOG_FATAL, "Error configuring filters.\n"); - exit(1); + exit_program(1); + } + + if (o->stop_time != INT64_MAX && o->recording_time != INT64_MAX) { + o->stop_time = INT64_MAX; + av_log(NULL, AV_LOG_WARNING, "-t and -to cannot be used together; using -t.\n"); + } + + if (o->stop_time != INT64_MAX && o->recording_time == INT64_MAX) { + int64_t start_time = o->start_time == AV_NOPTS_VALUE ? 0 : o->start_time; + if (o->stop_time <= start_time) { + av_log(NULL, AV_LOG_WARNING, "-to value smaller than -ss; ignoring -to.\n"); + o->stop_time = INT64_MAX; + } else { + o->recording_time = o->stop_time - start_time; + } } + GROW_ARRAY(output_files, nb_output_files); + of = av_mallocz(sizeof(*of)); + if (!of) + exit_program(1); + output_files[nb_output_files - 1] = of; + + of->ost_index = nb_output_streams; + of->recording_time = o->recording_time; + 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); + if (!strcmp(filename, "-")) filename = "pipe:"; err = avformat_alloc_output_context2(&oc, NULL, o->format, filename); if (!oc) { print_error(filename, err); - exit(1); + exit_program(1); } + + of->ctx = oc; + if (o->recording_time != INT64_MAX) + oc->duration = o->recording_time; + file_oformat= oc->oformat; oc->interrupt_callback = int_cb; @@ -1544,15 +1723,25 @@ static int open_output_file(OptionsContext *o, const char *filename) } } + /* ffserver seeking with date=... needs a date reference */ if (!strcmp(file_oformat->name, "ffm") && av_strstart(filename, "http:", NULL)) { + int err = parse_option(o, "metadata", "creation_time=now", options); + if (err < 0) { + print_error(filename, err); + exit_program(1); + } + } + + if (!strcmp(file_oformat->name, "ffm") && !override_ffserver && + av_strstart(filename, "http:", NULL)) { int j; /* special case for files sent to ffserver: we get the stream parameters from ffserver */ int err = read_ffserver_streams(o, oc, filename); if (err < 0) { print_error(filename, err); - exit(1); + exit_program(1); } for(j = nb_output_streams - oc->nb_streams; j < nb_output_streams; j++) { ost = output_streams[j]; @@ -1570,7 +1759,7 @@ static int open_output_file(OptionsContext *o, const char *filename) } if(!ost->sync_ist){ av_log(NULL, AV_LOG_FATAL, "Missing %s stream which is required by this ffm\n", av_get_media_type_string(ost->st->codec->codec_type)); - exit(1); + exit_program(1); } } } else if (!o->nb_stream_maps) { @@ -1627,7 +1816,6 @@ static int open_output_file(OptionsContext *o, const char *filename) } else { for (i = 0; i < o->nb_stream_maps; i++) { StreamMap *map = &o->stream_maps[i]; - int src_idx = input_files[map->file_index]->ist_index + map->stream_index; if (map->disabled) continue; @@ -1651,10 +1839,12 @@ loop_end: if (!ofilter) { av_log(NULL, AV_LOG_FATAL, "Output with label '%s' does not exist " "in any defined filter graph, or was already used elsewhere.\n", map->linklabel); - exit(1); + exit_program(1); } init_output_filter(ofilter, o, oc); } else { + int src_idx = input_files[map->file_index]->ist_index + map->stream_index; + ist = input_streams[input_files[map->file_index]->ist_index + map->stream_index]; if(o->subtitle_disable && ist->st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) continue; @@ -1674,7 +1864,7 @@ loop_end: default: av_log(NULL, AV_LOG_FATAL, "Cannot map stream #%d:%d - unsupported type.\n", map->file_index, map->stream_index); - exit(1); + exit_program(1); } } } @@ -1690,17 +1880,17 @@ loop_end: if ((err = avio_open2(&pb, o->attachments[i], AVIO_FLAG_READ, &int_cb, NULL)) < 0) { av_log(NULL, AV_LOG_FATAL, "Could not open attachment file %s.\n", o->attachments[i]); - exit(1); + exit_program(1); } if ((len = avio_size(pb)) <= 0) { av_log(NULL, AV_LOG_FATAL, "Could not get size of the attachment %s.\n", o->attachments[i]); - exit(1); + exit_program(1); } if (!(attachment = av_malloc(len))) { av_log(NULL, AV_LOG_FATAL, "Attachment %s too large to fit into memory.\n", o->attachments[i]); - exit(1); + exit_program(1); } avio_read(pb, attachment, len); @@ -1724,40 +1914,9 @@ loop_end: && (e = av_dict_get(o->g->codec_opts, "flags", NULL, AV_DICT_IGNORE_SUFFIX)) && (!e->key[5] || check_stream_specifier(oc, ost->st, e->key+6))) if (av_opt_set(ost->st->codec, "flags", e->value, 0) < 0) - exit(1); - } - - if (o->stop_time != INT64_MAX && o->recording_time != INT64_MAX) { - o->stop_time = INT64_MAX; - av_log(NULL, AV_LOG_WARNING, "-t and -to cannot be used together; using -t.\n"); + exit_program(1); } - if (o->stop_time != INT64_MAX && o->recording_time == INT64_MAX) { - if (o->stop_time <= o->start_time) { - av_log(NULL, AV_LOG_WARNING, "-to value smaller than -ss; ignoring -to.\n"); - o->stop_time = INT64_MAX; - } else { - o->recording_time = o->stop_time - o->start_time; - } - } - - GROW_ARRAY(output_files, nb_output_files); - of = av_mallocz(sizeof(*of)); - if (!of) - exit(1); - output_files[nb_output_files - 1] = of; - - 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; - 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++) { @@ -1779,9 +1938,13 @@ loop_end: "output file #%d (%s) is not an encoding option.\n", e->key, option->help ? option->help : "", nb_output_files - 1, filename); - exit(1); + exit_program(1); } + // gop_timecode is injected by generic code but not always used + if (!strcmp(e->key, "gop_timecode")) + continue; + 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 " @@ -1795,7 +1958,7 @@ loop_end: if (oc->oformat->flags & AVFMT_NEEDNUMBER) { if (!av_filename_number_test(oc->filename)) { print_error(oc->filename, AVERROR(EINVAL)); - exit(1); + exit_program(1); } } @@ -1808,7 +1971,7 @@ loop_end: &oc->interrupt_callback, &of->opts)) < 0) { print_error(filename, err); - exit(1); + exit_program(1); } } else if (strcmp(oc->oformat->name, "image2")==0 && !av_filename_number_test(filename)) assert_file_overwrite(filename); @@ -1827,7 +1990,7 @@ loop_end: if (in_file_index >= nb_input_files) { av_log(NULL, AV_LOG_FATAL, "Invalid input file index %d while processing metadata maps\n", in_file_index); - exit(1); + exit_program(1); } copy_metadata(o->metadata_map[i].specifier, *p ? p + 1 : p, oc, in_file_index >= 0 ? @@ -1847,7 +2010,7 @@ loop_end: } else { av_log(NULL, AV_LOG_FATAL, "Invalid input file index %d in chapter mapping.\n", o->chapters_input_file); - exit(1); + exit_program(1); } } if (o->chapters_input_file >= 0) @@ -1882,7 +2045,7 @@ loop_end: if (!val) { av_log(NULL, AV_LOG_FATAL, "No '=' character in metadata string %s.\n", o->metadata[i].u.str); - exit(1); + exit_program(1); } *val++ = 0; @@ -1892,7 +2055,7 @@ loop_end: if ((ret = check_stream_specifier(oc, oc->streams[j], stream_spec)) > 0) { av_dict_set(&oc->streams[j]->metadata, o->metadata[i].u.str, *val ? val : NULL, 0); } else if (ret < 0) - exit(1); + exit_program(1); } } else { @@ -1903,13 +2066,13 @@ loop_end: case 'c': if (index < 0 || index >= oc->nb_chapters) { av_log(NULL, AV_LOG_FATAL, "Invalid chapter index %d in metadata specifier.\n", index); - exit(1); + exit_program(1); } m = &oc->chapters[index]->metadata; break; default: av_log(NULL, AV_LOG_FATAL, "Invalid metadata specifier %s.\n", o->metadata[i].specifier); - exit(1); + exit_program(1); } av_dict_set(m, o->metadata[i].u.str, *val ? val : NULL, 0); } @@ -1963,30 +2126,29 @@ static int opt_target(void *optctx, const char *opt, const char *arg) av_log(NULL, AV_LOG_FATAL, "Could not determine norm (PAL/NTSC/NTSC-Film) for target.\n"); av_log(NULL, AV_LOG_FATAL, "Please prefix target with \"pal-\", \"ntsc-\" or \"film-\",\n"); av_log(NULL, AV_LOG_FATAL, "or set a framerate with \"-r xxx\".\n"); - exit(1); + exit_program(1); } if (!strcmp(arg, "vcd")) { opt_video_codec(o, "c:v", "mpeg1video"); opt_audio_codec(o, "c:a", "mp2"); parse_option(o, "f", "vcd", options); - av_dict_set(&o->g->codec_opts, "b:v", arg, 0); parse_option(o, "s", norm == PAL ? "352x288" : "352x240", options); parse_option(o, "r", frame_rates[norm], options); - av_dict_set(&o->g->codec_opts, "g", norm == PAL ? "15" : "18", 0); + av_dict_set(&o->g->codec_opts, "g", norm == PAL ? "15" : "18", AV_DICT_DONT_OVERWRITE); - av_dict_set(&o->g->codec_opts, "b:v", "1150000", 0); - av_dict_set(&o->g->codec_opts, "maxrate", "1150000", 0); - av_dict_set(&o->g->codec_opts, "minrate", "1150000", 0); - av_dict_set(&o->g->codec_opts, "bufsize", "327680", 0); // 40*1024*8; + av_dict_set(&o->g->codec_opts, "b:v", "1150000", AV_DICT_DONT_OVERWRITE); + av_dict_set(&o->g->codec_opts, "maxrate", "1150000", AV_DICT_DONT_OVERWRITE); + av_dict_set(&o->g->codec_opts, "minrate", "1150000", AV_DICT_DONT_OVERWRITE); + av_dict_set(&o->g->codec_opts, "bufsize", "327680", AV_DICT_DONT_OVERWRITE); // 40*1024*8; - av_dict_set(&o->g->codec_opts, "b:a", "224000", 0); + av_dict_set(&o->g->codec_opts, "b:a", "224000", AV_DICT_DONT_OVERWRITE); parse_option(o, "ar", "44100", options); parse_option(o, "ac", "2", options); - av_dict_set(&o->g->format_opts, "packetsize", "2324", 0); - av_dict_set(&o->g->format_opts, "muxrate", "1411200", 0); // 2352 * 75 * 8; + av_dict_set(&o->g->format_opts, "packetsize", "2324", AV_DICT_DONT_OVERWRITE); + av_dict_set(&o->g->format_opts, "muxrate", "1411200", AV_DICT_DONT_OVERWRITE); // 2352 * 75 * 8; /* 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 @@ -2003,18 +2165,18 @@ static int opt_target(void *optctx, const char *opt, const char *arg) parse_option(o, "s", norm == PAL ? "480x576" : "480x480", options); parse_option(o, "r", frame_rates[norm], options); parse_option(o, "pix_fmt", "yuv420p", options); - av_dict_set(&o->g->codec_opts, "g", norm == PAL ? "15" : "18", 0); + av_dict_set(&o->g->codec_opts, "g", norm == PAL ? "15" : "18", AV_DICT_DONT_OVERWRITE); - av_dict_set(&o->g->codec_opts, "b:v", "2040000", 0); - av_dict_set(&o->g->codec_opts, "maxrate", "2516000", 0); - av_dict_set(&o->g->codec_opts, "minrate", "0", 0); // 1145000; - av_dict_set(&o->g->codec_opts, "bufsize", "1835008", 0); // 224*1024*8; - av_dict_set(&o->g->codec_opts, "scan_offset", "1", 0); + av_dict_set(&o->g->codec_opts, "b:v", "2040000", AV_DICT_DONT_OVERWRITE); + av_dict_set(&o->g->codec_opts, "maxrate", "2516000", AV_DICT_DONT_OVERWRITE); + av_dict_set(&o->g->codec_opts, "minrate", "0", AV_DICT_DONT_OVERWRITE); // 1145000; + av_dict_set(&o->g->codec_opts, "bufsize", "1835008", AV_DICT_DONT_OVERWRITE); // 224*1024*8; + av_dict_set(&o->g->codec_opts, "scan_offset", "1", AV_DICT_DONT_OVERWRITE); - av_dict_set(&o->g->codec_opts, "b:a", "224000", 0); + av_dict_set(&o->g->codec_opts, "b:a", "224000", AV_DICT_DONT_OVERWRITE); parse_option(o, "ar", "44100", options); - av_dict_set(&o->g->format_opts, "packetsize", "2324", 0); + av_dict_set(&o->g->format_opts, "packetsize", "2324", AV_DICT_DONT_OVERWRITE); } else if (!strcmp(arg, "dvd")) { @@ -2025,17 +2187,17 @@ static int opt_target(void *optctx, const char *opt, const char *arg) parse_option(o, "s", norm == PAL ? "720x576" : "720x480", options); parse_option(o, "r", frame_rates[norm], options); parse_option(o, "pix_fmt", "yuv420p", options); - av_dict_set(&o->g->codec_opts, "g", norm == PAL ? "15" : "18", 0); + av_dict_set(&o->g->codec_opts, "g", norm == PAL ? "15" : "18", AV_DICT_DONT_OVERWRITE); - av_dict_set(&o->g->codec_opts, "b:v", "6000000", 0); - av_dict_set(&o->g->codec_opts, "maxrate", "9000000", 0); - av_dict_set(&o->g->codec_opts, "minrate", "0", 0); // 1500000; - av_dict_set(&o->g->codec_opts, "bufsize", "1835008", 0); // 224*1024*8; + av_dict_set(&o->g->codec_opts, "b:v", "6000000", AV_DICT_DONT_OVERWRITE); + av_dict_set(&o->g->codec_opts, "maxrate", "9000000", AV_DICT_DONT_OVERWRITE); + av_dict_set(&o->g->codec_opts, "minrate", "0", AV_DICT_DONT_OVERWRITE); // 1500000; + av_dict_set(&o->g->codec_opts, "bufsize", "1835008", AV_DICT_DONT_OVERWRITE); // 224*1024*8; - av_dict_set(&o->g->format_opts, "packetsize", "2048", 0); // from www.mpucoder.com: DVD sectors contain 2048 bytes of data, this is also the size of one pack. - av_dict_set(&o->g->format_opts, "muxrate", "10080000", 0); // from mplex project: data_rate = 1260000. mux_rate = data_rate * 8 + av_dict_set(&o->g->format_opts, "packetsize", "2048", AV_DICT_DONT_OVERWRITE); // from www.mpucoder.com: DVD sectors contain 2048 bytes of data, this is also the size of one pack. + av_dict_set(&o->g->format_opts, "muxrate", "10080000", AV_DICT_DONT_OVERWRITE); // from mplex project: data_rate = 1260000. mux_rate = data_rate * 8 - av_dict_set(&o->g->codec_opts, "b:a", "448000", 0); + av_dict_set(&o->g->codec_opts, "b:a", "448000", AV_DICT_DONT_OVERWRITE); parse_option(o, "ar", "48000", options); } else if (!strncmp(arg, "dv", 2)) { @@ -2129,7 +2291,7 @@ static int opt_preset(void *optctx, const char *opt, const char *arg) av_log(NULL, AV_LOG_FATAL, "Please use -preset <speed> -qp 0\n"); }else av_log(NULL, AV_LOG_FATAL, "File for preset '%s' not found\n", arg); - exit(1); + exit_program(1); } while (fgets(line, sizeof(line), f)) { @@ -2137,11 +2299,11 @@ static int opt_preset(void *optctx, const char *opt, const char *arg) if (strcspn(line, "#\n\r") == 0) continue; - strcpy(tmp_line, line); + av_strlcpy(tmp_line, line, sizeof(tmp_line)); if (!av_strtok(key, "=", &value) || !av_strtok(value, "\r\n", &endptr)) { av_log(NULL, AV_LOG_FATAL, "%s: Invalid syntax: '%s'\n", filename, line); - exit(1); + exit_program(1); } av_log(NULL, AV_LOG_DEBUG, "ffpreset[%s]: set '%s' = '%s'\n", filename, key, value); @@ -2152,7 +2314,7 @@ static int opt_preset(void *optctx, const char *opt, const char *arg) else if (opt_default_new(o, key, value) < 0) { av_log(NULL, AV_LOG_FATAL, "%s: Invalid option or argument: '%s', parsed as '%s' = '%s'\n", filename, line, key, value); - exit(1); + exit_program(1); } } @@ -2233,15 +2395,6 @@ static int opt_vsync(void *optctx, const char *opt, const char *arg) return 0; } -#if FF_API_DEINTERLACE -static int opt_deinterlace(void *optctx, const char *opt, const char *arg) -{ - av_log(NULL, AV_LOG_WARNING, "-%s is deprecated, use -filter:v yadif instead\n", opt); - do_deinterlace = 1; - return 0; -} -#endif - static int opt_timecode(void *optctx, const char *opt, const char *arg) { OptionsContext *o = optctx; @@ -2300,8 +2453,24 @@ static int opt_filter_complex(void *optctx, const char *opt, const char *arg) GROW_ARRAY(filtergraphs, nb_filtergraphs); if (!(filtergraphs[nb_filtergraphs - 1] = av_mallocz(sizeof(*filtergraphs[0])))) return AVERROR(ENOMEM); - filtergraphs[nb_filtergraphs - 1]->index = nb_filtergraphs - 1; - filtergraphs[nb_filtergraphs - 1]->graph_desc = arg; + filtergraphs[nb_filtergraphs - 1]->index = nb_filtergraphs - 1; + filtergraphs[nb_filtergraphs - 1]->graph_desc = av_strdup(arg); + if (!filtergraphs[nb_filtergraphs - 1]->graph_desc) + return AVERROR(ENOMEM); + return 0; +} + +static int opt_filter_complex_script(void *optctx, const char *opt, const char *arg) +{ + uint8_t *graph_desc = read_file(arg); + if (!graph_desc) + return AVERROR(EINVAL); + + GROW_ARRAY(filtergraphs, nb_filtergraphs); + if (!(filtergraphs[nb_filtergraphs - 1] = av_mallocz(sizeof(*filtergraphs[0])))) + return AVERROR(ENOMEM); + filtergraphs[nb_filtergraphs - 1]->index = nb_filtergraphs - 1; + filtergraphs[nb_filtergraphs - 1]->graph_desc = graph_desc; return 0; } @@ -2365,9 +2534,11 @@ void show_help_default(const char *opt, const char *arg) int flags = AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_ENCODING_PARAM; show_help_children(avcodec_get_class(), flags); show_help_children(avformat_get_class(), flags); +#if CONFIG_SWSCALE show_help_children(sws_get_class(), flags); +#endif show_help_children(swr_get_class(), AV_OPT_FLAG_AUDIO_PARAM); - show_help_children(avfilter_get_class(), AV_OPT_FLAG_FILTERING_PARAM); + show_help_children(avfilter_get_class(), AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM); } } @@ -2397,7 +2568,7 @@ static int open_files(OptionGroupList *l, const char *inout, OptionGroup *g = &l->groups[i]; OptionsContext o; - init_options(&o, !strcmp(inout, "input")); + init_options(&o); o.g = g; ret = parse_optgroup(&o, g); @@ -2409,7 +2580,7 @@ static int open_files(OptionGroupList *l, const char *inout, av_log(NULL, AV_LOG_DEBUG, "Opening an %s file: %s.\n", inout, g->arg); ret = open_file(&o, g->arg); - uninit_options(&o, !strcmp(inout, "input")); + uninit_options(&o); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Error opening %s file %s.\n", inout, g->arg); @@ -2494,7 +2665,7 @@ const OptionDef options[] = { { "y", OPT_BOOL, { &file_overwrite }, "overwrite output files" }, { "n", OPT_BOOL, { &no_file_overwrite }, - "do not overwrite output files" }, + "never overwrite output files" }, { "c", HAS_ARG | OPT_STRING | OPT_SPEC | OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(codec_names) }, "codec name", "codec" }, @@ -2517,7 +2688,8 @@ const OptionDef options[] = { { "map_chapters", HAS_ARG | OPT_INT | OPT_EXPERT | OPT_OFFSET | OPT_OUTPUT, { .off = OFFSET(chapters_input_file) }, "set chapters mapping", "input_file_index" }, - { "t", HAS_ARG | OPT_TIME | OPT_OFFSET | OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(recording_time) }, + { "t", HAS_ARG | OPT_TIME | OPT_OFFSET | + OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(recording_time) }, "record or transcode \"duration\" seconds of audio/video", "duration" }, { "to", HAS_ARG | OPT_TIME | OPT_OFFSET | OPT_OUTPUT, { .off = OFFSET(stop_time) }, @@ -2527,6 +2699,9 @@ const OptionDef options[] = { { "ss", HAS_ARG | OPT_TIME | OPT_OFFSET | OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(start_time) }, "set the start time offset", "time_off" }, + { "accurate_seek", OPT_BOOL | OPT_OFFSET | OPT_EXPERT | + OPT_INPUT, { .off = OFFSET(accurate_seek) }, + "enable/disable accurate seeking with -ss" }, { "itsoffset", HAS_ARG | OPT_TIME | OPT_OFFSET | OPT_EXPERT | OPT_INPUT, { .off = OFFSET(input_ts_offset) }, "set the input ts offset", "time_off" }, @@ -2573,6 +2748,9 @@ const OptionDef options[] = { { "shortest", OPT_BOOL | OPT_EXPERT | OPT_OFFSET | OPT_OUTPUT, { .off = OFFSET(shortest) }, "finish encoding within shortest input" }, + { "apad", OPT_STRING | HAS_ARG | OPT_SPEC | + OPT_OUTPUT, { .off = OFFSET(apad) }, + "audio pad", "" }, { "dts_delta_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, { &dts_delta_threshold }, "timestamp discontinuity delta threshold", "threshold" }, { "dts_error_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, { &dts_error_threshold }, @@ -2599,12 +2777,16 @@ const OptionDef options[] = { "set profile", "profile" }, { "filter", HAS_ARG | OPT_STRING | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(filters) }, "set stream filtergraph", "filter_graph" }, + { "filter_script", HAS_ARG | OPT_STRING | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(filter_scripts) }, + "read stream filtergraph description from a file", "filename" }, { "reinit_filter", HAS_ARG | OPT_INT | OPT_SPEC | OPT_INPUT, { .off = OFFSET(reinit_filters) }, "reinit filtergraph on input parameter changes", "" }, { "filter_complex", HAS_ARG | OPT_EXPERT, { .func_arg = opt_filter_complex }, "create a complex filtergraph", "graph_description" }, { "lavfi", HAS_ARG | OPT_EXPERT, { .func_arg = opt_filter_complex }, "create a complex filtergraph", "graph_description" }, + { "filter_complex_script", HAS_ARG | OPT_EXPERT, { .func_arg = opt_filter_complex_script }, + "read complex filtergraph description from a file", "filename" }, { "stats", OPT_BOOL, { &print_stats }, "print progress report during encoding", }, { "attach", HAS_ARG | OPT_PERFILE | OPT_EXPERT | @@ -2615,6 +2797,8 @@ const OptionDef options[] = { "extract an attachment into a file", "filename" }, { "debug_ts", OPT_BOOL | OPT_EXPERT, { &debug_ts }, "print timestamp debugging info" }, + { "max_error_rate", HAS_ARG | OPT_FLOAT, { &max_error_rate }, + "maximum error rate", "ratio of errors (0.0: no errors, 1.0: 100% errors) above which ffmpeg returns an error instead of success." }, /* video options */ { "vframes", OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_video_frames }, @@ -2656,10 +2840,8 @@ const OptionDef options[] = { { "passlogfile", OPT_VIDEO | HAS_ARG | OPT_STRING | OPT_EXPERT | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(passlogfiles) }, "select two pass log file name prefix", "prefix" }, -#if FF_API_DEINTERLACE - { "deinterlace", OPT_VIDEO | OPT_EXPERT , { .func_arg = opt_deinterlace }, + { "deinterlace", OPT_VIDEO | OPT_BOOL | OPT_EXPERT, { &do_deinterlace }, "this option is deprecated, use the yadif filter instead" }, -#endif { "psnr", OPT_VIDEO | OPT_BOOL | OPT_EXPERT, { &do_psnr }, "calculate PSNR of compressed frames" }, { "vstats", OPT_VIDEO | OPT_EXPERT , { &opt_vstats }, @@ -2695,6 +2877,12 @@ const OptionDef options[] = { "force key frames at specified timestamps", "timestamps" }, { "b", OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_bitrate }, "video bitrate (please use -b:v)", "bitrate" }, + { "hwaccel", OPT_VIDEO | OPT_STRING | HAS_ARG | OPT_EXPERT | + OPT_SPEC | OPT_INPUT, { .off = OFFSET(hwaccels) }, + "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" }, /* audio options */ { "aframes", OPT_AUDIO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_audio_frames }, @@ -2752,6 +2940,8 @@ const OptionDef options[] = { "set the maximum demux-decode delay", "seconds" }, { "muxpreload", OPT_FLOAT | HAS_ARG | OPT_EXPERT | OPT_OFFSET | OPT_OUTPUT, { .off = OFFSET(mux_preload) }, "set the initial demux-decode delay", "seconds" }, + { "override_ffserver", OPT_BOOL | OPT_EXPERT | OPT_OUTPUT, { &override_ffserver }, + "override the options from ffserver", "" }, { "bsf", HAS_ARG | OPT_STRING | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT, { .off = OFFSET(bitstream_filters) }, "A comma-separated list of bitstream filters", "bitstream_filters" }, |
