From: Niklas Haas <ffmpeg@haasn.xyz>
To: ffmpeg-devel@ffmpeg.org
Cc: Niklas Haas <git@haasn.dev>
Subject: [FFmpeg-devel] [PATCH 5/6] lavfi/vf_libplacebo: allow fps conversion
Date: Wed, 10 May 2023 15:55:08 +0200
Message-ID: <20230510135509.4074-5-ffmpeg@haasn.xyz> (raw)
In-Reply-To: <20230510135509.4074-1-ffmpeg@haasn.xyz>
From: Niklas Haas <git@haasn.dev>
This exposes libplacebo's frame mixing functionality to vf_libplacebo,
by allowing users to specify a desired target fps to output at. Incoming
frames will be smoothly resampled (in a manner determined by the
`frame_mixer` option, to be added in the next commit).
To generate a consistently timed output stream, we directly use the
desired framerate as the timebase, and simply output frames in
sequential order (tracked by the number of frames output so far).
---
doc/filters.texi | 7 +++++++
libavfilter/vf_libplacebo.c | 38 ++++++++++++++++++++++++++++++-------
2 files changed, 38 insertions(+), 7 deletions(-)
diff --git a/doc/filters.texi b/doc/filters.texi
index 206fb23785..3e17ba1654 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -16034,6 +16034,13 @@ and @code{(oh-ph)/2}.
Set the output placement width/height expressions, default values are @code{ow}
and @code{oh}.
+@item fps
+Set the output frame rate. This can be rational, e.g. @code{60000/1001}. If
+set to the special string @code{none} (the default), input timestamps will
+instead be passed through to the output unmodified. Otherwise, the input video
+frames will be interpolated as necessary to rescale the video to the specified
+target framerate, in a manner as determined by the @option{frame_mixer} option.
+
@item format
Set the output format override. If unset (the default), frames will be output
in the same format as the respective input frames. Otherwise, format conversion
diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c
index d8128351c8..2bec942358 100644
--- a/libavfilter/vf_libplacebo.c
+++ b/libavfilter/vf_libplacebo.c
@@ -139,6 +139,8 @@ typedef struct LibplaceboContext {
double var_values[VAR_VARS_NB];
char *w_expr;
char *h_expr;
+ char *fps_string;
+ AVRational fps; ///< parsed FPS, or 0/0 for "none"
char *crop_x_expr, *crop_y_expr;
char *crop_w_expr, *crop_h_expr;
char *pos_x_expr, *pos_y_expr;
@@ -166,6 +168,7 @@ typedef struct LibplaceboContext {
float antiringing;
int sigmoid;
int skip_aa;
+ int skip_cache;
float polar_cutoff;
int disable_linear;
int disable_builtin;
@@ -400,7 +403,7 @@ static int update_settings(AVFilterContext *ctx)
.num_hooks = s->num_hooks,
.skip_anti_aliasing = s->skip_aa,
- .skip_caching_single_frame = true,
+ .skip_caching_single_frame = s->skip_cache,
.polar_cutoff = s->polar_cutoff,
.disable_linear_scaling = s->disable_linear,
.disable_builtin_scalers = s->disable_builtin,
@@ -465,6 +468,8 @@ static int libplacebo_init(AVFilterContext *avctx)
/* Initialize dynamic filter state */
s->out_pts = av_fifo_alloc2(1, sizeof(int64_t), AV_FIFO_FLAG_AUTO_GROW);
+ if (strcmp(s->fps_string, "none") != 0)
+ RET(av_parse_video_rate(&s->fps, s->fps_string));
/* Note: s->vulkan etc. are initialized later, when hwctx is available */
return 0;
@@ -672,6 +677,8 @@ static int output_frame_mix(AVFilterContext *ctx,
out->pts = pts;
out->width = outlink->w;
out->height = outlink->h;
+ if (s->fps.num)
+ out->duration = 1;
if (s->apply_dovi && av_frame_get_side_data(ref, AV_FRAME_DATA_DOVI_METADATA)) {
/* Output of dovi reshaping is always BT.2020+PQ, so infer the correct
@@ -793,9 +800,11 @@ static int libplacebo_activate(AVFilterContext *ctx)
.discard = discard_frame,
});
- /* Internally queue an output frame for the same PTS */
- av_assert1(!av_cmp_q(link->time_base, outlink->time_base));
- av_fifo_write(s->out_pts, &in->pts, 1);
+ if (!s->fps.num) {
+ /* Internally queue an output frame for the same PTS */
+ av_assert1(!av_cmp_q(link->time_base, outlink->time_base));
+ av_fifo_write(s->out_pts, &in->pts, 1);
+ }
}
if (ret < 0)
@@ -808,7 +817,8 @@ static int libplacebo_activate(AVFilterContext *ctx)
/* Signal EOF to pl_queue, and enqueue this output frame to
* make sure we see PL_QUEUE_EOF returned eventually */
pl_queue_push(s->queue, NULL);
- av_fifo_write(s->out_pts, &pts, 1);
+ if (!s->fps.num)
+ av_fifo_write(s->out_pts, &pts, 1);
} else {
ff_outlink_set_status(outlink, status, pts);
return 0;
@@ -819,7 +829,9 @@ static int libplacebo_activate(AVFilterContext *ctx)
struct pl_frame_mix mix;
enum pl_queue_status ret;
- if (av_fifo_peek(s->out_pts, &pts, 1, 0) < 0) {
+ if (s->fps.num) {
+ pts = outlink->frame_count_out;
+ } else if (av_fifo_peek(s->out_pts, &pts, 1, 0) < 0) {
ff_inlink_request_frame(inlink);
return 0;
}
@@ -835,7 +847,8 @@ static int libplacebo_activate(AVFilterContext *ctx)
ff_inlink_request_frame(inlink);
return 0;
case PL_QUEUE_OK:
- av_fifo_drain2(s->out_pts, 1);
+ if (!s->fps.num)
+ av_fifo_drain2(s->out_pts, 1);
return output_frame_mix(ctx, &mix, pts);
case PL_QUEUE_EOF:
ff_outlink_set_status(outlink, AVERROR_EOF, pts);
@@ -939,6 +952,7 @@ static int libplacebo_config_output(AVFilterLink *outlink)
AVVulkanFramesContext *vkfc;
AVRational scale_sar;
+ /* Frame dimensions */
RET(ff_scale_eval_dimensions(s, s->w_expr, s->h_expr, inlink, outlink,
&outlink->w, &outlink->h));
@@ -962,6 +976,15 @@ static int libplacebo_config_output(AVFilterLink *outlink)
outlink->sample_aspect_ratio = scale_sar;
}
+ /* Frame rate */
+ if (s->fps.num) {
+ outlink->frame_rate = s->fps;
+ outlink->time_base = av_inv_q(s->fps);
+ s->skip_cache = av_cmp_q(inlink->frame_rate, s->fps) > 0;
+ } else {
+ s->skip_cache = true;
+ }
+
/* Static variables */
s->var_values[VAR_IN_W] = s->var_values[VAR_IW] = inlink->w;
s->var_values[VAR_IN_H] = s->var_values[VAR_IH] = inlink->h;
@@ -1006,6 +1029,7 @@ fail:
static const AVOption libplacebo_options[] = {
{ "w", "Output video frame width", OFFSET(w_expr), AV_OPT_TYPE_STRING, {.str = "iw"}, .flags = STATIC },
{ "h", "Output video frame height", OFFSET(h_expr), AV_OPT_TYPE_STRING, {.str = "ih"}, .flags = STATIC },
+ { "fps", "Output video frame rate", OFFSET(fps_string), AV_OPT_TYPE_STRING, {.str = "none"}, .flags = STATIC },
{ "crop_x", "Input video crop x", OFFSET(crop_x_expr), AV_OPT_TYPE_STRING, {.str = "(iw-cw)/2"}, .flags = DYNAMIC },
{ "crop_y", "Input video crop y", OFFSET(crop_y_expr), AV_OPT_TYPE_STRING, {.str = "(ih-ch)/2"}, .flags = DYNAMIC },
{ "crop_w", "Input video crop w", OFFSET(crop_w_expr), AV_OPT_TYPE_STRING, {.str = "iw"}, .flags = DYNAMIC },
--
2.40.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
next prev parent reply other threads:[~2023-05-10 13:56 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-05-10 13:55 [FFmpeg-devel] [PATCH 1/6] lavfi/vf_libplacebo: update render params on demand Niklas Haas
2023-05-10 13:55 ` [FFmpeg-devel] [PATCH 2/6] lavfi/vf_libplacebo: split and refactor logic Niklas Haas
2023-05-10 13:55 ` [FFmpeg-devel] [PATCH 3/6] lavfi/vf_libplacebo: switch to pl_queue-based design Niklas Haas
2023-05-10 13:55 ` [FFmpeg-devel] [PATCH 4/6] lavfi/vf_libplacebo: switch to activate() Niklas Haas
2023-05-10 13:55 ` Niklas Haas [this message]
2023-05-10 13:55 ` [FFmpeg-devel] [PATCH 6/6] lavfi/vf_libplacebo: add frame_mixer option Niklas Haas
2023-05-14 9:22 ` [FFmpeg-devel] [PATCH 1/6] lavfi/vf_libplacebo: update render params on demand Niklas Haas
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230510135509.4074-5-ffmpeg@haasn.xyz \
--to=ffmpeg@haasn.xyz \
--cc=ffmpeg-devel@ffmpeg.org \
--cc=git@haasn.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
This inbox may be cloned and mirrored by anyone:
git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git
# If you have public-inbox 1.1+ installed, you may
# initialize and index your mirror using the following commands:
public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
ffmpegdev@gitmailbox.com
public-inbox-index ffmpegdev
Example config snippet for mirrors.
AGPL code for this site: git clone https://public-inbox.org/public-inbox.git