You've already forked FFmpeg
mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-09-16 08:36:51 +02:00
avfilter/vf_premultiply: add dynamic variant of this filter
We need a filter that can premultiply and unpremultiply the alpha channel dynamically, on demand, in response to the negotiated alpha mode, analogous to how vf_scale operates. Introduce a new filter "vf_premultiply_dynamic" that accomplishes this.
This commit is contained in:
@@ -410,6 +410,7 @@ extern const FFFilter ff_vf_pixelize;
|
||||
extern const FFFilter ff_vf_pixscope;
|
||||
extern const FFFilter ff_vf_pp7;
|
||||
extern const FFFilter ff_vf_premultiply;
|
||||
extern const FFFilter ff_vf_premultiply_dynamic;
|
||||
extern const FFFilter ff_vf_prewitt;
|
||||
extern const FFFilter ff_vf_prewitt_opencl;
|
||||
extern const FFFilter ff_vf_procamp_vaapi;
|
||||
|
@@ -41,6 +41,7 @@ typedef struct PreMultiplyContext {
|
||||
int planes;
|
||||
int inverse;
|
||||
int inplace;
|
||||
int dynamic;
|
||||
int half, depth, offset, max;
|
||||
FFFrameSync fs;
|
||||
|
||||
@@ -95,18 +96,25 @@ static int query_formats(const AVFilterContext *ctx,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Configure alpha mode corresponding to the chosen direction */
|
||||
if (s->inplace) {
|
||||
formats = ff_make_formats_list_singleton(s->inverse ? AVALPHA_MODE_PREMULTIPLIED
|
||||
: AVALPHA_MODE_STRAIGHT);
|
||||
ret = ff_formats_ref(formats, &cfg_in[0]->alpha_modes);
|
||||
if (s->dynamic) {
|
||||
ret = ff_formats_ref(ff_all_alpha_modes(), &cfg_in[0]->alpha_modes);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
return ff_formats_ref(ff_all_alpha_modes(), &cfg_out[0]->alpha_modes);
|
||||
} else {
|
||||
/* Configure alpha mode corresponding to the chosen direction */
|
||||
if (s->inplace) {
|
||||
formats = ff_make_formats_list_singleton(s->inverse ? AVALPHA_MODE_PREMULTIPLIED
|
||||
: AVALPHA_MODE_STRAIGHT);
|
||||
ret = ff_formats_ref(formats, &cfg_in[0]->alpha_modes);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
formats = ff_make_formats_list_singleton(s->inverse ? AVALPHA_MODE_STRAIGHT
|
||||
: AVALPHA_MODE_PREMULTIPLIED);
|
||||
return ff_formats_ref(formats, &cfg_out[0]->alpha_modes);
|
||||
formats = ff_make_formats_list_singleton(s->inverse ? AVALPHA_MODE_STRAIGHT
|
||||
: AVALPHA_MODE_PREMULTIPLIED);
|
||||
return ff_formats_ref(formats, &cfg_out[0]->alpha_modes);
|
||||
}
|
||||
}
|
||||
|
||||
static void premultiply8(const uint8_t *msrc, const uint8_t *asrc,
|
||||
@@ -530,7 +538,7 @@ static int filter_frame(AVFilterContext *ctx,
|
||||
PreMultiplyContext *s = ctx->priv;
|
||||
AVFilterLink *outlink = ctx->outputs[0];
|
||||
|
||||
if (ctx->is_disabled) {
|
||||
if (ctx->is_disabled || outlink->alpha_mode == base->alpha_mode) {
|
||||
*out = av_frame_clone(base);
|
||||
if (!*out)
|
||||
return AVERROR(ENOMEM);
|
||||
@@ -741,6 +749,9 @@ static int config_output(AVFilterLink *outlink)
|
||||
outlink->sample_aspect_ratio = base->sample_aspect_ratio;
|
||||
ol->frame_rate = il->frame_rate;
|
||||
|
||||
if (s->dynamic)
|
||||
s->inverse = base->alpha_mode == AVALPHA_MODE_PREMULTIPLIED;
|
||||
|
||||
if (s->inplace)
|
||||
return 0;
|
||||
|
||||
@@ -802,6 +813,11 @@ static av_cold int init(AVFilterContext *ctx)
|
||||
AVFilterPad pad = { 0 };
|
||||
int ret;
|
||||
|
||||
if (!strcmp(ctx->filter->name, "premultiply_dynamic")) {
|
||||
s->dynamic = s->inplace = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strcmp(ctx->filter->name, "unpremultiply"))
|
||||
s->inverse = 1;
|
||||
|
||||
@@ -877,3 +893,29 @@ const FFFilter ff_vf_unpremultiply = {
|
||||
};
|
||||
|
||||
#endif /* CONFIG_UNPREMULTIPLY_FILTER */
|
||||
|
||||
#if CONFIG_PREMULTIPLY_DYNAMIC_FILTER
|
||||
|
||||
static const AVFilterPad premultiply_input[] = {
|
||||
{
|
||||
.name = "default",
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.config_props = config_input,
|
||||
},
|
||||
};
|
||||
|
||||
const FFFilter ff_vf_premultiply_dynamic = {
|
||||
.p.name = "premultiply_dynamic",
|
||||
.p.description = NULL_IF_CONFIG_SMALL("Premultiply or unpremultiply an image in-place, as needed."),
|
||||
.p.priv_class = &premultiply_class,
|
||||
.p.flags = AVFILTER_FLAG_SLICE_THREADS,
|
||||
.priv_size = sizeof(PreMultiplyContext),
|
||||
.init = init,
|
||||
.uninit = uninit,
|
||||
.activate = activate,
|
||||
FILTER_INPUTS(premultiply_input),
|
||||
FILTER_OUTPUTS(premultiply_outputs),
|
||||
FILTER_QUERY_FUNC2(query_formats),
|
||||
};
|
||||
|
||||
#endif /* CONFIG_UNPREMULTIPLY_DYNAMIC_FILTER */
|
||||
|
Reference in New Issue
Block a user