avfilter: add negotiation API for color space/range

Motivated by YUVJ removal. This change will allow full negotiation
between color ranges and matrices as needed. By default, all ranges and
matrices are marked as supported.

Because grayscale formats are currently handled very inconsistently (and
in particular, assumed as forced full-range by swscale), we exclude them
from negotiation altogether for the time being, to get this API merged.

After filter negotiation is available, we can relax the
grayscale-is-forced-jpeg restriction again, when it will be more
feasible to do so without breaking a million test cases.

Note that this commit updates one FATE test as a consequence of the
sanity fallback for non-YUV formats. In particular, the test case now
writes rgb24(pc, gbr/unspecified/unspecified) to the matroska file,
instead of rgb24(unspecified/unspecified/unspecified) as before.
This commit is contained in:
Niklas Haas 2023-12-31 13:35:03 -08:00
parent e687a84854
commit 8c7934f73a
11 changed files with 406 additions and 10 deletions

View File

@ -2,6 +2,9 @@ The last version increases of all libraries were on 2023-02-09
API changes, most recent first:
2023-11-xx - xxxxxxxxxx - lavfi 58.15.100 - avfilter.h
Add AVFilterLink.colorspace, AVFilterLink.color_range
2023-12-xx - xxxxxxxxxx - lavu 58.36.100 - pixfmt.h hwcontext.h hwcontext_d3d12va.h
Add AV_HWDEVICE_TYPE_D3D12VA and AV_PIX_FMT_D3D12.
Add AVD3D12VADeviceContext, AVD3D12VASyncContext, AVD3D12VAFrame and

View File

@ -185,6 +185,7 @@ int avfilter_link(AVFilterContext *src, unsigned srcpad,
link->type = src->output_pads[srcpad].type;
av_assert0(AV_PIX_FMT_NONE == -1 && AV_SAMPLE_FMT_NONE == -1);
link->format = -1;
link->colorspace = AVCOL_SPC_UNSPECIFIED;
ff_framequeue_init(&link->fifo, &src->graph->internal->frame_queues);
return 0;
@ -286,6 +287,12 @@ int avfilter_insert_filter(AVFilterLink *link, AVFilterContext *filt,
if (link->outcfg.formats)
ff_formats_changeref(&link->outcfg.formats,
&filt->outputs[filt_dstpad_idx]->outcfg.formats);
if (link->outcfg.color_spaces)
ff_formats_changeref(&link->outcfg.color_spaces,
&filt->outputs[filt_dstpad_idx]->outcfg.color_spaces);
if (link->outcfg.color_ranges)
ff_formats_changeref(&link->outcfg.color_ranges,
&filt->outputs[filt_dstpad_idx]->outcfg.color_ranges);
if (link->outcfg.samplerates)
ff_formats_changeref(&link->outcfg.samplerates,
&filt->outputs[filt_dstpad_idx]->outcfg.samplerates);
@ -730,6 +737,10 @@ static void free_link(AVFilterLink *link)
ff_formats_unref(&link->incfg.formats);
ff_formats_unref(&link->outcfg.formats);
ff_formats_unref(&link->incfg.color_spaces);
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.samplerates);
ff_formats_unref(&link->outcfg.samplerates);
ff_channel_layouts_unref(&link->incfg.channel_layouts);
@ -987,9 +998,9 @@ int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
strcmp(link->dst->filter->name, "idet") &&
strcmp(link->dst->filter->name, "null") &&
strcmp(link->dst->filter->name, "scale")) {
av_assert1(frame->format == link->format);
av_assert1(frame->width == link->w);
av_assert1(frame->height == link->h);
av_assert1(frame->format == link->format);
av_assert1(frame->width == link->w);
av_assert1(frame->height == link->h);
}
frame->sample_aspect_ratio = link->sample_aspect_ratio;

View File

