diff --git a/libavutil/opt.c b/libavutil/opt.c
index 9081a593a1..3e776804a6 100644
--- a/libavutil/opt.c
+++ b/libavutil/opt.c
@@ -39,6 +39,7 @@
 #include "opt.h"
 #include "samplefmt.h"
 #include "bprint.h"
+#include "version.h"
 
 #include <float.h>
 
@@ -71,7 +72,9 @@ static int read_number(const AVOption *o, const void *dst, double *num, int *den
     case AV_OPT_TYPE_INT:
         *intnum = *(int *)dst;
         return 0;
+#if FF_API_OLD_CHANNEL_LAYOUT
     case AV_OPT_TYPE_CHANNEL_LAYOUT:
+#endif
     case AV_OPT_TYPE_DURATION:
     case AV_OPT_TYPE_INT64:
     case AV_OPT_TYPE_UINT64:
@@ -126,7 +129,9 @@ static int write_number(void *obj, const AVOption *o, void *dst, double num, int
         *(int *)dst = llrint(num / den) * intnum;
         break;
     case AV_OPT_TYPE_DURATION:
+#if FF_API_OLD_CHANNEL_LAYOUT
     case AV_OPT_TYPE_CHANNEL_LAYOUT:
+#endif
     case AV_OPT_TYPE_INT64:{
         double d = num / den;
         if (intnum == 1 && d == (double)INT64_MAX) {
@@ -446,6 +451,16 @@ 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_channel_layout(void *obj, const AVOption *o,
+                                     const char *val, void *dst)
+{
+    AVChannelLayout *channel_layout = dst;
+    av_channel_layout_uninit(channel_layout);
+    if (!val)
+        return 0;
+    return av_channel_layout_from_string(channel_layout, val);
+}
+
 int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
 {
     int ret = 0;
@@ -457,7 +472,10 @@ 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))
+#if FF_API_OLD_CHANNEL_LAYOUT
+                 o->type != AV_OPT_TYPE_CHANNEL_LAYOUT &&
+#endif
+                 o->type != AV_OPT_TYPE_BOOL))
         return AVERROR(EINVAL);
 
     if (o->flags & AV_OPT_FLAG_READONLY)
@@ -514,6 +532,7 @@ int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
         }
     case AV_OPT_TYPE_COLOR:
         return set_string_color(obj, o, val, dst);
+#if FF_API_OLD_CHANNEL_LAYOUT
     case AV_OPT_TYPE_CHANNEL_LAYOUT:
         if (!val || !strcmp(val, "none")) {
             *(int64_t *)dst = 0;
@@ -527,6 +546,9 @@ int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
             return ret;
         }
         break;
+#endif
+    case AV_OPT_TYPE_CHLAYOUT:
+        return set_string_channel_layout(obj, o, val, dst);
     }
 
     av_log(obj, AV_LOG_ERROR, "Invalid option type.\n");
@@ -688,6 +710,7 @@ 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);
 }
 
