From patchwork Tue May 1 19:39:56 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul B Mahol X-Patchwork-Id: 8716 Delivered-To: ffmpegpatchwork@gmail.com Received: by 2002:a02:155:0:0:0:0:0 with SMTP id c82-v6csp4903793jad; Tue, 1 May 2018 12:41:44 -0700 (PDT) X-Google-Smtp-Source: AB8JxZqP6cvP0VvzgsjfL/SuoMT1zKODc5QiuqS4ykfRnyLZZnSVG7IXhSjq7yGn2bQ8YMGZDiY5 X-Received: by 10.28.11.69 with SMTP id 66mr9731830wml.155.1525203703931; Tue, 01 May 2018 12:41:43 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1525203703; cv=none; d=google.com; s=arc-20160816; b=ndx13SBgDtaIPQrpcCM9Tx51CnpDwMOz9D/ghZwgEF7lM/q9T5IqCCngtcNWtQn7zv BJ3zQcNCN5hdd0deeNCVbP106SLu25LN/PD03lGMd1sq+zTlhFSuDI6hsSgAy5mOb2mN t4fPBzoOuEFVwba3w9Tf9b/jN1ATAPkRFHX+PIICyiYiTfHyIyuIusjnebfAX3p+z0hb DUMe+fyXdfyEhU+yVhQUzHR87rfzrhxb35t9XVLd5iPIcYwB0RH/xHiH0UXcTB0IkK2V r+DE9P34op8nV+nzvfoxQwCpL+hptNrrrcKKc3sxuLECFFY6FdH8F1aGUjSVXip6ivX+ GBjA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:references:in-reply-to:message-id:date :to:from:dkim-signature:delivered-to:arc-authentication-results; bh=RCDT+unIQfxaabbd8V7TCTBCVMPjv1Jam52k/htbjdY=; b=VZ/SNoJV4odf0TK/4i2XD0RgFthkWTpsLTS3Y4Ob3ibW7pzoVAuPYjnOTBXs5fYUVr AWVnP2orOfMLqjliAe34eCUk4FKgug5QTup8STuAa9y6VBuM36AxldJ6zpUEKJK6u38j 4NK3R/hw5C28xu4B0Lh61e+lkGHYak4Cg/ugPiAJJzTck+UvqJWgItB7sIOxd2P441O6 BmNLyvhNIJp1HbTOiEq8dNgp1kc7CwKmWtSDrYr13Al9roVrEXr8mtqCSo84tl6i62cY eFLRI05JE4kSM9dZbCo1P62j1h1rjJoAx6wYMkrH+tDybGUM1+mupHjopZD2CLX+k/+n JpyQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=EJ/CsQTk; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id m2-v6si8085756wri.460.2018.05.01.12.41.43; Tue, 01 May 2018 12:41:43 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=EJ/CsQTk; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 5FE6768A3C7; Tue, 1 May 2018 22:40:34 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wr0-f196.google.com (mail-wr0-f196.google.com [209.85.128.196]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id B15D868A3B0 for ; Tue, 1 May 2018 22:40:32 +0300 (EEST) Received: by mail-wr0-f196.google.com with SMTP id v15-v6so11694417wrm.10 for ; Tue, 01 May 2018 12:41:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references; bh=3fd+9rd+od8/IbjZQaUfd0RH/W8jzO6aQ4PlJlynI6E=; b=EJ/CsQTk64jC2/PCq+xLAjL/bRaIbhYvwJ8+dQQxEmdUcDfQNoDoIsUqwyQEbeHdwD 61Nh72xxCJAl3REkY74sOOcfxzr07zDImLC1IIm4FkPI0Nozf746DZoZ85UUZwTmyc6C qQzPUNn5YE/5G9nxdceGFj+cXN1YhTcJiSIf4+jMGSxT90BpOV7xADupm3knIHZCSxm8 XtVgqylqeVXkFx3eO+vMyg52U781qWCjUEm8sn7AnPhGKFZva/cu6lkcSyaP7EZigtEz MspiV+8Lab8auT6Wx7ez2ezPv+Wj21HL4hcjAouBkKBV8EDScbxKGmot6d6s0c26HYvm 7K0Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=3fd+9rd+od8/IbjZQaUfd0RH/W8jzO6aQ4PlJlynI6E=; b=ZejlbxRAshUG4E6c7rKKrQSeQOTzLjMaV3o3ZOeY1D0t0T0Wlfgl26LvoS5OZ/shEw FK6H3qvN8AWK8sJc49/kkVSRpax3s3Vs+DxG25MblJCg7lOyv2pYBzQmrYT5GUwuXt8K GefKQD8u2sjM/Do2bUwMpxzB1hqPUheWFILYgs1rOy/NyWCx5EHRtU6tkYLqwDysHxgt XMfuKGcLljs9hePkEmd4Oql5/N5FH52Vt9fXHI25+uIgrOuGcX4wfoRSSCW0cB8DucxB OfqjWWKH6o2m/hDyYoiYkSIgAmjjgzH2TO93Ey1eGq8o0J1GawUBvggsIjnu0x42eP7P 8R8Q== X-Gm-Message-State: ALQs6tBacaP1K6xqvTc/UL1gQ4wlxzJZUXARCggpEy0s2nklcytlPZuo EP2tNAXEJGa+lJZZoYxs9fqCIg== X-Received: by 2002:adf:a98f:: with SMTP id b15-v6mr12037890wrd.48.1525203663998; Tue, 01 May 2018 12:41:03 -0700 (PDT) Received: from localhost.localdomain ([94.250.174.60]) by smtp.gmail.com with ESMTPSA id h12sm11839115wmc.7.2018.05.01.12.41.02 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 01 May 2018 12:41:03 -0700 (PDT) From: Paul B Mahol To: ffmpeg-devel@ffmpeg.org Date: Tue, 1 May 2018 21:39:56 +0200 Message-Id: <20180501194013.9552-7-onemda@gmail.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20180501194013.9552-1-onemda@gmail.com> References: <20180501194013.9552-1-onemda@gmail.com> Subject: [FFmpeg-devel] [PATCH 07/24] avfilter: negotiate color_range between filters X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Signed-off-by: Paul B Mahol --- fftools/ffmpeg.c | 2 ++ fftools/ffmpeg.h | 1 + fftools/ffmpeg_filter.c | 57 +++++++++++++++++++++++++++++--- fftools/ffmpeg_opt.c | 2 ++ libavcodec/utils.c | 11 +++++++ libavfilter/avf_abitscope.c | 4 +++ libavfilter/avf_ahistogram.c | 4 +++ libavfilter/avf_aphasemeter.c | 4 +++ libavfilter/avf_avectorscope.c | 4 +++ libavfilter/avf_concat.c | 12 ++++++- libavfilter/avf_showcqt.c | 4 +++ libavfilter/avf_showfreqs.c | 4 +++ libavfilter/avf_showspectrum.c | 4 +++ libavfilter/avf_showvolume.c | 4 +++ libavfilter/avf_showwaves.c | 4 +++ libavfilter/avfilter.c | 9 +++-- libavfilter/avfilter.h | 4 ++- libavfilter/avfiltergraph.c | 53 +++++++++++++++++++++++++++++ libavfilter/buffersink.c | 16 +++++++++ libavfilter/buffersink.h | 1 + libavfilter/buffersrc.c | 4 +++ libavfilter/f_drawgraph.c | 4 +++ libavfilter/formats.c | 75 +++++++++++++++++++++++++++++++++++++++--- libavfilter/formats.h | 31 +++++++++++++++++ libavfilter/internal.h | 11 +++++++ libavfilter/vf_format.c | 46 +++++++++++++++++++++++++- libavfilter/vf_noise.c | 6 +++- libavfilter/vf_scale.c | 17 ++++++++-- libavfilter/vsrc_testsrc.c | 15 +++++++-- tests/fate/filter-video.mak | 2 +- tests/fate/pixlet.mak | 2 +- 31 files changed, 394 insertions(+), 23 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 5dc198f933..5a7d504904 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -3378,6 +3378,8 @@ static int init_output_stream_encode(OutputStream *ost) enc_ctx->bits_per_raw_sample = FFMIN(dec_ctx->bits_per_raw_sample, av_pix_fmt_desc_get(enc_ctx->pix_fmt)->comp[0].depth); + enc_ctx->color_range = av_buffersink_get_color_range(ost->filter->filter); + enc_ctx->framerate = ost->frame_rate; ost->st->avg_frame_rate = ost->frame_rate; diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index d44b7a5c72..9b09fa73bb 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -268,6 +268,7 @@ typedef struct OutputFilter { /* desired output stream properties */ int width, height; + enum AVColorRange color_range; AVRational frame_rate; int format; int sample_rate; diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 068f499e0b..a6fe813f02 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -90,6 +90,28 @@ enum AVPixelFormat choose_pixel_fmt(AVStream *st, AVCodecContext *enc_ctx, AVCod return target; } +static enum AVColorRange choose_color_range(AVStream *st, AVCodecContext *enc_ctx, AVCodec *codec, enum AVColorRange target) +{ + if (codec && codec->color_ranges) { + const enum AVColorRange *p = codec->color_ranges; + + for (; *p != AVCOL_RANGE_UNSPECIFIED; p++) { + if (*p == target) + break; + } + if (*p == AVCOL_RANGE_UNSPECIFIED) { + if (target != AVCOL_RANGE_UNSPECIFIED) + av_log(NULL, AV_LOG_WARNING, + "Incompatible color range '%s' for codec '%s', auto-selecting color range '%s'\n", + av_color_range_name(target), + codec->name, + av_color_range_name(codec->color_ranges[0])); + return codec->color_ranges[0]; + } + } + return target; +} + void choose_sample_fmt(AVStream *st, AVCodec *codec) { if (codec && codec->sample_fmts) { @@ -128,7 +150,19 @@ static char *choose_pix_fmts(OutputFilter *ofilter) return av_strdup(av_get_pix_fmt_name(ost->enc_ctx->pix_fmt)); } if (ost->enc_ctx->pix_fmt != AV_PIX_FMT_NONE) { - return av_strdup(av_get_pix_fmt_name(choose_pixel_fmt(ost->st, ost->enc_ctx, ost->enc, ost->enc_ctx->pix_fmt))); + AVIOContext *s = NULL; + uint8_t *ret; + int len; + + if (avio_open_dyn_buf(&s) < 0) + exit_program(1); + + avio_printf(s, "%s:%s", av_get_pix_fmt_name(choose_pixel_fmt(ost->st, ost->enc_ctx, ost->enc, ost->enc_ctx->pix_fmt)), + av_color_range_name(choose_color_range(ost->st, ost->enc_ctx, ost->enc, ost->enc_ctx->color_range))); + + len = avio_close_dyn_buf(s, &ret); + ret[len] = 0; + return ret; } else if (ost->enc && ost->enc->pix_fmts) { const enum AVPixelFormat *p; AVIOContext *s = NULL; @@ -145,7 +179,20 @@ static char *choose_pix_fmts(OutputFilter *ofilter) for (; *p != AV_PIX_FMT_NONE; p++) { const char *name = av_get_pix_fmt_name(*p); - avio_printf(s, "%s|", name); + avio_printf(s, "%s", name); + if (*(p + 1) != AV_PIX_FMT_NONE) + avio_printf(s, "|"); + else + avio_printf(s, ":"); + } + + if (ost->enc->color_ranges) { + const enum AVColorRange *c = ost->enc->color_ranges; + + for (; *c != AVCOL_RANGE_UNSPECIFIED; c++) { + const char *name = av_color_range_name(*c); + avio_printf(s, "%s|", name); + } } len = avio_close_dyn_buf(s, &ret); ret[len - 1] = 0; @@ -778,10 +825,11 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, av_bprint_init(&args, 0, 1); av_bprintf(&args, "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:" - "pixel_aspect=%d/%d:sws_param=flags=%d", + "pixel_aspect=%d/%d:sws_param=flags=%d:color_range=%s", ifilter->width, ifilter->height, ifilter->format, tb.num, tb.den, sar.num, sar.den, - SWS_BILINEAR + ((ist->dec_ctx->flags&AV_CODEC_FLAG_BITEXACT) ? SWS_BITEXACT:0)); + SWS_BILINEAR + ((ist->dec_ctx->flags&AV_CODEC_FLAG_BITEXACT) ? SWS_BITEXACT:0), + av_color_range_name(ist->dec_ctx->color_range)); if (fr.num && fr.den) av_bprintf(&args, ":frame_rate=%d/%d", fr.num, fr.den); snprintf(name, sizeof(name), "graph %d input from stream %d:%d", fg->index, @@ -1111,6 +1159,7 @@ int configure_filtergraph(FilterGraph *fg) ofilter->width = av_buffersink_get_w(sink); ofilter->height = av_buffersink_get_h(sink); + ofilter->color_range = av_buffersink_get_color_range(sink); ofilter->sample_rate = av_buffersink_get_sample_rate(sink); ofilter->channel_layout = av_buffersink_get_channel_layout(sink); diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 8ae68aec0e..8036b8c31f 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -2411,6 +2411,8 @@ loop_end: f->frame_rate = ost->frame_rate; f->width = ost->enc_ctx->width; f->height = ost->enc_ctx->height; + if (ost->enc_ctx->color_range != AVCOL_RANGE_UNSPECIFIED) + f->color_range = ost->enc_ctx->color_range; if (ost->enc_ctx->pix_fmt != AV_PIX_FMT_NONE) { f->format = ost->enc_ctx->pix_fmt; } else if (ost->enc->pix_fmts) { diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 59d41ccbb6..f9f124ee47 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -801,6 +801,17 @@ FF_ENABLE_DEPRECATION_WARNINGS avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ444P) avctx->color_range = AVCOL_RANGE_JPEG; } + if (avctx->codec->color_ranges) { + for (i = 0; avctx->codec->color_ranges[i] != AVCOL_RANGE_UNSPECIFIED; i++) + if (avctx->color_range == avctx->codec->color_ranges[i]) + break; + if (avctx->codec->color_ranges[i] == AVCOL_RANGE_UNSPECIFIED) { + av_log(avctx, AV_LOG_ERROR, "Specified color range %s is invalid or not supported\n", + (char *)av_x_if_null(av_color_range_name(avctx->color_range), "unknown")); + ret = AVERROR(EINVAL); + goto free_and_end; + } + } if (avctx->codec->supported_samplerates) { for (i = 0; avctx->codec->supported_samplerates[i] != 0; i++) if (avctx->sample_rate == avctx->codec->supported_samplerates[i]) diff --git a/libavfilter/avf_abitscope.c b/libavfilter/avf_abitscope.c index 0e3eaa422e..439999b94d 100644 --- a/libavfilter/avf_abitscope.c +++ b/libavfilter/avf_abitscope.c @@ -84,6 +84,10 @@ static int query_formats(AVFilterContext *ctx) if ((ret = ff_formats_ref(formats, &outlink->in_formats)) < 0) return ret; + formats = ff_jpeg_color_ranges(); + if ((ret = ff_formats_ref(formats, &outlink->in_color_ranges)) < 0) + return ret; + return 0; } diff --git a/libavfilter/avf_ahistogram.c b/libavfilter/avf_ahistogram.c index 587415175b..afcea8ca9e 100644 --- a/libavfilter/avf_ahistogram.c +++ b/libavfilter/avf_ahistogram.c @@ -110,6 +110,10 @@ static int query_formats(AVFilterContext *ctx) if ((ret = ff_formats_ref(formats, &outlink->in_formats)) < 0) return ret; + formats = ff_mpeg_color_ranges(); + if ((ret = ff_formats_ref(formats, &outlink->in_color_ranges)) < 0) + return ret; + return 0; } diff --git a/libavfilter/avf_aphasemeter.c b/libavfilter/avf_aphasemeter.c index 8cdee9464c..60d248e9f9 100644 --- a/libavfilter/avf_aphasemeter.c +++ b/libavfilter/avf_aphasemeter.c @@ -94,6 +94,10 @@ static int query_formats(AVFilterContext *ctx) formats = ff_make_format_list(pix_fmts); if ((ret = ff_formats_ref(formats, &outlink->in_formats)) < 0) return ret; + + formats = ff_jpeg_color_ranges(); + if ((ret = ff_formats_ref(formats, &outlink->in_color_ranges)) < 0) + return ret; } return 0; diff --git a/libavfilter/avf_avectorscope.c b/libavfilter/avf_avectorscope.c index af9f1da1ec..f8dfc1a5fd 100644 --- a/libavfilter/avf_avectorscope.c +++ b/libavfilter/avf_avectorscope.c @@ -201,6 +201,10 @@ static int query_formats(AVFilterContext *ctx) if ((ret = ff_formats_ref(formats, &outlink->in_formats)) < 0) return ret; + formats = ff_jpeg_color_ranges(); + if ((ret = ff_formats_ref(formats, &outlink->in_color_ranges)) < 0) + return ret; + return 0; } diff --git a/libavfilter/avf_concat.c b/libavfilter/avf_concat.c index 46bd42359b..cedddf249c 100644 --- a/libavfilter/avf_concat.c +++ b/libavfilter/avf_concat.c @@ -78,7 +78,7 @@ static int query_formats(AVFilterContext *ctx) { ConcatContext *cat = ctx->priv; unsigned type, nb_str, idx0 = 0, idx, str, seg; - AVFilterFormats *formats, *rates = NULL; + AVFilterFormats *formats, *color_ranges = NULL, *rates = NULL; AVFilterChannelLayouts *layouts = NULL; int ret; @@ -101,6 +101,12 @@ static int query_formats(AVFilterContext *ctx) return ret; } + if (type == AVMEDIA_TYPE_VIDEO) { + color_ranges = ff_all_color_ranges(); + if ((ret = ff_formats_ref(color_ranges, &ctx->outputs[idx]->in_color_ranges)) < 0) + return ret; + } + /* Set the same formats for each corresponding input */ for (seg = 0; seg < cat->nb_segments; seg++) { if ((ret = ff_formats_ref(formats, &ctx->inputs[idx]->out_formats)) < 0) @@ -110,6 +116,10 @@ static int query_formats(AVFilterContext *ctx) (ret = ff_channel_layouts_ref(layouts, &ctx->inputs[idx]->out_channel_layouts)) < 0) return ret; } + if (type == AVMEDIA_TYPE_VIDEO) { + if ((ret = ff_formats_ref(color_ranges, &ctx->inputs[idx]->out_color_ranges)) < 0) + return ret; + } idx += ctx->nb_outputs; } diff --git a/libavfilter/avf_showcqt.c b/libavfilter/avf_showcqt.c index 875ba48cee..24a99de12b 100644 --- a/libavfilter/avf_showcqt.c +++ b/libavfilter/avf_showcqt.c @@ -1347,6 +1347,10 @@ static int query_formats(AVFilterContext *ctx) if ((ret = ff_formats_ref(formats, &outlink->in_formats)) < 0) return ret; + formats = ff_all_color_ranges(); + if ((ret = ff_formats_ref(formats, &outlink->in_color_ranges)) < 0) + return ret; + return 0; } diff --git a/libavfilter/avf_showfreqs.c b/libavfilter/avf_showfreqs.c index 22f28ec387..eff2808d5a 100644 --- a/libavfilter/avf_showfreqs.c +++ b/libavfilter/avf_showfreqs.c @@ -158,6 +158,10 @@ static int query_formats(AVFilterContext *ctx) if ((ret = ff_formats_ref(formats, &outlink->in_formats)) < 0) return ret; + formats = ff_jpeg_color_ranges(); + if ((ret = ff_formats_ref(formats, &outlink->in_color_ranges)) < 0) + return ret; + return 0; } diff --git a/libavfilter/avf_showspectrum.c b/libavfilter/avf_showspectrum.c index 956f62f3ad..17025f17bd 100644 --- a/libavfilter/avf_showspectrum.c +++ b/libavfilter/avf_showspectrum.c @@ -288,6 +288,10 @@ static int query_formats(AVFilterContext *ctx) if ((ret = ff_formats_ref(formats, &outlink->in_formats)) < 0) return ret; + formats = ff_mpeg_color_ranges(); + if ((ret = ff_formats_ref(formats, &outlink->in_color_ranges)) < 0) + return ret; + return 0; } diff --git a/libavfilter/avf_showvolume.c b/libavfilter/avf_showvolume.c index 6b553c4eba..b77ef1027b 100644 --- a/libavfilter/avf_showvolume.c +++ b/libavfilter/avf_showvolume.c @@ -138,6 +138,10 @@ static int query_formats(AVFilterContext *ctx) if ((ret = ff_formats_ref(formats, &outlink->in_formats)) < 0) return ret; + formats = ff_jpeg_color_ranges(); + if ((ret = ff_formats_ref(formats, &outlink->in_color_ranges)) < 0) + return ret; + return 0; } diff --git a/libavfilter/avf_showwaves.c b/libavfilter/avf_showwaves.c index bb7f4ea87e..3dbd42bdfc 100644 --- a/libavfilter/avf_showwaves.c +++ b/libavfilter/avf_showwaves.c @@ -169,6 +169,10 @@ static int query_formats(AVFilterContext *ctx) if ((ret = ff_formats_ref(formats, &outlink->in_formats)) < 0) return ret; + formats = ff_jpeg_color_ranges(); + if ((ret = ff_formats_ref(formats, &outlink->in_color_ranges)) < 0) + return ret; + return 0; } diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index 3f0dc14d01..123cf48499 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -264,6 +264,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); @@ -752,6 +755,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); @@ -937,9 +942,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 11cd586bae..46a07ccd4b 100644 --- a/libavfilter/avfilter.h +++ b/libavfilter/avfilter.h @@ -472,7 +472,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. @@ -480,6 +480,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 a149f8fb6d..bd7ea540a8 100644 --- a/libavfilter/avfiltergraph.c +++ b/libavfilter/avfiltergraph.c @@ -317,6 +317,7 @@ static int filter_query_formats(AVFilterContext *ctx) { int ret, i; AVFilterFormats *formats; + AVFilterFormats *color_ranges; AVFilterChannelLayouts *chlayouts; AVFilterFormats *samplerates; enum AVMediaType type = ctx->inputs && ctx->inputs [0] ? ctx->inputs [0]->type : @@ -338,6 +339,11 @@ static int filter_query_formats(AVFilterContext *ctx) formats = ff_all_formats(type); if ((ret = ff_set_common_formats(ctx, formats)) < 0) return ret; + if (type == AVMEDIA_TYPE_VIDEO) { + color_ranges = ff_all_color_ranges(); + if ((ret = ff_set_common_color_ranges(ctx, color_ranges)) < 0) + return ret; + } if (type == AVMEDIA_TYPE_AUDIO) { samplerates = ff_all_samplerates(); if ((ret = ff_set_common_samplerates(ctx, samplerates)) < 0) @@ -360,6 +366,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 +377,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 +497,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 +528,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)) + convert_needed = 1; + ) + } MERGE_DISPATCH(formats, if (!ff_merge_formats(link->in_formats, link->out_formats, link->type)) @@ -575,6 +603,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); @@ -588,6 +622,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) || @@ -710,6 +750,17 @@ static int pick_format(AVFilterLink *link, AVFilterLink *ref) link->in_formats->nb_formats = 1; link->format = link->in_formats->formats[0]; + if (link->type == AVMEDIA_TYPE_VIDEO) { + if (!link->in_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->in_color_ranges->nb_formats = 1; + link->color_range = link->in_color_ranges->formats[0]; + } + if (link->type == AVMEDIA_TYPE_AUDIO) { if (!link->in_samplerates->nb_formats) { av_log(link->src, AV_LOG_ERROR, "Cannot select sample rate for" @@ -740,6 +791,8 @@ static int pick_format(AVFilterLink *link, AVFilterLink *ref) 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); diff --git a/libavfilter/buffersink.c b/libavfilter/buffersink.c index 897396cac4..f3abb7de6e 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 enum AVColorRange color_ranges[] = { AVCOL_RANGE_UNSPECIFIED }; 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, AVCOL_RANGE_UNSPECIFIED, 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..300a7bfb3a 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 AVColorRange *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/f_drawgraph.c b/libavfilter/f_drawgraph.c index 8be9b9f95a..7cbfee611f 100644 --- a/libavfilter/f_drawgraph.c +++ b/libavfilter/f_drawgraph.c @@ -132,6 +132,10 @@ static int query_formats(AVFilterContext *ctx) if ((ret = ff_formats_ref(fmts_list, &outlink->in_formats)) < 0) return ret; + fmts_list = ff_jpeg_color_ranges(); + if ((ret = ff_formats_ref(fmts_list, &outlink->in_color_ranges)) < 0) + return ret; + return 0; } diff --git a/libavfilter/formats.c b/libavfilter/formats.c index 31ee445c49..47d7f95a70 100644 --- a/libavfilter/formats.c +++ b/libavfilter/formats.c @@ -262,11 +262,11 @@ int ff_fmt_is_in(int fmt, const int *fmts) return 0; } -#define MAKE_FORMAT_LIST(type, field, count_field) \ +#define MAKE_FORMAT_LIST(type, field, count_field, end) \ type *formats; \ int count = 0; \ if (fmts) \ - for (count = 0; fmts[count] != -1; count++) \ + for (count = 0; fmts[count] != end; count++) \ ; \ formats = av_mallocz(sizeof(*formats)); \ if (!formats) \ @@ -282,7 +282,16 @@ int ff_fmt_is_in(int fmt, const int *fmts) AVFilterFormats *ff_make_format_list(const int *fmts) { - MAKE_FORMAT_LIST(AVFilterFormats, formats, nb_formats); + MAKE_FORMAT_LIST(AVFilterFormats, formats, nb_formats, -1); + while (count--) + formats->formats[count] = fmts[count]; + + return formats; +} + +AVFilterFormats *ff_make_color_range_list(const int *fmts) +{ + MAKE_FORMAT_LIST(AVFilterFormats, formats, nb_formats, AVCOL_RANGE_UNSPECIFIED); while (count--) formats->formats[count] = fmts[count]; @@ -292,7 +301,7 @@ AVFilterFormats *ff_make_format_list(const int *fmts) AVFilterChannelLayouts *ff_make_formatu64_list(const uint64_t *fmts) { MAKE_FORMAT_LIST(AVFilterChannelLayouts, - channel_layouts, nb_channel_layouts); + channel_layouts, nb_channel_layouts, -1); if (count) memcpy(formats->channel_layouts, fmts, sizeof(*formats->channel_layouts) * count); @@ -303,7 +312,7 @@ AVFilterChannelLayouts *ff_make_formatu64_list(const uint64_t *fmts) AVFilterChannelLayouts *avfilter_make_format64_list(const int64_t *fmts) { MAKE_FORMAT_LIST(AVFilterChannelLayouts, - channel_layouts, nb_channel_layouts); + channel_layouts, nb_channel_layouts, -1); if (count) memcpy(formats->channel_layouts, fmts, sizeof(*formats->channel_layouts) * count); @@ -398,6 +407,39 @@ 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; +} + +AVFilterFormats *ff_all_color_ranges(void) +{ + AVFilterFormats *fmts = NULL; + + if (ff_add_format(&fmts, AVCOL_RANGE_MPEG) < 0) + return NULL; + if (ff_add_format(&fmts, AVCOL_RANGE_JPEG) < 0) + return NULL; + if (ff_add_format(&fmts, AVCOL_RANGE_UNSPECIFIED) < 0) + return NULL; + return fmts; +} + AVFilterChannelLayouts *ff_all_channel_layouts(void) { AVFilterChannelLayouts *ret = av_mallocz(sizeof(*ret)); @@ -560,6 +602,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 +639,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 +713,17 @@ int ff_parse_sample_rate(int *ret, const char *arg, void *log_ctx) return 0; } +int ff_parse_color_range(enum AVColorRange *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 498bd3328d..8d028b522d 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(enum AVColorRange *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..420a01ec8a 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; + enum AVColorRange *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, {.str = "unknown"}, .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 c7f2b07f0b..3e22921b32 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,10 @@ static int query_formats(AVFilterContext *ctx) } if ((ret = ff_formats_ref(formats, &ctx->outputs[0]->in_formats)) < 0) return ret; + + color_ranges = ff_all_color_ranges(); + if ((ret = ff_formats_ref(color_ranges, &ctx->outputs[0]->in_color_ranges)) < 0) + return ret; } return 0; @@ -275,6 +285,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) @@ -347,11 +358,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 a790974d14..fddd7f55ee 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_all_color_ranges()); } static const AVFilterPad avfilter_vsrc_testsrc_outputs[] = { diff --git a/tests/fate/filter-video.mak b/tests/fate/filter-video.mak index 17d6363678..9b6405947b 100644 --- a/tests/fate/filter-video.mak +++ b/tests/fate/filter-video.mak @@ -1,5 +1,5 @@ FATE_FILTER_SAMPLES-$(call ALLYES, SMJPEG_DEMUXER MJPEG_DECODER PERMS_FILTER OWDENOISE_FILTER) += fate-filter-owdenoise-sample -fate-filter-owdenoise-sample: CMD = ffmpeg -idct simple -i $(TARGET_SAMPLES)/smjpeg/scenwin.mjpg -vf "trim=duration=0.5,perms=random,owdenoise=10:20:20:enable=not(between(t\,0.2\,1.2))" -an -f rawvideo - +fate-filter-owdenoise-sample: CMD = ffmpeg -idct simple -i $(TARGET_SAMPLES)/smjpeg/scenwin.mjpg -vf "trim=duration=0.5,perms=random,owdenoise=10:20:20:enable=not(between(t\,0.2\,1.2)),format=yuv420p:tv" -an -f rawvideo - fate-filter-owdenoise-sample: REF = $(TARGET_SAMPLES)/filter-reference/owdenoise-scenwin.raw fate-filter-owdenoise-sample: CMP_TARGET = 1 fate-filter-owdenoise-sample: FUZZ = 3539 diff --git a/tests/fate/pixlet.mak b/tests/fate/pixlet.mak index c720f32616..e42c06d194 100644 --- a/tests/fate/pixlet.mak +++ b/tests/fate/pixlet.mak @@ -1,5 +1,5 @@ FATE_PIXLET += fate-pixlet-rgb -fate-pixlet-rgb: CMD = framecrc -i $(TARGET_SAMPLES)/pixlet/pixlet_rgb.mov -an -pix_fmt yuv420p16le +fate-pixlet-rgb: CMD = framecrc -i $(TARGET_SAMPLES)/pixlet/pixlet_rgb.mov -an -vf format=yuv420p16le:pc FATE_SAMPLES_AVCONV-$(call DEMDEC, MOV, PIXLET) += $(FATE_PIXLET) fate-pixlet: $(FATE_PIXLET)