From patchwork Tue Jun 7 12:14:35 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gyan Doshi X-Patchwork-Id: 36089 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:6914:b0:82:6b11:2509 with SMTP id q20csp6837101pzj; Tue, 7 Jun 2022 05:15:14 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzqFSHNag8bHcDG4faF1DOoyeFxreG2z8ewhLcRhQ+OnNKPLe4ZW4LIreAm/dV2zqsOdZWk X-Received: by 2002:a05:6402:120b:b0:42f:aa44:4d85 with SMTP id c11-20020a056402120b00b0042faa444d85mr23612359edw.338.1654604114710; Tue, 07 Jun 2022 05:15:14 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1654604114; cv=none; d=google.com; s=arc-20160816; b=qRSR0vw1wmekC6lk6jLHhooEC6eyNII2GRCDNEhKdRqTQIbkwHeWhM5dPovK4CYJza AK5wMLbyf8pPLSkNnpM4IwKUka6dd2mTcnTAS2Fc1/3iSrbk8u0D77hmYfcv+n7zdOfk DwNnWx4+jLSINrJ9MGUqJ6SvNYskNj7Rwmr12cbLI+SFAdk5KtmWvEV+kyoKabHwUGVJ gagnqcaNlki4zTmy7Mebwp0DSHHYk5mSIT3LZIIVCyWqrURcVALxSLMdHZ72Mp0yof+I 5kTWqrGzDZ2QxIVCTdBTVJ60NVkljzmsvDYOPiDebI+dFGPDsqp/wWjTenRGmqS7kKTP yDaw== 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:message-id:date:to:from :delivered-to; bh=dQFYptVbIEN+yG6oIdVueimnq7/D3q00HBbqD+u6GJw=; b=clwyglpeBIIQPPnGwf+4zJlE9EGgIx5O+YNwtI+H1HBOAZl3oKYz0hKugq4S0ZR1n8 GLme20LkY0oypksEF6cFJElqK+XZnhVhrcZ3en/v8ErMWoq0lYBn1lMfzMiRnbA/J2CC mrJNDyNqOaIWfjhkf7VnM1+z3ccIJReC89GgQqI83Sla1XI9pbPSDRpasf2PHZMJpZ7c rQneRRxw1vlVqybF7Gq7M/R6N67fzRtF/uIlty1PLbLzrgsfDBr4Pc8r5vW/PaHO0V/K WkBTAqBFyf+4EeTqYmCpGjz/y/7n+dikR9MIkyFMg/s27cNmAqD6SzJ5He5tG2XP5exA +uZw== 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 hs6-20020a1709073e8600b006fe8e64d480si14535923ejc.701.2022.06.07.05.15.14; Tue, 07 Jun 2022 05:15:14 -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 BEDC568B65B; Tue, 7 Jun 2022 15:15:10 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mout-p-202.mailbox.org (mout-p-202.mailbox.org [80.241.56.172]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 05B9868B49D for ; Tue, 7 Jun 2022 15:15:04 +0300 (EEST) Received: from smtp1.mailbox.org (smtp1.mailbox.org [10.196.197.1]) (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-202.mailbox.org (Postfix) with ESMTPS id 4LHTnd4Txbz9sTv for ; Tue, 7 Jun 2022 14:15:01 +0200 (CEST) From: Gyan Doshi To: ffmpeg-devel@ffmpeg.org Date: Tue, 7 Jun 2022 17:44:35 +0530 Message-Id: <20220607121435.11837-1-ffmpeg@gyani.pro> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH] 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: xv6uFqMdHWcY fps_mode sets video sync per output stream. Overrides vsync for matching streams. --- doc/ffmpeg.texi | 8 +++++--- fftools/ffmpeg.c | 9 +++++---- fftools/ffmpeg.h | 3 +++ fftools/ffmpeg_mux.c | 2 +- fftools/ffmpeg_opt.c | 41 ++++++++++++++++++++++++++++++----------- 5 files changed, 44 insertions(+), 19 deletions(-) diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index 0d7e1a479d..395ddc34ba 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -1618,10 +1618,12 @@ 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. +@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. -For compatibility reasons some of the values can be specified as numbers (shown +For compatibility reasons some of the values for vsync can be specified as numbers (shown in parentheses in the following table). This is deprecated and will stop working in the future. diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 5ed287c522..2922a1e707 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -3018,11 +3018,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 or 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..0993985765 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,7 @@ 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"); - } + parse_and_set_vsync(arg, &video_sync_method, -1, -1, 1); return 0; } @@ -3620,7 +3636,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 / fps_mode globally", "" }, { "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 +3793,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" },