+#if FF_API_OLD_CHANNEL_LAYOUT
 int av_opt_set_channel_layout(void *obj, const char *name, int64_t cl, int search_flags)
 {
     void *target_obj;
@@ -703,6 +726,7 @@ int av_opt_set_channel_layout(void *obj, const char *name, int64_t cl, int searc
     *(int64_t *)(((uint8_t *)target_obj) + o->offset) = cl;
     return 0;
 }
+#endif
 
 int av_opt_set_dict_val(void *obj, const char *name, const AVDictionary *val,
                         int search_flags)
@@ -723,6 +747,22 @@ int av_opt_set_dict_val(void *obj, const char *name, const AVDictionary *val,
     return 0;
 }
 
+int av_opt_set_chlayout(void *obj, const char *name,
+                        const AVChannelLayout *channel_layout,
+                        int search_flags)
+{
+    void *target_obj;
+    const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
+    AVChannelLayout *dst;
+
+    if (!o || !target_obj)
+        return AVERROR_OPTION_NOT_FOUND;
+
+    dst = (AVChannelLayout*)((uint8_t*)target_obj + o->offset);
+
+    return av_channel_layout_copy(dst, channel_layout);
+}
+
 static void format_duration(char *buf, size_t size, int64_t d)
 {
     char *e;
@@ -851,10 +891,15 @@ int av_opt_get(void *obj, const char *name, int search_flags, uint8_t **out_val)
                        (int)((uint8_t *)dst)[0], (int)((uint8_t *)dst)[1],
                        (int)((uint8_t *)dst)[2], (int)((uint8_t *)dst)[3]);
         break;
+#if FF_API_OLD_CHANNEL_LAYOUT
     case AV_OPT_TYPE_CHANNEL_LAYOUT:
         i64 = *(int64_t *)dst;
         ret = snprintf(buf, sizeof(buf), "0x%"PRIx64, i64);
         break;
+#endif
+    case AV_OPT_TYPE_CHLAYOUT:
+        *out_val = av_channel_layout_describe(dst);
+        return *out_val ? 0 : AVERROR(EINVAL);
     default:
         return AVERROR(EINVAL);
     }
@@ -987,6 +1032,7 @@ 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");
 }
 
