avfilter/vf_scale: switch to FFFrameSync

Preliminary commit, in anticipation of adding support for multiple
inputs (with proper synchronization and activate() callback).
This commit is contained in:
Niklas Haas 2024-04-24 11:39:01 +02:00
parent a5032dc12a
commit e82a3997cd
2 changed files with 63 additions and 6 deletions

View File

@ -20989,8 +20989,8 @@ the next filter, the scale filter will convert the input to the
requested format. requested format.
@subsection Options @subsection Options
The filter accepts the following options, or any of the options The filter accepts the following options, any of the options supported
supported by the libswscale scaler. by the libswscale scaler, as well as any of the @ref{framesync} options.
See @ref{scaler_options,,the ffmpeg-scaler manual,ffmpeg-scaler} for See @ref{scaler_options,,the ffmpeg-scaler manual,ffmpeg-scaler} for
the complete list of scaler options. the complete list of scaler options.

View File

@ -29,6 +29,7 @@
#include "avfilter.h" #include "avfilter.h"
#include "formats.h" #include "formats.h"
#include "framesync.h"
#include "internal.h" #include "internal.h"
#include "scale_eval.h" #include "scale_eval.h"
#include "video.h" #include "video.h"
@ -113,6 +114,7 @@ typedef struct ScaleContext {
struct SwsContext *isws[2]; ///< software scaler context for interlaced material struct SwsContext *isws[2]; ///< software scaler context for interlaced material
// context used for forwarding options to sws // context used for forwarding options to sws
struct SwsContext *sws_opts; struct SwsContext *sws_opts;
FFFrameSync fs;
/** /**
* New dimensions. Special values are: * New dimensions. Special values are:
@ -287,6 +289,8 @@ static av_cold int preinit(AVFilterContext *ctx)
if (ret < 0) if (ret < 0)
return ret; return ret;
ff_framesync_preinit(&scale->fs);
return 0; return 0;
} }
@ -302,6 +306,8 @@ static const int sws_colorspaces[] = {
-1 -1
}; };
static int do_scale(FFFrameSync *fs);
static av_cold int init(AVFilterContext *ctx) static av_cold int init(AVFilterContext *ctx)
{ {
ScaleContext *scale = ctx->priv; ScaleContext *scale = ctx->priv;
@ -388,6 +394,7 @@ static av_cold void uninit(AVFilterContext *ctx)
av_expr_free(scale->w_pexpr); av_expr_free(scale->w_pexpr);
av_expr_free(scale->h_pexpr); av_expr_free(scale->h_pexpr);
scale->w_pexpr = scale->h_pexpr = NULL; scale->w_pexpr = scale->h_pexpr = NULL;
ff_framesync_uninit(&scale->fs);
sws_freeContext(scale->sws_opts); sws_freeContext(scale->sws_opts);
sws_freeContext(scale->sws); sws_freeContext(scale->sws);
sws_freeContext(scale->isws[0]); sws_freeContext(scale->isws[0]);
@ -677,6 +684,21 @@ static int config_props(AVFilterLink *outlink)
flags_val); flags_val);
av_freep(&flags_val); av_freep(&flags_val);
if (ctx->filter != &ff_vf_scale2ref) {
ret = ff_framesync_init(&scale->fs, ctx, ctx->nb_inputs);
if (ret < 0)
return ret;
scale->fs.on_event = do_scale;
scale->fs.in[0].time_base = ctx->inputs[0]->time_base;
scale->fs.in[0].sync = 1;
scale->fs.in[0].before = EXT_STOP;
scale->fs.in[0].after = EXT_STOP;
ret = ff_framesync_configure(&scale->fs);
if (ret < 0)
return ret;
}
return 0; return 0;
fail: fail:
@ -894,6 +916,26 @@ scale:
return ret; return ret;
} }
static int do_scale(FFFrameSync *fs)
{
AVFilterContext *ctx = fs->parent;
AVFilterLink *outlink = ctx->outputs[0];
AVFrame *in, *out;
int ret;
ret = ff_framesync_get_frame(fs, 0, &in, 1);
if (ret < 0)
return ret;
ret = scale_frame(ctx->inputs[0], in, &out);
if (out) {
out->pts = av_rescale_q(fs->pts, fs->time_base, outlink->time_base);
return ff_filter_frame(outlink, out);
}
return ret;
}
static int filter_frame(AVFilterLink *link, AVFrame *in) static int filter_frame(AVFilterLink *link, AVFrame *in)
{ {
AVFilterContext *ctx = link->dst; AVFilterContext *ctx = link->dst;
@ -972,11 +1014,24 @@ static int process_command(AVFilterContext *ctx, const char *cmd, const char *ar
return ret; return ret;
} }
static int activate(AVFilterContext *ctx)
{
ScaleContext *scale = ctx->priv;
return ff_framesync_activate(&scale->fs);
}
static const AVClass *child_class_iterate(void **iter) static const AVClass *child_class_iterate(void **iter)
{ {
const AVClass *c = *iter ? NULL : sws_get_class(); switch ((uintptr_t) *iter) {
*iter = (void*)(uintptr_t)c; case 0:
return c; *iter = (void*)(uintptr_t) 1;
return sws_get_class();
case 1:
*iter = (void*)(uintptr_t) 2;
return &ff_framesync_class;
}
return NULL;
} }
static void *child_next(void *obj, void *prev) static void *child_next(void *obj, void *prev)
@ -984,6 +1039,8 @@ static void *child_next(void *obj, void *prev)
ScaleContext *s = obj; ScaleContext *s = obj;
if (!prev) if (!prev)
return s->sws_opts; return s->sws_opts;
if (prev == s->sws_opts)
return &s->fs;
return NULL; return NULL;
} }
@ -1051,7 +1108,6 @@ static const AVFilterPad avfilter_vf_scale_inputs[] = {
{ {
.name = "default", .name = "default",
.type = AVMEDIA_TYPE_VIDEO, .type = AVMEDIA_TYPE_VIDEO,
.filter_frame = filter_frame,
}, },
}; };
@ -1074,6 +1130,7 @@ const AVFilter ff_vf_scale = {
FILTER_INPUTS(avfilter_vf_scale_inputs), FILTER_INPUTS(avfilter_vf_scale_inputs),
FILTER_OUTPUTS(avfilter_vf_scale_outputs), FILTER_OUTPUTS(avfilter_vf_scale_outputs),
FILTER_QUERY_FUNC(query_formats), FILTER_QUERY_FUNC(query_formats),
.activate = activate,
.process_command = process_command, .process_command = process_command,
}; };