diff --git a/doc/APIchanges b/doc/APIchanges index c33e27fe79..b8895142ed 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -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 diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index bde1c33d07..31300bb515 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -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; diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h index d69381aed4..246d000251 100644 --- a/libavfilter/avfilter.h +++ b/libavfilter/avfilter.h @@ -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 diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c index 114dfaa655..727eff81ee 100644 --- a/libavfilter/avfiltergraph.c +++ b/libavfilter/avfiltergraph.c @@ -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); diff --git a/libavfilter/formats.c b/libavfilter/formats.c index 114886aeb2..681f0b1203 100644 --- a/libavfilter/formats.c +++ b/libavfilter/formats.c @@ -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) || diff --git a/libavfilter/formats.h b/libavfilter/formats.h index d44890109e..82b3af4be1 100644 --- a/libavfilter/formats.h +++ b/libavfilter/formats.h @@ -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); diff --git a/libavfilter/internal.h b/libavfilter/internal.h index 4e36df6189..dcc7fb1df4 100644 --- a/libavfilter/internal.h +++ b/libavfilter/internal.h @@ -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 */ /** diff --git a/libavfilter/vaapi_vpp.c b/libavfilter/vaapi_vpp.c index cf2592e068..59961bfa4a 100644 --- a/libavfilter/vaapi_vpp.c +++ b/libavfilter/vaapi_vpp.c @@ -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; } diff --git a/libavfilter/version.h b/libavfilter/version.h index aa0bfc2df7..59330858bd 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -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, \ diff --git a/libavfilter/video.c b/libavfilter/video.c index 42eeb98c28..243762c8fd 100644 --- a/libavfilter/video.c +++ b/libavfilter/video.c @@ -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; } diff --git a/tests/ref/fate/shortest-sub b/tests/ref/fate/shortest-sub index 9caee587ce..16b1324e83 100644 --- a/tests/ref/fate/shortest-sub +++ b/tests/ref/fate/shortest-sub @@ -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