@ -301,6 +301,14 @@ typedef struct AVFilter {
* @ref AVFilterFormatsConfig.formats "incfg.formats"
* on every output link to a list of pixel/sample formats that the filter
* supports on that link.
* For video links, this filter may also set
* @ref AVFilterFormatsConfig.color_spaces "incfg.color_spaces"
* /
* @ref AVFilterFormatsConfig.color_spaces "outcfg.color_spaces"
* and @ref AVFilterFormatsConfig.color_ranges "incfg.color_ranges"
* /
* @ref AVFilterFormatsConfig.color_ranges "outcfg.color_ranges"
* analogously.
* For audio links, this filter must also set
* @ref AVFilterFormatsConfig.samplerates "incfg.samplerates"
* /
@ -322,6 +330,10 @@ typedef struct AVFilter {
* to indicate that this filter supports each of these pixel formats,
* provided that all inputs and outputs use the same pixel format.
*
* In addition to that the generic code will mark all inputs
* and all outputs as supporting all color spaces and ranges, as
* long as all inputs and outputs use the same color space/range.
*
* This list must never be NULL if the union is in this state.
* The type of all inputs and outputs of filters using this must
* be AVMEDIA_TYPE_VIDEO.
@ -514,6 +526,12 @@ typedef struct AVFilterFormatsConfig {
*/
AVFilterChannelLayouts *channel_layouts;
/**
* Lists of supported YUV color metadata, only for YUV video.
*/
AVFilterFormats *color_spaces; ///< AVColorSpace
AVFilterFormats *color_ranges; ///< AVColorRange
} AVFilterFormatsConfig;
/**
@ -565,6 +583,16 @@ struct AVFilterLink {
AVChannelLayout ch_layout; ///< channel layout of current buffer (see libavutil/channel_layout.h)
/**
* For non-YUV links, these are respectively set to fallback values (as
* appropriate for that colorspace).
*
* Note: This includes grayscale formats, as these are currently treated
* as forced full range always.
*/
enum AVColorSpace colorspace; ///< agreed upon YUV color space
enum AVColorRange color_range; ///< agreed upon YUV color range
/*****************************************************************
* 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

@ -27,6 +27,7 @@
#include "libavutil/avassert.h"
#include "libavutil/bprint.h"
#include "libavutil/channel_layout.h"
#include "libavutil/hwcontext.h"
#include "libavutil/imgutils.h"
#include "libavutil/opt.h"
#include "libavutil/pixdesc.h"
@ -297,7 +298,9 @@ static int filter_link_check_formats(void *log, AVFilterLink *link, AVFilterForm
switch (link->type) {
case AVMEDIA_TYPE_VIDEO:
if ((ret = ff_formats_check_pixel_formats(log, cfg->formats)) < 0)
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)
return ret;
break;
@ -364,6 +367,10 @@ static int formats_declared(AVFilterContext *f)
for (i = 0; i < f->nb_inputs; i++) {
if (!f->inputs[i]->outcfg.formats)
return 0;
if (f->inputs[i]->type == AVMEDIA_TYPE_VIDEO &&
!(f->inputs[i]->outcfg.color_ranges &&
f->inputs[i]->outcfg.color_spaces))
return 0;
if (f->inputs[i]->type == AVMEDIA_TYPE_AUDIO &&
!(f->inputs[i]->outcfg.samplerates &&
f->inputs[i]->outcfg.channel_layouts))
@ -372,6 +379,10 @@ static int formats_declared(AVFilterContext *f)
for (i = 0; i < f->nb_outputs; i++) {
if (!f->outputs[i]->incfg.formats)
return 0;
if (f->outputs[i]->type == AVMEDIA_TYPE_VIDEO &&
!(f->outputs[i]->incfg.color_ranges &&
f->outputs[i]->incfg.color_spaces))
return 0;
if (f->outputs[i]->type == AVMEDIA_TYPE_AUDIO &&
!(f->outputs[i]->incfg.samplerates &&
f->outputs[i]->incfg.channel_layouts))
@ -492,7 +503,16 @@ static int query_formats(AVFilterGraph *graph, void *log_ctx)
av_assert0( inlink->outcfg.formats->refcount > 0);
av_assert0(outlink->incfg.formats->refcount > 0);
av_assert0(outlink->outcfg.formats->refcount > 0);
if (outlink->type == AVMEDIA_TYPE_AUDIO) {
if (outlink->type == AVMEDIA_TYPE_VIDEO) {
av_assert0( inlink-> incfg.color_spaces->refcount > 0);
av_assert0( inlink->outcfg.color_spaces->refcount > 0);
av_assert0(outlink-> incfg.color_spaces->refcount > 0);
av_assert0(outlink->outcfg.color_spaces->refcount > 0);
av_assert0( inlink-> incfg.color_ranges->refcount > 0);
av_assert0( inlink->outcfg.color_ranges->refcount > 0);
av_assert0(outlink-> incfg.color_ranges->refcount > 0);
av_assert0(outlink->outcfg.color_ranges->refcount > 0);
} else if (outlink->type == AVMEDIA_TYPE_AUDIO) {
av_assert0( inlink-> incfg.samplerates->refcount > 0);
av_assert0( inlink->outcfg.samplerates->refcount > 0);
av_assert0(outlink-> incfg.samplerates->refcount > 0);
@ -582,6 +602,30 @@ static enum AVSampleFormat find_best_sample_fmt_of_2(enum AVSampleFormat dst_fmt
return score1 < score2 ? dst_fmt1 : dst_fmt2;
}
int ff_fmt_is_regular_yuv(enum AVPixelFormat fmt)
{
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt);
if (!desc)
return 0;
if (desc->nb_components < 3)
return 0; /* Grayscale is explicitly full-range in swscale */
av_assert1(!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL));
if (desc->flags & (AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_PAL |
AV_PIX_FMT_FLAG_XYZ | AV_PIX_FMT_FLAG_FLOAT))
return 0;
switch (fmt) {
case AV_PIX_FMT_YUVJ420P:
case AV_PIX_FMT_YUVJ422P:
case AV_PIX_FMT_YUVJ444P:
case AV_PIX_FMT_YUVJ440P:
case AV_PIX_FMT_YUVJ411P:
return 0;
default:
return 1;
}
}
static int pick_format(AVFilterLink *link, AVFilterLink *ref)
{
if (!link || !link->incfg.formats)
@ -620,7 +664,46 @@ static int pick_format(AVFilterLink *link, AVFilterLink *ref)
link->incfg.formats->nb_formats = 1;
link->format = link->incfg.formats->formats[0];
if (link->type == AVMEDIA_TYPE_AUDIO) {
if (link->type == AVMEDIA_TYPE_VIDEO) {
enum AVPixelFormat swfmt = link->format;
if (av_pix_fmt_desc_get(swfmt)->flags & AV_PIX_FMT_FLAG_HWACCEL) {
av_assert1(link->hw_frames_ctx);
swfmt = ((AVHWFramesContext *) link->hw_frames_ctx->data)->sw_format;
}
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)
link->color_range = AVCOL_RANGE_UNSPECIFIED;
else
link->color_range = AVCOL_RANGE_JPEG;
if (desc->flags & (AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_XYZ)) {
link->colorspace = AVCOL_SPC_RGB;
} else {
link->colorspace = AVCOL_SPC_UNSPECIFIED;
}
} else {
if (!link->incfg.color_spaces->nb_formats) {
av_log(link->src, AV_LOG_ERROR, "Cannot select color space for"
" the link between filters %s and %s.\n", link->src->name,
link->dst->name);
return AVERROR(EINVAL);
}
link->incfg.color_spaces->nb_formats = 1;
link->colorspace = link->incfg.color_spaces->formats[0];
if (!link->incfg.color_ranges->nb_formats) {
av_log(link->src, AV_LOG_ERROR, "Cannot select color range for"
" the link between filters %s and %s.\n", link->src->name,
link->dst->name);
return AVERROR(EINVAL);
}
link->incfg.color_ranges->nb_formats = 1;
link->color_range = link->incfg.color_ranges->formats[0];
}
} else if (link->type == AVMEDIA_TYPE_AUDIO) {
int ret;
if (!link->incfg.samplerates->nb_formats) {
@ -660,6 +743,10 @@ FF_ENABLE_DEPRECATION_WARNINGS
ff_formats_unref(&link->outcfg.samplerates);
ff_channel_layouts_unref(&link->incfg.channel_layouts);
ff_channel_layouts_unref(&link->outcfg.channel_layouts);
ff_formats_unref(&link->incfg.color_spaces);
ff_formats_unref(&link->outcfg.color_spaces);
ff_formats_unref(&link->incfg.color_ranges);
ff_formats_unref(&link->outcfg.color_ranges);
return 0;
}
@ -821,6 +908,82 @@ static void swap_samplerates(AVFilterGraph *graph)
swap_samplerates_on_filter(graph->filters[i]);
}
static void swap_color_spaces_on_filter(AVFilterContext *filter)
{
AVFilterLink *link = NULL;
enum AVColorSpace csp;
int i;
for (i = 0; i < filter->nb_inputs; i++) {
link = filter->inputs[i];
if (link->type == AVMEDIA_TYPE_VIDEO &&
link->outcfg.color_spaces->nb_formats == 1)
break;
}
if (i == filter->nb_inputs)
return;
csp = link->outcfg.color_spaces->formats[0];
for (i = 0; i < filter->nb_outputs; i++) {
AVFilterLink *outlink = filter->outputs[i];
if (outlink->type != AVMEDIA_TYPE_VIDEO)
continue;
/* there is no meaningful 'score' between different yuv matrices,
* so just prioritize an exact match if it exists */
for (int j = 0; j < outlink->incfg.color_spaces->nb_formats; j++) {
if (csp == outlink->incfg.color_spaces->formats[j]) {
FFSWAP(int, outlink->incfg.color_spaces->formats[0],
outlink->incfg.color_spaces->formats[j]);
break;
}
}
}
}
static void swap_color_spaces(AVFilterGraph *graph)
{
for (int i = 0; i < graph->nb_filters; i++)
swap_color_spaces_on_filter(graph->filters[i]);
}
static void swap_color_ranges_on_filter(AVFilterContext *filter)
{
AVFilterLink *link = NULL;
enum AVColorRange range;
int i;
for (i = 0; i < filter->nb_inputs; i++) {
link = filter->inputs[i];
if (link->type == AVMEDIA_TYPE_VIDEO &&
link->outcfg.color_ranges->nb_formats == 1)
break;
}
if (i == filter->nb_inputs)
return;
range = link->outcfg.color_ranges->formats[0];
for (i = 0; i < filter->nb_outputs; i++) {
AVFilterLink *outlink = filter->outputs[i];
if (outlink->type != AVMEDIA_TYPE_VIDEO)
continue;
for (int j = 0; j < outlink->incfg.color_ranges->nb_formats; j++) {
if (range == outlink->incfg.color_ranges->formats[j]) {
FFSWAP(int, outlink->incfg.color_ranges->formats[0],
outlink->incfg.color_ranges->formats[j]);
break;
}
}
}
}
static void swap_color_ranges(AVFilterGraph *graph)
{
for (int i = 0; i < graph->nb_filters; i++)
swap_color_ranges_on_filter(graph->filters[i]);
}
#define CH_CENTER_PAIR (AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER)
#define CH_FRONT_PAIR (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT)
#define CH_STEREO_PAIR (AV_CH_STEREO_LEFT | AV_CH_STEREO_RIGHT)
@ -1097,6 +1260,10 @@ static int graph_config_formats(AVFilterGraph *graph, void *log_ctx)
if ((ret = reduce_formats(graph)) < 0)
return ret;
/* for video filters, ensure that the best colorspace metadata is selected */
swap_color_spaces(graph);
swap_color_ranges(graph);
/* for audio filters, ensure the best format, sample rate and channel layout
* is selected */
swap_sample_fmts(graph);

