[FFmpeg-devel,07/24] avfilter: negotiate color_range between filters

Submitted by Paul B Mahol on May 1, 2018, 7:39 p.m.

Details

Message ID 20180501194013.9552-7-onemda@gmail.com
State New
Headers show

Commit Message

Paul B Mahol May 1, 2018, 7:39 p.m.
Signed-off-by: Paul B Mahol <onemda@gmail.com>
---
 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(-)

Patch hide | download patch | download mbox

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)