From patchwork Fri Jun 10 13:09:38 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gyan Doshi X-Patchwork-Id: 36143 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:6914:b0:82:6b11:2509 with SMTP id q20csp934824pzj; Fri, 10 Jun 2022 06:10:22 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyIz3oEraJJDJ+XFf8ZKCrsemyANIpCiyD5cP/u3BEbyAmO8dXOZko9lT3teCmyz1MEhPnw X-Received: by 2002:a05:6402:1208:b0:432:dd71:c1 with SMTP id c8-20020a056402120800b00432dd7100c1mr14788321edw.265.1654866622580; Fri, 10 Jun 2022 06:10:22 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1654866622; cv=none; d=google.com; s=arc-20160816; b=NzJ3kEop52GVIxLHMyCDmVfnz7rSwdpOfVknz+lK0oiW5Gu+T1UFFeDlOGlwrkfPK/ Hv+Yi+4j9/QzW9fOGdwLalmtg1s1KljRTfVTWpIiRCBgiAwDW69naFcqr2xqPiMWGsYu 1AyCPT9z3I5m6WDaKkyaK9EuRmiexcCm1upYCGJRAg7FPDq5u7oW/dpfQTWlh4GtvrZV LYBtczrg6GCnK1c3OVFH/nnd5wcyCy8bTmBwpfyyw3YQHHAw8QlRIIGkjgzY0oTovKUo Zcg8PASKaxIpXltRYxRZFu0jv5nZ0xn22pH9hZIPBmX65Tvo+r8J6rF2lvBl8WKTB4Br ennA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:reply-to:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:subject:mime-version:references:in-reply-to:message-id :date:to:from:delivered-to; bh=kPZWyhIunwFiXIOG6iwgTsNneNHAz2Qjbn+esFBVgCY=; b=MiunKXCaI9+l/ZB9BFI2/zOYi0XLBH2kkmdDtsdnGZSiAOt0rRNfj7gTBg/FkMXghB 1zfm9W33AOzp3x6Lmw+Bv0gcwRdjiR2XwHZUYukhX06ab3GeaJxLXfBSwf+mgs1+/Dab EgODUoe5RT7xOlIToFnnfJSe3PBJu+harys/D2fARW88kX9Gf/5L2mcs3aNLB2tJ2slp 5yOfR1wUBVSBCg/l4tMn4nR46DG6BGCrfWV9r1lysId4b80X0+vbsaOWDGIZYEEK12+o EmGaFJw3LaBmG7/lU7XW9DwJMvdLv6iLG1xJm0TNRTA/nj5iMvHxInh56Kd0zPKVVyhO iamA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id y18-20020a170906915200b006e8d07f934dsi10742127ejw.45.2022.06.10.06.10.21; Fri, 10 Jun 2022 06:10:22 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id AA59A68B7D2; Fri, 10 Jun 2022 16:10:18 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mout-p-103.mailbox.org (mout-p-103.mailbox.org [80.241.56.161]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id E39C268B7AF for ; Fri, 10 Jun 2022 16:10:11 +0300 (EEST) Received: from smtp202.mailbox.org (smtp202.mailbox.org [IPv6:2001:67c:2050:b231:465::202]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-384) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-103.mailbox.org (Postfix) with ESMTPS id 4LKLss4hNDz9sR7 for ; Fri, 10 Jun 2022 15:10:09 +0200 (CEST) From: Gyan Doshi To: ffmpeg-devel@ffmpeg.org Date: Fri, 10 Jun 2022 18:39:38 +0530 Message-Id: <20220610130938.862-1-ffmpeg@gyani.pro> In-Reply-To: <6bd1f042-08e2-9f73-3512-744c017afcff@gyani.pro> References: <6bd1f042-08e2-9f73-3512-744c017afcff@gyani.pro> MIME-Version: 1.0 X-Rspamd-Queue-Id: 4LKLss4hNDz9sR7 Subject: [FFmpeg-devel] [PATCH v2] ffmpeg: add option fps_mode X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: kT2zbXiYfYNq fps_mode sets video sync per output stream. Overrides vsync for matching streams. vsync is deprecated. --- doc/ffmpeg.texi | 14 ++++++++------ fftools/ffmpeg.c | 9 +++++---- fftools/ffmpeg.h | 3 +++ fftools/ffmpeg_mux.c | 2 +- fftools/ffmpeg_opt.c | 42 +++++++++++++++++++++++++++++++----------- 5 files changed, 48 insertions(+), 22 deletions(-) diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index 0d7e1a479d..51515c2cb8 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -1618,12 +1618,14 @@ it may cause packet loss. It is useful for when flow speed of output packets is important, such as live streaming. @item -re (@emph{input}) Read input at native frame rate. This is equivalent to setting @code{-readrate 1}. -@item -vsync @var{parameter} -Video sync method. - -For compatibility reasons some of the values can be specified as numbers (shown -in parentheses in the following table). This is deprecated and will stop working -in the future. +@item -vsync @var{parameter} (@emph{global}) +@itemx -fps_mode[:@var{stream_specifier}] @var{parameter} (@emph{output,per-stream}) +Set video sync method / framerate mode. vsync is applied to all output video streams +but can be overridden for a stream by setting fps_mode. vsync is deprecated and will be +removed in the future. + +For compatibility reasons some of the values for vsync can be specified as numbers (shown +in parentheses in the following table). @table @option @item passthrough (0) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index a5e1bf3993..09caa3e3c4 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -3017,11 +3017,12 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) if (!(enc_ctx->time_base.num && enc_ctx->time_base.den)) enc_ctx->time_base = av_buffersink_get_time_base(ost->filter->filter); - if ( av_q2d(enc_ctx->time_base) < 0.001 && video_sync_method != VSYNC_PASSTHROUGH - && (video_sync_method == VSYNC_CFR || video_sync_method == VSYNC_VSCFR || - (video_sync_method == VSYNC_AUTO && !(of->format->flags & AVFMT_VARIABLE_FPS)))){ + if ( av_q2d(enc_ctx->time_base) < 0.001 && ost->vsync_method != VSYNC_PASSTHROUGH + && (ost->vsync_method == VSYNC_CFR || ost->vsync_method == VSYNC_VSCFR || + (ost->vsync_method == VSYNC_AUTO && !(of->format->flags & AVFMT_VARIABLE_FPS)))){ av_log(oc, AV_LOG_WARNING, "Frame rate very high for a muxer not efficiently supporting it.\n" - "Please consider specifying a lower framerate, a different muxer or -vsync 2\n"); + "Please consider specifying a lower framerate, a different muxer or " + "setting vsync/fps_mode to vfr\n"); } enc_ctx->width = av_buffersink_get_w(ost->filter->filter); diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 7326193caf..69a368b8d1 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -176,6 +176,8 @@ typedef struct OptionsContext { int nb_qscale; SpecifierOpt *forced_key_frames; int nb_forced_key_frames; + SpecifierOpt *fps_mode; + int nb_fps_mode; SpecifierOpt *force_fps; int nb_force_fps; SpecifierOpt *frame_aspect_ratios; @@ -489,6 +491,7 @@ typedef struct OutputStream { AVRational max_frame_rate; enum VideoSyncMethod vsync_method; int is_cfr; + const char *fps_mode; int force_fps; int top_field_first; int rotate_overridden; diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c index 794d580635..a55fd18f8f 100644 --- a/fftools/ffmpeg_mux.c +++ b/fftools/ffmpeg_mux.c @@ -96,7 +96,7 @@ void of_write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, return; } - if ((st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && video_sync_method == VSYNC_DROP) || + if ((st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && ost->vsync_method == VSYNC_DROP) || (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && audio_sync_method < 0)) pkt->pts = pkt->dts = AV_NOPTS_VALUE; diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 2c1b3bd0dd..398067da96 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -81,6 +81,7 @@ static const char *const opt_name_codec_tags[] = {"tag", "atag", static const char *const opt_name_sample_fmts[] = {"sample_fmt", NULL}; static const char *const opt_name_qscale[] = {"q", "qscale", NULL}; static const char *const opt_name_forced_key_frames[] = {"forced_key_frames", NULL}; +static const char *const opt_name_fps_mode[] = {"fps_mode", NULL}; static const char *const opt_name_force_fps[] = {"force_fps", NULL}; static const char *const opt_name_frame_aspect_ratios[] = {"aspect", NULL}; static const char *const opt_name_rc_overrides[] = {"rc_override", NULL}; @@ -265,6 +266,26 @@ static AVDictionary *strip_specifiers(AVDictionary *dict) return ret; } +static int parse_and_set_vsync(const char *arg, int *vsync_var, int file_idx, int st_idx, int is_global) +{ + if (!av_strcasecmp(arg, "cfr")) *vsync_var = VSYNC_CFR; + else if (!av_strcasecmp(arg, "vfr")) *vsync_var = VSYNC_VFR; + else if (!av_strcasecmp(arg, "passthrough")) *vsync_var = VSYNC_PASSTHROUGH; + else if (!av_strcasecmp(arg, "drop")) *vsync_var = VSYNC_DROP; + else if (!is_global && !av_strcasecmp(arg, "auto")) *vsync_var = VSYNC_AUTO; + else if (!is_global) { + av_log(NULL, AV_LOG_FATAL, "Invalid value %s specified for fps_mode of #%d:%d.\n", arg, file_idx, st_idx); + exit_program(1); + } + + if (is_global && *vsync_var == VSYNC_AUTO) { + video_sync_method = parse_number_or_die("vsync", arg, OPT_INT, VSYNC_AUTO, VSYNC_VFR); + av_log(NULL, AV_LOG_WARNING, "Passing a number to -vsync is deprecated," + " use a string argument as described in the manual.\n"); + } + return 0; +} + static int opt_filter_threads(void *optctx, const char *opt, const char *arg) { av_free(filter_nbthreads); @@ -1905,6 +1926,10 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in MATCH_PER_STREAM_OPT(top_field_first, i, ost->top_field_first, oc, st); ost->vsync_method = video_sync_method; + MATCH_PER_STREAM_OPT(fps_mode, str, ost->fps_mode, oc, st); + if (ost->fps_mode) + parse_and_set_vsync(ost->fps_mode, &ost->vsync_method, ost->file_index, ost->index, 0); + if (ost->vsync_method == VSYNC_AUTO) { if (!strcmp(oc->oformat->name, "avi")) { ost->vsync_method = VSYNC_VFR; @@ -3248,16 +3273,8 @@ static int opt_audio_filters(void *optctx, const char *opt, const char *arg) static int opt_vsync(void *optctx, const char *opt, const char *arg) { - if (!av_strcasecmp(arg, "cfr")) video_sync_method = VSYNC_CFR; - else if (!av_strcasecmp(arg, "vfr")) video_sync_method = VSYNC_VFR; - else if (!av_strcasecmp(arg, "passthrough")) video_sync_method = VSYNC_PASSTHROUGH; - else if (!av_strcasecmp(arg, "drop")) video_sync_method = VSYNC_DROP; - - if (video_sync_method == VSYNC_AUTO) { - video_sync_method = parse_number_or_die("vsync", arg, OPT_INT, VSYNC_AUTO, VSYNC_VFR); - av_log(NULL, AV_LOG_WARNING, "Passing a number to -vsync is deprecated," - " use a string argument as described in the manual.\n"); - } + av_log(NULL, AV_LOG_WARNING, "-vsync is deprecated. Use -fps_mode\n"); + parse_and_set_vsync(arg, &video_sync_method, -1, -1, 1); return 0; } @@ -3620,7 +3637,7 @@ const OptionDef options[] = { "specify target file type (\"vcd\", \"svcd\", \"dvd\", \"dv\" or \"dv50\" " "with optional prefixes \"pal-\", \"ntsc-\" or \"film-\")", "type" }, { "vsync", HAS_ARG | OPT_EXPERT, { .func_arg = opt_vsync }, - "video sync method", "" }, + "set video sync method globally; deprecated, use -fps_mode", "" }, { "frame_drop_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, { &frame_drop_threshold }, "frame drop threshold", "" }, { "async", HAS_ARG | OPT_INT | OPT_EXPERT, { &audio_sync_method }, @@ -3777,6 +3794,9 @@ const OptionDef options[] = { "force video tag/fourcc", "fourcc/tag" }, { "qphist", OPT_VIDEO | OPT_BOOL | OPT_EXPERT , { &qp_hist }, "show QP histogram" }, + { "fps_mode", OPT_VIDEO | HAS_ARG | OPT_STRING | OPT_EXPERT | + OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(fps_mode) }, + "set framerate mode for matching video streams; overrides vsync" }, { "force_fps", OPT_VIDEO | OPT_BOOL | OPT_EXPERT | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(force_fps) }, "force the selected framerate, disable the best supported framerate selection" },