View File

@ -321,12 +321,46 @@ static int merge_channel_layouts(void *a, void *b)
return merge_channel_layouts_internal(a, b, 0);
}
static int merge_generic_internal(AVFilterFormats *a,
AVFilterFormats *b, int check)
{
av_assert2(check || (a->refcount && b->refcount));
if (a == b)
return 1;
MERGE_FORMATS(a, b, formats, nb_formats, AVFilterFormats, check, 0);
return 1;
}
static int can_merge_generic(const void *a, const void *b)
{
return merge_generic_internal((AVFilterFormats *)a,
(AVFilterFormats *)b, 1);
}
static int merge_generic(void *a, void *b)
{
return merge_generic_internal(a, b, 0);
}
static const AVFilterFormatsMerger mergers_video[] = {
{
.offset = offsetof(AVFilterFormatsConfig, formats),
.merge = merge_pix_fmts,
.can_merge = can_merge_pix_fmts,
},
{
.offset = offsetof(AVFilterFormatsConfig, color_spaces),
.merge = merge_generic,
.can_merge = can_merge_generic,
},
{
.offset = offsetof(AVFilterFormatsConfig, color_ranges),
.merge = merge_generic,
.can_merge = can_merge_generic,
},
};
static const AVFilterFormatsMerger mergers_audio[] = {
@ -594,6 +628,33 @@ AVFilterChannelLayouts *ff_all_channel_counts(void)
return ret;
}
AVFilterFormats *ff_all_color_spaces(void)
{
AVFilterFormats *ret = NULL;
if (ff_add_format(&ret, AVCOL_SPC_UNSPECIFIED) < 0)
return NULL;
for (int csp = 0; csp < AVCOL_SPC_NB; csp++) {
if (csp == AVCOL_SPC_RESERVED ||
csp == AVCOL_SPC_UNSPECIFIED)
continue;
if (ff_add_format(&ret, csp) < 0)
return NULL;
}
return ret;
}
AVFilterFormats *ff_all_color_ranges(void)
{
AVFilterFormats *ret = NULL;
for (int range = 0; range < AVCOL_RANGE_NB; range++) {
if (ff_add_format(&ret, range) < 0)
return NULL;
}
return ret;
}
#define FORMATS_REF(f, ref, unref_fn) \
void *tmp; \
\
@ -763,6 +824,42 @@ int ff_set_common_all_samplerates(AVFilterContext *ctx)
return ff_set_common_samplerates(ctx, ff_all_samplerates());
}
int ff_set_common_color_spaces(AVFilterContext *ctx,
AVFilterFormats *color_spaces)
{
SET_COMMON_FORMATS(ctx, color_spaces, AVMEDIA_TYPE_VIDEO,
ff_formats_ref, ff_formats_unref);
}
int ff_set_common_color_spaces_from_list(AVFilterContext *ctx,
const int *color_ranges)
{
return ff_set_common_color_spaces(ctx, ff_make_format_list(color_ranges));
}
int ff_set_common_all_color_spaces(AVFilterContext *ctx)
{
return ff_set_common_color_spaces(ctx, ff_all_color_spaces());
}
int ff_set_common_color_ranges(AVFilterContext *ctx,
AVFilterFormats *color_ranges)
{
SET_COMMON_FORMATS(ctx, color_ranges, AVMEDIA_TYPE_VIDEO,
ff_formats_ref, ff_formats_unref);
}
int ff_set_common_color_ranges_from_list(AVFilterContext *ctx,
const int *color_ranges)
{
return ff_set_common_color_ranges(ctx, ff_make_format_list(color_ranges));
}
int ff_set_common_all_color_ranges(AVFilterContext *ctx)
{
return ff_set_common_color_ranges(ctx, ff_all_color_ranges());
}
/**
* 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
@ -818,6 +915,14 @@ int ff_default_query_formats(AVFilterContext *ctx)
ret = ff_set_common_formats(ctx, formats);
if (ret < 0)
return ret;
if (type != AVMEDIA_TYPE_AUDIO) {
ret = ff_set_common_all_color_spaces(ctx);
if (ret < 0)
return ret;
ret = ff_set_common_all_color_ranges(ctx);
if (ret < 0)
return ret;
}
if (type != AVMEDIA_TYPE_VIDEO) {
ret = ff_set_common_all_channel_counts(ctx);
if (ret < 0)
@ -936,6 +1041,22 @@ int ff_formats_check_sample_rates(void *log, const AVFilterFormats *fmts)
return check_list(log, "sample rate", fmts);
}
int ff_formats_check_color_spaces(void *log, const AVFilterFormats *fmts)
{
for (int i = 0; fmts && i < fmts->nb_formats; i++) {
if (fmts->formats[i] == AVCOL_SPC_RESERVED) {
av_log(log, AV_LOG_ERROR, "Invalid color range\n");
return AVERROR(EINVAL);
}
}
return check_list(log, "color space", fmts);
}
int ff_formats_check_color_ranges(void *log, const AVFilterFormats *fmts)
{
return check_list(log, "color range", fmts);
}
static int layouts_compatible(const AVChannelLayout *a, const AVChannelLayout *b)
{
return !av_channel_layout_compare(a, b) ||

View File

@ -130,6 +130,20 @@ AVFilterChannelLayouts *ff_all_channel_counts(void);
av_warn_unused_result
AVFilterChannelLayouts *ff_make_channel_layout_list(const AVChannelLayout *fmts);
/**
* Construct an AVFilterFormats representing all possible color spaces.
*
* Note: This list does not include AVCOL_SPC_RESERVED.
*/
av_warn_unused_result
AVFilterFormats *ff_all_color_spaces(void);
/**
* Construct an AVFilterFormats representing all possible color ranges.
*/
av_warn_unused_result
AVFilterFormats *ff_all_color_ranges(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,
@ -165,6 +179,38 @@ int ff_set_common_samplerates_from_list(AVFilterContext *ctx,
av_warn_unused_result
int ff_set_common_all_samplerates(AVFilterContext *ctx);
av_warn_unused_result
int ff_set_common_color_spaces(AVFilterContext *ctx,
AVFilterFormats *color_spaces);
/**
* Equivalent to ff_set_common_color_spaces(ctx, ff_make_format_list(color_spaces))
*/
av_warn_unused_result
int ff_set_common_color_spaces_from_list(AVFilterContext *ctx,
const int *color_spaces);
/**
* Equivalent to ff_set_common_color_spaces(ctx, ff_all_color_spaces())
*/
av_warn_unused_result
int ff_set_common_all_color_spaces(AVFilterContext *ctx);
av_warn_unused_result
int ff_set_common_color_ranges(AVFilterContext *ctx,
AVFilterFormats *color_ranges);
/**
* Equivalent to ff_set_common_color_ranges(ctx, ff_make_format_list(color_ranges))
*/
av_warn_unused_result
int ff_set_common_color_ranges_from_list(AVFilterContext *ctx,
const int *color_ranges);
/**
* Equivalent to ff_set_common_color_ranges(ctx, ff_all_color_ranges())
*/
av_warn_unused_result
int ff_set_common_all_color_ranges(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
@ -328,6 +374,14 @@ int ff_formats_check_sample_rates(void *log, const AVFilterFormats *fmts);
*/
int ff_formats_check_channel_layouts(void *log, const AVFilterChannelLayouts *fmts);
/**
* Check that fmts is a valid formats list for YUV colorspace metadata.
*
* In particular, check for duplicates.
*/
int ff_formats_check_color_spaces(void *log, const AVFilterFormats *fmts);
int ff_formats_check_color_ranges(void *log, const AVFilterFormats *fmts);
typedef struct AVFilterFormatMerger {
unsigned offset;
int (*merge)(void *a, void *b);

View File

@ -203,6 +203,12 @@ enum FilterFormatsState {
*/
int ff_fmt_is_in(int fmt, const int *fmts);
/**
* Returns true if a pixel format is "regular YUV", which includes all pixel
* formats that are affected by YUV colorspace negotiation.
*/
int ff_fmt_is_regular_yuv(enum AVPixelFormat fmt);
/* Functions to parse audio format arguments */
/**

View File

@ -38,6 +38,10 @@ int ff_vaapi_vpp_query_formats(AVFilterContext *avctx)
&avctx->outputs[0]->incfg.formats)) < 0)
return err;
if ((err = ff_set_common_all_color_spaces(avctx)) < 0 ||
(err = ff_set_common_all_color_ranges(avctx)) < 0)
return err;
return 0;
}

View File

@ -31,8 +31,8 @@
#include "version_major.h"
#define LIBAVFILTER_VERSION_MINOR 14
#define LIBAVFILTER_VERSION_MICRO 102
#define LIBAVFILTER_VERSION_MINOR 15
#define LIBAVFILTER_VERSION_MICRO 100
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \

View File

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

View File

@ -1,5 +1,5 @@
73d142a80965f9e0884a5863abde0dab *tests/data/fate/shortest-sub.matroska
139249 tests/data/fate/shortest-sub.matroska
d6608277c93097383e62388196dc62f0 *tests/data/fate/shortest-sub.matroska
139260 tests/data/fate/shortest-sub.matroska
#extradata 1: 167, 0xf7272d5f
#tb 0: 1/1000
#media_type 0: video