X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=avconv.c;h=74120c8c5e1e3ffe7382f60f924e6e768523dbee;hb=34d2bf30a082d489487493df40496cc18ca4300b;hp=d81a118f75d54b6fdf8117427567a4a6c8b0e6ac;hpb=0e68c78385606e86cfc5d20203ef3d24e8b005ff;p=ffmpeg diff --git a/avconv.c b/avconv.c index d81a118f75d..74120c8c5e1 100644 --- a/avconv.c +++ b/avconv.c @@ -97,28 +97,16 @@ typedef struct MetadataMap { static const OptionDef options[]; -/* indexed by output file stream index */ -static int *streamid_map = NULL; -static int nb_streamid_map = 0; - -static uint16_t *intra_matrix = NULL; -static uint16_t *inter_matrix = NULL; static int video_discard = 0; static int same_quant = 0; static int do_deinterlace = 0; -static int top_field_first = -1; -static int me_threshold = 0; static int intra_dc_precision = 8; static int qp_hist = 0; -#if CONFIG_AVFILTER -static char *vfilters = NULL; -#endif static int file_overwrite = 0; static int do_benchmark = 0; static int do_hex_dump = 0; static int do_pkt_dump = 0; -static int do_psnr = 0; static int do_pass = 0; static char *pass_logfilename_prefix = NULL; static int video_sync_method= -1; @@ -207,6 +195,7 @@ typedef struct OutputStream { int resample_pix_fmt; AVRational frame_rate; int force_fps; + int top_field_first; float frame_aspect_ratio; @@ -306,6 +295,10 @@ typedef struct OptionsContext { int subtitle_disable; int data_disable; + /* indexed by output file stream index */ + int *streamid_map; + int nb_streamid_map; + SpecifierOpt *metadata; int nb_metadata; SpecifierOpt *max_frames; @@ -326,6 +319,16 @@ typedef struct OptionsContext { int nb_frame_aspect_ratios; SpecifierOpt *rc_overrides; int nb_rc_overrides; + SpecifierOpt *intra_matrices; + int nb_intra_matrices; + SpecifierOpt *inter_matrices; + int nb_inter_matrices; + SpecifierOpt *top_field_first; + int nb_top_field_first; +#if CONFIG_AVFILTER + SpecifierOpt *filters; + int nb_filters; +#endif } OptionsContext; #define MATCH_PER_STREAM_OPT(name, type, outvar, fmtctx, st)\ @@ -365,6 +368,7 @@ static void reset_options(OptionsContext *o) av_freep(&o->stream_maps); av_freep(&o->meta_data_maps); + av_freep(&o->streamid_map); memset(o, 0, sizeof(*o)); @@ -512,9 +516,6 @@ void exit_program(int ret) for (i = 0; i < nb_input_streams; i++) av_dict_free(&input_streams[i].opts); - av_free(intra_matrix); - av_free(inter_matrix); - if (vstats_file) fclose(vstats_file); av_free(vstats_filename); @@ -1208,16 +1209,16 @@ static void do_video_out(AVFormatContext *s, settings */ big_picture.interlaced_frame = in_picture->interlaced_frame; if (ost->st->codec->flags & (CODEC_FLAG_INTERLACED_DCT|CODEC_FLAG_INTERLACED_ME)) { - if(top_field_first == -1) + if (ost->top_field_first == -1) big_picture.top_field_first = in_picture->top_field_first; else - big_picture.top_field_first = top_field_first; + big_picture.top_field_first = !!ost->top_field_first; } /* handles same_quant here. This is not correct because it may not be a global option */ big_picture.quality = quality; - if(!me_threshold) + if (!enc->me_threshold) big_picture.pict_type = 0; // big_picture.pts = AV_NOPTS_VALUE; big_picture.pts= ost->sync_opts; @@ -2187,6 +2188,9 @@ static int transcode_init(OutputFile *output_files, av_log(NULL, AV_LOG_WARNING, "The bitrate parameter is set too low." "It takes bits/s as argument, not kbits/s\n"); extra_size += ost->st->codec->extradata_size; + + if (ost->st->codec->me_threshold) + input_streams[ost->source_index].st->codec->debug |= FF_DEBUG_MV; } } @@ -2502,12 +2506,6 @@ static int transcode(OutputFile *output_files, return ret; } -static int opt_me_threshold(const char *opt, const char *arg) -{ - me_threshold = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX); - return 0; -} - static int opt_verbose(const char *opt, const char *arg) { verbose = parse_number_or_die(opt, arg, OPT_INT64, -10, 10); @@ -2538,12 +2536,6 @@ static double parse_frame_aspect_ratio(const char *arg) return ar; } -static int opt_top_field_first(const char *opt, const char *arg) -{ - top_field_first = parse_number_or_die(opt, arg, OPT_INT, 0, 1); - return 0; -} - static int opt_audio_codec(OptionsContext *o, const char *opt, const char *arg) { return parse_option(o, "codec:a", arg, options); @@ -2779,8 +2771,6 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) dec->height >>= dec->lowres; dec->width >>= dec->lowres; } - if(me_threshold) - dec->debug |= FF_DEBUG_MV; if (dec->time_base.den != rfps*dec->ticks_per_frame || dec->time_base.num != rfps_base) { @@ -2945,7 +2935,7 @@ static void parse_forced_key_frames(char *kf, OutputStream *ost, static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, enum AVMediaType type) { OutputStream *ost; - AVStream *st = av_new_stream(oc, oc->nb_streams < nb_streamid_map ? streamid_map[oc->nb_streams] : 0); + 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; int64_t max_frames = INT64_MAX; char *bsf = NULL, *next, *codec_tag = NULL; @@ -3010,6 +3000,23 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e return ost; } +static void parse_matrix_coeffs(uint16_t *dest, const char *str) +{ + int i; + const char *p = str; + for(i = 0;; i++) { + dest[i] = atoi(p); + if(i == 63) + break; + p = strchr(p, ','); + if(!p) { + fprintf(stderr, "Syntax error in matrix \"%s\" at coeff %d\n", str, i); + exit_program(1); + } + p++; + } +} + static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc) { AVStream *st; @@ -3018,13 +3025,6 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc) ost = new_output_stream(o, oc, AVMEDIA_TYPE_VIDEO); st = ost->st; - if (!st->stream_copy) { -#if CONFIG_AVFILTER - ost->avfilter= vfilters; - vfilters = NULL; -#endif - } - video_enc = st->codec; if(oc->oformat->flags & AVFMT_GLOBALHEADER) { @@ -3035,7 +3035,8 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc) const char *p = NULL; char *forced_key_frames = NULL, *frame_rate = NULL, *frame_size = NULL; char *frame_aspect_ratio = NULL, *frame_pix_fmt = NULL; - int i, force_fps = 0; + char *intra_matrix = NULL, *inter_matrix = NULL, *filters = NULL; + int i, force_fps = 0, top_field_first = -1; MATCH_PER_STREAM_OPT(frame_rates, str, frame_rate, oc, st); if (frame_rate && av_parse_video_rate(&ost->frame_rate, frame_rate) < 0) { @@ -3060,10 +3061,22 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc) } st->sample_aspect_ratio = video_enc->sample_aspect_ratio; - if(intra_matrix) - video_enc->intra_matrix = intra_matrix; - if(inter_matrix) - video_enc->inter_matrix = inter_matrix; + MATCH_PER_STREAM_OPT(intra_matrices, str, intra_matrix, oc, st); + if (intra_matrix) { + if (!(video_enc->intra_matrix = av_mallocz(sizeof(*video_enc->intra_matrix) * 64))) { + av_log(NULL, AV_LOG_ERROR, "Could not allocate memory for intra matrix.\n"); + exit_program(1); + } + parse_matrix_coeffs(video_enc->intra_matrix, intra_matrix); + } + MATCH_PER_STREAM_OPT(inter_matrices, str, inter_matrix, oc, st); + if (inter_matrix) { + if (!(video_enc->inter_matrix = av_mallocz(sizeof(*video_enc->inter_matrix) * 64))) { + av_log(NULL, AV_LOG_ERROR, "Could not allocate memory for inter matrix.\n"); + exit_program(1); + } + parse_matrix_coeffs(video_enc->inter_matrix, inter_matrix); + } MATCH_PER_STREAM_OPT(rc_overrides, str, p, oc, st); for(i=0; p; i++){ @@ -3092,12 +3105,8 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc) video_enc->rc_override_count=i; if (!video_enc->rc_initial_buffer_occupancy) video_enc->rc_initial_buffer_occupancy = video_enc->rc_buffer_size*3/4; - video_enc->me_threshold= me_threshold; video_enc->intra_dc_precision= intra_dc_precision - 8; - if (do_psnr) - video_enc->flags|= CODEC_FLAG_PSNR; - /* two pass mode */ if (do_pass) { if (do_pass == 1) { @@ -3113,6 +3122,15 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc) MATCH_PER_STREAM_OPT(force_fps, i, force_fps, oc, st); ost->force_fps = force_fps; + + MATCH_PER_STREAM_OPT(top_field_first, i, top_field_first, oc, st); + ost->top_field_first = top_field_first; + +#if CONFIG_AVFILTER + MATCH_PER_STREAM_OPT(filters, str, filters, oc, st); + if (filters) + ost->avfilter = av_strdup(filters); +#endif } return ost; @@ -3192,7 +3210,7 @@ static OutputStream *new_subtitle_stream(OptionsContext *o, AVFormatContext *oc) } /* arg format is "output-stream-index:streamid-value". */ -static int opt_streamid(const char *opt, const char *arg) +static int opt_streamid(OptionsContext *o, const char *opt, const char *arg) { int idx; char *p; @@ -3208,8 +3226,8 @@ static int opt_streamid(const char *opt, const char *arg) } *p++ = '\0'; idx = parse_number_or_die(opt, idx_str, OPT_INT, 0, INT_MAX); - streamid_map = grow_array(streamid_map, sizeof(*streamid_map), &nb_streamid_map, idx+1); - streamid_map[idx] = parse_number_or_die(opt, p, OPT_INT, 0, INT_MAX); + o->streamid_map = grow_array(o->streamid_map, sizeof(*o->streamid_map), &o->nb_streamid_map, idx+1); + o->streamid_map[idx] = parse_number_or_die(opt, p, OPT_INT, 0, INT_MAX); return 0; } @@ -3471,7 +3489,7 @@ static void opt_output_file(void *optctx, const char *filename) } if (o->chapters_input_file >= 0) copy_chapters(&input_files[o->chapters_input_file], &output_files[nb_output_files - 1], - o->metadata_chapters_manual); + !o->metadata_chapters_manual); /* copy metadata */ for (i = 0; i < o->nb_meta_data_maps; i++) { @@ -3553,14 +3571,14 @@ static void opt_output_file(void *optctx, const char *filename) av_log(NULL, AV_LOG_ERROR, "Invalid stream index %d in metadata specifier.\n", index); exit_program(1); } - m = &oc->streams[i]->metadata; + m = &oc->streams[index]->metadata; break; case 'c': if (index < 0 || index >= oc->nb_chapters) { av_log(NULL, AV_LOG_ERROR, "Invalid chapter index %d in metadata specifier.\n", index); exit_program(1); } - m = &oc->chapters[i]->metadata; + m = &oc->chapters[index]->metadata; break; default: av_log(NULL, AV_LOG_ERROR, "Invalid metadata specifier %s.\n", o->metadata[i].specifier); @@ -3570,9 +3588,6 @@ static void opt_output_file(void *optctx, const char *filename) av_dict_set(m, o->metadata[i].u.str, *val ? val : NULL, 0); } - av_freep(&streamid_map); - nb_streamid_map = 0; - reset_options(o); } @@ -3619,35 +3634,6 @@ static int64_t getmaxrss(void) #endif } -static void parse_matrix_coeffs(uint16_t *dest, const char *str) -{ - int i; - const char *p = str; - for(i = 0;; i++) { - dest[i] = atoi(p); - if(i == 63) - break; - p = strchr(p, ','); - if(!p) { - fprintf(stderr, "Syntax error in matrix \"%s\" at coeff %d\n", str, i); - exit_program(1); - } - p++; - } -} - -static void opt_inter_matrix(const char *arg) -{ - inter_matrix = av_mallocz(sizeof(uint16_t) * 64); - parse_matrix_coeffs(inter_matrix, arg); -} - -static void opt_intra_matrix(const char *arg) -{ - intra_matrix = av_mallocz(sizeof(uint16_t) * 64); - parse_matrix_coeffs(intra_matrix, arg); -} - static int opt_audio_qscale(OptionsContext *o, const char *opt, const char *arg) { return parse_option(o, "q:a", arg, options); @@ -3914,6 +3900,11 @@ static int opt_subtitle_tag(OptionsContext *o, const char *opt, const char *arg) return parse_option(o, "tag:s", arg, options); } +static int opt_video_filters(OptionsContext *o, const char *opt, const char *arg) +{ + return parse_option(o, "filter:v", arg, options); +} + #define OFFSET(x) offsetof(OptionsContext, x) static const OptionDef options[] = { /* main options */ @@ -3957,6 +3948,9 @@ static const OptionDef options[] = { { "tag", OPT_STRING | HAS_ARG | OPT_SPEC, {.off = OFFSET(codec_tags)}, "force codec tag/fourcc", "fourcc/tag" }, { "q", HAS_ARG | OPT_EXPERT | OPT_DOUBLE | OPT_SPEC, {.off = OFFSET(qscale)}, "use fixed quality scale (VBR)", "q" }, { "qscale", HAS_ARG | OPT_EXPERT | OPT_DOUBLE | OPT_SPEC, {.off = OFFSET(qscale)}, "use fixed quality scale (VBR)", "q" }, +#if CONFIG_AVFILTER + { "filter", HAS_ARG | OPT_STRING | OPT_SPEC, {.off = OFFSET(filters)}, "set stream filterchain", "filter_list" }, +#endif /* video options */ { "vframes", HAS_ARG | OPT_VIDEO | OPT_FUNC2, {(void*)opt_video_frames}, "set the number of video frames to record", "number" }, @@ -3968,27 +3962,25 @@ static const OptionDef options[] = { { "vdt", OPT_INT | HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)&video_discard}, "discard threshold", "n" }, { "rc_override", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_STRING | OPT_SPEC, {.off = OFFSET(rc_overrides)}, "rate control override for specific intervals", "override" }, { "vcodec", HAS_ARG | OPT_VIDEO | OPT_FUNC2, {(void*)opt_video_codec}, "force video codec ('copy' to copy stream)", "codec" }, - { "me_threshold", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_me_threshold}, "motion estimation threshold", "threshold" }, { "same_quant", OPT_BOOL | OPT_VIDEO, {(void*)&same_quant}, "use same quantizer as source (implies VBR)" }, { "pass", HAS_ARG | OPT_VIDEO, {(void*)opt_pass}, "select the pass number (1 or 2)", "n" }, { "passlogfile", HAS_ARG | OPT_STRING | OPT_VIDEO, {(void*)&pass_logfilename_prefix}, "select two pass log file name prefix", "prefix" }, { "deinterlace", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&do_deinterlace}, "deinterlace pictures" }, - { "psnr", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&do_psnr}, "calculate PSNR of compressed frames" }, { "vstats", OPT_EXPERT | OPT_VIDEO, {(void*)&opt_vstats}, "dump video coding statistics to file" }, { "vstats_file", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_vstats_file}, "dump video coding statistics to file", "file" }, #if CONFIG_AVFILTER - { "vf", OPT_STRING | HAS_ARG, {(void*)&vfilters}, "video filters", "filter list" }, + { "vf", HAS_ARG | OPT_VIDEO | OPT_FUNC2, {(void*)opt_video_filters}, "video filters", "filter list" }, #endif - { "intra_matrix", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_intra_matrix}, "specify intra matrix coeffs", "matrix" }, - { "inter_matrix", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_inter_matrix}, "specify inter matrix coeffs", "matrix" }, - { "top", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_top_field_first}, "top=1/bottom=0/auto=-1 field first", "" }, + { "intra_matrix", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_STRING | OPT_SPEC, {.off = OFFSET(intra_matrices)}, "specify intra matrix coeffs", "matrix" }, + { "inter_matrix", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_STRING | OPT_SPEC, {.off = OFFSET(inter_matrices)}, "specify inter matrix coeffs", "matrix" }, + { "top", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_INT| OPT_SPEC, {.off = OFFSET(top_field_first)}, "top=1/bottom=0/auto=-1 field first", "" }, { "dc", OPT_INT | HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)&intra_dc_precision}, "intra_dc_precision", "precision" }, { "vtag", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_FUNC2, {(void*)opt_video_tag}, "force video tag/fourcc", "fourcc/tag" }, { "qphist", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, { (void *)&qp_hist }, "show QP histogram" }, { "force_fps", OPT_BOOL | OPT_EXPERT | OPT_VIDEO | OPT_SPEC, {.off = OFFSET(force_fps)}, "force the selected framerate, disable the best supported framerate selection" }, - { "streamid", HAS_ARG | OPT_EXPERT, {(void*)opt_streamid}, "set the value of an outfile streamid", "streamIndex:value" }, + { "streamid", HAS_ARG | OPT_EXPERT | OPT_FUNC2, {(void*)opt_streamid}, "set the value of an outfile streamid", "streamIndex:value" }, { "force_key_frames", OPT_STRING | HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_SPEC, {.off = OFFSET(forced_key_frames)}, "force key frames at specified timestamps", "timestamps" }, /* audio options */