On 12/11/17, Nicolas George <geo...@nsup.org> wrote: > I do not have time to look at the code in details right now, and I do > not know when I will have time, but here are a few remarks. > > Paul B Mahol (2017-12-11): >> Signed-off-by: Paul B Mahol <one...@gmail.com> >> --- >> >> This is with color range negotiation. >> To be applied on top of previous patch set. >> It fixes issue Michael found. > >> This needs more work as every filter needs its query_formats() changed. > > This is annoying. Could you not get the framework set a reasonable value > (all supported) when the list is not set?
Done locally. > >> >> --- >> fftools/ffmpeg_filter.c | 13 +++------- >> libavfilter/avfilter.c | 9 ++++--- >> libavfilter/avfilter.h | 4 ++- >> libavfilter/avfiltergraph.c | 34 ++++++++++++++++++++++++ >> libavfilter/buffersink.c | 16 ++++++++++++ >> libavfilter/buffersink.h | 1 + >> libavfilter/buffersrc.c | 4 +++ >> libavfilter/formats.c | 63 >> +++++++++++++++++++++++++++++++++++++++++++++ >> libavfilter/formats.h | 31 ++++++++++++++++++++++ >> libavfilter/internal.h | 11 ++++++++ >> libavfilter/vf_format.c | 46 ++++++++++++++++++++++++++++++++- >> libavfilter/vf_noise.c | 6 ++++- >> libavfilter/vf_scale.c | 19 +++++++++++--- >> libavfilter/vsrc_testsrc.c | 15 +++++++++-- >> 14 files changed, 251 insertions(+), 21 deletions(-) >> >> diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c >> index 3aad564b81..a8fbcdecfb 100644 >> --- a/fftools/ffmpeg_filter.c >> +++ b/fftools/ffmpeg_filter.c >> @@ -144,6 +144,8 @@ static char *choose_pix_fmts(OutputFilter *ofilter) >> const char *name = av_get_pix_fmt_name(*p); >> avio_printf(s, "%s|", name); >> } >> + if (av_color_range_name(ost->enc->color_range)) >> + avio_printf(s, ":color_ranges=%s|", >> av_color_range_name(ost->enc->color_range)); >> len = avio_close_dyn_buf(s, &ret); >> ret[len - 1] = 0; >> return ret; >> @@ -447,7 +449,6 @@ static int configure_output_video_filter(FilterGraph >> *fg, OutputFilter *ofilter, >> OutputStream *ost = ofilter->ost; >> OutputFile *of = output_files[ost->file_index]; >> AVFilterContext *last_filter = out->filter_ctx; >> - AVDictionaryEntry *cre = NULL; >> int pad_idx = out->pad_idx; >> int ret; >> char name[255]; >> @@ -460,9 +461,7 @@ static int configure_output_video_filter(FilterGraph >> *fg, OutputFilter *ofilter, >> if (ret < 0) >> return ret; >> >> - cre = av_dict_get(ost->encoder_opts, "color_range", NULL, 0); >> - >> - if (ofilter->width || ofilter->height || (cre && cre->value) || >> ost->enc->color_range) { >> + if (ofilter->width || ofilter->height) { >> char args[255]; >> AVFilterContext *filter; >> AVDictionaryEntry *e = NULL; >> @@ -475,12 +474,6 @@ static int configure_output_video_filter(FilterGraph >> *fg, OutputFilter *ofilter, >> av_strlcatf(args, sizeof(args), ":%s=%s", e->key, e->value); >> } >> >> - if (cre && cre->value) { >> - av_strlcatf(args, sizeof(args), ":out_range=%s", >> cre->value); >> - } else if (ost->enc->color_range) { >> - av_strlcatf(args, sizeof(args), ":out_range=%s", >> av_color_range_name(ost->enc->color_range)); >> - } >> - >> snprintf(name, sizeof(name), "scaler_out_%d_%d", >> ost->file_index, ost->index); >> if ((ret = avfilter_graph_create_filter(&filter, >> avfilter_get_by_name("scale"), >> diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c >> index 4a579bb49d..c3a19d100c 100644 >> --- a/libavfilter/avfilter.c >> +++ b/libavfilter/avfilter.c >> @@ -262,6 +262,9 @@ int avfilter_insert_filter(AVFilterLink *link, >> AVFilterContext *filt, >> if (link->out_formats) >> ff_formats_changeref(&link->out_formats, >> >> &filt->outputs[filt_dstpad_idx]->out_formats); >> + if (link->out_color_ranges) >> + ff_formats_changeref(&link->out_color_ranges, >> + >> &filt->outputs[filt_dstpad_idx]->out_color_ranges); >> if (link->out_samplerates) >> ff_formats_changeref(&link->out_samplerates, >> >> &filt->outputs[filt_dstpad_idx]->out_samplerates); >> @@ -785,6 +788,8 @@ static void free_link(AVFilterLink *link) >> >> ff_formats_unref(&link->in_formats); >> ff_formats_unref(&link->out_formats); >> + ff_formats_unref(&link->in_color_ranges); >> + ff_formats_unref(&link->out_color_ranges); >> ff_formats_unref(&link->in_samplerates); >> ff_formats_unref(&link->out_samplerates); >> ff_channel_layouts_unref(&link->in_channel_layouts); >> @@ -970,9 +975,7 @@ int avfilter_init_str(AVFilterContext *filter, const >> char *args) >> } >> >> #if FF_API_OLD_FILTER_OPTS_ERROR >> - if ( !strcmp(filter->filter->name, "format") || >> - !strcmp(filter->filter->name, "noformat") || >> - !strcmp(filter->filter->name, "frei0r") || >> + if ( !strcmp(filter->filter->name, "frei0r") || >> !strcmp(filter->filter->name, "frei0r_src") || >> !strcmp(filter->filter->name, "ocv") || >> !strcmp(filter->filter->name, "pan") || >> diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h >> index 40ad28ffd8..138bdeb5c9 100644 >> --- a/libavfilter/avfilter.h >> +++ b/libavfilter/avfilter.h >> @@ -456,7 +456,7 @@ struct AVFilterLink { >> ***************************************************************** >> */ >> /** >> - * Lists of formats and channel layouts supported by the input and >> output >> + * Lists of formats, color_ranges and channel layouts supported by >> the input and output >> * filters respectively. These lists are used for negotiating the >> format >> * to actually be used, which will be loaded into the format and >> * channel_layout members, above, when chosen. >> @@ -464,6 +464,8 @@ struct AVFilterLink { >> */ >> AVFilterFormats *in_formats; >> AVFilterFormats *out_formats; >> + AVFilterFormats *in_color_ranges; >> + AVFilterFormats *out_color_ranges; >> >> /** >> * Lists of channel layouts and sample rates used for automatic >> diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c >> index a959a9ef3f..ee5ddebe22 100644 >> --- a/libavfilter/avfiltergraph.c >> +++ b/libavfilter/avfiltergraph.c >> @@ -360,6 +360,9 @@ static int formats_declared(AVFilterContext *f) >> !(f->inputs[i]->out_samplerates && >> f->inputs[i]->out_channel_layouts)) >> return 0; >> + if (f->inputs[i]->type == AVMEDIA_TYPE_VIDEO && >> + !(f->inputs[i]->out_color_ranges)) >> + return 0; >> } >> for (i = 0; i < f->nb_outputs; i++) { >> if (!f->outputs[i]->in_formats) >> @@ -368,6 +371,9 @@ static int formats_declared(AVFilterContext *f) >> !(f->outputs[i]->in_samplerates && >> f->outputs[i]->in_channel_layouts)) >> return 0; >> + if (f->outputs[i]->type == AVMEDIA_TYPE_VIDEO && >> + !(f->outputs[i]->in_color_ranges)) >> + return 0; >> } >> return 1; >> } >> @@ -485,6 +491,15 @@ static int query_formats(AVFilterGraph *graph, >> AVClass *log_ctx) >> convert_needed = 1; >> } >> >> + if (link->type == AVMEDIA_TYPE_VIDEO) { >> + if (link->in_color_ranges != link->out_color_ranges >> + && link->in_color_ranges && link->out_color_ranges) >> + if (!can_merge_formats(link->in_color_ranges, >> + link->out_color_ranges, >> + 0, 1)) >> + convert_needed = 1; >> + } >> + >> #define MERGE_DISPATCH(field, statement) >> \ >> if (!(link->in_ ## field && link->out_ ## field)) { >> \ >> count_delayed++; >> \ >> @@ -507,6 +522,13 @@ static int query_formats(AVFilterGraph *graph, >> AVClass *log_ctx) >> convert_needed = 1; >> ) >> } >> + if (link->type == AVMEDIA_TYPE_VIDEO) { >> + MERGE_DISPATCH(color_ranges, > >> + if (!ff_merge_samplerates(link->in_color_ranges, >> + link->out_color_ranges)) > > Did you use ff_merge_samplerates() instead of ff_merge_formats on > purpose? IIRC, ff_merge_samplerates() makes a special case. ff_merge_samplerates expect list that ends with -1. ff_merge_formats expect pix_fmts for video type. > >> + convert_needed = 1; >> + ) >> + } >> MERGE_DISPATCH(formats, >> if (!ff_merge_formats(link->in_formats, >> link->out_formats, >> link->type)) >> @@ -580,6 +602,12 @@ static int query_formats(AVFilterGraph *graph, >> AVClass *log_ctx) >> av_assert0( inlink->out_formats->refcount > 0); >> av_assert0(outlink-> in_formats->refcount > 0); >> av_assert0(outlink->out_formats->refcount > 0); >> + if (outlink->type == AVMEDIA_TYPE_VIDEO) { >> + av_assert0( inlink-> in_color_ranges->refcount > 0); >> + av_assert0( inlink->out_color_ranges->refcount > 0); >> + av_assert0(outlink-> in_color_ranges->refcount > 0); >> + av_assert0(outlink->out_color_ranges->refcount > 0); >> + } >> if (outlink->type == AVMEDIA_TYPE_AUDIO) { >> av_assert0( inlink-> in_samplerates->refcount > 0); >> av_assert0( inlink->out_samplerates->refcount > 0); >> @@ -593,6 +621,12 @@ static int query_formats(AVFilterGraph *graph, >> AVClass *log_ctx) >> if (!ff_merge_formats( inlink->in_formats, >> inlink->out_formats, inlink->type) || >> !ff_merge_formats(outlink->in_formats, >> outlink->out_formats, outlink->type)) >> ret = AVERROR(ENOSYS); >> + if (inlink->type == AVMEDIA_TYPE_VIDEO && >> + (!ff_merge_samplerates(inlink->in_color_ranges, >> inlink->out_color_ranges))) >> + ret = AVERROR(ENOSYS); >> + if (outlink->type == AVMEDIA_TYPE_VIDEO && >> + (!ff_merge_samplerates(outlink->in_color_ranges, >> outlink->out_color_ranges))) >> + ret = AVERROR(ENOSYS); >> if (inlink->type == AVMEDIA_TYPE_AUDIO && >> (!ff_merge_samplerates(inlink->in_samplerates, >> inlink->out_samplerates) || >> diff --git a/libavfilter/buffersink.c b/libavfilter/buffersink.c >> index 897396cac4..8fe109106b 100644 >> --- a/libavfilter/buffersink.c >> +++ b/libavfilter/buffersink.c >> @@ -45,6 +45,8 @@ typedef struct BufferSinkContext { >> /* only used for video */ >> enum AVPixelFormat *pixel_fmts; ///< list of accepted pixel >> formats, must be terminated with -1 >> int pixel_fmts_size; >> + enum AVColorRange *color_ranges; ///< list of accepted color >> ranges, must be terminated with 0 >> + int color_ranges_size; >> >> /* only used for audio */ >> enum AVSampleFormat *sample_fmts; ///< list of accepted sample >> formats, terminated by AV_SAMPLE_FMT_NONE >> @@ -130,11 +132,13 @@ int attribute_align_arg >> av_buffersink_get_samples(AVFilterContext *ctx, >> AVBufferSinkParams *av_buffersink_params_alloc(void) >> { >> static const int pixel_fmts[] = { AV_PIX_FMT_NONE }; >> + static const int color_ranges[] = { -1}; >> AVBufferSinkParams *params = av_malloc(sizeof(AVBufferSinkParams)); >> if (!params) >> return NULL; >> >> params->pixel_fmts = pixel_fmts; >> + params->color_ranges = color_ranges; >> return params; >> } >> >> @@ -211,6 +215,8 @@ static av_cold int vsink_init(AVFilterContext *ctx, >> void *opaque) >> if (params) { >> if ((ret = av_opt_set_int_list(buf, "pix_fmts", >> params->pixel_fmts, AV_PIX_FMT_NONE, 0)) < 0) >> return ret; >> + if ((ret = av_opt_set_int_list(buf, "color_ranges", >> params->color_ranges, -1, 0)) < 0) >> + return ret; >> } >> >> return common_init(ctx); >> @@ -227,16 +233,25 @@ static int vsink_query_formats(AVFilterContext >> *ctx) >> { >> BufferSinkContext *buf = ctx->priv; >> AVFilterFormats *formats = NULL; >> + AVFilterFormats *color_ranges = NULL; >> unsigned i; >> int ret; >> >> CHECK_LIST_SIZE(pixel_fmts) >> + CHECK_LIST_SIZE(color_ranges) >> if (buf->pixel_fmts_size) { >> for (i = 0; i < NB_ITEMS(buf->pixel_fmts); i++) >> if ((ret = ff_add_format(&formats, buf->pixel_fmts[i])) < 0) >> return ret; >> if ((ret = ff_set_common_formats(ctx, formats)) < 0) >> return ret; >> + } >> + if (buf->color_ranges_size) { >> + for (i = 0; i < NB_ITEMS(buf->color_ranges); i++) >> + if ((ret = ff_add_format(&color_ranges, >> buf->color_ranges[i])) < 0) >> + return ret; >> + if ((ret = ff_set_common_color_ranges(ctx, color_ranges)) < 0) >> + return ret; >> } else { >> if ((ret = ff_default_query_formats(ctx)) < 0) >> return ret; >> @@ -318,6 +333,7 @@ static int asink_query_formats(AVFilterContext *ctx) >> #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM >> static const AVOption buffersink_options[] = { >> { "pix_fmts", "set the supported pixel formats", OFFSET(pixel_fmts), >> AV_OPT_TYPE_BINARY, .flags = FLAGS }, >> + { "color_ranges", "set the supported color ranges", >> OFFSET(color_ranges), AV_OPT_TYPE_BINARY, .flags = FLAGS }, >> { NULL }, >> }; >> #undef FLAGS >> diff --git a/libavfilter/buffersink.h b/libavfilter/buffersink.h >> index e6d6504832..3a74a039a2 100644 >> --- a/libavfilter/buffersink.h >> +++ b/libavfilter/buffersink.h >> @@ -64,6 +64,7 @@ int av_buffersink_get_frame_flags(AVFilterContext *ctx, >> AVFrame *frame, int flag >> */ >> typedef struct AVBufferSinkParams { >> const enum AVPixelFormat *pixel_fmts; ///< list of allowed pixel >> formats, terminated by AV_PIX_FMT_NONE >> + const enum AVPixelFormat *color_ranges; ///< list of allowed color >> ranges, terminated by AVCOL_RANGE_UNSPECIFIED >> } AVBufferSinkParams; >> >> /** >> diff --git a/libavfilter/buffersrc.c b/libavfilter/buffersrc.c >> index 51a1a9fb49..e450a2bca7 100644 >> --- a/libavfilter/buffersrc.c >> +++ b/libavfilter/buffersrc.c >> @@ -412,6 +412,7 @@ static int query_formats(AVFilterContext *ctx) >> BufferSourceContext *c = ctx->priv; >> AVFilterChannelLayouts *channel_layouts = NULL; >> AVFilterFormats *formats = NULL; >> + AVFilterFormats *color_ranges = NULL; >> AVFilterFormats *samplerates = NULL; >> int ret; >> >> @@ -420,6 +421,9 @@ static int query_formats(AVFilterContext *ctx) >> if ((ret = ff_add_format (&formats, c->pix_fmt)) < 0 || >> (ret = ff_set_common_formats (ctx , formats )) < 0) >> return ret; >> + if ((ret = ff_add_format (&color_ranges, c->color_range)) >> < 0 || >> + (ret = ff_set_common_color_ranges(ctx, color_ranges)) < 0) >> + return ret; >> break; >> case AVMEDIA_TYPE_AUDIO: >> if ((ret = ff_add_format (&formats , c->sample_fmt >> )) < 0 || >> diff --git a/libavfilter/formats.c b/libavfilter/formats.c >> index d4de862237..560b348524 100644 >> --- a/libavfilter/formats.c >> +++ b/libavfilter/formats.c >> @@ -289,6 +289,15 @@ AVFilterFormats *ff_make_format_list(const int >> *fmts) >> return formats; >> } >> > >> +AVFilterFormats *ff_make_color_range_list(const int *fmts) > > Looks strange. It seems you are aiming for type safety, but the > parameter is still int. Using enum will not work with -1 to signal end of list. > >> +{ >> + MAKE_FORMAT_LIST(AVFilterFormats, formats, nb_formats); >> + while (count--) >> + formats->formats[count] = fmts[count]; >> + >> + return formats; >> +} >> + >> AVFilterChannelLayouts *ff_make_formatu64_list(const uint64_t *fmts) >> { >> MAKE_FORMAT_LIST(AVFilterChannelLayouts, >> @@ -398,6 +407,37 @@ AVFilterFormats *ff_all_samplerates(void) >> return ret; >> } >> > >> +AVFilterFormats *ff_jpeg_color_ranges(void) >> +{ >> + AVFilterFormats *ret = NULL; >> + >> + if (ff_add_format(&ret, AVCOL_RANGE_JPEG) < 0) >> + return NULL; >> + >> + return ret; >> +} >> + >> +AVFilterFormats *ff_mpeg_color_ranges(void) >> +{ >> + AVFilterFormats *ret = NULL; >> + >> + if (ff_add_format(&ret, AVCOL_RANGE_MPEG) < 0) >> + return NULL; >> + >> + return ret; > > I think one function to return a list with a single element would be > more convenient. Do we not already have that? Looks like not. > >> +} >> + >> +AVFilterFormats *ff_all_color_ranges(void) >> +{ >> + AVFilterFormats *fmts = NULL; >> + int ret; >> + >> + ret = ff_add_format(&fmts, AVCOL_RANGE_UNSPECIFIED); >> + ret = ff_add_format(&fmts, AVCOL_RANGE_MPEG); >> + ret = ff_add_format(&fmts, AVCOL_RANGE_JPEG); >> + return fmts; >> +} >> + >> AVFilterChannelLayouts *ff_all_channel_layouts(void) >> { >> AVFilterChannelLayouts *ret = av_mallocz(sizeof(*ret)); >> @@ -560,6 +600,13 @@ int ff_set_common_samplerates(AVFilterContext *ctx, >> ff_formats_ref, ff_formats_unref, formats); >> } >> >> +int ff_set_common_color_ranges(AVFilterContext *ctx, >> + AVFilterFormats *color_ranges) >> +{ >> + SET_COMMON_FORMATS(ctx, color_ranges, in_color_ranges, >> out_color_ranges, >> + ff_formats_ref, ff_formats_unref, formats); >> +} >> + >> /** >> * 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 >> @@ -590,6 +637,11 @@ static int >> default_query_formats_common(AVFilterContext *ctx, >> if (ret < 0) >> return ret; >> } >> + if (type == AVMEDIA_TYPE_VIDEO) { >> + ret = ff_set_common_color_ranges(ctx, ff_all_color_ranges()); >> + if (ret < 0) >> + return ret; >> + } >> >> return 0; >> } >> @@ -659,6 +711,17 @@ int ff_parse_sample_rate(int *ret, const char *arg, >> void *log_ctx) >> return 0; >> } >> >> +int ff_parse_color_range(int *ret, const char *arg, void *log_ctx) >> +{ >> + int color_range = av_color_range_from_name(arg); >> + if (color_range < 0) { >> + av_log(log_ctx, AV_LOG_ERROR, "Invalid color range '%s'\n", >> arg); >> + return AVERROR(EINVAL); >> + } >> + *ret = color_range; >> + return 0; >> +} >> + >> int ff_parse_channel_layout(int64_t *ret, int *nret, const char *arg, >> void *log_ctx) >> { >> diff --git a/libavfilter/formats.h b/libavfilter/formats.h >> index 870809b5a0..6706f76dce 100644 >> --- a/libavfilter/formats.h >> +++ b/libavfilter/formats.h >> @@ -166,6 +166,9 @@ av_warn_unused_result >> int ff_set_common_formats(AVFilterContext *ctx, AVFilterFormats >> *formats); >> >> av_warn_unused_result >> +int ff_set_common_color_ranges(AVFilterContext *ctx, AVFilterFormats >> *color_ranges); >> + >> +av_warn_unused_result >> int ff_add_channel_layout(AVFilterChannelLayouts **l, uint64_t >> channel_layout); >> >> /** >> @@ -205,6 +208,16 @@ av_warn_unused_result >> AVFilterFormats *ff_make_format_list(const int *fmts); >> >> /** >> + * Create a list of supported color ranges. This is intended for use in >> + * AVFilter->query_formats(). >> + * >> + * @param fmts list of color ranges, terminated by -1 >> + * @return the format list, with no existing references >> + */ >> +av_warn_unused_result >> +AVFilterFormats *ff_make_color_range_list(const int *color_ranges); >> + >> +/** >> * Add fmt to the list of media formats contained in *avff. >> * If *avff is NULL the function allocates the filter formats struct >> * and puts its pointer in *avff. >> @@ -222,6 +235,24 @@ av_warn_unused_result >> AVFilterFormats *ff_all_formats(enum AVMediaType type); >> >> /** >> + * Return a list of all color ranges supported by FFmpeg. >> + */ >> +av_warn_unused_result >> +AVFilterFormats *ff_all_color_ranges(void); >> + >> +/** >> + * Return a list of all mpeg color ranges supported by FFmpeg. >> + */ >> +av_warn_unused_result >> +AVFilterFormats *ff_mpeg_color_ranges(void); >> + >> +/** >> + * Return a list of all jpeg color ranges supported by FFmpeg. >> + */ >> +av_warn_unused_result >> +AVFilterFormats *ff_jpeg_color_ranges(void); >> + >> +/** >> * Construct a formats list containing all planar sample formats. >> */ >> av_warn_unused_result >> diff --git a/libavfilter/internal.h b/libavfilter/internal.h >> index f9679ed1d7..ca806d9443 100644 >> --- a/libavfilter/internal.h >> +++ b/libavfilter/internal.h >> @@ -191,6 +191,17 @@ av_warn_unused_result >> int ff_parse_sample_rate(int *ret, const char *arg, void *log_ctx); >> >> /** >> + * Parse a color range. >> + * >> + * @param ret unsigned enum pointer to where the value should be written >> + * @param arg string to parse >> + * @param log_ctx log context >> + * @return >= 0 in case of success, a negative AVERROR code on error >> + */ >> +av_warn_unused_result >> +int ff_parse_color_range(int *ret, const char *arg, void *log_ctx); >> + >> +/** >> * Parse a time base. >> * >> * @param ret unsigned AVRational pointer to where the value should be >> written >> diff --git a/libavfilter/vf_format.c b/libavfilter/vf_format.c >> index a57c99d797..067c03aa5a 100644 >> --- a/libavfilter/vf_format.c >> +++ b/libavfilter/vf_format.c >> @@ -38,18 +38,21 @@ >> typedef struct FormatContext { >> const AVClass *class; >> char *pix_fmts; >> + char *color_ranges_str; >> >> /** >> * pix_fmts parsed into AVPixelFormats and terminated with >> * AV_PIX_FMT_NONE >> */ >> enum AVPixelFormat *formats; >> + int *color_ranges; >> } FormatContext; >> >> static av_cold void uninit(AVFilterContext *ctx) >> { >> FormatContext *s = ctx->priv; >> av_freep(&s->formats); >> + av_freep(&s->color_ranges); >> } >> >> static av_cold int init(AVFilterContext *ctx) >> @@ -57,6 +60,7 @@ static av_cold int init(AVFilterContext *ctx) >> FormatContext *s = ctx->priv; >> char *cur, *sep; >> int nb_formats = 1; >> + int nb_color_ranges = 1; >> int i; >> int ret; >> >> @@ -91,6 +95,37 @@ static av_cold int init(AVFilterContext *ctx) >> } >> s->formats[nb_formats] = AV_PIX_FMT_NONE; >> >> + if (!s->color_ranges_str) { >> + av_log(ctx, AV_LOG_ERROR, "Empty output color range string.\n"); >> + return AVERROR(EINVAL); >> + } >> + >> + /* count the color ranges */ >> + cur = s->color_ranges_str; >> + while ((cur = strchr(cur, '|'))) { >> + nb_color_ranges++; >> + if (*cur) >> + cur++; >> + } >> + >> + s->color_ranges = av_malloc_array(nb_color_ranges + 1, >> sizeof(*s->color_ranges)); >> + if (!s->color_ranges) >> + return AVERROR(ENOMEM); >> + >> + /* parse the list of formats */ >> + cur = s->color_ranges_str; >> + for (i = 0; i < nb_color_ranges; i++) { >> + sep = strchr(cur, '|'); >> + if (sep) >> + *sep++ = 0; >> + >> + if ((ret = ff_parse_color_range(&s->color_ranges[i], cur, ctx)) < >> 0) >> + return ret; >> + >> + cur = sep; >> + } >> + s->color_ranges[nb_color_ranges] = -1; >> + >> if (!strcmp(ctx->filter->name, "noformat")) { >> const AVPixFmtDescriptor *desc = NULL; >> enum AVPixelFormat *formats_allowed; >> @@ -130,17 +165,26 @@ static int query_formats(AVFilterContext *ctx) >> { >> FormatContext *s = ctx->priv; >> AVFilterFormats *formats = ff_make_format_list(s->formats); >> + AVFilterFormats *color_ranges = >> ff_make_color_range_list(s->color_ranges); >> + int ret; >> >> if (!formats) >> return AVERROR(ENOMEM); >> >> - return ff_set_common_formats(ctx, formats); >> + ret = ff_set_common_formats(ctx, formats); >> + if (ret < 0) >> + return ret; >> + >> + if (!color_ranges) >> + return AVERROR(ENOMEM); >> + return ff_set_common_color_ranges(ctx, color_ranges); >> } >> >> >> #define OFFSET(x) offsetof(FormatContext, x) >> static const AVOption options[] = { >> { "pix_fmts", "A '|'-separated list of pixel formats", >> OFFSET(pix_fmts), AV_OPT_TYPE_STRING, .flags = AV_OPT_FLAG_VIDEO_PARAM | >> AV_OPT_FLAG_FILTERING_PARAM }, >> + { "color_ranges", "A '|'-separated list of color ranges", >> OFFSET(color_ranges_str), AV_OPT_TYPE_STRING, .flags = >> AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM }, >> { NULL } >> }; >> >> diff --git a/libavfilter/vf_noise.c b/libavfilter/vf_noise.c >> index abdf04708b..c7af77b669 100644 >> --- a/libavfilter/vf_noise.c >> +++ b/libavfilter/vf_noise.c >> @@ -142,7 +142,11 @@ static int query_formats(AVFilterContext *ctx) >> return ret; >> } >> >> - return ff_set_common_formats(ctx, formats); >> + ret = ff_set_common_formats(ctx, formats); >> + if (ret < 0) >> + return ret; >> + >> + return ff_set_common_color_ranges(ctx, ff_all_color_ranges()); >> } >> >> static int config_input(AVFilterLink *inlink) >> diff --git a/libavfilter/vf_scale.c b/libavfilter/vf_scale.c >> index 802f841cc3..a571673b37 100644 >> --- a/libavfilter/vf_scale.c >> +++ b/libavfilter/vf_scale.c >> @@ -157,7 +157,9 @@ static av_cold void uninit(AVFilterContext *ctx) >> >> static int query_formats(AVFilterContext *ctx) >> { >> + ScaleContext *scale = ctx->priv; >> AVFilterFormats *formats; >> + AVFilterFormats *color_ranges; >> enum AVPixelFormat pix_fmt; >> int ret; >> >> @@ -174,10 +176,14 @@ static int query_formats(AVFilterContext *ctx) >> } >> if ((ret = ff_formats_ref(formats, &ctx->inputs[0]->out_formats)) >> < 0) >> return ret; >> + color_ranges = ff_all_color_ranges(); >> + if ((ret = ff_formats_ref(color_ranges, >> &ctx->inputs[0]->out_color_ranges)) < 0) >> + return ret; >> } >> if (ctx->outputs[0]) { >> const AVPixFmtDescriptor *desc = NULL; >> formats = NULL; >> + color_ranges = NULL; >> while ((desc = av_pix_fmt_desc_next(desc))) { >> pix_fmt = av_pix_fmt_desc_get_id(desc); >> if ((sws_isSupportedOutput(pix_fmt) || pix_fmt == >> AV_PIX_FMT_PAL8 || >> @@ -188,6 +194,12 @@ static int query_formats(AVFilterContext *ctx) >> } >> if ((ret = ff_formats_ref(formats, &ctx->outputs[0]->in_formats)) >> < 0) >> return ret; >> + >> + ret = ff_add_format(&color_ranges, scale->out_range ? >> scale->out_range : AVCOL_RANGE_MPEG); >> + if (ret < 0) >> + return ret; >> + if ((ret = ff_formats_ref(color_ranges, >> &ctx->outputs[0]->in_color_ranges)) < 0) >> + return ret; >> } >> >> return 0; >> @@ -276,6 +288,7 @@ static int config_props(AVFilterLink *outlink) >> scale->isws[0] = scale->isws[1] = scale->sws = NULL; >> if (inlink0->w == outlink->w && >> inlink0->h == outlink->h && >> + inlink0->color_range == outlink->color_range && >> !scale->out_color_matrix && >> scale->in_range == scale->out_range && >> inlink0->format == outlink->format) >> @@ -348,11 +361,11 @@ static int config_props(AVFilterLink *outlink) >> } else >> outlink->sample_aspect_ratio = inlink0->sample_aspect_ratio; >> >> - av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d fmt:%s sar:%d/%d -> w:%d h:%d >> fmt:%s sar:%d/%d flags:0x%0x\n", >> + av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d fmt:%s sar:%d/%d cr:%d -> w:%d >> h:%d fmt:%s sar:%d/%d cr:%d flags:0x%0x\n", >> inlink ->w, inlink ->h, av_get_pix_fmt_name( inlink->format), >> - inlink->sample_aspect_ratio.num, >> inlink->sample_aspect_ratio.den, >> + inlink->sample_aspect_ratio.num, >> inlink->sample_aspect_ratio.den, inlink->color_range, >> outlink->w, outlink->h, av_get_pix_fmt_name(outlink->format), >> - outlink->sample_aspect_ratio.num, >> outlink->sample_aspect_ratio.den, >> + outlink->sample_aspect_ratio.num, >> outlink->sample_aspect_ratio.den, outlink->color_range, >> scale->flags); >> return 0; >> >> diff --git a/libavfilter/vsrc_testsrc.c b/libavfilter/vsrc_testsrc.c >> index eb12335472..a531e76f06 100644 >> --- a/libavfilter/vsrc_testsrc.c >> +++ b/libavfilter/vsrc_testsrc.c >> @@ -207,7 +207,13 @@ static av_cold int color_init(AVFilterContext *ctx) >> >> static int color_query_formats(AVFilterContext *ctx) >> { >> - return ff_set_common_formats(ctx, >> ff_draw_supported_pixel_formats(0)); >> + int ret; >> + >> + ret = ff_set_common_formats(ctx, >> ff_draw_supported_pixel_formats(0)); >> + if (ret < 0) >> + return ret; >> + >> + return ff_set_common_color_ranges(ctx, ff_mpeg_color_ranges()); >> } >> >> static int color_config_props(AVFilterLink *inlink) >> @@ -653,11 +659,16 @@ static int test_query_formats(AVFilterContext *ctx) >> static const enum AVPixelFormat pix_fmts[] = { >> AV_PIX_FMT_RGB24, AV_PIX_FMT_NONE >> }; >> + int ret; >> >> AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts); >> if (!fmts_list) >> return AVERROR(ENOMEM); >> - return ff_set_common_formats(ctx, fmts_list); >> + ret = ff_set_common_formats(ctx, fmts_list); >> + if (ret < 0) >> + return ret; >> + >> + return ff_set_common_color_ranges(ctx, ff_jpeg_color_ranges()); >> } >> >> static const AVFilterPad avfilter_vsrc_testsrc_outputs[] = { > > Regards, > > -- > Nicolas George > _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel