* [FFmpeg-devel] [PATCH v2 01/22] lavfi/vf_libplacebo: drop redundant case
2023-06-18 11:16 [FFmpeg-devel] lavfi/vf_libplacebo: generalize to multiple inputs Niklas Haas
@ 2023-06-18 11:16 ` Niklas Haas
2023-06-18 11:16 ` [FFmpeg-devel] [PATCH v2 02/22] lavfi/vf_libplacebo: move input-specific state to struct Niklas Haas
` (21 subsequent siblings)
22 siblings, 0 replies; 25+ messages in thread
From: Niklas Haas @ 2023-06-18 11:16 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
If the input queue is EOF, then the s->status check should already have
covered it, and prevented the code from getting this far.
If we still hit this case for some reason, it's probably a bug. Better
to hit the AVERROR_BUG branch.
---
libavfilter/vf_libplacebo.c | 3 ---
1 file changed, 3 deletions(-)
diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c
index 242c8a13f5a..a048424cecc 100644
--- a/libavfilter/vf_libplacebo.c
+++ b/libavfilter/vf_libplacebo.c
@@ -949,9 +949,6 @@ static int libplacebo_activate(AVFilterContext *ctx)
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);
- return 0;
case PL_QUEUE_ERR:
return AVERROR_EXTERNAL;
}
--
2.41.0
_______________________________________________
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".
^ permalink raw reply [flat|nested] 25+ messages in thread
* [FFmpeg-devel] [PATCH v2 02/22] lavfi/vf_libplacebo: move input-specific state to struct
2023-06-18 11:16 [FFmpeg-devel] lavfi/vf_libplacebo: generalize to multiple inputs Niklas Haas
2023-06-18 11:16 ` [FFmpeg-devel] [PATCH v2 01/22] lavfi/vf_libplacebo: drop redundant case Niklas Haas
@ 2023-06-18 11:16 ` Niklas Haas
2023-06-18 11:16 ` [FFmpeg-devel] [PATCH v2 03/22] lavfi/vf_libplacebo: move input handling to separate function Niklas Haas
` (20 subsequent siblings)
22 siblings, 0 replies; 25+ messages in thread
From: Niklas Haas @ 2023-06-18 11:16 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
In anticipation of a refactor which will enable multiple input support.
Note: the renderer is also input-specific because it maintains a frame
cache, HDR peak detection state and mixing cache, all of which are tied
to a specific input stream.
---
libavfilter/vf_libplacebo.c | 80 ++++++++++++++++++++++++-------------
1 file changed, 52 insertions(+), 28 deletions(-)
diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c
index a048424cecc..10fd4327458 100644
--- a/libavfilter/vf_libplacebo.c
+++ b/libavfilter/vf_libplacebo.c
@@ -113,6 +113,16 @@ enum var_name {
VAR_VARS_NB
};
+/* per-input dynamic filter state */
+typedef struct LibplaceboInput {
+ pl_renderer renderer;
+ pl_queue queue;
+ AVFilterLink *link;
+ AVFifo *out_pts; ///< timestamps of wanted output frames
+ int64_t status_pts;
+ int status;
+} LibplaceboInput;
+
typedef struct LibplaceboContext {
/* lavfi vulkan*/
FFVulkanContext vkctx;
@@ -121,14 +131,10 @@ typedef struct LibplaceboContext {
pl_log log;
pl_vulkan vulkan;
pl_gpu gpu;
- pl_renderer renderer;
- pl_queue queue;
pl_tex tex[4];
- /* filter state */
- AVFifo *out_pts; ///< timestamps of wanted output frames
- int64_t status_pts;
- int status;
+ /* input state */
+ LibplaceboInput input;
/* settings */
char *out_format_string;
@@ -536,8 +542,6 @@ static int libplacebo_init(AVFilterContext *avctx)
RET(av_expr_parse(&s->pos_h_pexpr, s->pos_h_expr, var_names,
NULL, NULL, NULL, NULL, 0, s));
- /* 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));
@@ -564,6 +568,28 @@ static void unlock_queue(void *priv, uint32_t qf, uint32_t qidx)
}
#endif
+static int input_init(AVFilterContext *avctx, AVFilterLink *link,
+ LibplaceboInput *input)
+{
+ LibplaceboContext *s = avctx->priv;
+
+ input->out_pts = av_fifo_alloc2(1, sizeof(int64_t), AV_FIFO_FLAG_AUTO_GROW);
+ if (!input->out_pts)
+ return AVERROR(ENOMEM);
+ input->queue = pl_queue_create(s->gpu);
+ input->renderer = pl_renderer_create(s->log, s->gpu);
+ input->link = link;
+
+ return 0;
+}
+
+static void input_uninit(LibplaceboInput *input)
+{
+ pl_renderer_destroy(&input->renderer);
+ pl_queue_destroy(&input->queue);
+ av_fifo_freep2(&input->out_pts);
+}
+
static int init_vulkan(AVFilterContext *avctx, const AVVulkanDeviceContext *hwctx)
{
int err = 0;
@@ -620,10 +646,7 @@ static int init_vulkan(AVFilterContext *avctx, const AVVulkanDeviceContext *hwct
goto fail;
}
- /* Create the renderer */
s->gpu = s->vulkan->gpu;
- s->renderer = pl_renderer_create(s->log, s->gpu);
- s->queue = pl_queue_create(s->gpu);
/* Parse the user shaders, if requested */
if (s->shader_bin_len)
@@ -634,6 +657,9 @@ static int init_vulkan(AVFilterContext *avctx, const AVVulkanDeviceContext *hwct
RET(parse_shader(avctx, buf, buf_len));
}
+ /* Initialize inputs */
+ RET(input_init(avctx, avctx->inputs[0], &s->input));
+
/* fall through */
fail:
if (buf)
@@ -649,8 +675,7 @@ static void libplacebo_uninit(AVFilterContext *avctx)
pl_tex_destroy(s->gpu, &s->tex[i]);
for (int i = 0; i < s->num_hooks; i++)
pl_mpv_user_shader_destroy(&s->hooks[i]);
- pl_renderer_destroy(&s->renderer);
- pl_queue_destroy(&s->queue);
+ input_uninit(&s->input);
pl_vulkan_destroy(&s->vulkan);
pl_log_destroy(&s->log);
ff_vk_uninit(&s->vkctx);
@@ -664,7 +689,6 @@ static void libplacebo_uninit(AVFilterContext *avctx)
av_expr_free(s->pos_y_pexpr);
av_expr_free(s->pos_w_pexpr);
av_expr_free(s->pos_h_pexpr);
- av_fifo_freep2(&s->out_pts);
}
static int libplacebo_process_command(AVFilterContext *ctx, const char *cmd,
@@ -826,7 +850,7 @@ static int output_frame_mix(AVFilterContext *ctx,
}
update_crops(ctx, mix, &target, ref_sig, out->pts * av_q2d(outlink->time_base));
- pl_render_image_mix(s->renderer, mix, &target, &s->params);
+ pl_render_image_mix(s->input.renderer, mix, &target, &s->params);
if (outdesc->flags & AV_PIX_FMT_FLAG_HWACCEL) {
pl_unmap_avframe(s->gpu, &target);
@@ -886,7 +910,7 @@ static int libplacebo_activate(AVFilterContext *ctx)
while ((ret = ff_inlink_consume_frame(inlink, &in)) > 0) {
in->opaque = s;
- pl_queue_push(s->queue, &(struct pl_source_frame) {
+ pl_queue_push(s->input.queue, &(struct pl_source_frame) {
.pts = in->pts * av_q2d(inlink->time_base),
.duration = in->duration * av_q2d(inlink->time_base),
.first_field = pl_field_from_avframe(in),
@@ -899,19 +923,19 @@ static int libplacebo_activate(AVFilterContext *ctx)
if (!s->fps.num) {
/* Internally queue an output frame for the same PTS */
av_assert1(!av_cmp_q(inlink->time_base, outlink->time_base));
- av_fifo_write(s->out_pts, &in->pts, 1);
+ av_fifo_write(s->input.out_pts, &in->pts, 1);
}
}
if (ret < 0)
return ret;
- if (!s->status && ff_inlink_acknowledge_status(inlink, &status, &pts)) {
+ if (!s->input.status && ff_inlink_acknowledge_status(inlink, &status, &pts)) {
pts = av_rescale_q_rnd(pts, inlink->time_base, outlink->time_base,
AV_ROUND_UP);
- pl_queue_push(s->queue, NULL); /* Signal EOF to pl_queue */
- s->status = status;
- s->status_pts = pts;
+ pl_queue_push(s->input.queue, NULL); /* Signal EOF to pl_queue */
+ s->input.status = status;
+ s->input.status_pts = pts;
}
if (ff_outlink_frame_wanted(outlink)) {
@@ -920,22 +944,22 @@ static int libplacebo_activate(AVFilterContext *ctx)
if (s->fps.num) {
pts = outlink->frame_count_out;
- } else if (av_fifo_peek(s->out_pts, &pts, 1, 0) < 0) {
+ } else if (av_fifo_peek(s->input.out_pts, &pts, 1, 0) < 0) {
/* No frames queued */
- if (s->status) {
- pts = s->status_pts;
+ if (s->input.status) {
+ pts = s->input.status_pts;
} else {
ff_inlink_request_frame(inlink);
return 0;
}
}
- if (s->status && pts >= s->status_pts) {
- ff_outlink_set_status(outlink, s->status, s->status_pts);
+ if (s->input.status && pts >= s->input.status_pts) {
+ ff_outlink_set_status(outlink, s->input.status, s->input.status_pts);
return 0;
}
- ret = pl_queue_update(s->queue, &mix, pl_queue_params(
+ ret = pl_queue_update(s->input.queue, &mix, pl_queue_params(
.pts = pts * av_q2d(outlink->time_base),
.radius = pl_frame_mix_radius(&s->params),
.vsync_duration = av_q2d(av_inv_q(outlink->frame_rate)),
@@ -947,7 +971,7 @@ static int libplacebo_activate(AVFilterContext *ctx)
return 0;
case PL_QUEUE_OK:
if (!s->fps.num)
- av_fifo_drain2(s->out_pts, 1);
+ av_fifo_drain2(s->input.out_pts, 1);
return output_frame_mix(ctx, &mix, pts);
case PL_QUEUE_ERR:
return AVERROR_EXTERNAL;
--
2.41.0
_______________________________________________
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".
^ permalink raw reply [flat|nested] 25+ messages in thread
* [FFmpeg-devel] [PATCH v2 03/22] lavfi/vf_libplacebo: move input handling to separate function
2023-06-18 11:16 [FFmpeg-devel] lavfi/vf_libplacebo: generalize to multiple inputs Niklas Haas
2023-06-18 11:16 ` [FFmpeg-devel] [PATCH v2 01/22] lavfi/vf_libplacebo: drop redundant case Niklas Haas
2023-06-18 11:16 ` [FFmpeg-devel] [PATCH v2 02/22] lavfi/vf_libplacebo: move input-specific state to struct Niklas Haas
@ 2023-06-18 11:16 ` Niklas Haas
2023-06-18 11:16 ` [FFmpeg-devel] [PATCH v2 04/22] lavfi/vf_libplacebo: cosmetic Niklas Haas
` (19 subsequent siblings)
22 siblings, 0 replies; 25+ messages in thread
From: Niklas Haas @ 2023-06-18 11:16 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
To be re-used once we support more than one input.
---
libavfilter/vf_libplacebo.c | 45 ++++++++++++++++++++++++-------------
1 file changed, 29 insertions(+), 16 deletions(-)
diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c
index 10fd4327458..879a3a05086 100644
--- a/libavfilter/vf_libplacebo.c
+++ b/libavfilter/vf_libplacebo.c
@@ -896,23 +896,19 @@ static void discard_frame(const struct pl_source_frame *src)
av_frame_free(&avframe);
}
-static int libplacebo_activate(AVFilterContext *ctx)
+static int handle_input(AVFilterContext *ctx, LibplaceboInput *input)
{
int ret, status;
LibplaceboContext *s = ctx->priv;
- AVFilterLink *inlink = ctx->inputs[0];
AVFilterLink *outlink = ctx->outputs[0];
AVFrame *in;
int64_t pts;
- FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);
- pl_log_level_update(s->log, get_log_level());
-
- while ((ret = ff_inlink_consume_frame(inlink, &in)) > 0) {
+ while ((ret = ff_inlink_consume_frame(input->link, &in)) > 0) {
in->opaque = s;
- pl_queue_push(s->input.queue, &(struct pl_source_frame) {
- .pts = in->pts * av_q2d(inlink->time_base),
- .duration = in->duration * av_q2d(inlink->time_base),
+ pl_queue_push(input->queue, &(struct pl_source_frame) {
+ .pts = in->pts * av_q2d(input->link->time_base),
+ .duration = in->duration * av_q2d(input->link->time_base),
.first_field = pl_field_from_avframe(in),
.frame_data = in,
.map = map_frame,
@@ -922,22 +918,39 @@ static int libplacebo_activate(AVFilterContext *ctx)
if (!s->fps.num) {
/* Internally queue an output frame for the same PTS */
- av_assert1(!av_cmp_q(inlink->time_base, outlink->time_base));
- av_fifo_write(s->input.out_pts, &in->pts, 1);
+ pts = av_rescale_q(in->pts, input->link->time_base, outlink->time_base);
+ av_fifo_write(input->out_pts, &pts, 1);
}
}
if (ret < 0)
return ret;
- if (!s->input.status && ff_inlink_acknowledge_status(inlink, &status, &pts)) {
- pts = av_rescale_q_rnd(pts, inlink->time_base, outlink->time_base,
+ if (!input->status && ff_inlink_acknowledge_status(input->link, &status, &pts)) {
+ pts = av_rescale_q_rnd(pts, input->link->time_base, outlink->time_base,
AV_ROUND_UP);
- pl_queue_push(s->input.queue, NULL); /* Signal EOF to pl_queue */
- s->input.status = status;
- s->input.status_pts = pts;
+ pl_queue_push(input->queue, NULL); /* Signal EOF to pl_queue */
+ input->status = status;
+ input->status_pts = pts;
}
+ return 0;
+}
+
+static int libplacebo_activate(AVFilterContext *ctx)
+{
+ int ret;
+ LibplaceboContext *s = ctx->priv;
+ AVFilterLink *inlink = ctx->inputs[0];
+ AVFilterLink *outlink = ctx->outputs[0];
+ int64_t pts;
+
+ FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);
+ pl_log_level_update(s->log, get_log_level());
+
+ if ((ret = handle_input(ctx, &s->input)) < 0)
+ return ret;
+
if (ff_outlink_frame_wanted(outlink)) {
struct pl_frame_mix mix;
enum pl_queue_status ret;
--
2.41.0
_______________________________________________
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".
^ permalink raw reply [flat|nested] 25+ messages in thread
* [FFmpeg-devel] [PATCH v2 04/22] lavfi/vf_libplacebo: cosmetic
2023-06-18 11:16 [FFmpeg-devel] lavfi/vf_libplacebo: generalize to multiple inputs Niklas Haas
` (2 preceding siblings ...)
2023-06-18 11:16 ` [FFmpeg-devel] [PATCH v2 03/22] lavfi/vf_libplacebo: move input handling to separate function Niklas Haas
@ 2023-06-18 11:16 ` Niklas Haas
2023-06-18 11:16 ` [FFmpeg-devel] [PATCH v2 05/22] lavfi/vf_libplacebo: move temporary vars into per-input struct Niklas Haas
` (18 subsequent siblings)
22 siblings, 0 replies; 25+ messages in thread
From: Niklas Haas @ 2023-06-18 11:16 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
Assign local variable 'in' for 's->input' and replace 'inlink' by
'in->link' to avoid hard-coding ID 0 in more than one place.
---
libavfilter/vf_libplacebo.c | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c
index 879a3a05086..beddd2f796d 100644
--- a/libavfilter/vf_libplacebo.c
+++ b/libavfilter/vf_libplacebo.c
@@ -941,14 +941,14 @@ static int libplacebo_activate(AVFilterContext *ctx)
{
int ret;
LibplaceboContext *s = ctx->priv;
- AVFilterLink *inlink = ctx->inputs[0];
+ LibplaceboInput *in = &s->input;
AVFilterLink *outlink = ctx->outputs[0];
int64_t pts;
- FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);
+ FF_FILTER_FORWARD_STATUS_BACK(outlink, in->link);
pl_log_level_update(s->log, get_log_level());
- if ((ret = handle_input(ctx, &s->input)) < 0)
+ if ((ret = handle_input(ctx, in)) < 0)
return ret;
if (ff_outlink_frame_wanted(outlink)) {
@@ -957,22 +957,22 @@ static int libplacebo_activate(AVFilterContext *ctx)
if (s->fps.num) {
pts = outlink->frame_count_out;
- } else if (av_fifo_peek(s->input.out_pts, &pts, 1, 0) < 0) {
+ } else if (av_fifo_peek(in->out_pts, &pts, 1, 0) < 0) {
/* No frames queued */
- if (s->input.status) {
- pts = s->input.status_pts;
+ if (in->status) {
+ pts = in->status_pts;
} else {
- ff_inlink_request_frame(inlink);
+ ff_inlink_request_frame(in->link);
return 0;
}
}
- if (s->input.status && pts >= s->input.status_pts) {
- ff_outlink_set_status(outlink, s->input.status, s->input.status_pts);
+ if (in->status && pts >= in->status_pts) {
+ ff_outlink_set_status(outlink, in->status, in->status_pts);
return 0;
}
- ret = pl_queue_update(s->input.queue, &mix, pl_queue_params(
+ ret = pl_queue_update(in->queue, &mix, pl_queue_params(
.pts = pts * av_q2d(outlink->time_base),
.radius = pl_frame_mix_radius(&s->params),
.vsync_duration = av_q2d(av_inv_q(outlink->frame_rate)),
@@ -980,11 +980,11 @@ static int libplacebo_activate(AVFilterContext *ctx)
switch (ret) {
case PL_QUEUE_MORE:
- ff_inlink_request_frame(inlink);
+ ff_inlink_request_frame(in->link);
return 0;
case PL_QUEUE_OK:
if (!s->fps.num)
- av_fifo_drain2(s->input.out_pts, 1);
+ av_fifo_drain2(in->out_pts, 1);
return output_frame_mix(ctx, &mix, pts);
case PL_QUEUE_ERR:
return AVERROR_EXTERNAL;
--
2.41.0
_______________________________________________
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".
^ permalink raw reply [flat|nested] 25+ messages in thread
* [FFmpeg-devel] [PATCH v2 05/22] lavfi/vf_libplacebo: move temporary vars into per-input struct
2023-06-18 11:16 [FFmpeg-devel] lavfi/vf_libplacebo: generalize to multiple inputs Niklas Haas
` (3 preceding siblings ...)
2023-06-18 11:16 ` [FFmpeg-devel] [PATCH v2 04/22] lavfi/vf_libplacebo: cosmetic Niklas Haas
@ 2023-06-18 11:16 ` Niklas Haas
2023-06-18 11:16 ` [FFmpeg-devel] [PATCH v2 06/22] lavif/vf_libplacebo: remove pl_frame_mix from output_frame_mix Niklas Haas
` (17 subsequent siblings)
22 siblings, 0 replies; 25+ messages in thread
From: Niklas Haas @ 2023-06-18 11:16 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
Including the queue status, because these will need to be re-queried
inside output_frame_mix when that function is refactored to handle
multiple inputs.
---
libavfilter/vf_libplacebo.c | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c
index beddd2f796d..4baa766bacf 100644
--- a/libavfilter/vf_libplacebo.c
+++ b/libavfilter/vf_libplacebo.c
@@ -117,6 +117,8 @@ enum var_name {
typedef struct LibplaceboInput {
pl_renderer renderer;
pl_queue queue;
+ enum pl_queue_status qstatus;
+ struct pl_frame_mix mix; ///< temporary storage
AVFilterLink *link;
AVFifo *out_pts; ///< timestamps of wanted output frames
int64_t status_pts;
@@ -952,9 +954,6 @@ static int libplacebo_activate(AVFilterContext *ctx)
return ret;
if (ff_outlink_frame_wanted(outlink)) {
- struct pl_frame_mix mix;
- enum pl_queue_status ret;
-
if (s->fps.num) {
pts = outlink->frame_count_out;
} else if (av_fifo_peek(in->out_pts, &pts, 1, 0) < 0) {
@@ -972,20 +971,20 @@ static int libplacebo_activate(AVFilterContext *ctx)
return 0;
}
- ret = pl_queue_update(in->queue, &mix, pl_queue_params(
+ in->qstatus = pl_queue_update(in->queue, &in->mix, pl_queue_params(
.pts = pts * av_q2d(outlink->time_base),
.radius = pl_frame_mix_radius(&s->params),
.vsync_duration = av_q2d(av_inv_q(outlink->frame_rate)),
));
- switch (ret) {
+ switch (in->qstatus) {
case PL_QUEUE_MORE:
ff_inlink_request_frame(in->link);
return 0;
case PL_QUEUE_OK:
if (!s->fps.num)
av_fifo_drain2(in->out_pts, 1);
- return output_frame_mix(ctx, &mix, pts);
+ return output_frame_mix(ctx, &in->mix, pts);
case PL_QUEUE_ERR:
return AVERROR_EXTERNAL;
}
--
2.41.0
_______________________________________________
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".
^ permalink raw reply [flat|nested] 25+ messages in thread
* [FFmpeg-devel] [PATCH v2 06/22] lavif/vf_libplacebo: remove pl_frame_mix from output_frame_mix
2023-06-18 11:16 [FFmpeg-devel] lavfi/vf_libplacebo: generalize to multiple inputs Niklas Haas
` (4 preceding siblings ...)
2023-06-18 11:16 ` [FFmpeg-devel] [PATCH v2 05/22] lavfi/vf_libplacebo: move temporary vars into per-input struct Niklas Haas
@ 2023-06-18 11:16 ` Niklas Haas
2023-06-18 11:16 ` [FFmpeg-devel] [PATCH v2 07/22] lavfi/vf_libplacebo: factor out ref frame logic Niklas Haas
` (16 subsequent siblings)
22 siblings, 0 replies; 25+ messages in thread
From: Niklas Haas @ 2023-06-18 11:16 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
Instead, rename this function to `output_frame` and make it pull the
`pl_frame_mix` from the input structure. Step towards handling multiple
inputs.
---
libavfilter/vf_libplacebo.c | 23 +++++++++++------------
1 file changed, 11 insertions(+), 12 deletions(-)
diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c
index 4baa766bacf..0289187b46b 100644
--- a/libavfilter/vf_libplacebo.c
+++ b/libavfilter/vf_libplacebo.c
@@ -760,20 +760,19 @@ static void update_crops(AVFilterContext *ctx,
}
}
-/* Construct and emit an output frame for a given frame mix */
-static int output_frame_mix(AVFilterContext *ctx,
- struct pl_frame_mix *mix,
- int64_t pts)
+/* Construct and emit an output frame for a given timestamp */
+static int output_frame(AVFilterContext *ctx, int64_t pts)
{
int err = 0, ok, changed_csp;
LibplaceboContext *s = ctx->priv;
+ LibplaceboInput *in = &s->input;
AVFilterLink *outlink = ctx->outputs[0];
const AVPixFmtDescriptor *outdesc = av_pix_fmt_desc_get(outlink->format);
struct pl_frame target;
const AVFrame *ref;
AVFrame *out;
uint64_t ref_sig;
- if (!mix->num_frames)
+ if (!in->mix.num_frames)
return 0;
out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
@@ -781,11 +780,11 @@ static int output_frame_mix(AVFilterContext *ctx,
return AVERROR(ENOMEM);
/* Use the last frame before current PTS value as reference */
- for (int i = 0; i < mix->num_frames; i++) {
- if (i && mix->timestamps[i] > 0.0f)
+ for (int i = 0; i < in->mix.num_frames; i++) {
+ if (i && in->mix.timestamps[i] > 0.0f)
break;
- ref = pl_get_mapped_avframe(mix->frames[i]);
- ref_sig = mix->signatures[i];
+ ref = pl_get_mapped_avframe(in->mix.frames[i]);
+ ref_sig = in->mix.signatures[i];
}
RET(av_frame_copy_props(out, ref));
@@ -851,8 +850,8 @@ static int output_frame_mix(AVFilterContext *ctx,
goto fail;
}
- update_crops(ctx, mix, &target, ref_sig, out->pts * av_q2d(outlink->time_base));
- pl_render_image_mix(s->input.renderer, mix, &target, &s->params);
+ update_crops(ctx, &in->mix, &target, ref_sig, out->pts * av_q2d(outlink->time_base));
+ pl_render_image_mix(in->renderer, &in->mix, &target, &s->params);
if (outdesc->flags & AV_PIX_FMT_FLAG_HWACCEL) {
pl_unmap_avframe(s->gpu, &target);
@@ -984,7 +983,7 @@ static int libplacebo_activate(AVFilterContext *ctx)
case PL_QUEUE_OK:
if (!s->fps.num)
av_fifo_drain2(in->out_pts, 1);
- return output_frame_mix(ctx, &in->mix, pts);
+ return output_frame(ctx, pts);
case PL_QUEUE_ERR:
return AVERROR_EXTERNAL;
}
--
2.41.0
_______________________________________________
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".
^ permalink raw reply [flat|nested] 25+ messages in thread
* [FFmpeg-devel] [PATCH v2 07/22] lavfi/vf_libplacebo: factor out ref frame logic
2023-06-18 11:16 [FFmpeg-devel] lavfi/vf_libplacebo: generalize to multiple inputs Niklas Haas
` (5 preceding siblings ...)
2023-06-18 11:16 ` [FFmpeg-devel] [PATCH v2 06/22] lavif/vf_libplacebo: remove pl_frame_mix from output_frame_mix Niklas Haas
@ 2023-06-18 11:16 ` Niklas Haas
2023-06-18 11:17 ` [FFmpeg-devel] [PATCH v2 08/22] lavfi/vf_libplacebo: use correct link in update_crops() Niklas Haas
` (15 subsequent siblings)
22 siblings, 0 replies; 25+ messages in thread
From: Niklas Haas @ 2023-06-18 11:16 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
Instead of finding the ref frame in output_frame() and then passing its
signature to update_crops(), pull out the logic and invoke it a second
time inside update_crops().
This may seem wasteful at present, but will actually become required in
the future, since update_crops() runs on *every* input, and needs values
specific to that input (which the signature isn't), while output_frame()
is only interested in a single input. It's much easier to just split the
logic cleanly.
---
libavfilter/vf_libplacebo.c | 29 +++++++++++++++--------------
1 file changed, 15 insertions(+), 14 deletions(-)
diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c
index 0289187b46b..b83df24a84b 100644
--- a/libavfilter/vf_libplacebo.c
+++ b/libavfilter/vf_libplacebo.c
@@ -706,11 +706,21 @@ fail:
return err;
}
+static const AVFrame *ref_frame(const struct pl_frame_mix *mix)
+{
+ for (int i = 0; i < mix->num_frames; i++) {
+ if (i+1 == mix->num_frames || mix->timestamps[i+1] > 0)
+ return pl_get_mapped_avframe(mix->frames[i]);
+ }
+ return NULL;
+}
+
static void update_crops(AVFilterContext *ctx,
struct pl_frame_mix *mix, struct pl_frame *target,
- uint64_t ref_sig, double target_pts)
+ double target_pts)
{
LibplaceboContext *s = ctx->priv;
+ const AVFrame *ref = ref_frame(mix);
for (int i = 0; i < mix->num_frames; i++) {
// Mutate the `pl_frame.crop` fields in-place. This is fine because we
@@ -745,7 +755,7 @@ static void update_crops(AVFilterContext *ctx,
image->crop.x1 = image->crop.x0 + s->var_values[VAR_CROP_W];
image->crop.y1 = image->crop.y0 + s->var_values[VAR_CROP_H];
- if (mix->signatures[i] == ref_sig) {
+ if (src == ref) {
/* Only update the target crop once, for the 'reference' frame */
target->crop.x0 = av_expr_eval(s->pos_x_pexpr, s->var_values, NULL);
target->crop.y0 = av_expr_eval(s->pos_y_pexpr, s->var_values, NULL);
@@ -768,25 +778,16 @@ static int output_frame(AVFilterContext *ctx, int64_t pts)
LibplaceboInput *in = &s->input;
AVFilterLink *outlink = ctx->outputs[0];
const AVPixFmtDescriptor *outdesc = av_pix_fmt_desc_get(outlink->format);
+ const AVFrame *ref = ref_frame(&in->mix);
struct pl_frame target;
- const AVFrame *ref;
AVFrame *out;
- uint64_t ref_sig;
- if (!in->mix.num_frames)
+ if (!ref)
return 0;
out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
if (!out)
return AVERROR(ENOMEM);
- /* Use the last frame before current PTS value as reference */
- for (int i = 0; i < in->mix.num_frames; i++) {
- if (i && in->mix.timestamps[i] > 0.0f)
- break;
- ref = pl_get_mapped_avframe(in->mix.frames[i]);
- ref_sig = in->mix.signatures[i];
- }
-
RET(av_frame_copy_props(out, ref));
out->pts = pts;
out->width = outlink->w;
@@ -850,7 +851,7 @@ static int output_frame(AVFilterContext *ctx, int64_t pts)
goto fail;
}
- update_crops(ctx, &in->mix, &target, ref_sig, out->pts * av_q2d(outlink->time_base));
+ update_crops(ctx, &in->mix, &target, out->pts * av_q2d(outlink->time_base));
pl_render_image_mix(in->renderer, &in->mix, &target, &s->params);
if (outdesc->flags & AV_PIX_FMT_FLAG_HWACCEL) {
--
2.41.0
_______________________________________________
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".
^ permalink raw reply [flat|nested] 25+ messages in thread
* [FFmpeg-devel] [PATCH v2 08/22] lavfi/vf_libplacebo: use correct link in update_crops()
2023-06-18 11:16 [FFmpeg-devel] lavfi/vf_libplacebo: generalize to multiple inputs Niklas Haas
` (6 preceding siblings ...)
2023-06-18 11:16 ` [FFmpeg-devel] [PATCH v2 07/22] lavfi/vf_libplacebo: factor out ref frame logic Niklas Haas
@ 2023-06-18 11:17 ` Niklas Haas
2023-06-18 11:17 ` [FFmpeg-devel] [PATCH v2 09/22] lavfi/vf_libplacebo: replace s->input by dynamic array Niklas Haas
` (14 subsequent siblings)
22 siblings, 0 replies; 25+ messages in thread
From: Niklas Haas @ 2023-06-18 11:17 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
Instead of hard-coding input 0, pass the per-input structure and use the
link contained inside it.
---
libavfilter/vf_libplacebo.c | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c
index b83df24a84b..408fb3918aa 100644
--- a/libavfilter/vf_libplacebo.c
+++ b/libavfilter/vf_libplacebo.c
@@ -715,19 +715,18 @@ static const AVFrame *ref_frame(const struct pl_frame_mix *mix)
return NULL;
}
-static void update_crops(AVFilterContext *ctx,
- struct pl_frame_mix *mix, struct pl_frame *target,
- double target_pts)
+static void update_crops(AVFilterContext *ctx, LibplaceboInput *in,
+ struct pl_frame *target, double target_pts)
{
LibplaceboContext *s = ctx->priv;
- const AVFrame *ref = ref_frame(mix);
+ const AVFrame *ref = ref_frame(&in->mix);
- for (int i = 0; i < mix->num_frames; i++) {
+ for (int i = 0; i < in->mix.num_frames; i++) {
// Mutate the `pl_frame.crop` fields in-place. This is fine because we
// own the entire pl_queue, and hence, the pointed-at frames.
- struct pl_frame *image = (struct pl_frame *) mix->frames[i];
+ struct pl_frame *image = (struct pl_frame *) in->mix.frames[i];
const AVFrame *src = pl_get_mapped_avframe(image);
- double image_pts = src->pts * av_q2d(ctx->inputs[0]->time_base);
+ double image_pts = src->pts * av_q2d(in->link->time_base);
/* Update dynamic variables */
s->var_values[VAR_IN_T] = s->var_values[VAR_T] = image_pts;
@@ -851,7 +850,7 @@ static int output_frame(AVFilterContext *ctx, int64_t pts)
goto fail;
}
- update_crops(ctx, &in->mix, &target, out->pts * av_q2d(outlink->time_base));
+ update_crops(ctx, in, &target, out->pts * av_q2d(outlink->time_base));
pl_render_image_mix(in->renderer, &in->mix, &target, &s->params);
if (outdesc->flags & AV_PIX_FMT_FLAG_HWACCEL) {
--
2.41.0
_______________________________________________
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".
^ permalink raw reply [flat|nested] 25+ messages in thread
* [FFmpeg-devel] [PATCH v2 09/22] lavfi/vf_libplacebo: replace s->input by dynamic array
2023-06-18 11:16 [FFmpeg-devel] lavfi/vf_libplacebo: generalize to multiple inputs Niklas Haas
` (7 preceding siblings ...)
2023-06-18 11:17 ` [FFmpeg-devel] [PATCH v2 08/22] lavfi/vf_libplacebo: use correct link in update_crops() Niklas Haas
@ 2023-06-18 11:17 ` Niklas Haas
2023-06-18 11:17 ` [FFmpeg-devel] [PATCH v2 10/22] lavfi/vf_libplacebo: keep track of latest status globally Niklas Haas
` (13 subsequent siblings)
22 siblings, 0 replies; 25+ messages in thread
From: Niklas Haas @ 2023-06-18 11:17 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
For now, hard-coded to 1 element.
---
libavfilter/vf_libplacebo.c | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)
diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c
index 408fb3918aa..ee8780036cf 100644
--- a/libavfilter/vf_libplacebo.c
+++ b/libavfilter/vf_libplacebo.c
@@ -136,7 +136,8 @@ typedef struct LibplaceboContext {
pl_tex tex[4];
/* input state */
- LibplaceboInput input;
+ LibplaceboInput *inputs;
+ int nb_inputs;
/* settings */
char *out_format_string;
@@ -660,7 +661,12 @@ static int init_vulkan(AVFilterContext *avctx, const AVVulkanDeviceContext *hwct
}
/* Initialize inputs */
- RET(input_init(avctx, avctx->inputs[0], &s->input));
+ s->nb_inputs = 1;
+ s->inputs = av_calloc(s->nb_inputs, sizeof(*s->inputs));
+ if (!s->inputs)
+ return AVERROR(ENOMEM);
+ for (int i = 0; i < s->nb_inputs; i++)
+ RET(input_init(avctx, avctx->inputs[i], &s->inputs[i]));
/* fall through */
fail:
@@ -677,7 +683,11 @@ static void libplacebo_uninit(AVFilterContext *avctx)
pl_tex_destroy(s->gpu, &s->tex[i]);
for (int i = 0; i < s->num_hooks; i++)
pl_mpv_user_shader_destroy(&s->hooks[i]);
- input_uninit(&s->input);
+ if (s->inputs) {
+ for (int i = 0; i < s->nb_inputs; i++)
+ input_uninit(&s->inputs[i]);
+ av_freep(&s->inputs);
+ }
pl_vulkan_destroy(&s->vulkan);
pl_log_destroy(&s->log);
ff_vk_uninit(&s->vkctx);
@@ -774,7 +784,7 @@ static int output_frame(AVFilterContext *ctx, int64_t pts)
{
int err = 0, ok, changed_csp;
LibplaceboContext *s = ctx->priv;
- LibplaceboInput *in = &s->input;
+ LibplaceboInput *in = &s->inputs[0];
AVFilterLink *outlink = ctx->outputs[0];
const AVPixFmtDescriptor *outdesc = av_pix_fmt_desc_get(outlink->format);
const AVFrame *ref = ref_frame(&in->mix);
@@ -942,7 +952,7 @@ static int libplacebo_activate(AVFilterContext *ctx)
{
int ret;
LibplaceboContext *s = ctx->priv;
- LibplaceboInput *in = &s->input;
+ LibplaceboInput *in = &s->inputs[0];
AVFilterLink *outlink = ctx->outputs[0];
int64_t pts;
--
2.41.0
_______________________________________________
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".
^ permalink raw reply [flat|nested] 25+ messages in thread
* [FFmpeg-devel] [PATCH v2 10/22] lavfi/vf_libplacebo: keep track of latest status globally
2023-06-18 11:16 [FFmpeg-devel] lavfi/vf_libplacebo: generalize to multiple inputs Niklas Haas
` (8 preceding siblings ...)
2023-06-18 11:17 ` [FFmpeg-devel] [PATCH v2 09/22] lavfi/vf_libplacebo: replace s->input by dynamic array Niklas Haas
@ 2023-06-18 11:17 ` Niklas Haas
2023-06-18 11:17 ` [FFmpeg-devel] [PATCH v2 11/22] lavfi/vf_libplacebo: support blending multiple inputs Niklas Haas
` (12 subsequent siblings)
22 siblings, 0 replies; 25+ messages in thread
From: Niklas Haas @ 2023-06-18 11:17 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
This field will effectively hold the most recent status set by any
input. Currently functionally equivalent to input->status, but will
change soon.
---
libavfilter/vf_libplacebo.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c
index ee8780036cf..5b45d4f8fb5 100644
--- a/libavfilter/vf_libplacebo.c
+++ b/libavfilter/vf_libplacebo.c
@@ -138,6 +138,8 @@ typedef struct LibplaceboContext {
/* input state */
LibplaceboInput *inputs;
int nb_inputs;
+ int64_t status_pts; ///< tracks status of most recently used input
+ int status;
/* settings */
char *out_format_string;
@@ -943,6 +945,11 @@ static int handle_input(AVFilterContext *ctx, LibplaceboInput *input)
pl_queue_push(input->queue, NULL); /* Signal EOF to pl_queue */
input->status = status;
input->status_pts = pts;
+ if (!s->status || pts >= s->status_pts) {
+ /* Also propagate to output unless overwritten by later status change */
+ s->status = status;
+ s->status_pts = pts;
+ }
}
return 0;
@@ -975,8 +982,8 @@ static int libplacebo_activate(AVFilterContext *ctx)
}
}
- if (in->status && pts >= in->status_pts) {
- ff_outlink_set_status(outlink, in->status, in->status_pts);
+ if (s->status && pts >= s->status_pts) {
+ ff_outlink_set_status(outlink, s->status, s->status_pts);
return 0;
}
--
2.41.0
_______________________________________________
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".
^ permalink raw reply [flat|nested] 25+ messages in thread
* [FFmpeg-devel] [PATCH v2 11/22] lavfi/vf_libplacebo: support blending multiple inputs
2023-06-18 11:16 [FFmpeg-devel] lavfi/vf_libplacebo: generalize to multiple inputs Niklas Haas
` (9 preceding siblings ...)
2023-06-18 11:17 ` [FFmpeg-devel] [PATCH v2 10/22] lavfi/vf_libplacebo: keep track of latest status globally Niklas Haas
@ 2023-06-18 11:17 ` Niklas Haas
2023-06-18 11:17 ` [FFmpeg-devel] [PATCH v2 12/22] lavfi/vf_libplacebo: handle " Niklas Haas
` (11 subsequent siblings)
22 siblings, 0 replies; 25+ messages in thread
From: Niklas Haas @ 2023-06-18 11:17 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
Subsequent inputs require frame blending to be enabled, in order to not
overwrite the existing frame contents.
For output metadata, we implicitly copy the metadata of the *first*
available stream (falling back to the second stream if the first has
already reached EOF, and so on). This is done to resolve any conflicts
between inputs with differing metadata. So when e.g. input 1 is HDR and
output 2 is SDR, the output will be HDR, and vice versa. This logic
could probablly be improved by dynamically determining some "superior"
set of metadata, but I don't want to handle that complexity in this
series.
---
libavfilter/vf_libplacebo.c | 24 ++++++++++++++++++++----
1 file changed, 20 insertions(+), 4 deletions(-)
diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c
index 5b45d4f8fb5..5ea6fcd7920 100644
--- a/libavfilter/vf_libplacebo.c
+++ b/libavfilter/vf_libplacebo.c
@@ -786,12 +786,18 @@ static int output_frame(AVFilterContext *ctx, int64_t pts)
{
int err = 0, ok, changed_csp;
LibplaceboContext *s = ctx->priv;
- LibplaceboInput *in = &s->inputs[0];
AVFilterLink *outlink = ctx->outputs[0];
const AVPixFmtDescriptor *outdesc = av_pix_fmt_desc_get(outlink->format);
- const AVFrame *ref = ref_frame(&in->mix);
struct pl_frame target;
+ const AVFrame *ref = NULL;
AVFrame *out;
+
+ /* Use the first active input as metadata reference */
+ for (int i = 0; i < s->nb_inputs; i++) {
+ const LibplaceboInput *in = &s->inputs[i];
+ if (in->qstatus == PL_QUEUE_OK && (ref = ref_frame(&in->mix)))
+ break;
+ }
if (!ref)
return 0;
@@ -862,8 +868,18 @@ static int output_frame(AVFilterContext *ctx, int64_t pts)
goto fail;
}
- update_crops(ctx, in, &target, out->pts * av_q2d(outlink->time_base));
- pl_render_image_mix(in->renderer, &in->mix, &target, &s->params);
+ /* Draw first frame opaque, others with blending */
+ s->params.skip_target_clearing = false;
+ s->params.blend_params = NULL;
+ for (int i = 0; i < s->nb_inputs; i++) {
+ LibplaceboInput *in = &s->inputs[i];
+ if (in->qstatus != PL_QUEUE_OK)
+ continue;
+ update_crops(ctx, in, &target, out->pts * av_q2d(outlink->time_base));
+ pl_render_image_mix(in->renderer, &in->mix, &target, &s->params);
+ s->params.skip_target_clearing = true;
+ s->params.blend_params = &pl_alpha_overlay;
+ }
if (outdesc->flags & AV_PIX_FMT_FLAG_HWACCEL) {
pl_unmap_avframe(s->gpu, &target);
--
2.41.0
_______________________________________________
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".
^ permalink raw reply [flat|nested] 25+ messages in thread
* [FFmpeg-devel] [PATCH v2 12/22] lavfi/vf_libplacebo: handle multiple inputs
2023-06-18 11:16 [FFmpeg-devel] lavfi/vf_libplacebo: generalize to multiple inputs Niklas Haas
` (10 preceding siblings ...)
2023-06-18 11:17 ` [FFmpeg-devel] [PATCH v2 11/22] lavfi/vf_libplacebo: support blending multiple inputs Niklas Haas
@ 2023-06-18 11:17 ` Niklas Haas
2023-06-18 11:17 ` [FFmpeg-devel] [PATCH v2 13/22] lavfi/vf_libplacebo: determine PTS of next frame from any input Niklas Haas
` (10 subsequent siblings)
22 siblings, 0 replies; 25+ messages in thread
From: Niklas Haas @ 2023-06-18 11:17 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
This commit still relies on a single input for PTS determination, to be
changed in the next commit.
---
libavfilter/vf_libplacebo.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c
index 5ea6fcd7920..a56ebbf54e7 100644
--- a/libavfilter/vf_libplacebo.c
+++ b/libavfilter/vf_libplacebo.c
@@ -979,11 +979,13 @@ static int libplacebo_activate(AVFilterContext *ctx)
AVFilterLink *outlink = ctx->outputs[0];
int64_t pts;
- FF_FILTER_FORWARD_STATUS_BACK(outlink, in->link);
+ FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, ctx);
pl_log_level_update(s->log, get_log_level());
- if ((ret = handle_input(ctx, in)) < 0)
- return ret;
+ for (int i = 0; i < s->nb_inputs; i++) {
+ if ((ret = handle_input(ctx, &s->inputs[i])) < 0)
+ return ret;
+ }
if (ff_outlink_frame_wanted(outlink)) {
if (s->fps.num) {
--
2.41.0
_______________________________________________
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".
^ permalink raw reply [flat|nested] 25+ messages in thread
* [FFmpeg-devel] [PATCH v2 13/22] lavfi/vf_libplacebo: determine PTS of next frame from any input
2023-06-18 11:16 [FFmpeg-devel] lavfi/vf_libplacebo: generalize to multiple inputs Niklas Haas
` (11 preceding siblings ...)
2023-06-18 11:17 ` [FFmpeg-devel] [PATCH v2 12/22] lavfi/vf_libplacebo: handle " Niklas Haas
@ 2023-06-18 11:17 ` Niklas Haas
2023-06-18 11:17 ` [FFmpeg-devel] [PATCH v2 14/22] lavfi/vf_libplacebo: only drain actually used PTS Niklas Haas
` (9 subsequent siblings)
22 siblings, 0 replies; 25+ messages in thread
From: Niklas Haas @ 2023-06-18 11:17 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
When combining multiple inputs with different PTS and durations, in
input-timed mode, we emit one output frame for every input frame PTS,
from *any* input. So when combining a low FPS stream with a high FPS
stream, the output framerate would match the higher FPS, independent of
which order they are specified in.
---
libavfilter/vf_libplacebo.c | 33 ++++++++++++++++++++-------------
1 file changed, 20 insertions(+), 13 deletions(-)
diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c
index a56ebbf54e7..47f019fa192 100644
--- a/libavfilter/vf_libplacebo.c
+++ b/libavfilter/vf_libplacebo.c
@@ -973,11 +973,11 @@ static int handle_input(AVFilterContext *ctx, LibplaceboInput *input)
static int libplacebo_activate(AVFilterContext *ctx)
{
- int ret;
+ int ret, retry = 0;
LibplaceboContext *s = ctx->priv;
LibplaceboInput *in = &s->inputs[0];
AVFilterLink *outlink = ctx->outputs[0];
- int64_t pts;
+ int64_t pts, out_pts;
FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, ctx);
pl_log_level_update(s->log, get_log_level());
@@ -989,24 +989,31 @@ static int libplacebo_activate(AVFilterContext *ctx)
if (ff_outlink_frame_wanted(outlink)) {
if (s->fps.num) {
- pts = outlink->frame_count_out;
- } else if (av_fifo_peek(in->out_pts, &pts, 1, 0) < 0) {
- /* No frames queued */
- if (in->status) {
- pts = in->status_pts;
- } else {
- ff_inlink_request_frame(in->link);
- return 0;
+ out_pts = outlink->frame_count_out;
+ } else {
+ /* Determine the PTS of the next frame from any active input */
+ out_pts = INT64_MAX;
+ for (int i = 0; i < s->nb_inputs; i++) {
+ LibplaceboInput *in = &s->inputs[i];
+ if (av_fifo_peek(in->out_pts, &pts, 1, 0) >= 0) {
+ out_pts = FFMIN(out_pts, pts);
+ } else if (!in->status) {
+ ff_inlink_request_frame(in->link);
+ retry = true;
+ }
}
+
+ if (retry) /* some inputs are incomplete */
+ return 0;
}
- if (s->status && pts >= s->status_pts) {
+ if (s->status && out_pts >= s->status_pts) {
ff_outlink_set_status(outlink, s->status, s->status_pts);
return 0;
}
in->qstatus = pl_queue_update(in->queue, &in->mix, pl_queue_params(
- .pts = pts * av_q2d(outlink->time_base),
+ .pts = out_pts * av_q2d(outlink->time_base),
.radius = pl_frame_mix_radius(&s->params),
.vsync_duration = av_q2d(av_inv_q(outlink->frame_rate)),
));
@@ -1018,7 +1025,7 @@ static int libplacebo_activate(AVFilterContext *ctx)
case PL_QUEUE_OK:
if (!s->fps.num)
av_fifo_drain2(in->out_pts, 1);
- return output_frame(ctx, pts);
+ return output_frame(ctx, out_pts);
case PL_QUEUE_ERR:
return AVERROR_EXTERNAL;
}
--
2.41.0
_______________________________________________
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".
^ permalink raw reply [flat|nested] 25+ messages in thread
* [FFmpeg-devel] [PATCH v2 14/22] lavfi/vf_libplacebo: only drain actually used PTS
2023-06-18 11:16 [FFmpeg-devel] lavfi/vf_libplacebo: generalize to multiple inputs Niklas Haas
` (12 preceding siblings ...)
2023-06-18 11:17 ` [FFmpeg-devel] [PATCH v2 13/22] lavfi/vf_libplacebo: determine PTS of next frame from any input Niklas Haas
@ 2023-06-18 11:17 ` Niklas Haas
2023-06-18 11:17 ` [FFmpeg-devel] [PATCH v2 15/22] lavfi/vf_libplacebo: generalize frame update to multiple inputs Niklas Haas
` (8 subsequent siblings)
22 siblings, 0 replies; 25+ messages in thread
From: Niklas Haas @ 2023-06-18 11:17 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
When combining multiple inputs, the output PTS may be less than the PTS
of the input. In this case, the current's code assumption of always
draining one value from the FIFO is incorrect. Replace by a smarter
function which drains only those PTS values that were actually consumed.
---
libavfilter/vf_libplacebo.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c
index 47f019fa192..753d6f3cc79 100644
--- a/libavfilter/vf_libplacebo.c
+++ b/libavfilter/vf_libplacebo.c
@@ -971,6 +971,13 @@ static int handle_input(AVFilterContext *ctx, LibplaceboInput *input)
return 0;
}
+static void drain_input_pts(LibplaceboInput *in, int64_t until)
+{
+ int64_t pts;
+ while (av_fifo_peek(in->out_pts, &pts, 1, 0) >= 0 && pts <= until)
+ av_fifo_drain2(in->out_pts, 1);
+}
+
static int libplacebo_activate(AVFilterContext *ctx)
{
int ret, retry = 0;
@@ -1023,8 +1030,7 @@ static int libplacebo_activate(AVFilterContext *ctx)
ff_inlink_request_frame(in->link);
return 0;
case PL_QUEUE_OK:
- if (!s->fps.num)
- av_fifo_drain2(in->out_pts, 1);
+ drain_input_pts(in, out_pts);
return output_frame(ctx, out_pts);
case PL_QUEUE_ERR:
return AVERROR_EXTERNAL;
--
2.41.0
_______________________________________________
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".
^ permalink raw reply [flat|nested] 25+ messages in thread
* [FFmpeg-devel] [PATCH v2 15/22] lavfi/vf_libplacebo: generalize frame update to multiple inputs
2023-06-18 11:16 [FFmpeg-devel] lavfi/vf_libplacebo: generalize to multiple inputs Niklas Haas
` (13 preceding siblings ...)
2023-06-18 11:17 ` [FFmpeg-devel] [PATCH v2 14/22] lavfi/vf_libplacebo: only drain actually used PTS Niklas Haas
@ 2023-06-18 11:17 ` Niklas Haas
2023-06-18 11:17 ` [FFmpeg-devel] [PATCH v2 16/22] lavfi/vf_libplacebo: make input-dependent vars dynamic Niklas Haas
` (7 subsequent siblings)
22 siblings, 0 replies; 25+ messages in thread
From: Niklas Haas @ 2023-06-18 11:17 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
In the event that some frame mixes are OK while others are not, the
priority goes:
1. Errors in updating any frame -> return error
2. Any input incomplete -> request frames and return
3. Any inputs OK -> ignore EOF streams and render remaining inputs
4. No inputs OK -> set output to most recent status
This logic ensures that we can continue rendering the remaining streams,
no matter which streams reach their end of life, until we have no
streams left at which point we forward the last EOF.
---
libavfilter/vf_libplacebo.c | 52 ++++++++++++++++++++++++-------------
1 file changed, 34 insertions(+), 18 deletions(-)
diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c
index 753d6f3cc79..6399aae0c67 100644
--- a/libavfilter/vf_libplacebo.c
+++ b/libavfilter/vf_libplacebo.c
@@ -980,9 +980,8 @@ static void drain_input_pts(LibplaceboInput *in, int64_t until)
static int libplacebo_activate(AVFilterContext *ctx)
{
- int ret, retry = 0;
+ int ret, ok = 0, retry = 0;
LibplaceboContext *s = ctx->priv;
- LibplaceboInput *in = &s->inputs[0];
AVFilterLink *outlink = ctx->outputs[0];
int64_t pts, out_pts;
@@ -1014,26 +1013,43 @@ static int libplacebo_activate(AVFilterContext *ctx)
return 0;
}
- if (s->status && out_pts >= s->status_pts) {
- ff_outlink_set_status(outlink, s->status, s->status_pts);
- return 0;
- }
+ /* Update all input queues to the chosen out_pts */
+ for (int i = 0; i < s->nb_inputs; i++) {
+ LibplaceboInput *in = &s->inputs[i];
+ if (in->status && out_pts >= in->status_pts) {
+ in->qstatus = PL_QUEUE_EOF;
+ continue;
+ }
- in->qstatus = pl_queue_update(in->queue, &in->mix, pl_queue_params(
- .pts = out_pts * av_q2d(outlink->time_base),
- .radius = pl_frame_mix_radius(&s->params),
- .vsync_duration = av_q2d(av_inv_q(outlink->frame_rate)),
- ));
+ in->qstatus = pl_queue_update(in->queue, &in->mix, pl_queue_params(
+ .pts = out_pts * av_q2d(outlink->time_base),
+ .radius = pl_frame_mix_radius(&s->params),
+ .vsync_duration = av_q2d(av_inv_q(outlink->frame_rate)),
+ ));
+
+ switch (in->qstatus) {
+ case PL_QUEUE_MORE:
+ ff_inlink_request_frame(in->link);
+ retry = true;
+ break;
+ case PL_QUEUE_OK:
+ ok = true;
+ break;
+ case PL_QUEUE_ERR:
+ return AVERROR_EXTERNAL;
+ }
+ }
- switch (in->qstatus) {
- case PL_QUEUE_MORE:
- ff_inlink_request_frame(in->link);
+ if (retry) {
return 0;
- case PL_QUEUE_OK:
- drain_input_pts(in, out_pts);
+ } else if (ok) {
+ /* Got any valid frame mixes, drain PTS queue and render output */
+ for (int i = 0; i < s->nb_inputs; i++)
+ drain_input_pts(&s->inputs[i], out_pts);
return output_frame(ctx, out_pts);
- case PL_QUEUE_ERR:
- return AVERROR_EXTERNAL;
+ } else if (s->status) {
+ ff_outlink_set_status(outlink, s->status, s->status_pts);
+ return 0;
}
return AVERROR_BUG;
--
2.41.0
_______________________________________________
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".
^ permalink raw reply [flat|nested] 25+ messages in thread
* [FFmpeg-devel] [PATCH v2 16/22] lavfi/vf_libplacebo: make input-dependent vars dynamic
2023-06-18 11:16 [FFmpeg-devel] lavfi/vf_libplacebo: generalize to multiple inputs Niklas Haas
` (14 preceding siblings ...)
2023-06-18 11:17 ` [FFmpeg-devel] [PATCH v2 15/22] lavfi/vf_libplacebo: generalize frame update to multiple inputs Niklas Haas
@ 2023-06-18 11:17 ` Niklas Haas
2023-06-18 11:17 ` [FFmpeg-devel] [PATCH v2 17/22] lavfi/vf_libplacebo: add in_idx variable Niklas Haas
` (6 subsequent siblings)
22 siblings, 0 replies; 25+ messages in thread
From: Niklas Haas @ 2023-06-18 11:17 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
Because these can differ based on the input, for multiple inputs.
---
libavfilter/vf_libplacebo.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c
index 6399aae0c67..a3a034766e2 100644
--- a/libavfilter/vf_libplacebo.c
+++ b/libavfilter/vf_libplacebo.c
@@ -741,6 +741,11 @@ static void update_crops(AVFilterContext *ctx, LibplaceboInput *in,
double image_pts = src->pts * av_q2d(in->link->time_base);
/* Update dynamic variables */
+ s->var_values[VAR_IN_W] = s->var_values[VAR_IW] = in->link->w;
+ s->var_values[VAR_IN_H] = s->var_values[VAR_IH] = in->link->h;
+ s->var_values[VAR_A] = (double) in->link->w / in->link->h;
+ s->var_values[VAR_SAR] = in->link->sample_aspect_ratio.num ?
+ av_q2d(in->link->sample_aspect_ratio) : 1.0;
s->var_values[VAR_IN_T] = s->var_values[VAR_T] = image_pts;
s->var_values[VAR_OUT_T] = s->var_values[VAR_OT] = target_pts;
s->var_values[VAR_N] = ctx->outputs[0]->frame_count_out;
@@ -1193,13 +1198,8 @@ static int libplacebo_config_output(AVFilterLink *outlink)
}
/* 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;
s->var_values[VAR_OUT_W] = s->var_values[VAR_OW] = outlink->w;
s->var_values[VAR_OUT_H] = s->var_values[VAR_OH] = outlink->h;
- s->var_values[VAR_A] = (double) inlink->w / inlink->h;
- s->var_values[VAR_SAR] = inlink->sample_aspect_ratio.num ?
- av_q2d(inlink->sample_aspect_ratio) : 1.0;
s->var_values[VAR_DAR] = outlink->sample_aspect_ratio.num ?
av_q2d(outlink->sample_aspect_ratio) : 1.0;
s->var_values[VAR_HSUB] = 1 << desc->log2_chroma_w;
--
2.41.0
_______________________________________________
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".
^ permalink raw reply [flat|nested] 25+ messages in thread
* [FFmpeg-devel] [PATCH v2 17/22] lavfi/vf_libplacebo: add in_idx variable
2023-06-18 11:16 [FFmpeg-devel] lavfi/vf_libplacebo: generalize to multiple inputs Niklas Haas
` (15 preceding siblings ...)
2023-06-18 11:17 ` [FFmpeg-devel] [PATCH v2 16/22] lavfi/vf_libplacebo: make input-dependent vars dynamic Niklas Haas
@ 2023-06-18 11:17 ` Niklas Haas
2023-06-18 11:17 ` [FFmpeg-devel] [PATCH v2 18/22] lavfi/vf_libplacebo: set format list for all inputs Niklas Haas
` (5 subsequent siblings)
22 siblings, 0 replies; 25+ messages in thread
From: Niklas Haas @ 2023-06-18 11:17 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
To allow placing an input dynamically, as a function of the input index.
---
doc/filters.texi | 2 ++
libavfilter/vf_libplacebo.c | 9 +++++++--
2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/doc/filters.texi b/doc/filters.texi
index 5e25cf293e5..cf17930b014 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -16249,6 +16249,8 @@ the @option{crop_w}, @option{crop_h}, @option{crop_x}, @option{crop_y},
also contain the following constants:
@table @option
+@item in_idx, idx
+The (0-based) numeric index of the currently active input stream.
@item crop_w, cw
@item crop_h, ch
The computed values of @option{crop_w} and @option{crop_h}.
diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c
index a3a034766e2..fcd3ad07e2c 100644
--- a/libavfilter/vf_libplacebo.c
+++ b/libavfilter/vf_libplacebo.c
@@ -70,6 +70,7 @@ enum {
};
static const char *const var_names[] = {
+ "in_idx", "idx",///< index of input
"in_w", "iw", ///< width of the input video frame
"in_h", "ih", ///< height of the input video frame
"out_w", "ow", ///< width of the output video frame
@@ -92,6 +93,7 @@ static const char *const var_names[] = {
};
enum var_name {
+ VAR_IN_IDX, VAR_IDX,
VAR_IN_W, VAR_IW,
VAR_IN_H, VAR_IH,
VAR_OUT_W, VAR_OW,
@@ -115,6 +117,7 @@ enum var_name {
/* per-input dynamic filter state */
typedef struct LibplaceboInput {
+ int idx;
pl_renderer renderer;
pl_queue queue;
enum pl_queue_status qstatus;
@@ -574,7 +577,7 @@ static void unlock_queue(void *priv, uint32_t qf, uint32_t qidx)
#endif
static int input_init(AVFilterContext *avctx, AVFilterLink *link,
- LibplaceboInput *input)
+ LibplaceboInput *input, int idx)
{
LibplaceboContext *s = avctx->priv;
@@ -584,6 +587,7 @@ static int input_init(AVFilterContext *avctx, AVFilterLink *link,
input->queue = pl_queue_create(s->gpu);
input->renderer = pl_renderer_create(s->log, s->gpu);
input->link = link;
+ input->idx = idx;
return 0;
}
@@ -668,7 +672,7 @@ static int init_vulkan(AVFilterContext *avctx, const AVVulkanDeviceContext *hwct
if (!s->inputs)
return AVERROR(ENOMEM);
for (int i = 0; i < s->nb_inputs; i++)
- RET(input_init(avctx, avctx->inputs[i], &s->inputs[i]));
+ RET(input_init(avctx, avctx->inputs[i], &s->inputs[i], i));
/* fall through */
fail:
@@ -741,6 +745,7 @@ static void update_crops(AVFilterContext *ctx, LibplaceboInput *in,
double image_pts = src->pts * av_q2d(in->link->time_base);
/* Update dynamic variables */
+ s->var_values[VAR_IN_IDX] = s->var_values[VAR_IDX] = in->idx;
s->var_values[VAR_IN_W] = s->var_values[VAR_IW] = in->link->w;
s->var_values[VAR_IN_H] = s->var_values[VAR_IH] = in->link->h;
s->var_values[VAR_A] = (double) in->link->w / in->link->h;
--
2.41.0
_______________________________________________
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".
^ permalink raw reply [flat|nested] 25+ messages in thread
* [FFmpeg-devel] [PATCH v2 18/22] lavfi/vf_libplacebo: set format list for all inputs
2023-06-18 11:16 [FFmpeg-devel] lavfi/vf_libplacebo: generalize to multiple inputs Niklas Haas
` (16 preceding siblings ...)
2023-06-18 11:17 ` [FFmpeg-devel] [PATCH v2 17/22] lavfi/vf_libplacebo: add in_idx variable Niklas Haas
@ 2023-06-18 11:17 ` Niklas Haas
2023-06-18 11:17 ` [FFmpeg-devel] [PATCH v2 19/22] lavfi/vf_libplacebo: skip cache selectively per-input Niklas Haas
` (4 subsequent siblings)
22 siblings, 0 replies; 25+ messages in thread
From: Niklas Haas @ 2023-06-18 11:17 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
---
libavfilter/vf_libplacebo.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c
index fcd3ad07e2c..627223256c6 100644
--- a/libavfilter/vf_libplacebo.c
+++ b/libavfilter/vf_libplacebo.c
@@ -1131,7 +1131,8 @@ static int libplacebo_query_format(AVFilterContext *ctx)
goto fail;
}
- RET(ff_formats_ref(infmts, &ctx->inputs[0]->outcfg.formats));
+ for (int i = 0; i < s->nb_inputs; i++)
+ RET(ff_formats_ref(infmts, &ctx->inputs[i]->outcfg.formats));
RET(ff_formats_ref(outfmts, &ctx->outputs[0]->incfg.formats));
return 0;
--
2.41.0
_______________________________________________
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".
^ permalink raw reply [flat|nested] 25+ messages in thread
* [FFmpeg-devel] [PATCH v2 19/22] lavfi/vf_libplacebo: skip cache selectively per-input
2023-06-18 11:16 [FFmpeg-devel] lavfi/vf_libplacebo: generalize to multiple inputs Niklas Haas
` (17 preceding siblings ...)
2023-06-18 11:17 ` [FFmpeg-devel] [PATCH v2 18/22] lavfi/vf_libplacebo: set format list for all inputs Niklas Haas
@ 2023-06-18 11:17 ` Niklas Haas
2023-06-18 11:17 ` [FFmpeg-devel] [PATCH v2 20/22] lavfi/vf_libplacebo: also skip cache if in FPS == out FPS Niklas Haas
` (3 subsequent siblings)
22 siblings, 0 replies; 25+ messages in thread
From: Niklas Haas @ 2023-06-18 11:17 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
It may be the case that we want to skip the single frame cache for some
inputs but not others.
---
libavfilter/vf_libplacebo.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c
index 627223256c6..f7b9bdba742 100644
--- a/libavfilter/vf_libplacebo.c
+++ b/libavfilter/vf_libplacebo.c
@@ -182,7 +182,6 @@ typedef struct LibplaceboContext {
float antiringing;
int sigmoid;
int skip_aa;
- int skip_cache;
float polar_cutoff;
int disable_linear;
int disable_builtin;
@@ -471,7 +470,6 @@ static int update_settings(AVFilterContext *ctx)
.num_hooks = s->num_hooks,
.skip_anti_aliasing = s->skip_aa,
- .skip_caching_single_frame = s->skip_cache,
.polar_cutoff = s->polar_cutoff,
.disable_linear_scaling = s->disable_linear,
.disable_builtin_scalers = s->disable_builtin,
@@ -883,8 +881,10 @@ static int output_frame(AVFilterContext *ctx, int64_t pts)
s->params.blend_params = NULL;
for (int i = 0; i < s->nb_inputs; i++) {
LibplaceboInput *in = &s->inputs[i];
+ int high_fps = av_cmp_q(in->link->frame_rate, outlink->frame_rate) > 0;
if (in->qstatus != PL_QUEUE_OK)
continue;
+ s->params.skip_caching_single_frame = high_fps;
update_crops(ctx, in, &target, out->pts * av_q2d(outlink->time_base));
pl_render_image_mix(in->renderer, &in->mix, &target, &s->params);
s->params.skip_target_clearing = true;
@@ -1198,9 +1198,6 @@ static int libplacebo_config_output(AVFilterLink *outlink)
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 */
--
2.41.0
_______________________________________________
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".
^ permalink raw reply [flat|nested] 25+ messages in thread
* [FFmpeg-devel] [PATCH v2 20/22] lavfi/vf_libplacebo: also skip cache if in FPS == out FPS
2023-06-18 11:16 [FFmpeg-devel] lavfi/vf_libplacebo: generalize to multiple inputs Niklas Haas
` (18 preceding siblings ...)
2023-06-18 11:17 ` [FFmpeg-devel] [PATCH v2 19/22] lavfi/vf_libplacebo: skip cache selectively per-input Niklas Haas
@ 2023-06-18 11:17 ` Niklas Haas
2023-06-18 11:17 ` [FFmpeg-devel] [PATCH v2 21/22] lavfi/vf_libplacebo: set time_base/frame_rate dynamically Niklas Haas
` (2 subsequent siblings)
22 siblings, 0 replies; 25+ messages in thread
From: Niklas Haas @ 2023-06-18 11:17 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
Fixes an oversight in the previous code which should have been >=, not >.
---
libavfilter/vf_libplacebo.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c
index f7b9bdba742..1085b6fdd0a 100644
--- a/libavfilter/vf_libplacebo.c
+++ b/libavfilter/vf_libplacebo.c
@@ -881,7 +881,7 @@ static int output_frame(AVFilterContext *ctx, int64_t pts)
s->params.blend_params = NULL;
for (int i = 0; i < s->nb_inputs; i++) {
LibplaceboInput *in = &s->inputs[i];
- int high_fps = av_cmp_q(in->link->frame_rate, outlink->frame_rate) > 0;
+ int high_fps = av_cmp_q(in->link->frame_rate, outlink->frame_rate) >= 0;
if (in->qstatus != PL_QUEUE_OK)
continue;
s->params.skip_caching_single_frame = high_fps;
--
2.41.0
_______________________________________________
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".
^ permalink raw reply [flat|nested] 25+ messages in thread
* [FFmpeg-devel] [PATCH v2 21/22] lavfi/vf_libplacebo: set time_base/frame_rate dynamically
2023-06-18 11:16 [FFmpeg-devel] lavfi/vf_libplacebo: generalize to multiple inputs Niklas Haas
` (19 preceding siblings ...)
2023-06-18 11:17 ` [FFmpeg-devel] [PATCH v2 20/22] lavfi/vf_libplacebo: also skip cache if in FPS == out FPS Niklas Haas
@ 2023-06-18 11:17 ` Niklas Haas
2023-06-18 11:17 ` [FFmpeg-devel] [PATCH v2 22/22] lavfi/vf_libplacebo: add nb_inputs option Niklas Haas
2023-06-20 14:50 ` [FFmpeg-devel] lavfi/vf_libplacebo: generalize to multiple inputs Marvin Scholz
22 siblings, 0 replies; 25+ messages in thread
From: Niklas Haas @ 2023-06-18 11:17 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
Use the gcd of all input timebases to ensure PTS accuracy. For the
framerate, just pick the highest of all the inputs, under the assumption
that we will render frames with approximately this frequency. Of course,
this is not 100% accurate, in particular if the input frames are badly
misaligned. But this field is informational to begin with.
Importantly, it covers the "common" case of combining high FPS and low
FPS streams with aligned frames.
---
libavfilter/vf_libplacebo.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c
index 1085b6fdd0a..09a24e7c291 100644
--- a/libavfilter/vf_libplacebo.c
+++ b/libavfilter/vf_libplacebo.c
@@ -1158,6 +1158,11 @@ static int libplacebo_config_input(AVFilterLink *inlink)
return 0;
}
+static inline AVRational max_q(AVRational a, AVRational b)
+{
+ return av_cmp_q(a, b) < 0 ? b : a;
+}
+
static int libplacebo_config_output(AVFilterLink *outlink)
{
int err;
@@ -1198,6 +1203,16 @@ static int libplacebo_config_output(AVFilterLink *outlink)
if (s->fps.num) {
outlink->frame_rate = s->fps;
outlink->time_base = av_inv_q(s->fps);
+ } else {
+ outlink->frame_rate = avctx->inputs[0]->frame_rate;
+ outlink->time_base = avctx->inputs[0]->time_base;
+ for (int i = 1; i < s->nb_inputs; i++) {
+ outlink->frame_rate = max_q(outlink->frame_rate,
+ avctx->inputs[i]->frame_rate);
+ outlink->time_base = av_gcd_q(outlink->time_base,
+ avctx->inputs[i]->time_base,
+ AV_TIME_BASE / 2, AV_TIME_BASE_Q);
+ }
}
/* Static variables */
--
2.41.0
_______________________________________________
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".
^ permalink raw reply [flat|nested] 25+ messages in thread
* [FFmpeg-devel] [PATCH v2 22/22] lavfi/vf_libplacebo: add nb_inputs option
2023-06-18 11:16 [FFmpeg-devel] lavfi/vf_libplacebo: generalize to multiple inputs Niklas Haas
` (20 preceding siblings ...)
2023-06-18 11:17 ` [FFmpeg-devel] [PATCH v2 21/22] lavfi/vf_libplacebo: set time_base/frame_rate dynamically Niklas Haas
@ 2023-06-18 11:17 ` Niklas Haas
2023-06-20 14:50 ` [FFmpeg-devel] lavfi/vf_libplacebo: generalize to multiple inputs Marvin Scholz
22 siblings, 0 replies; 25+ messages in thread
From: Niklas Haas @ 2023-06-18 11:17 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
To control the number of inputs.
---
doc/filters.texi | 5 +++++
libavfilter/vf_libplacebo.c | 25 ++++++++++++++-----------
2 files changed, 19 insertions(+), 11 deletions(-)
diff --git a/doc/filters.texi b/doc/filters.texi
index cf17930b014..c3d3f004b19 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -16153,6 +16153,11 @@ to preserve the source colorimetry and size as best as it can, but it will
apply any embedded film grain, dolby vision metadata or anamorphic SAR present
in source frames.
@table @option
+@item inputs
+Set the number of inputs. This can be used, alongside the @code{idx} variable,
+to allow placing/blending multiple inputs inside the output frame. This
+effectively enables functionality similar to @ref{hstack}, @ref{overlay}, etc.
+
@item w
@item h
Set the output video dimension expression. Default values are @code{iw} and
diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c
index 09a24e7c291..056041d2131 100644
--- a/libavfilter/vf_libplacebo.c
+++ b/libavfilter/vf_libplacebo.c
@@ -502,6 +502,7 @@ static int parse_shader(AVFilterContext *avctx, const void *shader, size_t len)
}
static void libplacebo_uninit(AVFilterContext *avctx);
+static int libplacebo_config_input(AVFilterLink *inlink);
static int libplacebo_init(AVFilterContext *avctx)
{
@@ -530,6 +531,17 @@ static int libplacebo_init(AVFilterContext *avctx)
s->out_format = AV_PIX_FMT_NONE;
}
+ for (int i = 0; i < s->nb_inputs; i++) {
+ AVFilterPad pad = {
+ .name = av_asprintf("input%d", i),
+ .type = AVMEDIA_TYPE_VIDEO,
+ .config_props = &libplacebo_config_input,
+ };
+ if (!pad.name)
+ return AVERROR(ENOMEM);
+ RET(ff_append_inpad_free_name(avctx, &pad));
+ }
+
RET(update_settings(avctx));
RET(av_expr_parse(&s->crop_x_pexpr, s->crop_x_expr, var_names,
NULL, NULL, NULL, NULL, 0, s));
@@ -665,7 +677,6 @@ static int init_vulkan(AVFilterContext *avctx, const AVVulkanDeviceContext *hwct
}
/* Initialize inputs */
- s->nb_inputs = 1;
s->inputs = av_calloc(s->nb_inputs, sizeof(*s->inputs));
if (!s->inputs)
return AVERROR(ENOMEM);
@@ -1252,6 +1263,7 @@ fail:
#define DYNAMIC (STATIC | AV_OPT_FLAG_RUNTIME_PARAM)
static const AVOption libplacebo_options[] = {
+ { "inputs", "Number of inputs", OFFSET(nb_inputs), AV_OPT_TYPE_INT, {.i64 = 1}, 1, INT_MAX, .flags = STATIC },
{ "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 },
@@ -1443,14 +1455,6 @@ static const AVOption libplacebo_options[] = {
AVFILTER_DEFINE_CLASS(libplacebo);
-static const AVFilterPad libplacebo_inputs[] = {
- {
- .name = "default",
- .type = AVMEDIA_TYPE_VIDEO,
- .config_props = &libplacebo_config_input,
- },
-};
-
static const AVFilterPad libplacebo_outputs[] = {
{
.name = "default",
@@ -1467,10 +1471,9 @@ const AVFilter ff_vf_libplacebo = {
.uninit = &libplacebo_uninit,
.activate = &libplacebo_activate,
.process_command = &libplacebo_process_command,
- FILTER_INPUTS(libplacebo_inputs),
FILTER_OUTPUTS(libplacebo_outputs),
FILTER_QUERY_FUNC(libplacebo_query_format),
.priv_class = &libplacebo_class,
.flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
- .flags = AVFILTER_FLAG_HWDEVICE,
+ .flags = AVFILTER_FLAG_HWDEVICE | AVFILTER_FLAG_DYNAMIC_INPUTS,
};
--
2.41.0
_______________________________________________
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".
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [FFmpeg-devel] lavfi/vf_libplacebo: generalize to multiple inputs
2023-06-18 11:16 [FFmpeg-devel] lavfi/vf_libplacebo: generalize to multiple inputs Niklas Haas
` (21 preceding siblings ...)
2023-06-18 11:17 ` [FFmpeg-devel] [PATCH v2 22/22] lavfi/vf_libplacebo: add nb_inputs option Niklas Haas
@ 2023-06-20 14:50 ` Marvin Scholz
2023-06-20 15:12 ` Niklas Haas
22 siblings, 1 reply; 25+ messages in thread
From: Marvin Scholz @ 2023-06-20 14:50 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On 18 Jun 2023, at 13:16, Niklas Haas wrote:
> Changes since v1:
> - added explicit `if (s->inputs)` check to input_uninit() loop
> - added extra `!s->status` check to handle case of negative PTS on
> status change (since `s->status_pts >= 0` would fail here)
>
>
Tested and LGTM from my side
> _______________________________________________
> 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".
_______________________________________________
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".
^ permalink raw reply [flat|nested] 25+ messages in thread