1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2025-09-16 08:36:51 +02:00

avfilter: add link negotiation for AVAlphaMode

This commit is contained in:
Niklas Haas
2025-08-13 11:27:32 +02:00
parent 8b375b2ffd
commit eea99a77ed
8 changed files with 158 additions and 5 deletions

View File

@@ -312,6 +312,9 @@ int avfilter_insert_filter(AVFilterLink *link, AVFilterContext *filt,
if (link->outcfg.color_ranges)
ff_formats_changeref(&link->outcfg.color_ranges,
&filt->outputs[filt_dstpad_idx]->outcfg.color_ranges);
if (link->outcfg.alpha_modes)
ff_formats_changeref(&link->outcfg.alpha_modes,
&filt->outputs[filt_dstpad_idx]->outcfg.alpha_modes);
if (link->outcfg.samplerates)
ff_formats_changeref(&link->outcfg.samplerates,
&filt->outputs[filt_dstpad_idx]->outcfg.samplerates);
@@ -784,6 +787,8 @@ static void free_link(AVFilterLink *link)
ff_formats_unref(&link->outcfg.color_spaces);
ff_formats_unref(&link->incfg.color_ranges);
ff_formats_unref(&link->outcfg.color_ranges);
ff_formats_unref(&link->incfg.alpha_modes);
ff_formats_unref(&link->outcfg.alpha_modes);
ff_formats_unref(&link->incfg.samplerates);
ff_formats_unref(&link->outcfg.samplerates);
ff_channel_layouts_unref(&link->incfg.channel_layouts);

View File

@@ -141,6 +141,11 @@ typedef struct AVFilterFormatsConfig {
AVFilterFormats *color_spaces; ///< AVColorSpace
AVFilterFormats *color_ranges; ///< AVColorRange
/**
* List of supported alpha modes, only for video with an alpha channel.
*/
AVFilterFormats *alpha_modes; ///< AVAlphaMode
} AVFilterFormatsConfig;
/**
@@ -428,6 +433,8 @@ struct AVFilterLink {
AVFrameSideData **side_data;
int nb_side_data;
enum AVAlphaMode alpha_mode; ///< alpha mode (for videos with an alpha channel)
/*****************************************************************
* All fields below this line are not part of the public API. They
* may not be used outside of libavfilter and can be changed and

View File

@@ -303,7 +303,8 @@ static int filter_link_check_formats(void *log, AVFilterLink *link, AVFilterForm
case AVMEDIA_TYPE_VIDEO:
if ((ret = ff_formats_check_pixel_formats(log, cfg->formats)) < 0 ||
(ret = ff_formats_check_color_spaces(log, cfg->color_spaces)) < 0 ||
(ret = ff_formats_check_color_ranges(log, cfg->color_ranges)) < 0)
(ret = ff_formats_check_color_ranges(log, cfg->color_ranges)) < 0 ||
(ret = ff_formats_check_alpha_modes(log, cfg->alpha_modes)) < 0)
return ret;
break;
@@ -418,7 +419,8 @@ static int formats_declared(AVFilterContext *f)
return 0;
if (f->inputs[i]->type == AVMEDIA_TYPE_VIDEO &&
!(f->inputs[i]->outcfg.color_ranges &&
f->inputs[i]->outcfg.color_spaces))
f->inputs[i]->outcfg.color_spaces &&
f->inputs[i]->outcfg.alpha_modes))
return 0;
if (f->inputs[i]->type == AVMEDIA_TYPE_AUDIO &&
!(f->inputs[i]->outcfg.samplerates &&
@@ -430,7 +432,8 @@ static int formats_declared(AVFilterContext *f)
return 0;
if (f->outputs[i]->type == AVMEDIA_TYPE_VIDEO &&
!(f->outputs[i]->incfg.color_ranges &&
f->outputs[i]->incfg.color_spaces))
f->outputs[i]->incfg.color_spaces &&
f->outputs[i]->incfg.alpha_modes))
return 0;
if (f->outputs[i]->type == AVMEDIA_TYPE_AUDIO &&
!(f->outputs[i]->incfg.samplerates &&
@@ -641,6 +644,10 @@ retry:
av_assert0( inlink->outcfg.color_ranges->refcount > 0);
av_assert0(outlink-> incfg.color_ranges->refcount > 0);
av_assert0(outlink->outcfg.color_ranges->refcount > 0);
av_assert0( inlink-> incfg.alpha_modes->refcount > 0);
av_assert0( inlink->outcfg.alpha_modes->refcount > 0);
av_assert0(outlink-> incfg.alpha_modes->refcount > 0);
av_assert0(outlink->outcfg.alpha_modes->refcount > 0);
} else if (outlink->type == AVMEDIA_TYPE_AUDIO) {
av_assert0( inlink-> incfg.samplerates->refcount > 0);
av_assert0( inlink->outcfg.samplerates->refcount > 0);
@@ -820,8 +827,8 @@ static int pick_format(AVFilterLink *link, AVFilterLink *ref)
swfmt = AV_PIX_FMT_YUV420P;
}
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(swfmt);
if (!ff_fmt_is_regular_yuv(swfmt)) {
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(swfmt);
/* These fields are explicitly documented as affecting YUV only,
* so set them to sane values for other formats. */
if (desc->flags & AV_PIX_FMT_FLAG_FLOAT)
@@ -856,6 +863,19 @@ static int pick_format(AVFilterLink *link, AVFilterLink *ref)
link->color_range = link->incfg.color_ranges->formats[0];
}
}
if (desc->flags & AV_PIX_FMT_FLAG_ALPHA) {
if (!link->incfg.alpha_modes->nb_formats) {
av_log(link->src, AV_LOG_ERROR, "Cannot select alpha mode for"
" the link between filters %s and %s.\n", link->src->name,
link->dst->name);
return AVERROR(EINVAL);
}
link->incfg.alpha_modes->nb_formats = 1;
link->alpha_mode = link->incfg.alpha_modes->formats[0];
} else {
link->alpha_mode = AVALPHA_MODE_UNSPECIFIED;
}
} else if (link->type == AVMEDIA_TYPE_AUDIO) {
int ret;
@@ -894,6 +914,8 @@ static int pick_format(AVFilterLink *link, AVFilterLink *ref)
ff_formats_unref(&link->outcfg.color_spaces);
ff_formats_unref(&link->incfg.color_ranges);
ff_formats_unref(&link->outcfg.color_ranges);
ff_formats_unref(&link->incfg.alpha_modes);
ff_formats_unref(&link->outcfg.alpha_modes);
return 0;
}
@@ -947,6 +969,8 @@ static int reduce_formats_on_filter(AVFilterContext *filter)
nb_formats, ff_add_format);
REDUCE_FORMATS(int, AVFilterFormats, color_ranges, formats,
nb_formats, ff_add_format);
REDUCE_FORMATS(int, AVFilterFormats, alpha_modes, formats,
nb_formats, ff_add_format);
/* reduce channel layouts */
for (i = 0; i < filter->nb_inputs; i++) {

View File

@@ -372,6 +372,11 @@ static const AVFilterFormatsMerger mergers_video[] = {
.can_merge = can_merge_generic,
CONVERSION_FILTER_SWSCALE
},
{
.offset = offsetof(AVFilterFormatsConfig, alpha_modes),
.merge = merge_generic,
.can_merge = can_merge_generic,
},
};
static const AVFilterFormatsMerger mergers_audio[] = {
@@ -665,6 +670,17 @@ AVFilterFormats *ff_all_color_ranges(void)
return ret;
}
AVFilterFormats *ff_all_alpha_modes(void)
{
AVFilterFormats *ret = NULL;
for (int range = 0; range < AVALPHA_MODE_NB; range++) {
if (ff_add_format(&ret, range) < 0)
return NULL;
}
return ret;
}
#define FORMATS_REF(f, ref, unref_fn) \
void *tmp; \
\
@@ -870,6 +886,24 @@ int ff_set_common_all_color_ranges(AVFilterContext *ctx)
return ff_set_common_color_ranges(ctx, ff_all_color_ranges());
}
int ff_set_common_alpha_modes(AVFilterContext *ctx,
AVFilterFormats *alpha_modes)
{
SET_COMMON_FORMATS(ctx, alpha_modes, AVMEDIA_TYPE_VIDEO,
ff_formats_ref, ff_formats_unref);
}
int ff_set_common_alpha_modes_from_list(AVFilterContext *ctx,
const int *alpha_modes)
{
return ff_set_common_alpha_modes(ctx, ff_make_format_list(alpha_modes));
}
int ff_set_common_all_alpha_modes(AVFilterContext *ctx)
{
return ff_set_common_alpha_modes(ctx, ff_all_alpha_modes());
}
/**
* A helper for query_formats() which sets all links to the same list of
* formats. If there are no links hooked to this filter, the list of formats is
@@ -1015,6 +1049,30 @@ int ff_set_common_all_color_ranges2(const AVFilterContext *ctx,
return ff_set_common_color_ranges2(ctx, cfg_in, cfg_out, ff_all_color_ranges());
}
int ff_set_common_alpha_modes2(const AVFilterContext *ctx,
AVFilterFormatsConfig **cfg_in,
AVFilterFormatsConfig **cfg_out,
AVFilterFormats *alpha_modes)
{
SET_COMMON_FORMATS2(ctx, cfg_in, cfg_out, alpha_modes, AVMEDIA_TYPE_VIDEO,
ff_formats_ref, ff_formats_unref);
}
int ff_set_common_alpha_modes_from_list2(const AVFilterContext *ctx,
AVFilterFormatsConfig **cfg_in,
AVFilterFormatsConfig **cfg_out,
const int *alpha_modes)
{
return ff_set_common_alpha_modes2(ctx, cfg_in, cfg_out, ff_make_format_list(alpha_modes));
}
int ff_set_common_all_alpha_modes2(const AVFilterContext *ctx,
AVFilterFormatsConfig **cfg_in,
AVFilterFormatsConfig **cfg_out)
{
return ff_set_common_alpha_modes2(ctx, cfg_in, cfg_out, ff_all_alpha_modes());
}
int ff_set_common_formats2(const AVFilterContext *ctx,
AVFilterFormatsConfig **cfg_in,
AVFilterFormatsConfig **cfg_out,
@@ -1080,6 +1138,9 @@ int ff_default_query_formats(AVFilterContext *ctx)
ret = ff_set_common_all_color_ranges(ctx);
if (ret < 0)
return ret;
ret = ff_set_common_all_alpha_modes(ctx);
if (ret < 0)
return ret;
}
if (type != AVMEDIA_TYPE_VIDEO) {
ret = ff_set_common_all_channel_counts(ctx);
@@ -1147,6 +1208,11 @@ int ff_formats_check_color_ranges(void *log, const AVFilterFormats *fmts)
return check_list(log, "color range", fmts);
}
int ff_formats_check_alpha_modes(void *log, const AVFilterFormats *fmts)
{
return check_list(log, "alpha mode", fmts);
}
static int layouts_compatible(const AVChannelLayout *a, const AVChannelLayout *b)
{
return !av_channel_layout_compare(a, b) ||

View File

@@ -144,6 +144,12 @@ AVFilterFormats *ff_all_color_spaces(void);
av_warn_unused_result
AVFilterFormats *ff_all_color_ranges(void);
/**
* Construct an AVFilterFormats representing all possible alpha modes.
*/
av_warn_unused_result
AVFilterFormats *ff_all_alpha_modes(void);
/**
* Helpers for query_formats() which set all free audio links to the same list
* of channel layouts/sample rates. If there are no links hooked to this list,
@@ -211,6 +217,23 @@ int ff_set_common_color_ranges_from_list(AVFilterContext *ctx,
av_warn_unused_result
int ff_set_common_all_color_ranges(AVFilterContext *ctx);
av_warn_unused_result
int ff_set_common_alpha_modes(AVFilterContext *ctx,
AVFilterFormats *alpha_modes);
/**
* Equivalent to ff_set_common_alpha_modes(ctx, ff_make_format_list(alpha_modes))
*/
av_warn_unused_result
int ff_set_common_alpha_modes_from_list(AVFilterContext *ctx,
const int *alpha_modes);
/**
* Equivalent to ff_set_common_alpha_modes(ctx, ff_all_alpha_modes())
*/
av_warn_unused_result
int ff_set_common_all_alpha_modes(AVFilterContext *ctx);
/**
* A helper for query_formats() which sets all links to the same list of
* formats. If there are no links hooked to this filter, the list of formats is
@@ -297,6 +320,23 @@ int ff_set_common_all_color_ranges2(const AVFilterContext *ctx,
AVFilterFormatsConfig **cfg_in,
AVFilterFormatsConfig **cfg_out);
av_warn_unused_result
int ff_set_common_alpha_modes2(const AVFilterContext *ctx,
AVFilterFormatsConfig **cfg_in,
AVFilterFormatsConfig **cfg_out,
AVFilterFormats *alpha_modes);
av_warn_unused_result
int ff_set_common_alpha_modes_from_list2(const AVFilterContext *ctx,
AVFilterFormatsConfig **cfg_in,
AVFilterFormatsConfig **cfg_out,
const int *alpha_modes);
av_warn_unused_result
int ff_set_common_all_alpha_modes2(const AVFilterContext *ctx,
AVFilterFormatsConfig **cfg_in,
AVFilterFormatsConfig **cfg_out);
av_warn_unused_result
int ff_set_common_formats2(const AVFilterContext *ctx,
AVFilterFormatsConfig **cfg_in,
@@ -466,6 +506,13 @@ int ff_formats_check_channel_layouts(void *log, const AVFilterChannelLayouts *fm
int ff_formats_check_color_spaces(void *log, const AVFilterFormats *fmts);
int ff_formats_check_color_ranges(void *log, const AVFilterFormats *fmts);
/**
* Check that fmts is a valid formats list for alpha modes.
*
* In particular, check for duplicates.
*/
int ff_formats_check_alpha_modes(void *log, const AVFilterFormats *fmts);
typedef struct AVFilterFormatMerger {
unsigned offset;
int (*merge)(void *a, void *b);

View File

@@ -31,7 +31,7 @@
#include "version_major.h"
#define LIBAVFILTER_VERSION_MINOR 5
#define LIBAVFILTER_VERSION_MINOR 6
#define LIBAVFILTER_VERSION_MICRO 100

View File

@@ -104,6 +104,7 @@ AVFrame *ff_default_get_video_buffer2(AVFilterLink *link, int w, int h, int alig
frame->sample_aspect_ratio = link->sample_aspect_ratio;
frame->colorspace = link->colorspace;
frame->color_range = link->color_range;
frame->alpha_mode = link->alpha_mode;
return frame;
}