+#if FF_API_OLD_CHANNEL_LAYOUT
 int av_opt_get_channel_layout(void *obj, const char *name, int search_flags, int64_t *cl)
 {
     void *dst, *target_obj;
@@ -1003,6 +1049,7 @@ int av_opt_get_channel_layout(void *obj, const char *name, int search_flags, int
     *cl = *(int64_t *)dst;
     return 0;
 }
+#endif
 
 int av_opt_get_dict_val(void *obj, const char *name, int search_flags, AVDictionary **out_val)
 {
@@ -1192,7 +1239,10 @@ static void opt_list(void *obj, void *av_log_obj, const char *unit,
             case AV_OPT_TYPE_COLOR:
                 av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<color>");
                 break;
+            case AV_OPT_TYPE_CHLAYOUT:
+#if FF_API_OLD_CHANNEL_LAYOUT
             case AV_OPT_TYPE_CHANNEL_LAYOUT:
+#endif
                 av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<channel_layout>");
                 break;
             case AV_OPT_TYPE_BOOL:
@@ -1298,11 +1348,14 @@ static void opt_list(void *obj, void *av_log_obj, const char *unit,
             case AV_OPT_TYPE_IMAGE_SIZE:
             case AV_OPT_TYPE_STRING:
             case AV_OPT_TYPE_VIDEO_RATE:
+            case AV_OPT_TYPE_CHLAYOUT:
                 av_log(av_log_obj, AV_LOG_INFO, "\"%s\"", opt->default_val.str);
                 break;
+#if FF_API_OLD_CHANNEL_LAYOUT
             case AV_OPT_TYPE_CHANNEL_LAYOUT:
                 av_log(av_log_obj, AV_LOG_INFO, "0x%"PRIx64, opt->default_val.i64);
                 break;
+#endif
             }
             av_log(av_log_obj, AV_LOG_INFO, ")");
         }
@@ -1352,7 +1405,9 @@ void av_opt_set_defaults2(void *s, int mask, int flags)
             case AV_OPT_TYPE_INT64:
             case AV_OPT_TYPE_UINT64:
             case AV_OPT_TYPE_DURATION:
+#if FF_API_OLD_CHANNEL_LAYOUT
             case AV_OPT_TYPE_CHANNEL_LAYOUT:
+#endif
             case AV_OPT_TYPE_PIXEL_FMT:
             case AV_OPT_TYPE_SAMPLE_FMT:
                 write_number(s, opt, dst, 1, 1, opt->default_val.i64);
@@ -1385,6 +1440,9 @@ void av_opt_set_defaults2(void *s, int mask, int flags)
             case AV_OPT_TYPE_BINARY:
                 set_string_binary(s, opt, opt->default_val.str, dst);
                 break;
+            case AV_OPT_TYPE_CHLAYOUT:
+                set_string_channel_layout(s, opt, opt->default_val.str, dst);
+                break;
             case AV_OPT_TYPE_DICT:
                 /* Cannot set defaults for these types */
             break;
@@ -1709,7 +1767,9 @@ static int opt_size(enum AVOptionType type)
     case AV_OPT_TYPE_FLAGS:
         return sizeof(int);
     case AV_OPT_TYPE_DURATION:
+#if FF_API_OLD_CHANNEL_LAYOUT
     case AV_OPT_TYPE_CHANNEL_LAYOUT:
+#endif
     case AV_OPT_TYPE_INT64:
     case AV_OPT_TYPE_UINT64:
         return sizeof(int64_t);
@@ -1848,7 +1908,9 @@ int av_opt_query_ranges_default(AVOptionRanges **ranges_arg, void *obj, const ch
     case AV_OPT_TYPE_DOUBLE:
     case AV_OPT_TYPE_DURATION:
     case AV_OPT_TYPE_COLOR:
+#if FF_API_OLD_CHANNEL_LAYOUT
     case AV_OPT_TYPE_CHANNEL_LAYOUT:
+#endif
         break;
     case AV_OPT_TYPE_STRING:
         range->component_min = 0;
@@ -1928,7 +1990,9 @@ int av_opt_is_set_to_default(void *obj, const AVOption *o)
     case AV_OPT_TYPE_PIXEL_FMT:
     case AV_OPT_TYPE_SAMPLE_FMT:
     case AV_OPT_TYPE_INT:
+#if FF_API_OLD_CHANNEL_LAYOUT
     case AV_OPT_TYPE_CHANNEL_LAYOUT:
+#endif
     case AV_OPT_TYPE_DURATION:
     case AV_OPT_TYPE_INT64:
     case AV_OPT_TYPE_UINT64:
diff --git a/libavutil/opt.h b/libavutil/opt.h
index bc98ab104d..f9b00ce7d5 100644
--- a/libavutil/opt.h
+++ b/libavutil/opt.h
@@ -29,6 +29,7 @@
 
 #include "rational.h"
 #include "avutil.h"
+#include "channel_layout.h"
 #include "dict.h"
 #include "log.h"
 #include "pixfmt.h"
@@ -236,8 +237,11 @@ enum AVOptionType{
     AV_OPT_TYPE_VIDEO_RATE, ///< offset must point to AVRational
     AV_OPT_TYPE_DURATION,
     AV_OPT_TYPE_COLOR,
-    AV_OPT_TYPE_CHANNEL_LAYOUT,
+#if FF_API_OLD_CHANNEL_LAYOUT
+    AV_OPT_TYPE_CHANNEL_LAYOUT attribute_deprecated,
+#endif
     AV_OPT_TYPE_BOOL,
+    AV_OPT_TYPE_CHLAYOUT,
 };
 
 /**
@@ -688,7 +692,11 @@ int av_opt_set_image_size(void *obj, const char *name, int w, int h, int search_
 int av_opt_set_pixel_fmt (void *obj, const char *name, enum AVPixelFormat fmt, int search_flags);
 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);
+#if FF_API_OLD_CHANNEL_LAYOUT
+attribute_deprecated
 int av_opt_set_channel_layout(void *obj, const char *name, int64_t ch_layout, int search_flags);
+#endif
+int av_opt_set_chlayout(void *obj, const char *name, const AVChannelLayout *layout, 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.
@@ -742,7 +750,11 @@ int av_opt_get_image_size(void *obj, const char *name, int search_flags, int *w_
 int av_opt_get_pixel_fmt (void *obj, const char *name, int search_flags, enum AVPixelFormat *out_fmt);
 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);
+#if FF_API_OLD_CHANNEL_LAYOUT
+attribute_deprecated
 int av_opt_get_channel_layout(void *obj, const char *name, int search_flags, int64_t *ch_layout);
+#endif
+int av_opt_get_chlayout(void *obj, const char *name, int search_flags, AVChannelLayout *layout);
 /**
  * @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
