Since the request_channel_layout is used only by a handful of codecs,
move the option to codec private contexts.
---
 libavcodec/avcodec.h       |  31 +++++++++
 libavcodec/decode.c        |  49 +++++++++-----
 libavcodec/encode.c        |   9 ++-
 libavcodec/internal.h      |   2 +
 libavcodec/options_table.h |   5 ++
 libavcodec/utils.c         | 162 +++++++++++++++++++++++++++++++++------------
 libavformat/utils.c        |  26 +++++++-
 7 files changed, 220 insertions(+), 64 deletions(-)

diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index bc7097c7bd..b0eac85f72 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -1834,7 +1834,13 @@ typedef struct AVCodecContext {
 
     /* audio only */
     int sample_rate; ///< samples per second
+#if FF_API_OLD_CHANNEL_LAYOUT
+    /**
+     * @deprecated use ch_layout.nb_channels
+     */
+    attribute_deprecated
     int channels;    ///< number of audio channels
+#endif
 
     /**
      * audio sample format
@@ -1879,19 +1885,25 @@ typedef struct AVCodecContext {
      */
     int cutoff;
 
+#if FF_API_OLD_CHANNEL_LAYOUT
     /**
      * Audio channel layout.
      * - encoding: set by user.
      * - decoding: set by libavcodec.
+     *   @deprecated use ch_layout
      */
+    attribute_deprecated
     uint64_t channel_layout;
 
     /**
      * Request decoder to use this channel layout if it can (0 for default)
      * - encoding: unused
      * - decoding: Set by user.
+     *   @deprecated use "downmix" codec private option
      */
+    attribute_deprecated
     uint64_t request_channel_layout;
+#endif
 
     /**
      * Type of service that the audio stream conveys.
@@ -2730,6 +2742,14 @@ typedef struct AVCodecContext {
      *             AVCodecContext.get_format callback)
      */
     int hwaccel_flags;
+
+    /**
+     * Audio channel layout.
+     * - encoding: must be set by the caller, to one of AVCodec.ch_layouts.
+     * - decoding: may be set by the caller if known e.g. from the container.
+     *             The decoder can then override during decoding as needed.
+     */
+    AVChannelLayout ch_layout;
 } AVCodecContext;
 
 /**
@@ -2771,10 +2791,21 @@ typedef struct AVCodec {
     const enum AVPixelFormat *pix_fmts;     ///< array of supported pixel 
formats, or NULL if unknown, array is terminated by -1
     const int *supported_samplerates;       ///< array of supported audio 
samplerates, or NULL if unknown, array is terminated by 0
     const enum AVSampleFormat *sample_fmts; ///< array of supported sample 
formats, or NULL if unknown, array is terminated by -1
+#if FF_API_OLD_CHANNEL_LAYOUT
+    /**
+     * @deprecated use ch_layouts instead
+     */
+    attribute_deprecated
     const uint64_t *channel_layouts;         ///< array of support channel 
layouts, or NULL if unknown. array is terminated by 0
+#endif
     const AVClass *priv_class;              ///< AVClass for the private 
context
     const AVProfile *profiles;              ///< array of recognized profiles, 
or NULL if unknown, array is terminated by {FF_PROFILE_UNKNOWN}
 
+    /**
+     * Array of supported channel layouts, terminated with a zeroed layout.
+     */
+    const AVChannelLayout *ch_layouts;
+
     /*****************************************************************
      * No fields below this line are part of the public API. They
      * may not be used outside of libavcodec and can be changed and
diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index b0d6b9fb33..c4bcfb95df 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -1131,27 +1131,42 @@ int ff_get_buffer(AVCodecContext *avctx, AVFrame 
*frame, int flags)
             frame->sample_rate    = avctx->sample_rate;
         if (frame->format < 0)
             frame->format         = avctx->sample_fmt;
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+        if (avctx->ch_layout.order == AV_CHANNEL_ORDER_NATIVE ||
+            avctx->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) {
+            if (!frame->ch_layout.nb_channels && (avctx->channel_layout || 
avctx->channels)) {
+                if (avctx->channel_layout)
+                    av_channel_layout_from_mask(&frame->ch_layout, 
avctx->channel_layout);
+                else
+                    av_channel_layout_default(&frame->ch_layout, 
avctx->channels);
+            }
+        }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
         if (!frame->ch_layout.nb_channels) {
-            if (avctx->channel_layout)
-                av_channel_layout_from_mask(&frame->ch_layout, 
avctx->channel_layout);
-            else
-                av_channel_layout_default(&frame->ch_layout, avctx->channels);
+            ret = av_channel_layout_copy(&frame->ch_layout, &avctx->ch_layout);
+            if (ret < 0)
+                return ret;
         }
 #if FF_API_OLD_CHANNEL_LAYOUT
 FF_DISABLE_DEPRECATION_WARNINGS
-        /* set the deprecated channel_layout field for callers
-         * that didn't update to the new API yet */
-        if (frame->ch_layout.nb_channels > FF_SANE_NB_CHANNELS) {
-            av_log(avctx, AV_LOG_ERROR, "Too many channels.\n");
-            return AVERROR(EINVAL);
-        }
-        if (!frame->channel_layout) {
-            if (frame->ch_layout.order == AV_CHANNEL_ORDER_NATIVE)
-                frame->channel_layout = frame->ch_layout.u.mask;
-            else {
-                frame->channel_layout = 
av_get_default_channel_layout(frame->ch_layout.nb_channels);
-                if (!frame->channel_layout)
-                    frame->channel_layout = (1ULL << 
frame->ch_layout.nb_channels) - 1;
+        if (avctx->ch_layout.order == AV_CHANNEL_ORDER_NATIVE ||
+            avctx->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) {
+            /* set the deprecated channel_layout field for callers
+             * that didn't update to the new API yet */
+            if (frame->ch_layout.nb_channels > FF_SANE_NB_CHANNELS) {
+                av_log(avctx, AV_LOG_ERROR, "Too many channels.\n");
+                return AVERROR(EINVAL);
+            }
+            if (!frame->channel_layout) {
+                if (frame->ch_layout.order == AV_CHANNEL_ORDER_NATIVE)
+                    frame->channel_layout = frame->ch_layout.u.mask;
+                else {
+                    frame->channel_layout = 
av_get_default_channel_layout(frame->ch_layout.nb_channels);
+                    if (!frame->channel_layout)
+                        frame->channel_layout = (1ULL << 
frame->ch_layout.nb_channels) - 1;
+                }
             }
         }
 FF_ENABLE_DEPRECATION_WARNINGS
diff --git a/libavcodec/encode.c b/libavcodec/encode.c
index cf77fa7cff..d315e218ab 100644
--- a/libavcodec/encode.c
+++ b/libavcodec/encode.c
@@ -54,6 +54,7 @@ int ff_alloc_packet(AVPacket *avpkt, int size)
 static int pad_last_frame(AVCodecContext *s, AVFrame **dst, const AVFrame *src)
 {
     AVFrame *frame = NULL;
+    int ch = s->ch_layout.nb_channels;
     int ret;
 
     if (!(frame = av_frame_alloc()))
@@ -63,6 +64,8 @@ static int pad_last_frame(AVCodecContext *s, AVFrame **dst, 
const AVFrame *src)
 #if FF_API_OLD_CHANNEL_LAYOUT
 FF_DISABLE_DEPRECATION_WARNINGS
     frame->channel_layout = src->channel_layout;
+    if (!ch)
+        ch = s->channels;
 FF_ENABLE_DEPRECATION_WARNINGS
 #endif
     frame->nb_samples     = s->frame_size;
@@ -80,11 +83,11 @@ FF_ENABLE_DEPRECATION_WARNINGS
         goto fail;
 
     if ((ret = av_samples_copy(frame->extended_data, src->extended_data, 0, 0,
-                               src->nb_samples, s->channels, s->sample_fmt)) < 
0)
+                               src->nb_samples, ch, s->sample_fmt)) < 0)
         goto fail;
     if ((ret = av_samples_set_silence(frame->extended_data, src->nb_samples,
                                       frame->nb_samples - src->nb_samples,
-                                      s->channels, s->sample_fmt)) < 0)
+                                      ch, s->sample_fmt)) < 0)
         goto fail;
 
     *dst = frame;
@@ -122,7 +125,7 @@ int attribute_align_arg 
avcodec_encode_audio2(AVCodecContext *avctx,
     /* ensure that extended_data is properly set */
     if (frame && !frame->extended_data) {
         if (av_sample_fmt_is_planar(avctx->sample_fmt) &&
-            avctx->channels > AV_NUM_DATA_POINTERS) {
+            avctx->ch_layout.nb_channels > AV_NUM_DATA_POINTERS) {
             av_log(avctx, AV_LOG_ERROR, "Encoding to a planar sample format, "
                                         "with more than %d channels, but 
extended_data is not set.\n",
                    AV_NUM_DATA_POINTERS);
diff --git a/libavcodec/internal.h b/libavcodec/internal.h
index 403fb4a090..2d695fafc2 100644
--- a/libavcodec/internal.h
+++ b/libavcodec/internal.h
@@ -75,7 +75,9 @@
 
 #define FF_DEFAULT_QUANT_BIAS 999999
 
+#if FF_API_OLD_CHANNEL_LAYOUT
 #define FF_SANE_NB_CHANNELS 63U
+#endif
 
 #define FF_SIGNBIT(x) (x >> CHAR_BIT * sizeof(x) - 1)
 
diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h
index 925ef376f3..b07f3fbbcf 100644
--- a/libavcodec/options_table.h
+++ b/libavcodec/options_table.h
@@ -71,7 +71,9 @@ static const AVOption avcodec_options[] = {
 {"time_base", NULL, OFFSET(time_base), AV_OPT_TYPE_RATIONAL, {.dbl = 0}, 
INT_MIN, INT_MAX},
 {"g", "set the group of picture (GOP) size", OFFSET(gop_size), 
AV_OPT_TYPE_INT, {.i64 = 12 }, INT_MIN, INT_MAX, V|E},
 {"ar", "set audio sampling rate (in Hz)", OFFSET(sample_rate), 
AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, A|D|E},
+#if FF_API_OLD_CHANNEL_LAYOUT
 {"ac", "set number of audio channels", OFFSET(channels), AV_OPT_TYPE_INT, 
{.i64 = DEFAULT }, INT_MIN, INT_MAX, A|D|E},
+#endif
 {"cutoff", "set cutoff bandwidth", OFFSET(cutoff), AV_OPT_TYPE_INT, {.i64 = 
DEFAULT }, INT_MIN, INT_MAX, A|E},
 {"frame_size", NULL, OFFSET(frame_size), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, 
INT_MIN, INT_MAX, A|E},
 {"frame_number", NULL, OFFSET(frame_number), AV_OPT_TYPE_INT, {.i64 = DEFAULT 
}, INT_MIN, INT_MAX},
@@ -308,8 +310,11 @@ static const AVOption avcodec_options[] = {
 {"timecode_frame_start", "GOP timecode frame start number, in non-drop-frame 
format", OFFSET(timecode_frame_start), AV_OPT_TYPE_INT64, {.i64 = 0 }, 0, 
INT64_MAX, V|E},
 #endif
 {"bits_per_raw_sample", NULL, OFFSET(bits_per_raw_sample), AV_OPT_TYPE_INT, 
{.i64 = DEFAULT }, INT_MIN, INT_MAX},
+#if FF_API_OLD_CHANNEL_LAYOUT
 {"channel_layout", NULL, OFFSET(channel_layout), AV_OPT_TYPE_INT64, {.i64 = 
DEFAULT }, 0, INT64_MAX, A|E|D, "channel_layout"},
 {"request_channel_layout", NULL, OFFSET(request_channel_layout), 
AV_OPT_TYPE_INT64, {.i64 = DEFAULT }, 0, INT64_MAX, A|D, 
"request_channel_layout"},
+#endif
+{"ch_layout",         NULL, OFFSET(ch_layout),         
AV_OPT_TYPE_CHANNEL_LAYOUT, { .str = NULL }, .flags = A|E|D},
 {"rc_max_vbv_use", NULL, OFFSET(rc_max_available_vbv_use), AV_OPT_TYPE_FLOAT, 
{.dbl = 1.0/3 }, 0.0, FLT_MAX, V|E},
 {"rc_min_vbv_use", NULL, OFFSET(rc_min_vbv_overflow_use),  AV_OPT_TYPE_FLOAT, 
{.dbl = 3 },     0.0, FLT_MAX, V|E},
 {"ticks_per_frame", NULL, OFFSET(ticks_per_frame), AV_OPT_TYPE_INT, {.i64 = 1 
}, 1, INT_MAX, A|V|E|D},
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index f8ae415d52..5290477b31 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -480,10 +480,25 @@ int attribute_align_arg avcodec_open2(AVCodecContext 
*avctx, const AVCodec *code
     if (av_codec_is_decoder(codec))
         av_freep(&avctx->subtitle_header);
 
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+    /* if the caller set the deprecated channels/channel_layout fields,
+     * convert them to the new channel layout */
     if (avctx->channels > FF_SANE_NB_CHANNELS) {
         ret = AVERROR(EINVAL);
         goto free_and_end;
     }
+    if (!avctx->ch_layout.nb_channels) {
+        if (avctx->channel_layout)
+            av_channel_layout_from_mask(&avctx->ch_layout, 
avctx->channel_layout);
+        else
+            avctx->ch_layout = (AVChannelLayout){
+                .nb_channels = avctx->channels,
+                .order = AV_CHANNEL_ORDER_UNSPEC,
+            };
+    }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
 
     avctx->codec = codec;
     if ((avctx->codec_type == AVMEDIA_TYPE_UNKNOWN || avctx->codec_type == 
codec->type) &&
@@ -542,7 +557,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
             for (i = 0; avctx->codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; 
i++) {
                 if (avctx->sample_fmt == avctx->codec->sample_fmts[i])
                     break;
-                if (avctx->channels == 1 &&
+                if (avctx->ch_layout.nb_channels == 1 &&
                     av_get_planar_sample_fmt(avctx->sample_fmt) ==
                     av_get_planar_sample_fmt(avctx->codec->sample_fmts[i])) {
                     avctx->sample_fmt = avctx->codec->sample_fmts[i];
@@ -580,7 +595,50 @@ FF_ENABLE_DEPRECATION_WARNINGS
                 goto free_and_end;
             }
         }
-        if (avctx->codec->channel_layouts) {
+
+        if (avctx->codec->ch_layouts) {
+            if (avctx->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) {
+                /* if the layout is unspecified, select a supported native one
+                 * with provided number of channels */
+                for (i = 0; avctx->codec->ch_layouts[i].nb_channels; i++) {
+                    if (avctx->codec->ch_layouts[i].nb_channels == 
avctx->ch_layout.nb_channels) {
+                        ret = av_channel_layout_copy(&avctx->ch_layout,
+                                                     
&avctx->codec->ch_layouts[i]);
+                        if (ret < 0)
+                            goto free_and_end;
+                        break;
+                    }
+                }
+                if (avctx->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) {
+                    av_log(avctx, AV_LOG_ERROR, "This encoder does not "
+                           "support any channel layout with %d channels.\n",
+                           avctx->ch_layout.nb_channels);
+                    ret = AVERROR(EINVAL);
+                    goto free_and_end;
+                }
+            } else {
+                /* check that the selected channel layout is supported */
+                for (i = 0; avctx->codec->ch_layouts[i].nb_channels; i++) {
+                    if 
(!av_channel_layout_compare(&avctx->codec->ch_layouts[i],
+                                                   &avctx->ch_layout))
+                        break;
+                }
+                if (!avctx->codec->ch_layouts[i].nb_channels) {
+                    av_log(avctx, AV_LOG_ERROR,
+                           "Specified channel_layout is not supported\n");
+                    ret = AVERROR(EINVAL);
+                    goto free_and_end;
+                }
+            }
+
+            if (!av_channel_layout_check(&avctx->ch_layout)) {
+                av_log(avctx, AV_LOG_ERROR, "Invalid channel layout 
provided.\n");
+                ret = AVERROR_INVALIDDATA;
+                goto free_and_end;
+            }
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+        } else if (avctx->codec->channel_layouts) {
             if (!avctx->channel_layout) {
                 av_log(avctx, AV_LOG_WARNING, "channel_layout not 
specified\n");
             } else {
@@ -593,15 +651,9 @@ FF_ENABLE_DEPRECATION_WARNINGS
                     goto free_and_end;
                 }
             }
-        }
-        if (avctx->channel_layout && avctx->channels) {
-            if (av_get_channel_layout_nb_channels(avctx->channel_layout) != 
avctx->channels) {
-                av_log(avctx, AV_LOG_ERROR, "channel layout does not match 
number of channels\n");
-                ret = AVERROR(EINVAL);
-                goto free_and_end;
-            }
-        } else if (avctx->channel_layout) {
-            avctx->channels = 
av_get_channel_layout_nb_channels(avctx->channel_layout);
+            av_channel_layout_from_mask(&avctx->ch_layout, 
avctx->channel_layout);
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
         }
 
         if (!avctx->rc_initial_buffer_occupancy)
@@ -646,24 +698,22 @@ FF_ENABLE_DEPRECATION_WARNINGS
         }
     }
 
-    if (av_codec_is_decoder(avctx->codec)) {
-        /* validate channel layout from the decoder */
-        if (avctx->channel_layout) {
-            int channels = 
av_get_channel_layout_nb_channels(avctx->channel_layout);
-            if (!avctx->channels)
-                avctx->channels = channels;
-            else if (channels != avctx->channels) {
-                av_log(avctx, AV_LOG_WARNING,
-                       "channel layout does not match number of channels\n");
-                avctx->channel_layout = 0;
-            }
-        }
-        if (avctx->channels && avctx->channels < 0 ||
-            avctx->channels > FF_SANE_NB_CHANNELS) {
-            ret = AVERROR(EINVAL);
-            goto free_and_end;
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+    if (avctx->ch_layout.order == AV_CHANNEL_ORDER_NATIVE ||
+        avctx->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) {
+        if (avctx->channel_layout && avctx->channel_layout != 
avctx->ch_layout.u.mask)
+            av_channel_layout_from_mask(&avctx->ch_layout, 
avctx->channel_layout);
+        else if (avctx->channels && avctx->channels != 
avctx->ch_layout.nb_channels)
+            av_channel_layout_default(&avctx->ch_layout, avctx->channels);
+        if (avctx->ch_layout.nb_channels) {
+            avctx->channel_layout = avctx->ch_layout.u.mask;
+            avctx->channels = avctx->ch_layout.nb_channels;
         }
     }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+
 end:
     if (!(codec->caps_internal & FF_CODEC_CAP_INIT_THREADSAFE) && codec->init) 
{
         entangled_thread_counter--;
@@ -764,6 +814,8 @@ av_cold int avcodec_close(AVCodecContext *avctx)
         av_freep(&avctx->internal);
     }
 
+    av_channel_layout_uninit(&avctx->ch_layout);
+
     for (i = 0; i < avctx->nb_coded_side_data; i++)
         av_freep(&avctx->coded_side_data[i].data);
     av_freep(&avctx->coded_side_data);
@@ -859,7 +911,7 @@ static int get_bit_rate(AVCodecContext *ctx)
         break;
     case AVMEDIA_TYPE_AUDIO:
         bits_per_sample = av_get_bits_per_sample(ctx->codec_id);
-        bit_rate = bits_per_sample ? ctx->sample_rate * ctx->channels * 
bits_per_sample : ctx->bit_rate;
+        bit_rate = bits_per_sample ? ctx->sample_rate * 
ctx->ch_layout.nb_channels * bits_per_sample : ctx->bit_rate;
         break;
     default:
         bit_rate = 0;
@@ -1004,7 +1056,13 @@ void avcodec_string(char *buf, int buf_size, 
AVCodecContext *enc, int encode)
             snprintf(buf + strlen(buf), buf_size - strlen(buf),
                      "%d Hz, ", enc->sample_rate);
         }
-        av_get_channel_layout_string(buf + strlen(buf), buf_size - 
strlen(buf), enc->channels, enc->channel_layout);
+
+        if (av_channel_layout_check(&enc->ch_layout)) {
+            char *chlstr = av_channel_layout_describe(&enc->ch_layout);
+            av_strlcat(buf, chlstr, buf_size);
+            av_free(chlstr);
+        }
+
         if (enc->sample_fmt != AV_SAMPLE_FMT_NONE) {
             snprintf(buf + strlen(buf), buf_size - strlen(buf),
                      ", %s", av_get_sample_fmt_name(enc->sample_fmt));
@@ -1292,8 +1350,15 @@ static int get_audio_frame_duration(enum AVCodecID id, 
int sr, int ch, int ba,
 
 int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes)
 {
+    int channels = avctx->ch_layout.nb_channels;
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+    if (!channels)
+        channels = avctx->channels;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
     return get_audio_frame_duration(avctx->codec_id, avctx->sample_rate,
-                                    avctx->channels, avctx->block_align,
+                                    channels, avctx->block_align,
                                     avctx->codec_tag, 
avctx->bits_per_coded_sample,
                                     frame_bytes);
 }
@@ -1601,6 +1666,8 @@ int avcodec_parameters_copy(AVCodecParameters *dst, const 
AVCodecParameters *src
 int avcodec_parameters_from_context(AVCodecParameters *par,
                                     const AVCodecContext *codec)
 {
+    int ret;
+
     codec_parameters_reset(par);
 
     par->codec_type = codec->codec_type;
@@ -1627,16 +1694,23 @@ int avcodec_parameters_from_context(AVCodecParameters 
*par,
         break;
     case AVMEDIA_TYPE_AUDIO:
         par->format          = codec->sample_fmt;
+        ret = av_channel_layout_copy(&par->ch_layout, &codec->ch_layout);
+        if (ret < 0)
+            return ret;
 #if FF_API_OLD_CHANNEL_LAYOUT
 FF_DISABLE_DEPRECATION_WARNINGS
-        par->channel_layout  = codec->channel_layout;
-        par->channels        = codec->channels;
+        if (!av_channel_layout_check(&codec->ch_layout))
+            if (codec->channel_layout)
+                av_channel_layout_from_mask(&par->ch_layout, 
codec->channel_layout);
+            else
+                av_channel_layout_default(&par->ch_layout, codec->channels);
+        if (codec->ch_layout.order == AV_CHANNEL_ORDER_NATIVE ||
+            codec->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) {
+            par->channel_layout  = codec->channel_layout;
+            par->channels        = codec->channels;
+        }
 FF_ENABLE_DEPRECATION_WARNINGS
 #endif
-        if (codec->channel_layout)
-            av_channel_layout_from_mask(&par->ch_layout, 
codec->channel_layout);
-        else
-            av_channel_layout_default(&par->ch_layout, codec->channels);
         par->sample_rate     = codec->sample_rate;
         par->block_align     = codec->block_align;
         par->initial_padding = codec->initial_padding;
@@ -1657,6 +1731,8 @@ FF_ENABLE_DEPRECATION_WARNINGS
 int avcodec_parameters_to_context(AVCodecContext *codec,
                                   const AVCodecParameters *par)
 {
+    int ret;
+
     codec->codec_type = par->codec_type;
     codec->codec_id   = par->codec_id;
     codec->codec_tag  = par->codec_tag;
@@ -1681,16 +1757,18 @@ int avcodec_parameters_to_context(AVCodecContext *codec,
         break;
     case AVMEDIA_TYPE_AUDIO:
         codec->sample_fmt      = par->format;
+        ret = av_channel_layout_copy(&codec->ch_layout, &par->ch_layout);
+        if (ret < 0)
+            return ret;
 #if FF_API_OLD_CHANNEL_LAYOUT
 FF_DISABLE_DEPRECATION_WARNINGS
-        codec->channel_layout = par->channel_layout;
-        codec->channels       = par->channels;
+        if (par->ch_layout.order == AV_CHANNEL_ORDER_NATIVE ||
+            par->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) {
+            codec->channel_layout = par->ch_layout.u.mask;
+            codec->channels       = par->ch_layout.nb_channels;
+        }
 FF_ENABLE_DEPRECATION_WARNINGS
 #endif
-        if (par->ch_layout.u.mask)
-            codec->channel_layout = par->ch_layout.u.mask;
-        if (par->ch_layout.nb_channels)
-            codec->channels = par->ch_layout.nb_channels;
         codec->sample_rate     = par->sample_rate;
         codec->block_align     = par->block_align;
         codec->initial_padding = par->initial_padding;
diff --git a/libavformat/utils.c b/libavformat/utils.c
index c8bb04aa70..b12e91f78b 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -1862,11 +1862,18 @@ static void estimate_timings(AVFormatContext *ic, 
int64_t old_offset)
 static int has_codec_parameters(AVStream *st)
 {
     AVCodecContext *avctx = st->internal->avctx;
-    int val;
+    int val, ch;
 
     switch (avctx->codec_type) {
     case AVMEDIA_TYPE_AUDIO:
-        val = avctx->sample_rate && avctx->channels;
+        ch = avctx->ch_layout.nb_channels;
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+        if (!ch)
+            ch = avctx->channels;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+        val = avctx->sample_rate && ch;
         if (st->info->found_decoder >= 0 &&
             avctx->sample_fmt == AV_SAMPLE_FMT_NONE)
             return 0;
@@ -1965,6 +1972,21 @@ FF_ENABLE_DEPRECATION_WARNINGS
         }
     }
 
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+    /* temporary compatibility layer */
+    if (!avctx->ch_layout.nb_channels) {
+        av_channel_layout_uninit(&avctx->ch_layout);
+        if (avctx->channel_layout)
+            av_channel_layout_from_mask(&avctx->ch_layout, 
avctx->channel_layout);
+        else {
+            avctx->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+            avctx->ch_layout.nb_channels = avctx->channels;
+        }
+    }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+
 fail:
     av_frame_free(&frame);
     return ret;
-- 
2.13.1

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to