diff --git a/avconv.c b/avconv.c index e13b2aa5ae..cbf66c44eb 100644 --- a/avconv.c +++ b/avconv.c @@ -203,6 +203,7 @@ typedef struct InputStream { int is_start; /* is 1 at the start and after a discontinuity */ int showed_multi_packet_warning; AVDictionary *opts; + AVRational framerate; /* framerate forced with -r */ int resample_height; int resample_width; @@ -931,10 +932,15 @@ static int configure_output_filter(FilterGraph *fg, OutputFilter *ofilter, AVFil static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, AVFilterInOut *in) { + AVFilterContext *first_filter = in->filter_ctx; AVFilter *filter = avfilter_get_by_name("buffer"); InputStream *ist = ifilter->ist; + AVRational tb = ist->framerate.num ? (AVRational){ist->framerate.den, + ist->framerate.num} : + ist->st->time_base; AVRational sar; char args[255]; + int pad_idx = in->pad_idx; int ret; sar = ist->st->sample_aspect_ratio.num ? @@ -942,13 +948,29 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, ist->st->codec->sample_aspect_ratio; snprintf(args, sizeof(args), "%d:%d:%d:%d:%d:%d:%d", ist->st->codec->width, ist->st->codec->height, ist->st->codec->pix_fmt, - ist->st->time_base.num, ist->st->time_base.den, - sar.num, sar.den); + tb.num, tb.den, sar.num, sar.den); if ((ret = avfilter_graph_create_filter(&ifilter->filter, filter, in->name, args, NULL, fg->graph)) < 0) return ret; - if ((ret = avfilter_link(ifilter->filter, 0, in->filter_ctx, in->pad_idx)) < 0) + + if (ist->framerate.num) { + AVFilterContext *setpts; + + if ((ret = avfilter_graph_create_filter(&setpts, + avfilter_get_by_name("setpts"), + "setpts", "N", NULL, + fg->graph)) < 0) + return ret; + + if ((ret = avfilter_link(setpts, 0, first_filter, pad_idx)) < 0) + return ret; + + first_filter = setpts; + pad_idx = 0; + } + + if ((ret = avfilter_link(ifilter->filter, 0, first_filter, pad_idx)) < 0) return ret; return 0; } @@ -3358,6 +3380,7 @@ 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; if (!ist) exit_program(1); @@ -3382,6 +3405,14 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) ist->resample_width = dec->width; ist->resample_pix_fmt = dec->pix_fmt; + MATCH_PER_STREAM_OPT(frame_rates, str, framerate, ic, st); + if (framerate && av_parse_video_rate(&ist->framerate, + framerate) < 0) { + av_log(NULL, AV_LOG_ERROR, "Error parsing framerate %s.\n", + framerate); + exit_program(1); + } + break; case AVMEDIA_TYPE_AUDIO: guess_input_channel_layout(ist); @@ -3503,7 +3534,14 @@ static int opt_input_file(OptionsContext *o, const char *opt, const char *filena } } if (o->nb_frame_rates) { - av_dict_set(&format_opts, "framerate", o->frame_rates[o->nb_frame_rates - 1].u.str, 0); + /* set the format-level framerate option; + * this is important for video grabbers, e.g. x11 */ + if (file_iformat && file_iformat->priv_class && + av_opt_find(&file_iformat->priv_class, "framerate", NULL, 0, + AV_OPT_SEARCH_FAKE_OBJ)) { + av_dict_set(&format_opts, "framerate", + o->frame_rates[o->nb_frame_rates - 1].u.str, 0); + } } if (o->nb_frame_sizes) { av_dict_set(&format_opts, "video_size", o->frame_sizes[o->nb_frame_sizes - 1].u.str, 0); diff --git a/configure b/configure index c3edc9375c..67371c8102 100755 --- a/configure +++ b/configure @@ -1536,7 +1536,8 @@ avfilter_deps="swscale" avformat_deps="avcodec" # programs -avconv_deps="avcodec avfilter avformat avresample swscale format_filter" +avconv_deps="avcodec avfilter avformat avresample swscale format_filter + setpts_filter" avplay_deps="avcodec avformat swscale sdl" avplay_select="rdft" avprobe_deps="avcodec avformat" diff --git a/doc/avconv.texi b/doc/avconv.texi index 693c45e429..2ebfe9fe44 100644 --- a/doc/avconv.texi +++ b/doc/avconv.texi @@ -257,8 +257,15 @@ attachments. @item -vframes @var{number} (@emph{output}) Set the number of video frames to record. This is an alias for @code{-frames:v}. @item -r[:@var{stream_specifier}] @var{fps} (@emph{input/output,per-stream}) -Set frame rate (Hz value, fraction or abbreviation), (default = 25). For output -streams implies @code{-vsync cfr}. +Set frame rate (Hz value, fraction or abbreviation). + +As an input option, ignore any timestamps stored in the file and instead +generate timestamps assuming constant frame rate @var{fps}. + +As an output option, duplicate or drop input frames to achieve constant output +frame rate @var{fps} (note that this actually causes the @code{fps} filter to be +inserted to the end of the corresponding filtergraph). + @item -s[:@var{stream_specifier}] @var{size} (@emph{input/output,per-stream}) Set frame size.