Hi,
This patch adds command support for dynamic change the size in the “scale_cuda”
resize filter. In fact, it’s the first GPU filter accepting realtime commands.
Using similar changes it’s possible to port it to other hwaccelerators. The
only limitation is that the values cannot exceed the initial values. It is
therefore necessary to set up the graph with the higher values you may need.
One example: { -filter_complex "scale_cuda=720:576,hwdownload,format=nv12,zmq" }
And then you can use the <c> or ZMQ messages to change the width and/or height.
Warning: This patch requires, to have sense, to apply too this other patch that
fixes the hwdownload filter.
https://patchwork.ffmpeg.org/patch/11165/
From 46c58c1da02ba40c1fab0ec93febc995db90caca Mon Sep 17 00:00:00 2001
From: M. Sanders <hidden at gmail.com>
Date: Mon, 26 Nov 2018 17:52:52 +0000
Subject: [PATCH 2/2] libavfilter: scale_cuda dynamic command values
---
libavfilter/vf_scale_cuda.c | 72 +++++++++++++++++++++++++++++++++++++------
1 file changed, 62 insertions(+), 10 deletions(-)
diff --git a/libavfilter/vf_scale_cuda.c b/libavfilter/vf_scale_cuda.c
index 53b7aa9..ac8f8cc 100644
--- a/libavfilter/vf_scale_cuda.c
+++ b/libavfilter/vf_scale_cuda.c
@@ -78,6 +78,8 @@ typedef struct CUDAScaleContext {
char *w_expr; ///< width expression string
char *h_expr; ///< height expression string
+ int target_width;
+ int target_height;
CUcontext cu_ctx;
CUevent cu_event;
@@ -314,9 +316,22 @@ static av_cold int cudascale_config_props(AVFilterLink
*outlink)
outlink->w = w;
outlink->h = h;
- ret = init_processing_chain(ctx, inlink->w, inlink->h, w, h);
- if (ret < 0)
- return ret;
+ if (!s->frames_ctx) {
+ ret = init_processing_chain(ctx, inlink->w, inlink->h, w, h);
+ if (ret < 0)
+ return ret;
+ } else {
+ // We are reconfiguring, so reuse the current hw_context
+ av_log(s, AV_LOG_DEBUG, "Reusing the current hw_context.\n");
+ if (s->planes_out && outlink->w > s->planes_out[0].width) {
+ outlink->w = s->planes_out[0].width;
+ av_log(s, AV_LOG_ERROR, "Impossible to resize above the Context
width.\n");
+ }
+ if (s->planes_out && outlink->h > s->planes_out[0].height) {
+ outlink->h = s->planes_out[0].height;
+ av_log(s, AV_LOG_ERROR, "Impossible to resize above the Context
height.\n");
+ }
+ }
av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d -> w:%d h:%d\n",
inlink->w, inlink->h, outlink->w, outlink->h);
@@ -329,6 +344,9 @@ static av_cold int cudascale_config_props(AVFilterLink
*outlink)
outlink->sample_aspect_ratio = inlink->sample_aspect_ratio;
}
+ s->target_width = outlink->w;
+ s->target_height = outlink->h;
+
return 0;
fail:
@@ -375,11 +393,11 @@ static int scalecuda_resize(AVFilterContext *ctx,
1);
call_resize_kernel(s, s->cu_func_uchar, s->cu_tex_uchar, 1,
in->data[0]+in->linesize[0]*in->height,
in->width/2, in->height/2, in->linesize[0]/2,
- out->data[0]+out->linesize[0]*out->height,
out->width/2, out->height/2, out->linesize[0]/2,
+
out->data[0]+out->linesize[0]*s->planes_out[0].height, out->width/2,
out->height/2, out->linesize[0]/2,
1);
call_resize_kernel(s, s->cu_func_uchar, s->cu_tex_uchar, 1,
in->data[0]+
ALIGN_UP((in->linesize[0]*in->height*5)/4, s->tex_alignment), in->width/2,
in->height/2, in->linesize[0]/2,
- out->data[0]+(out->linesize[0]*out->height*5)/4,
out->width/2, out->height/2, out->linesize[0]/2,
+
out->data[0]+(out->linesize[0]*s->planes_out[0].height*5)/4, out->width/2,
out->height/2, out->linesize[0]/2,
1);
break;
case AV_PIX_FMT_YUV444P:
@@ -389,11 +407,11 @@ static int scalecuda_resize(AVFilterContext *ctx,
1);
call_resize_kernel(s, s->cu_func_uchar, s->cu_tex_uchar, 1,
in->data[0]+in->linesize[0]*in->height, in->width,
in->height, in->linesize[0],
- out->data[0]+out->linesize[0]*out->height,
out->width, out->height, out->linesize[0],
+
out->data[0]+out->linesize[0]*s->planes_out[0].height, out->width, out->height,
out->linesize[0],
1);
call_resize_kernel(s, s->cu_func_uchar, s->cu_tex_uchar, 1,
in->data[0]+in->linesize[0]*in->height*2,
in->width, in->height, in->linesize[0],
- out->data[0]+out->linesize[0]*out->height*2,
out->width, out->height, out->linesize[0],
+
out->data[0]+out->linesize[0]*s->planes_out[0].height*2, out->width,
out->height, out->linesize[0],
1);
break;
case AV_PIX_FMT_NV12:
@@ -401,9 +419,10 @@ static int scalecuda_resize(AVFilterContext *ctx,
in->data[0], in->width, in->height, in->linesize[0],
out->data[0], out->width, out->height,
out->linesize[0],
1);
+
call_resize_kernel(s, s->cu_func_uchar2, s->cu_tex_uchar2, 2,
in->data[1], in->width/2, in->height/2,
in->linesize[1],
- out->data[0] + out->linesize[0] * ((out->height +
31) & ~0x1f), out->width/2, out->height/2, out->linesize[1]/2,
+ out->data[0] + out->linesize[0] *
((s->planes_out[0].height + 31) & ~0x1f), out->width/2, out->height/2,
out->linesize[1]/2,
1);
break;
case AV_PIX_FMT_P010LE:
@@ -413,7 +432,7 @@ static int scalecuda_resize(AVFilterContext *ctx,
2);
call_resize_kernel(s, s->cu_func_ushort2, s->cu_tex_ushort2, 2,
in->data[1], in->width / 2, in->height / 2,
in->linesize[1]/2,
- out->data[0] + out->linesize[0] * ((out->height +
31) & ~0x1f), out->width / 2, out->height / 2, out->linesize[1] / 4,
+ out->data[0] + out->linesize[0] *
((s->planes_out[0].height + 31) & ~0x1f), out->width / 2, out->height / 2,
out->linesize[1] / 4,
2);
break;
case AV_PIX_FMT_P016LE:
@@ -423,7 +442,7 @@ static int scalecuda_resize(AVFilterContext *ctx,
2);
call_resize_kernel(s, s->cu_func_ushort2, s->cu_tex_ushort2, 2,
in->data[1], in->width / 2, in->height / 2,
in->linesize[1] / 2,
- out->data[0] + out->linesize[0] * ((out->height +
31) & ~0x1f), out->width / 2, out->height / 2, out->linesize[1] / 4,
+ out->data[0] + out->linesize[0] *
((s->planes_out[0].height + 31) & ~0x1f), out->width / 2, out->height / 2,
out->linesize[1] / 4,
2);
break;
default:
@@ -439,6 +458,11 @@ static int cudascale_scale(AVFilterContext *ctx, AVFrame
*out, AVFrame *in)
AVFrame *src = in;
int ret;
+ out->width = s->target_width;
+ out->height = s->target_height;
+ s->frame->width = out->width;
+ s->frame->height = out->height;
+
ret = scalecuda_resize(ctx, s->frame, src);
if (ret < 0)
return ret;
@@ -499,6 +523,33 @@ fail:
return ret;
}
+static int process_command(AVFilterContext *ctx, const char *cmd, const char
*args,
+ char *res, int res_len, int flags)
+{
+ CUDAScaleContext *s = ctx->priv;
+ int ret;
+
+ if ( !strcmp(cmd, "width") || !strcmp(cmd, "w")
+ || !strcmp(cmd, "height") || !strcmp(cmd, "h")) {
+
+ int old_w = s->target_width;
+ int old_h = s->target_height;
+ AVFilterLink *outlink = ctx->outputs[0];
+
+ av_opt_set(s, cmd, args, 0);
+ if ((ret = cudascale_config_props(outlink)) < 0) {
+ s->target_width = old_w;
+ s->target_height = old_h;
+ } else {
+ av_log(ctx, AV_LOG_VERBOSE, "Reconfiguration w:%d h:%d -> w:%d
h:%d\n",
+ ctx->inputs[0]->w, ctx->inputs[0]->h, ctx->outputs[0]->w,
ctx->outputs[0]->h);
+ }
+ } else
+ ret = AVERROR(ENOSYS);
+
+ return ret;
+}
+
#define OFFSET(x) offsetof(CUDAScaleContext, x)
#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM)
static const AVOption options[] = {
@@ -545,6 +596,7 @@ AVFilter ff_vf_scale_cuda = {
.inputs = cudascale_inputs,
.outputs = cudascale_outputs,
+ .process_command = process_command,
.flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
};
--
1.7.10.4
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel