diff --git a/libavutil/opt.c b/libavutil/opt.c
index df88663e3f..0bfd0ca952 100644
--- a/libavutil/opt.c
+++ b/libavutil/opt.c
@@ -67,6 +67,9 @@ static int read_number(const AVOption *o, const void *dst, double *num, int *den
     case AV_OPT_TYPE_SAMPLE_FMT:
         *intnum = *(enum AVSampleFormat *)dst;
         return 0;
+    case AV_OPT_TYPE_COLOR_RANGE:
+        *intnum = *(enum AVColorRange *)dst;
+        return 0;
     case AV_OPT_TYPE_BOOL:
     case AV_OPT_TYPE_INT:
         *intnum = *(int *)dst;
@@ -120,6 +123,9 @@ static int write_number(void *obj, const AVOption *o, void *dst, double num, int
     case AV_OPT_TYPE_SAMPLE_FMT:
         *(enum AVSampleFormat *)dst = llrint(num / den) * intnum;
         break;
+    case AV_OPT_TYPE_COLOR_RANGE:
+        *(enum AVColorRange *)dst = llrint(num / den) * intnum;
+        break;
     case AV_OPT_TYPE_BOOL:
     case AV_OPT_TYPE_FLAGS:
     case AV_OPT_TYPE_INT:
@@ -446,6 +452,12 @@ static int set_string_sample_fmt(void *obj, const AVOption *o, const char *val,
                           AV_SAMPLE_FMT_NB, av_get_sample_fmt, "sample format");
 }
 
+static int set_string_color_range(void *obj, const AVOption *o, const char *val, uint8_t *dst)
+{
+    return set_string_fmt(obj, o, val, dst,
+                          AVCOL_RANGE_NB, av_color_range_from_name, "color range");
+}
+
 int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
 {
     int ret = 0;
@@ -457,7 +469,8 @@ int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
                  o->type != AV_OPT_TYPE_PIXEL_FMT && o->type != AV_OPT_TYPE_SAMPLE_FMT &&
                  o->type != AV_OPT_TYPE_IMAGE_SIZE && o->type != AV_OPT_TYPE_VIDEO_RATE &&
                  o->type != AV_OPT_TYPE_DURATION && o->type != AV_OPT_TYPE_COLOR &&
-                 o->type != AV_OPT_TYPE_CHANNEL_LAYOUT && o->type != AV_OPT_TYPE_BOOL))
+                 o->type != AV_OPT_TYPE_CHANNEL_LAYOUT && o->type != AV_OPT_TYPE_BOOL &&
+                 o->type != AV_OPT_TYPE_COLOR_RANGE))
         return AVERROR(EINVAL);
 
     if (o->flags & AV_OPT_FLAG_READONLY)
@@ -492,6 +505,8 @@ int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
         return set_string_pixel_fmt(obj, o, val, dst);
     case AV_OPT_TYPE_SAMPLE_FMT:
         return set_string_sample_fmt(obj, o, val, dst);
+    case AV_OPT_TYPE_COLOR_RANGE:
+        return set_string_color_range(obj, o, val, dst);
     case AV_OPT_TYPE_DURATION:
         if (!val) {
             *(int64_t *)dst = 0;
@@ -678,6 +693,11 @@ int av_opt_set_sample_fmt(void *obj, const char *name, enum AVSampleFormat fmt,
     return set_format(obj, name, fmt, search_flags, AV_OPT_TYPE_SAMPLE_FMT, "sample", AV_SAMPLE_FMT_NB);
 }
 
+int av_opt_set_color_range(void *obj, const char *name, enum AVColorRange range, int search_flags)
+{
+    return set_format(obj, name, range, search_flags, AV_OPT_TYPE_COLOR_RANGE, "range", AVCOL_RANGE_NB);
+}
+
 int av_opt_set_channel_layout(void *obj, const char *name, int64_t cl, int search_flags)
 {
     void *target_obj;
@@ -828,6 +848,9 @@ int av_opt_get(void *obj, const char *name, int search_flags, uint8_t **out_val)
     case AV_OPT_TYPE_SAMPLE_FMT:
         ret = snprintf(buf, sizeof(buf), "%s", (char *)av_x_if_null(av_get_sample_fmt_name(*(enum AVSampleFormat *)dst), "none"));
         break;
+    case AV_OPT_TYPE_COLOR_RANGE:
+        ret = snprintf(buf, sizeof(buf), "%s", (char *)av_x_if_null(av_color_range_name(*(enum AVColorRange *)dst), "none"));
+        break;
     case AV_OPT_TYPE_DURATION:
         i64 = *(int64_t *)dst;
         format_duration(buf, sizeof(buf), i64);
@@ -974,6 +997,11 @@ int av_opt_get_sample_fmt(void *obj, const char *name, int search_flags, enum AV
     return get_format(obj, name, search_flags, out_fmt, AV_OPT_TYPE_SAMPLE_FMT, "sample");
 }
 
+int av_opt_get_color_range(void *obj, const char *name, int search_flags, enum AVColorRange *out_range)
+{
+    return get_format(obj, name, search_flags, (int *)out_range, AV_OPT_TYPE_COLOR_RANGE, "range");
+}
+
 int av_opt_get_channel_layout(void *obj, const char *name, int search_flags, int64_t *cl)
 {
     void *dst, *target_obj;
@@ -1156,6 +1184,9 @@ static void opt_list(void *obj, void *av_log_obj, const char *unit,
             case AV_OPT_TYPE_SAMPLE_FMT:
                 av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<sample_fmt>");
                 break;
+            case AV_OPT_TYPE_COLOR_RANGE:
+                av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<color_range>");
+                break;
             case AV_OPT_TYPE_DURATION:
                 av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<duration>");
                 break;
@@ -1257,6 +1288,9 @@ static void opt_list(void *obj, void *av_log_obj, const char *unit,
             case AV_OPT_TYPE_SAMPLE_FMT:
                 av_log(av_log_obj, AV_LOG_INFO, "%s", (char *)av_x_if_null(av_get_sample_fmt_name(opt->default_val.i64), "none"));
                 break;
+            case AV_OPT_TYPE_COLOR_RANGE:
+                av_log(av_log_obj, AV_LOG_INFO, "%s", (char *)av_x_if_null(av_color_range_name(opt->default_val.i64), "none"));
+                break;
             case AV_OPT_TYPE_COLOR:
             case AV_OPT_TYPE_IMAGE_SIZE:
             case AV_OPT_TYPE_STRING:
@@ -1318,6 +1352,7 @@ void av_opt_set_defaults2(void *s, int mask, int flags)
             case AV_OPT_TYPE_CHANNEL_LAYOUT:
             case AV_OPT_TYPE_PIXEL_FMT:
             case AV_OPT_TYPE_SAMPLE_FMT:
+            case AV_OPT_TYPE_COLOR_RANGE:
                 write_number(s, opt, dst, 1, 1, opt->default_val.i64);
                 break;
             case AV_OPT_TYPE_DOUBLE:
@@ -1693,6 +1728,8 @@ static int opt_size(enum AVOptionType type)
         return sizeof(enum AVPixelFormat);
     case AV_OPT_TYPE_SAMPLE_FMT:
         return sizeof(enum AVSampleFormat);
+    case AV_OPT_TYPE_COLOR_RANGE:
+        return sizeof(enum AVColorRange);
     case AV_OPT_TYPE_COLOR:
         return 4;
     }
@@ -1807,6 +1844,7 @@ int av_opt_query_ranges_default(AVOptionRanges **ranges_arg, void *obj, const ch
     case AV_OPT_TYPE_UINT64:
     case AV_OPT_TYPE_PIXEL_FMT:
     case AV_OPT_TYPE_SAMPLE_FMT:
+    case AV_OPT_TYPE_COLOR_RANGE:
     case AV_OPT_TYPE_FLOAT:
     case AV_OPT_TYPE_DOUBLE:
     case AV_OPT_TYPE_DURATION:
@@ -1890,6 +1928,7 @@ int av_opt_is_set_to_default(void *obj, const AVOption *o)
     case AV_OPT_TYPE_FLAGS:
     case AV_OPT_TYPE_PIXEL_FMT:
     case AV_OPT_TYPE_SAMPLE_FMT:
+    case AV_OPT_TYPE_COLOR_RANGE:
     case AV_OPT_TYPE_INT:
     case AV_OPT_TYPE_CHANNEL_LAYOUT:
     case AV_OPT_TYPE_DURATION:
diff --git a/libavutil/opt.h b/libavutil/opt.h
index 391720f2e2..95f0ddb8ec 100644
--- a/libavutil/opt.h
+++ b/libavutil/opt.h
@@ -238,6 +238,7 @@ enum AVOptionType{
     AV_OPT_TYPE_COLOR,
     AV_OPT_TYPE_CHANNEL_LAYOUT,
     AV_OPT_TYPE_BOOL,
+    AV_OPT_TYPE_COLOR_RANGE, ///< offset must point to enum AVColorRange
 };
 
 /**
@@ -686,6 +687,7 @@ int av_opt_set_pixel_fmt (void *obj, const char *name, enum AVPixelFormat fmt, i
 int av_opt_set_sample_fmt(void *obj, const char *name, enum AVSampleFormat fmt, int search_flags);
 int av_opt_set_video_rate(void *obj, const char *name, AVRational val, int search_flags);
 int av_opt_set_channel_layout(void *obj, const char *name, int64_t ch_layout, int search_flags);
+int av_opt_set_color_range(void *obj, const char *name, enum AVColorRange range, int search_flags);
 /**
  * @note Any old dictionary present is discarded and replaced with a copy of the new one. The
  * caller still owns val is and responsible for freeing it.
@@ -740,6 +742,7 @@ int av_opt_get_pixel_fmt (void *obj, const char *name, int search_flags, enum AV
 int av_opt_get_sample_fmt(void *obj, const char *name, int search_flags, enum AVSampleFormat *out_fmt);
 int av_opt_get_video_rate(void *obj, const char *name, int search_flags, AVRational *out_val);
 int av_opt_get_channel_layout(void *obj, const char *name, int search_flags, int64_t *ch_layout);
+int av_opt_get_color_range(void *obj, const char *name, int search_flags, enum AVColorRange *out_range);
 /**
  * @param[out] out_val The returned dictionary is a copy of the actual value and must
  * be freed with av_dict_free() by the caller
