Discussion:
[PATCH 00/25] New channel API, review compatibility
(too old to reply)
Vittorio Giovara
2017-06-28 22:10:44 UTC
Permalink
Hello,
it has brought to my attention that reviewing 200 patches is not
desirable, and following the reviewers' suggestions, I squashed the
more mundane replacement patches across the codebase, and left the
more important or complex ones separate to simplify review.

Some of the single patches at the beginning have already been published
and reviewed, added for completeness.

Cheers,
Vittorio

Anton Khirnov (5):
Add a new channel layout API
lavu: support AVChannelLayout AVOptions
lavc: deprecate channel count/layout changing side data
avframe: switch to the new channel layout API
lavr: switch to the new channel layout API

Vittorio Giovara (20):
avtools: Use the new channel layout API in AVFrame
lavfi, buffersrc: switch to the new channel layout API
libavfilter changes for the new channel layout API
lavfi: Port filter negotiation to use the new channel layout API
avcodecpar: switch to the new channel layout API
libavformat changes for the new channel layout API
lavc: switch to the new channel layout API
aac: convert to new channel layout API
ac3: convert to new channel layout API
libavcodec changes for the the new channel layout API
tools, examples changes for the new channel layout API
channel_layout: Add Ambisonic components and channel order
lavr: Only let pass-through ambisonic channel layouts
opus: Implement mapping type 2 for Ambisonic support
lavf: Add non diegetic stream disposition flag
mov: Implement spatial audio support
aac: Allow pass-through transcoding of ambisonic audio
avprobe: Print the channel layout string
fate: Add ambisonic tests
Bump library versions, update Changelog and APIchanges

Changelog | 1 +
avtools/avconv.c | 30 +--
avtools/avconv.h | 8 +-
avtools/avconv_filter.c | 44 +++-
avtools/avconv_opt.c | 52 ++--
avtools/avplay.c | 52 ++--
avtools/avprobe.c | 6 +-
avtools/cmdutils.c | 17 +-
avtools/cmdutils.h | 8 -
doc/APIchanges | 22 ++
doc/examples/decode_audio.c | 2 +-
doc/examples/encode_audio.c | 36 +--
doc/examples/filter_audio.c | 11 +-
doc/examples/output.c | 30 ++-
doc/examples/transcode_aac.c | 29 ++-
libavcodec/8svx.c | 15 +-
libavcodec/aac.h | 7 +-
libavcodec/aac_ac3_parser.c | 9 +-
libavcodec/aaccoder.c | 2 +-
libavcodec/aacdec.c | 79 +++++-
libavcodec/aacdectab.h | 16 ++
libavcodec/aacenc.c | 2 +-
libavcodec/aacpsy.c | 10 +-
libavcodec/ac3dec.c | 49 +++-
libavcodec/ac3dec.h | 2 +
libavcodec/ac3enc.c | 83 +++++--
libavcodec/ac3enc.h | 4 +-
libavcodec/ac3enc_fixed.c | 5 +
libavcodec/ac3enc_float.c | 5 +
libavcodec/adpcm.c | 57 ++---
libavcodec/adpcmenc.c | 92 +++----
libavcodec/adx.c | 16 +-
libavcodec/adxdec.c | 6 +-
libavcodec/adxenc.c | 11 +-
libavcodec/alac.c | 18 +-
libavcodec/alac_data.c | 12 +
libavcodec/alac_data.h | 6 +
libavcodec/alacenc.c | 20 +-
libavcodec/alsdec.c | 65 ++---
libavcodec/amrnbdec.c | 6 +-
libavcodec/amrwbdec.c | 6 +-
libavcodec/apedec.c | 9 +-
libavcodec/atrac1.c | 10 +-
libavcodec/atrac3.c | 26 +-
libavcodec/atrac3plusdec.c | 25 +-
libavcodec/avcodec.h | 47 ++++
libavcodec/binkaudio.c | 17 +-
libavcodec/bmvaudio.c | 4 +-
libavcodec/cngdec.c | 3 +-
libavcodec/cngenc.c | 6 +-
libavcodec/cook.c | 22 +-
libavcodec/cook_parser.c | 4 +-
libavcodec/dca.h | 2 +
libavcodec/dca_xll.c | 6 +-
libavcodec/dcadec.c | 54 +++--
libavcodec/decode.c | 88 +++++--
libavcodec/dpcm.c | 14 +-
libavcodec/dsicinaudio.c | 4 +-
libavcodec/dss_sp.c | 4 +-
libavcodec/eac3enc.c | 5 +
libavcodec/encode.c | 18 +-
libavcodec/flac.c | 37 +--
libavcodec/flac.h | 2 +-
libavcodec/flac_parser.c | 7 +-
libavcodec/flacdec.c | 10 +-
libavcodec/flacenc.c | 2 +-
libavcodec/g722dec.c | 4 +-
libavcodec/g722enc.c | 8 +-
libavcodec/g723_1dec.c | 4 +-
libavcodec/g723_1enc.c | 8 +-
libavcodec/g726.c | 6 +-
libavcodec/gsmdec.c | 4 +-
libavcodec/imc.c | 22 +-
libavcodec/internal.h | 2 +
libavcodec/libdcadec.c | 6 +-
libavcodec/libfdk-aacdec.c | 34 ++-
libavcodec/libfdk-aacenc.c | 36 ++-
libavcodec/libgsmdec.c | 4 +-
libavcodec/libgsmenc.c | 4 +-
libavcodec/libilbc.c | 4 +-
libavcodec/libopencore-amr.c | 8 +-
libavcodec/libopusdec.c | 42 ++--
libavcodec/libopusenc.c | 32 ++-
libavcodec/libspeexdec.c | 18 +-
libavcodec/mace.c | 11 +-
libavcodec/metasound.c | 31 +--
libavcodec/mlp_parser.c | 34 +--
libavcodec/mlp_parser.h | 4 +-
libavcodec/mlpdec.c | 96 ++++----
libavcodec/mpc7.c | 7 +-
libavcodec/mpc8.c | 5 +-
libavcodec/mpegaudio_parser.c | 2 +-
libavcodec/mpegaudiodec_template.c | 37 +--
libavcodec/mpegaudioenc.c | 11 +-
libavcodec/nellymoserdec.c | 4 +-
libavcodec/nellymoserenc.c | 6 +-
libavcodec/on2avc.c | 19 +-
libavcodec/options_table.h | 5 +
libavcodec/opus.c | 42 +++-
libavcodec/opusdec.c | 13 +-
libavcodec/pafaudio.c | 5 +-
libavcodec/pcm-bluray.c | 36 ++-
libavcodec/pcm-dvd.c | 24 +-
libavcodec/pcm.c | 23 +-
libavcodec/psymodel.c | 8 +-
libavcodec/qcelpdec.c | 4 +-
libavcodec/qdm2.c | 6 +-
libavcodec/ra144dec.c | 4 +-
libavcodec/ra144enc.c | 6 +-
libavcodec/ra288.c | 4 +-
libavcodec/ralf.c | 16 +-
libavcodec/roqaudioenc.c | 20 +-
libavcodec/s302m.c | 15 +-
libavcodec/shorten.c | 6 +-
libavcodec/sipr.c | 4 +-
libavcodec/smacker.c | 11 +-
libavcodec/takdec.c | 40 ++--
libavcodec/truespeech.c | 7 +-
libavcodec/tta.c | 15 +-
libavcodec/twinvq.c | 20 +-
libavcodec/twinvqdec.c | 18 +-
libavcodec/utils.c | 173 +++++++++++---
libavcodec/vima.c | 5 +-
libavcodec/vmdaudio.c | 22 +-
libavcodec/vorbis.h | 5 +
libavcodec/vorbis_data.c | 18 ++
libavcodec/vorbisdec.c | 18 +-
libavcodec/vorbisenc.c | 4 +-
libavcodec/wavpack.c | 19 +-
libavcodec/wma.c | 13 +-
libavcodec/wmadec.c | 25 +-
libavcodec/wmaenc.c | 27 ++-
libavcodec/wmalosslessdec.c | 36 ++-
libavcodec/wmaprodec.c | 66 +++--
libavcodec/wmavoice.c | 4 +-
libavcodec/ws-snd1.c | 4 +-
libavdevice/alsa.c | 10 +-
libavfilter/af_aformat.c | 30 ++-
libavfilter/af_amix.c | 11 +-
libavfilter/af_ashowinfo.c | 12 +-
libavfilter/af_asyncts.c | 6 +-
libavfilter/af_channelmap.c | 92 +++----
libavfilter/af_channelsplit.c | 40 ++--
libavfilter/af_compand.c | 8 +-
libavfilter/af_hdcd.c | 2 +-
libavfilter/af_join.c | 84 +++----
libavfilter/af_resample.c | 33 +--
libavfilter/af_volume.c | 2 +-
libavfilter/audio.c | 17 +-
libavfilter/avfilter.c | 9 +-
libavfilter/avfilter.h | 13 +-
libavfilter/avfiltergraph.c | 116 +++++++--
libavfilter/buffersink.c | 2 +-
libavfilter/buffersrc.c | 53 +++--
libavfilter/buffersrc.h | 12 +-
libavfilter/fifo.c | 7 +-
libavfilter/formats.c | 45 +++-
libavfilter/formats.h | 4 +-
libavfilter/trim.c | 3 +-
libavformat/4xm.c | 7 +-
libavformat/adxdec.c | 11 +-
libavformat/aea.c | 11 +-
libavformat/aiffdec.c | 13 +-
libavformat/aiffenc.c | 4 +-
libavformat/amr.c | 3 +-
libavformat/apc.c | 12 +-
libavformat/ape.c | 3 +-
libavformat/au.c | 5 +-
libavformat/audiointerleave.c | 2 +-
libavformat/avformat.h | 6 +
libavformat/bethsoftvid.c | 3 +-
libavformat/bfi.c | 3 +-
libavformat/bink.c | 12 +-
libavformat/bmv.c | 3 +-
libavformat/cafdec.c | 3 +-
libavformat/cdxl.c | 9 +-
libavformat/dashenc.c | 2 +-
libavformat/dauddec.c | 3 +-
libavformat/daudenc.c | 2 +-
libavformat/dsicin.c | 7 +-
libavformat/dss.c | 3 +-
libavformat/dump.c | 11 +-
libavformat/dv.c | 3 +-
libavformat/dvenc.c | 2 +-
libavformat/eacdata.c | 3 +-
libavformat/electronicarts.c | 7 +-
libavformat/flacdec.c | 2 +-
libavformat/flacenc.c | 13 +-
libavformat/flic.c | 3 +-
libavformat/flvdec.c | 21 +-
libavformat/flvenc.c | 6 +-
libavformat/g722.c | 2 +-
libavformat/g723_1.c | 3 +-
libavformat/g729dec.c | 2 +-
libavformat/gsmdec.c | 3 +-
libavformat/gxf.c | 9 +-
libavformat/gxfenc.c | 2 +-
libavformat/idcin.c | 4 +-
libavformat/idroqdec.c | 12 +-
libavformat/iff.c | 16 +-
libavformat/ilbc.c | 2 +-
libavformat/ipmovie.c | 8 +-
libavformat/isom.c | 5 +-
libavformat/iss.c | 17 +-
libavformat/jvdec.c | 3 +-
libavformat/lxfdec.c | 3 +-
libavformat/matroskadec.c | 4 +-
libavformat/matroskaenc.c | 15 +-
libavformat/mm.c | 3 +-
libavformat/mmf.c | 3 +-
libavformat/mov.c | 158 ++++++++++--
libavformat/mov_chan.c | 26 +-
libavformat/mov_chan.h | 4 +-
libavformat/movenc.c | 8 +-
libavformat/mp3enc.c | 2 +-
libavformat/mpc.c | 3 +-
libavformat/mpc8.c | 5 +-
libavformat/mpegenc.c | 6 +-
libavformat/mux.c | 2 +-
libavformat/mvdec.c | 10 +-
libavformat/mvi.c | 3 +-
libavformat/mxfdec.c | 13 +-
libavformat/mxfenc.c | 6 +-
libavformat/mxg.c | 3 +-
libavformat/nsvdec.c | 2 +-
libavformat/nutdec.c | 2 +-
libavformat/nutenc.c | 2 +-
libavformat/nuv.c | 7 +-
libavformat/oggparsecelt.c | 3 +-
libavformat/oggparseogm.c | 6 +-
libavformat/oggparseopus.c | 3 +-
libavformat/oggparsespeex.c | 8 +-
libavformat/oggparsevorbis.c | 3 +-
libavformat/oma.c | 19 +-
libavformat/oma.h | 5 +-
libavformat/omadec.c | 10 +-
libavformat/omaenc.c | 4 +-
libavformat/paf.c | 3 +-
libavformat/pcm.c | 2 +-
libavformat/pcmdec.c | 7 +-
libavformat/pmpdec.c | 3 +-
libavformat/psxstr.c | 10 +-
libavformat/qcp.c | 3 +-
libavformat/r3d.c | 3 +-
libavformat/riffdec.c | 13 +-
libavformat/riffenc.c | 11 +-
libavformat/rl2.c | 7 +-
libavformat/rmdec.c | 6 +-
libavformat/rmenc.c | 2 +-
libavformat/rpl.c | 8 +-
libavformat/rsodec.c | 3 +-
libavformat/rsoenc.c | 2 +-
libavformat/rtp.c | 10 +-
libavformat/rtpdec_amr.c | 3 +-
libavformat/rtpenc.c | 12 +-
libavformat/rtsp.c | 6 +-
libavformat/rtsp.h | 1 -
libavformat/sdp.c | 34 +--
libavformat/segafilm.c | 9 +-
libavformat/sierravmd.c | 12 +-
libavformat/siff.c | 3 +-
libavformat/smacker.c | 12 +-
libavformat/smjpegdec.c | 3 +-
libavformat/smjpegenc.c | 2 +-
libavformat/smoothstreamingenc.c | 2 +-
libavformat/smush.c | 4 +-
libavformat/sol.c | 4 +-
libavformat/soxdec.c | 14 +-
libavformat/soxenc.c | 4 +-
libavformat/swfdec.c | 8 +-
libavformat/swfenc.c | 2 +-
libavformat/takdec.c | 7 +-
libavformat/tests/movenc.c | 2 +-
libavformat/thp.c | 3 +-
libavformat/tiertexseq.c | 7 +-
libavformat/tmv.c | 10 +-
libavformat/tta.c | 3 +-
libavformat/utils.c | 35 ++-
libavformat/voc_packet.c | 7 +-
libavformat/vocenc.c | 8 +-
libavformat/vqf.c | 11 +-
libavformat/wavdec.c | 4 +-
libavformat/wc3movie.c | 8 +-
libavformat/westwood_aud.c | 6 +-
libavformat/westwood_vqa.c | 2 +-
libavformat/wtv.c | 6 +-
libavformat/wvdec.c | 3 +-
libavformat/xa.c | 7 +-
libavformat/xmv.c | 3 +-
libavformat/xwma.c | 8 +-
libavformat/yop.c | 3 +-
libavresample/audio_mix.c | 148 +++++++-----
libavresample/audio_mix_matrix.c | 477 +++++++++++++++++++++----------------
libavresample/avresample.h | 42 +++-
libavresample/internal.h | 10 +-
libavresample/options.c | 8 +
libavresample/tests/avresample.c | 26 +-
libavresample/utils.c | 135 ++++++++---
libavutil/channel_layout.c | 467 +++++++++++++++++++++++++++++++-----
libavutil/channel_layout.h | 395 ++++++++++++++++++++++++++++--
libavutil/frame.c | 88 ++++++-
libavutil/frame.h | 12 +-
libavutil/opt.c | 47 ++++
libavutil/opt.h | 10 +
libavutil/version.h | 3 +
tests/fate/ac3.mak | 12 +-
tests/fate/lossless-audio.mak | 2 +-
tests/fate/mov.mak | 3 +
tests/fate/opus.mak | 5 +
tests/ref/fate/mov-ambisonic | 1 +
tests/ref/fate/opus-ambisonic | 1 +
tools/graph2dot.c | 7 +-
tools/ismindex.c | 2 +-
tools/sidxindex.c | 2 +-
314 files changed, 4084 insertions(+), 2119 deletions(-)
create mode 100644 tests/ref/fate/mov-ambisonic
create mode 100644 tests/ref/fate/opus-ambisonic
--
2.13.1
Vittorio Giovara
2017-06-28 22:10:46 UTC
Permalink
From: Anton Khirnov <***@khirnov.net>

Signed-off-by: Vittorio Giovara <***@gmail.com>
---
libavutil/opt.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
libavutil/opt.h | 10 ++++++++++
2 files changed, 57 insertions(+)

diff --git a/libavutil/opt.c b/libavutil/opt.c
index 44d6299117..698f6e97e0 100644
--- a/libavutil/opt.c
+++ b/libavutil/opt.c
@@ -242,6 +242,14 @@ static int set_string_number(void *obj, void *target_obj, const AVOption *o, con
}
}

+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);
+ return av_channel_layout_from_string(channel_layout, val);
+}
+
int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
{
void *dst, *target_obj;
@@ -264,6 +272,8 @@ int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
case AV_OPT_TYPE_DOUBLE:
case AV_OPT_TYPE_RATIONAL:
return set_string_number(obj, target_obj, o, val, dst);
+ case AV_OPT_TYPE_CHANNEL_LAYOUT:
+ return set_string_channel_layout(obj, o, val, dst);
}

av_log(obj, AV_LOG_ERROR, "Invalid option type.\n");
@@ -365,6 +375,22 @@ int av_opt_set_dict_val(void *obj, const char *name, const AVDictionary *val,
return 0;
}

+int av_opt_set_channel_layout(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);
+}
+
int av_opt_get(void *obj, const char *name, int search_flags, uint8_t **out_val)
{
void *dst, *target_obj;
@@ -414,6 +440,9 @@ int av_opt_get(void *obj, const char *name, int search_flags, uint8_t **out_val)
for (i = 0; i < len; i++)
snprintf(*out_val + i * 2, 3, "%02X", bin[i]);
return 0;
+ case AV_OPT_TYPE_CHANNEL_LAYOUT:
+ *out_val = av_channel_layout_describe(dst);
+ return *out_val ? 0 : AVERROR(EINVAL);
default:
return AVERROR(EINVAL);
}
@@ -499,6 +528,20 @@ int av_opt_get_dict_val(void *obj, const char *name, int search_flags, AVDiction
return 0;
}

+int av_opt_get_channel_layout(void *obj, const char *name, int search_flags,
+ AVChannelLayout *channel_layout)
+{
+ void *dst, *target_obj;
+ const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
+
+ if (!o || !target_obj)
+ return AVERROR_OPTION_NOT_FOUND;
+
+ dst = ((uint8_t*)target_obj) + o->offset;
+
+ return av_channel_layout_copy(channel_layout, dst);
+}
+
int av_opt_flag_is_set(void *obj, const char *field_name, const char *flag_name)
{
const AVOption *field = av_opt_find(obj, field_name, NULL, 0, 0);
@@ -561,6 +604,9 @@ static void opt_list(void *obj, void *av_log_obj, const char *unit,
case AV_OPT_TYPE_BINARY:
av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<binary>");
break;
+ case AV_OPT_TYPE_CHANNEL_LAYOUT:
+ av_log(av_log_obj, AV_LOG_INFO, "%-7s", "<channel layout>");
+ break;
case AV_OPT_TYPE_CONST:
default:
av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "");
@@ -626,6 +672,7 @@ void av_opt_set_defaults(void *s)
}
break;
case AV_OPT_TYPE_STRING:
+ case AV_OPT_TYPE_CHANNEL_LAYOUT:
av_opt_set(s, opt->name, opt->default_val.str, 0);
break;
case AV_OPT_TYPE_BINARY:
diff --git a/libavutil/opt.h b/libavutil/opt.h
index b68a396da7..a30c53b0ab 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"

@@ -225,6 +226,11 @@ enum AVOptionType{
AV_OPT_TYPE_RATIONAL,
AV_OPT_TYPE_BINARY, ///< offset must point to a pointer immediately followed by an int for the length
AV_OPT_TYPE_DICT,
+ /**
+ * The offset point to an AVChannelLayout, the default is .str, which gets
+ * passed to av_channel_layout_from_string().
+ */
+ AV_OPT_TYPE_CHANNEL_LAYOUT,
AV_OPT_TYPE_CONST = 128,
};

@@ -499,6 +505,8 @@ int av_opt_set_bin (void *obj, const char *name, const uint8_t *val, int siz
* caller still owns val is and responsible for freeing it.
*/
int av_opt_set_dict_val(void *obj, const char *name, const AVDictionary *val, int search_flags);
+int av_opt_set_channel_layout(void *obj, const char *name,
+ const AVChannelLayout *channel_layout, int search_flags);
/**
* @}
*/
@@ -528,6 +536,8 @@ int av_opt_get_q (void *obj, const char *name, int search_flags, AVRationa
*/
int av_opt_get_dict_val(void *obj, const char *name, int search_flags, AVDictionary **out_val);

+int av_opt_get_channel_layout(void *obj, const char *name, int search_flags,
+ AVChannelLayout *channel_layout);
/**
* Copy options from src object into dest object.
*
--
2.13.1
Vittorio Giovara
2017-06-28 22:10:45 UTC
Permalink
From: Anton Khirnov <***@khirnov.net>

The new API is more extensible and allows for custom layouts.
More accurate information is exported, eg for decoders that do not
set a channel layout, lavc will not make one up for them.

Deprecate the old API working with just uint64_t bitmasks.

Expanded and completed by Vittorio Giovara <***@gmail.com>.
Signed-off-by: Vittorio Giovara <***@gmail.com>
---
libavutil/channel_layout.c | 387 +++++++++++++++++++++++++++++++++++++--------
libavutil/channel_layout.h | 362 +++++++++++++++++++++++++++++++++++++++---
libavutil/version.h | 3 +
3 files changed, 662 insertions(+), 90 deletions(-)

diff --git a/libavutil/channel_layout.c b/libavutil/channel_layout.c
index 41340ecdb6..285997446d 100644
--- a/libavutil/channel_layout.c
+++ b/libavutil/channel_layout.c
@@ -31,77 +31,90 @@
#include "common.h"

static const char * const channel_names[] = {
- [0] = "FL", /* front left */
- [1] = "FR", /* front right */
- [2] = "FC", /* front center */
- [3] = "LFE", /* low frequency */
- [4] = "BL", /* back left */
- [5] = "BR", /* back right */
- [6] = "FLC", /* front left-of-center */
- [7] = "FRC", /* front right-of-center */
- [8] = "BC", /* back-center */
- [9] = "SL", /* side left */
- [10] = "SR", /* side right */
- [11] = "TC", /* top center */
- [12] = "TFL", /* top front left */
- [13] = "TFC", /* top front center */
- [14] = "TFR", /* top front right */
- [15] = "TBL", /* top back left */
- [16] = "TBC", /* top back center */
- [17] = "TBR", /* top back right */
- [29] = "DL", /* downmix left */
- [30] = "DR", /* downmix right */
- [31] = "WL", /* wide left */
- [32] = "WR", /* wide right */
- [33] = "SDL", /* surround direct left */
- [34] = "SDR", /* surround direct right */
- [35] = "LFE2", /* low frequency 2 */
+ [AV_CHAN_FRONT_LEFT ] = "FL",
+ [AV_CHAN_FRONT_RIGHT ] = "FR",
+ [AV_CHAN_FRONT_CENTER ] = "FC",
+ [AV_CHAN_LOW_FREQUENCY ] = "LFE",
+ [AV_CHAN_BACK_LEFT ] = "BL",
+ [AV_CHAN_BACK_RIGHT ] = "BR",
+ [AV_CHAN_FRONT_LEFT_OF_CENTER ] = "FLC",
+ [AV_CHAN_FRONT_RIGHT_OF_CENTER ] = "FRC",
+ [AV_CHAN_BACK_CENTER ] = "BC",
+ [AV_CHAN_SIDE_LEFT ] = "SL",
+ [AV_CHAN_SIDE_RIGHT ] = "SR",
+ [AV_CHAN_TOP_CENTER ] = "TC",
+ [AV_CHAN_TOP_FRONT_LEFT ] = "TFL",
+ [AV_CHAN_TOP_FRONT_CENTER ] = "TFC",
+ [AV_CHAN_TOP_FRONT_RIGHT ] = "TFR",
+ [AV_CHAN_TOP_BACK_LEFT ] = "TBL",
+ [AV_CHAN_TOP_BACK_CENTER ] = "TBC",
+ [AV_CHAN_TOP_BACK_RIGHT ] = "TBR",
+ [AV_CHAN_STEREO_LEFT ] = "DL",
+ [AV_CHAN_STEREO_RIGHT ] = "DR",
+ [AV_CHAN_WIDE_LEFT ] = "WL",
+ [AV_CHAN_WIDE_RIGHT ] = "WR",
+ [AV_CHAN_SURROUND_DIRECT_LEFT ] = "SDL",
+ [AV_CHAN_SURROUND_DIRECT_RIGHT ] = "SDR",
+ [AV_CHAN_LOW_FREQUENCY_2 ] = "LFE2",
+ [AV_CHAN_SILENCE ] = "PAD",
};

-static const char *get_channel_name(int channel_id)
+const char *av_channel_name(enum AVChannel channel_id)
{
- if (channel_id < 0 || channel_id >= FF_ARRAY_ELEMS(channel_names))
- return NULL;
+ if ((unsigned) channel_id >= FF_ARRAY_ELEMS(channel_names))
+ return "?";
return channel_names[channel_id];
}

+int av_channel_from_string(const char *str)
+{
+ int i;
+ for (i = 0; i < FF_ARRAY_ELEMS(channel_names); i++) {
+ if (channel_names[i] && !strcmp(str, channel_names[i])) {
+ return i;
+ }
+ }
+ return AVERROR(EINVAL);
+}
+
static const struct {
const char *name;
- int nb_channels;
- uint64_t layout;
+ AVChannelLayout layout;
} channel_layout_map[] = {
- { "mono", 1, AV_CH_LAYOUT_MONO },
- { "stereo", 2, AV_CH_LAYOUT_STEREO },
- { "stereo", 2, AV_CH_LAYOUT_STEREO_DOWNMIX },
- { "2.1", 3, AV_CH_LAYOUT_2POINT1 },
- { "3.0", 3, AV_CH_LAYOUT_SURROUND },
- { "3.0(back)", 3, AV_CH_LAYOUT_2_1 },
- { "3.1", 4, AV_CH_LAYOUT_3POINT1 },
- { "4.0", 4, AV_CH_LAYOUT_4POINT0 },
- { "quad", 4, AV_CH_LAYOUT_QUAD },
- { "quad(side)", 4, AV_CH_LAYOUT_2_2 },
- { "4.1", 5, AV_CH_LAYOUT_4POINT1 },
- { "5.0", 5, AV_CH_LAYOUT_5POINT0 },
- { "5.0", 5, AV_CH_LAYOUT_5POINT0_BACK },
- { "5.1", 6, AV_CH_LAYOUT_5POINT1 },
- { "5.1", 6, AV_CH_LAYOUT_5POINT1_BACK },
- { "6.0", 6, AV_CH_LAYOUT_6POINT0 },
- { "6.0(front)", 6, AV_CH_LAYOUT_6POINT0_FRONT },
- { "hexagonal", 6, AV_CH_LAYOUT_HEXAGONAL },
- { "6.1", 7, AV_CH_LAYOUT_6POINT1 },
- { "6.1", 7, AV_CH_LAYOUT_6POINT1_BACK },
- { "6.1(front)", 7, AV_CH_LAYOUT_6POINT1_FRONT },
- { "7.0", 7, AV_CH_LAYOUT_7POINT0 },
- { "7.0(front)", 7, AV_CH_LAYOUT_7POINT0_FRONT },
- { "7.1", 8, AV_CH_LAYOUT_7POINT1 },
- { "7.1(wide)", 8, AV_CH_LAYOUT_7POINT1_WIDE },
- { "7.1(wide)", 8, AV_CH_LAYOUT_7POINT1_WIDE_BACK },
- { "octagonal", 8, AV_CH_LAYOUT_OCTAGONAL },
- { "hexadecagonal", 16, AV_CH_LAYOUT_HEXADECAGONAL },
- { "downmix", 2, AV_CH_LAYOUT_STEREO_DOWNMIX, },
+ { "mono", AV_CHANNEL_LAYOUT_MONO },
+ { "stereo", AV_CHANNEL_LAYOUT_STEREO },
+ { "stereo", AV_CHANNEL_LAYOUT_STEREO_DOWNMIX },
+ { "2.1", AV_CHANNEL_LAYOUT_2POINT1 },
+ { "3.0", AV_CHANNEL_LAYOUT_SURROUND },
+ { "3.0(back)", AV_CHANNEL_LAYOUT_2_1 },
+ { "3.1", AV_CHANNEL_LAYOUT_3POINT1 },
+ { "4.0", AV_CHANNEL_LAYOUT_4POINT0 },
+ { "quad", AV_CHANNEL_LAYOUT_QUAD },
+ { "quad(side)", AV_CHANNEL_LAYOUT_2_2 },
+ { "4.1", AV_CHANNEL_LAYOUT_4POINT1 },
+ { "5.0", AV_CHANNEL_LAYOUT_5POINT0 },
+ { "5.0(back)", AV_CHANNEL_LAYOUT_5POINT0_BACK },
+ { "5.1", AV_CHANNEL_LAYOUT_5POINT1 },
+ { "5.1(back)", AV_CHANNEL_LAYOUT_5POINT1_BACK },
+ { "6.0", AV_CHANNEL_LAYOUT_6POINT0 },
+ { "6.0(front)", AV_CHANNEL_LAYOUT_6POINT0_FRONT },
+ { "hexagonal", AV_CHANNEL_LAYOUT_HEXAGONAL },
+ { "6.1", AV_CHANNEL_LAYOUT_6POINT1 },
+ { "6.1(back)", AV_CHANNEL_LAYOUT_6POINT1_BACK },
+ { "6.1(front)", AV_CHANNEL_LAYOUT_6POINT1_FRONT },
+ { "7.0", AV_CHANNEL_LAYOUT_7POINT0 },
+ { "7.0(front)", AV_CHANNEL_LAYOUT_7POINT0_FRONT },
+ { "7.1", AV_CHANNEL_LAYOUT_7POINT1 },
+ { "7.1(wide)", AV_CHANNEL_LAYOUT_7POINT1_WIDE },
+ { "7.1(wide-back)", AV_CHANNEL_LAYOUT_7POINT1_WIDE_BACK },
+ { "octagonal", AV_CHANNEL_LAYOUT_OCTAGONAL },
+ { "hexadecagonal", AV_CHANNEL_LAYOUT_HEXADECAGONAL },
+ { "downmix", AV_CHANNEL_LAYOUT_STEREO_DOWNMIX, },
{ 0 }
};

+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
static uint64_t get_channel_layout_single(const char *name, int name_len)
{
int i;
@@ -111,7 +124,7 @@ static uint64_t get_channel_layout_single(const char *name, int name_len)
for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map) - 1; i++) {
if (strlen(channel_layout_map[i].name) == name_len &&
!memcmp(channel_layout_map[i].name, name, name_len))
- return channel_layout_map[i].layout;
+ return channel_layout_map[i].layout.u.mask;
}
for (i = 0; i < FF_ARRAY_ELEMS(channel_names); i++)
if (channel_names[i] &&
@@ -153,8 +166,8 @@ void av_get_channel_layout_string(char *buf, int buf_size,
nb_channels = av_get_channel_layout_nb_channels(channel_layout);

for (i = 0; channel_layout_map[i].name; i++)
- if (nb_channels == channel_layout_map[i].nb_channels &&
- channel_layout == channel_layout_map[i].layout) {
+ if (nb_channels == channel_layout_map[i].layout.nb_channels &&
+ channel_layout == channel_layout_map[i].layout.u.mask) {
av_strlcpy(buf, channel_layout_map[i].name, buf_size);
return;
}
@@ -165,7 +178,7 @@ void av_get_channel_layout_string(char *buf, int buf_size,
av_strlcat(buf, " (", buf_size);
for (i = 0, ch = 0; i < 64; i++) {
if ((channel_layout & (UINT64_C(1) << i))) {
- const char *name = get_channel_name(i);
+ const char *name = av_channel_name(i);
if (name) {
if (ch > 0)
av_strlcat(buf, "|", buf_size);
@@ -216,7 +229,7 @@ const char *av_get_channel_name(uint64_t channel)
return NULL;
for (i = 0; i < 64; i++)
if ((1ULL<<i) & channel)
- return get_channel_name(i);
+ return av_channel_name(i);
return NULL;
}

@@ -233,3 +246,249 @@ uint64_t av_channel_layout_extract_channel(uint64_t channel_layout, int index)
}
return 0;
}
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+
+void av_channel_layout_from_mask(AVChannelLayout *channel_layout,
+ uint64_t mask)
+{
+ channel_layout->order = AV_CHANNEL_ORDER_NATIVE;
+ channel_layout->nb_channels = av_popcount64(mask);
+ channel_layout->u.mask = mask;
+}
+
+int av_channel_layout_from_string(AVChannelLayout *channel_layout,
+ const char *str)
+{
+ int i, channels;
+ const char *dup = str;
+ uint64_t mask = 0;
+
+ /* channel layout names */
+ for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); i++) {
+ if (channel_layout_map[i].name && !strcmp(str, channel_layout_map[i].name)) {
+ *channel_layout = channel_layout_map[i].layout;
+ return 0;
+ }
+ }
+
+ /* channel names */
+ while (*dup) {
+ char *chname = av_get_token(&dup, "|");
+ if (!chname)
+ return AVERROR(ENOMEM);
+ if (*dup)
+ dup++; // skip separator
+ for (i = 0; i < FF_ARRAY_ELEMS(channel_names); i++) {
+ if (channel_names[i] && !strcmp(chname, channel_names[i])) {
+ mask |= 1ULL << i;
+ }
+ }
+ av_free(chname);
+ }
+ if (mask) {
+ av_channel_layout_from_mask(channel_layout, mask);
+ return 0;
+ }
+
+ /* channel layout mask */
+ if (!strncmp(str, "0x", 2) && sscanf(str, "%llx", &mask) == 1) {
+ av_channel_layout_from_mask(channel_layout, mask);
+ return 0;
+ }
+
+ /* number of channels */
+ if (sscanf(str, "%d", &channels) == 1) {
+ av_channel_layout_default(channel_layout, channels);
+ return 0;
+ }
+
+ /* number of unordered channels */
+ if (sscanf(str, "%d channels", &channel_layout->nb_channels) == 1) {
+ channel_layout->order = AV_CHANNEL_ORDER_UNSPEC;
+ return 0;
+ }
+
+ return AVERROR_INVALIDDATA;
+}
+
+void av_channel_layout_uninit(AVChannelLayout *channel_layout)
+{
+ if (channel_layout->order == AV_CHANNEL_ORDER_CUSTOM)
+ av_freep(&channel_layout->u.map);
+ memset(channel_layout, 0, sizeof(*channel_layout));
+}
+
+int av_channel_layout_copy(AVChannelLayout *dst, const AVChannelLayout *src)
+{
+ av_channel_layout_uninit(dst);
+ *dst = *src;
+ if (src->order == AV_CHANNEL_ORDER_CUSTOM) {
+ dst->u.map = av_malloc(src->nb_channels * sizeof(*dst->u.map));
+ if (!dst->u.map)
+ return AVERROR(ENOMEM);
+ memcpy(dst->u.map, src->u.map, src->nb_channels * sizeof(*src->u.map));
+ }
+ return 0;
+}
+
+char *av_channel_layout_describe(const AVChannelLayout *channel_layout)
+{
+ int i;
+
+ switch (channel_layout->order) {
+ case AV_CHANNEL_ORDER_NATIVE:
+ for (i = 0; channel_layout_map[i].name; i++)
+ if (channel_layout->u.mask == channel_layout_map[i].layout.u.mask)
+ return av_strdup(channel_layout_map[i].name);
+ // fall-through
+ case AV_CHANNEL_ORDER_CUSTOM: {
+ // max 4 bytes for channel name + a separator
+ int size = 5 * channel_layout->nb_channels + 1;
+ char *ret;
+
+ ret = av_mallocz(size);
+ if (!ret)
+ return NULL;
+
+ for (i = 0; i < channel_layout->nb_channels; i++) {
+ enum AVChannel ch = av_channel_layout_get_channel(channel_layout, i);
+ const char *ch_name = av_channel_name(ch);
+
+ if (i)
+ av_strlcat(ret, "|", size);
+ av_strlcat(ret, ch_name, size);
+ }
+ return ret;
+ }
+ case AV_CHANNEL_ORDER_UNSPEC: {
+ char buf[64];
+ snprintf(buf, sizeof(buf), "%d channels", channel_layout->nb_channels);
+ return av_strdup(buf);
+ }
+ default:
+ return NULL;
+ }
+}
+
+int av_channel_layout_get_channel(const AVChannelLayout *channel_layout, int idx)
+{
+ int i;
+
+ if (idx < 0 || idx >= channel_layout->nb_channels)
+ return AVERROR(EINVAL);
+
+ switch (channel_layout->order) {
+ case AV_CHANNEL_ORDER_CUSTOM:
+ return channel_layout->u.map[idx];
+ case AV_CHANNEL_ORDER_NATIVE:
+ for (i = 0; i < 64; i++) {
+ if ((1ULL << i) & channel_layout->u.mask && !idx--)
+ return i;
+ }
+ default:
+ return AVERROR(EINVAL);
+ }
+}
+
+int av_channel_layout_channel_index(const AVChannelLayout *channel_layout,
+ enum AVChannel channel)
+{
+ int i;
+
+ switch (channel_layout->order) {
+ case AV_CHANNEL_ORDER_CUSTOM:
+ for (i = 0; i < channel_layout->nb_channels; i++)
+ if (channel_layout->u.map[i] == channel)
+ return i;
+ return AVERROR(EINVAL);
+ case AV_CHANNEL_ORDER_NATIVE: {
+ uint64_t mask = channel_layout->u.mask;
+ if (!(mask & (1ULL << channel)))
+ return AVERROR(EINVAL);
+ mask &= (1ULL << channel) - 1;
+ return av_popcount64(mask);
+ }
+ default:
+ return AVERROR(EINVAL);
+ }
+}
+
+int av_channel_layout_check(const AVChannelLayout *channel_layout)
+{
+ if (!channel_layout || channel_layout->nb_channels <= 0)
+ return 0;
+
+ switch (channel_layout->order) {
+ case AV_CHANNEL_ORDER_NATIVE:
+ return av_popcount64(channel_layout->u.mask) == channel_layout->nb_channels;
+ case AV_CHANNEL_ORDER_CUSTOM:
+ return !!channel_layout->u.map;
+ case AV_CHANNEL_ORDER_UNSPEC:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+int av_channel_layout_compare(const AVChannelLayout *chl, const AVChannelLayout *chl1)
+{
+ int i;
+
+ /* different channel counts -> not equal */
+ if (chl->nb_channels != chl1->nb_channels)
+ return 1;
+
+ /* if only one is unspecified -> not equal */
+ if ((chl->order == AV_CHANNEL_ORDER_UNSPEC) !=
+ (chl1->order == AV_CHANNEL_ORDER_UNSPEC))
+ return 1;
+ /* both are unspecified -> equal */
+ else if (chl->order == AV_CHANNEL_ORDER_UNSPEC)
+ return 0;
+
+ /* can compare masks directly */
+ if (chl->order != AV_CHANNEL_ORDER_CUSTOM &&
+ chl->order == chl1->order)
+ return chl->u.mask != chl1->u.mask;
+
+ /* compare channel by channel */
+ for (i = 0; i < chl->nb_channels; i++)
+ if (av_channel_layout_get_channel(chl, i) !=
+ av_channel_layout_get_channel(chl1, i))
+ return 1;
+ return 0;
+}
+
+void av_channel_layout_default(AVChannelLayout *ch_layout, int nb_channels)
+{
+ switch (nb_channels) {
+ case 1: *ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; break;
+ case 2: *ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; break;
+ case 3: *ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_SURROUND; break;
+ case 4: *ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_QUAD; break;
+ case 5: *ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT0; break;
+ case 6: *ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1; break;
+ case 7: *ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_6POINT1; break;
+ case 8: *ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_7POINT1; break;
+ default:
+ ch_layout->order = AV_CHANNEL_ORDER_UNSPEC;
+ ch_layout->nb_channels = nb_channels;
+ }
+}
+
+uint64_t av_channel_layout_subset(const AVChannelLayout *channel_layout,
+ uint64_t mask)
+{
+ uint64_t ret = 0;
+ int i;
+
+ if (channel_layout->order == AV_CHANNEL_ORDER_NATIVE)
+ return channel_layout->u.mask & mask;
+
+ for (i = 0; i < 64; i++)
+ if (mask & (1ULL << i) && av_channel_layout_channel_index(channel_layout, i) >= 0)
+ ret |= (1ULL << i);
+
+ return ret;
+}
diff --git a/libavutil/channel_layout.h b/libavutil/channel_layout.h
index 5bd0c2ce6e..2604ad1537 100644
--- a/libavutil/channel_layout.h
+++ b/libavutil/channel_layout.h
@@ -24,6 +24,9 @@

#include <stdint.h>

+#include "version.h"
+#include "attributes.h"
+
/**
* @file
* audio channel layout utility functions
@@ -34,40 +37,99 @@
* @{
*/

+enum AVChannel {
+ AV_CHAN_FRONT_LEFT,
+ AV_CHAN_FRONT_RIGHT,
+ AV_CHAN_FRONT_CENTER,
+ AV_CHAN_LOW_FREQUENCY,
+ AV_CHAN_BACK_LEFT,
+ AV_CHAN_BACK_RIGHT,
+ AV_CHAN_FRONT_LEFT_OF_CENTER,
+ AV_CHAN_FRONT_RIGHT_OF_CENTER,
+ AV_CHAN_BACK_CENTER,
+ AV_CHAN_SIDE_LEFT,
+ AV_CHAN_SIDE_RIGHT,
+ AV_CHAN_TOP_CENTER,
+ AV_CHAN_TOP_FRONT_LEFT,
+ AV_CHAN_TOP_FRONT_CENTER,
+ AV_CHAN_TOP_FRONT_RIGHT,
+ AV_CHAN_TOP_BACK_LEFT,
+ AV_CHAN_TOP_BACK_CENTER,
+ AV_CHAN_TOP_BACK_RIGHT,
+ /** Stereo downmix. */
+ AV_CHAN_STEREO_LEFT = 29,
+ /** See above. */
+ AV_CHAN_STEREO_RIGHT,
+ AV_CHAN_WIDE_LEFT,
+ AV_CHAN_WIDE_RIGHT,
+ AV_CHAN_SURROUND_DIRECT_LEFT,
+ AV_CHAN_SURROUND_DIRECT_RIGHT,
+ AV_CHAN_LOW_FREQUENCY_2,
+
+ /** Channel is empty can be safely skipped. */
+ AV_CHAN_SILENCE = 64,
+};
+
+enum AVChannelOrder {
+ /**
+ * The native channel order, i.e. the channels are in the same order in
+ * which they are defined in the AVChannel enum. This supports up to 63
+ * different channels.
+ */
+ AV_CHANNEL_ORDER_NATIVE,
+ /**
+ * The channel order does not correspond to any other predefined order and
+ * is stored as an explicit map. For example, this could be used to support
+ * layouts with 64 or more channels, or with channels that could be skipped.
+ */
+ AV_CHANNEL_ORDER_CUSTOM,
+ /**
+ * Only the channel count is specified, without any further information
+ * about the channel order.
+ */
+ AV_CHANNEL_ORDER_UNSPEC,
+};
+
+
/**
* @defgroup channel_masks Audio channel masks
* @{
*/
-#define AV_CH_FRONT_LEFT 0x00000001
-#define AV_CH_FRONT_RIGHT 0x00000002
-#define AV_CH_FRONT_CENTER 0x00000004
-#define AV_CH_LOW_FREQUENCY 0x00000008
-#define AV_CH_BACK_LEFT 0x00000010
-#define AV_CH_BACK_RIGHT 0x00000020
-#define AV_CH_FRONT_LEFT_OF_CENTER 0x00000040
-#define AV_CH_FRONT_RIGHT_OF_CENTER 0x00000080
-#define AV_CH_BACK_CENTER 0x00000100
-#define AV_CH_SIDE_LEFT 0x00000200
-#define AV_CH_SIDE_RIGHT 0x00000400
-#define AV_CH_TOP_CENTER 0x00000800
-#define AV_CH_TOP_FRONT_LEFT 0x00001000
-#define AV_CH_TOP_FRONT_CENTER 0x00002000
-#define AV_CH_TOP_FRONT_RIGHT 0x00004000
-#define AV_CH_TOP_BACK_LEFT 0x00008000
-#define AV_CH_TOP_BACK_CENTER 0x00010000
-#define AV_CH_TOP_BACK_RIGHT 0x00020000
-#define AV_CH_STEREO_LEFT 0x20000000 ///< Stereo downmix.
-#define AV_CH_STEREO_RIGHT 0x40000000 ///< See AV_CH_STEREO_LEFT.
-#define AV_CH_WIDE_LEFT 0x0000000080000000ULL
-#define AV_CH_WIDE_RIGHT 0x0000000100000000ULL
-#define AV_CH_SURROUND_DIRECT_LEFT 0x0000000200000000ULL
-#define AV_CH_SURROUND_DIRECT_RIGHT 0x0000000400000000ULL
-#define AV_CH_LOW_FREQUENCY_2 0x0000000800000000ULL
+#define AV_CH_FRONT_LEFT (1ULL << AV_CHAN_FRONT_LEFT )
+#define AV_CH_FRONT_RIGHT (1ULL << AV_CHAN_FRONT_RIGHT )
+#define AV_CH_FRONT_CENTER (1ULL << AV_CHAN_FRONT_CENTER )
+#define AV_CH_LOW_FREQUENCY (1ULL << AV_CHAN_LOW_FREQUENCY )
+#define AV_CH_BACK_LEFT (1ULL << AV_CHAN_BACK_LEFT )
+#define AV_CH_BACK_RIGHT (1ULL << AV_CHAN_BACK_RIGHT )
+#define AV_CH_FRONT_LEFT_OF_CENTER (1ULL << AV_CHAN_FRONT_LEFT_OF_CENTER )
+#define AV_CH_FRONT_RIGHT_OF_CENTER (1ULL << AV_CHAN_FRONT_RIGHT_OF_CENTER)
+#define AV_CH_BACK_CENTER (1ULL << AV_CHAN_BACK_CENTER )
+#define AV_CH_SIDE_LEFT (1ULL << AV_CHAN_SIDE_LEFT )
+#define AV_CH_SIDE_RIGHT (1ULL << AV_CHAN_SIDE_RIGHT )
+#define AV_CH_TOP_CENTER (1ULL << AV_CHAN_TOP_CENTER )
+#define AV_CH_TOP_FRONT_LEFT (1ULL << AV_CHAN_TOP_FRONT_LEFT )
+#define AV_CH_TOP_FRONT_CENTER (1ULL << AV_CHAN_TOP_FRONT_CENTER )
+#define AV_CH_TOP_FRONT_RIGHT (1ULL << AV_CHAN_TOP_FRONT_RIGHT )
+#define AV_CH_TOP_BACK_LEFT (1ULL << AV_CHAN_TOP_BACK_LEFT )
+#define AV_CH_TOP_BACK_CENTER (1ULL << AV_CHAN_TOP_BACK_CENTER )
+#define AV_CH_TOP_BACK_RIGHT (1ULL << AV_CHAN_TOP_BACK_RIGHT )
+#define AV_CH_STEREO_LEFT (1ULL << AV_CHAN_STEREO_LEFT )
+#define AV_CH_STEREO_RIGHT (1ULL << AV_CHAN_STEREO_RIGHT )
+#define AV_CH_WIDE_LEFT (1ULL << AV_CHAN_WIDE_LEFT )
+#define AV_CH_WIDE_RIGHT (1ULL << AV_CHAN_WIDE_RIGHT )
+#define AV_CH_SURROUND_DIRECT_LEFT (1ULL << AV_CHAN_SURROUND_DIRECT_LEFT )
+#define AV_CH_SURROUND_DIRECT_RIGHT (1ULL << AV_CHAN_SURROUND_DIRECT_RIGHT)
+#define AV_CH_LOW_FREQUENCY_2 (1ULL << AV_CHAN_LOW_FREQUENCY_2 )

+#if FF_API_OLD_CHANNEL_LAYOUT
/** Channel mask value used for AVCodecContext.request_channel_layout
to indicate that the user requests the channel order of the decoder output
- to be the native codec channel order. */
+ to be the native codec channel order.
+ @deprecated channel order is now indicated in a special field in
+ AVChannelLayout
+ */
#define AV_CH_LAYOUT_NATIVE 0x8000000000000000ULL
+#endif

/**
* @}
@@ -119,6 +181,123 @@ enum AVMatrixEncoding {
*/

/**
+ * An AVChannelLayout holds information about the channel layout of audio data.
+ *
+ * A channel layout here is defined as a set of channels ordered in a specific
+ * way (unless the channel order is AV_CHANNEL_ORDER_UNSPEC, in which case an
+ * AVChannelLayout carries only the channel count).
+ *
+ * Unlike most structures in Libav, sizeof(AVChannelLayout) is a part of the
+ * public ABI and may be used by the caller. E.g. it may be allocated on stack.
+ * No new fields may be added to it without a major version bump.
+ *
+ * An AVChannelLayout can be constructed using the convenience function
+ * av_channel_layout_from_mask() / av_channel_layout_from_string(), or it can be
+ * built manually by the caller.
+ */
+typedef struct AVChannelLayout {
+ /**
+ * Channel order used in this layout.
+ */
+ enum AVChannelOrder order;
+
+ /**
+ * Number of channels in this layout. Mandatory field.
+ */
+ int nb_channels;
+
+ /**
+ * Details about which channels are present in this layout.
+ * For AV_CHANNEL_ORDER_UNSPEC, this field is undefined and must not be
+ * used.
+ */
+ union {
+ /**
+ * This member must be used for AV_CHANNEL_ORDER_NATIVE.
+ * It is a bitmask, where the position of each set bit means that the
+ * AVChannel with the corresponding value is present.
+ *
+ * I.e. when (mask & (1 << AV_CHAN_FOO)) is non-zero, then AV_CHAN_FOO
+ * is present in the layout. Otherwise it is not present.
+ *
+ * @note when a channel layout using a bitmask is constructed or
+ * modified manually (i.e. not using any of the av_channel_layout_*
+ * functions), the code doing it must ensure that the number of set bits
+ * is equal to nb_channels.
+ */
+ uint64_t mask;
+ /**
+ * This member must be used when the channel order is
+ * AV_CHANNEL_ORDER_CUSTOM. It is a nb_channels-sized array, with each
+ * element signalling the presend of the AVChannel with the
+ * corresponding value.
+ *
+ * I.e. when map[i] is equal to AV_CHAN_FOO, then AV_CH_FOO is the i-th
+ * channel in the audio data.
+ */
+ enum AVChannel *map;
+ } u;
+} AVChannelLayout;
+
+#define AV_CHANNEL_LAYOUT_MONO \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 1, .u = { .mask = AV_CH_LAYOUT_MONO }}
+#define AV_CHANNEL_LAYOUT_STEREO \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 2, .u = { .mask = AV_CH_LAYOUT_STEREO }}
+#define AV_CHANNEL_LAYOUT_2POINT1 \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 3, .u = { .mask = AV_CH_LAYOUT_2POINT1 }}
+#define AV_CHANNEL_LAYOUT_2_1 \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 3, .u = { .mask = AV_CH_LAYOUT_2_1 }}
+#define AV_CHANNEL_LAYOUT_SURROUND \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 3, .u = { .mask = AV_CH_LAYOUT_SURROUND }}
+#define AV_CHANNEL_LAYOUT_3POINT1 \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 4, .u = { .mask = AV_CH_LAYOUT_3POINT1 }}
+#define AV_CHANNEL_LAYOUT_4POINT0 \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 4, .u = { .mask = AV_CH_LAYOUT_4POINT0 }}
+#define AV_CHANNEL_LAYOUT_4POINT1 \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 5, .u = { .mask = AV_CH_LAYOUT_4POINT1 }}
+#define AV_CHANNEL_LAYOUT_2_2 \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 4, .u = { .mask = AV_CH_LAYOUT_2_2 }}
+#define AV_CHANNEL_LAYOUT_QUAD \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 4, .u = { .mask = AV_CH_LAYOUT_QUAD }}
+#define AV_CHANNEL_LAYOUT_5POINT0 \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 5, .u = { .mask = AV_CH_LAYOUT_5POINT0 }}
+#define AV_CHANNEL_LAYOUT_5POINT1 \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 6, .u = { .mask = AV_CH_LAYOUT_5POINT1 }}
+#define AV_CHANNEL_LAYOUT_5POINT0_BACK \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 5, .u = { .mask = AV_CH_LAYOUT_5POINT0_BACK }}
+#define AV_CHANNEL_LAYOUT_5POINT1_BACK \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 6, .u = { .mask = AV_CH_LAYOUT_5POINT1_BACK }}
+#define AV_CHANNEL_LAYOUT_6POINT0 \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 6, .u = { .mask = AV_CH_LAYOUT_6POINT0 }}
+#define AV_CHANNEL_LAYOUT_6POINT0_FRONT \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 6, .u = { .mask = AV_CH_LAYOUT_6POINT0_FRONT }}
+#define AV_CHANNEL_LAYOUT_HEXAGONAL \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 6, .u = { .mask = AV_CH_LAYOUT_HEXAGONAL }}
+#define AV_CHANNEL_LAYOUT_6POINT1 \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 7, .u = { .mask = AV_CH_LAYOUT_6POINT1 }}
+#define AV_CHANNEL_LAYOUT_6POINT1_BACK \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 7, .u = { .mask = AV_CH_LAYOUT_6POINT1_BACK }}
+#define AV_CHANNEL_LAYOUT_6POINT1_FRONT \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 7, .u = { .mask = AV_CH_LAYOUT_6POINT1_FRONT }}
+#define AV_CHANNEL_LAYOUT_7POINT0 \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 7, .u = { .mask = AV_CH_LAYOUT_7POINT0 }}
+#define AV_CHANNEL_LAYOUT_7POINT0_FRONT \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 7, .u = { .mask = AV_CH_LAYOUT_7POINT0_FRONT }}
+#define AV_CHANNEL_LAYOUT_7POINT1 \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 8, .u = { .mask = AV_CH_LAYOUT_7POINT1 }}
+#define AV_CHANNEL_LAYOUT_7POINT1_WIDE \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 8, .u = { .mask = AV_CH_LAYOUT_7POINT1_WIDE }}
+#define AV_CHANNEL_LAYOUT_7POINT1_WIDE_BACK \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 8, .u = { .mask = AV_CH_LAYOUT_7POINT1_WIDE_BACK }}
+#define AV_CHANNEL_LAYOUT_OCTAGONAL \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 8, .u = { .mask = AV_CH_LAYOUT_OCTAGONAL }}
+#define AV_CHANNEL_LAYOUT_HEXADECAGONAL \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 16, .u = { .mask = AV_CH_LAYOUT_HEXAGONAL }}
+#define AV_CHANNEL_LAYOUT_STEREO_DOWNMIX \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 2, .u = { .mask = AV_CH_LAYOUT_STEREO_DOWNMIX }}
+
+#if FF_API_OLD_CHANNEL_LAYOUT
+/**
* Return a channel layout id that matches name, or 0 if no match is found.
*
* name can be one or several of the following notations,
@@ -134,7 +313,10 @@ enum AVMatrixEncoding {
* AV_CH_* macros).
*
* Example: "stereo+FC" = "2+FC" = "2c+1c" = "0x7"
+ *
+ * @deprecated use av_channel_layout_from_string()
*/
+attribute_deprecated
uint64_t av_get_channel_layout(const char *name);

/**
@@ -143,17 +325,24 @@ uint64_t av_get_channel_layout(const char *name);
*
* @param buf put here the string containing the channel layout
* @param buf_size size in bytes of the buffer
+ * @deprecated use av_channel_layout_describe()
*/
+attribute_deprecated
void av_get_channel_layout_string(char *buf, int buf_size, int nb_channels, uint64_t channel_layout);

/**
* Return the number of channels in the channel layout.
+ * @deprecated use AVChannelLayout.nb_channels
*/
+attribute_deprecated
int av_get_channel_layout_nb_channels(uint64_t channel_layout);

/**
* Return default channel layout for a given number of channels.
+ *
+ * @deprecated use av_channel_layout_default()
*/
+attribute_deprecated
uint64_t av_get_default_channel_layout(int nb_channels);

/**
@@ -164,21 +353,142 @@ uint64_t av_get_default_channel_layout(int nb_channels);
*
* @return index of channel in channel_layout on success, a negative AVERROR
* on error.
+ *
+ * @deprecated use av_channel_layout_channel_index()
*/
+attribute_deprecated
int av_get_channel_layout_channel_index(uint64_t channel_layout,
uint64_t channel);

/**
* Get the channel with the given index in channel_layout.
+ * @deprecated use av_channel_layout_get_channel()
*/
+attribute_deprecated
uint64_t av_channel_layout_extract_channel(uint64_t channel_layout, int index);

/**
* Get the name of a given channel.
*
* @return channel name on success, NULL on error.
+ *
+ * @deprecated use av_channel_name()
*/
+attribute_deprecated
const char *av_get_channel_name(uint64_t channel);
+#endif
+
+/**
+ * @return a string describing a given channel.
+ */
+const char *av_channel_name(enum AVChannel channel);
+
+/**
+ * @return a channel described by the given string.
+ */
+int av_channel_from_string(const char *name);
+
+/**
+ * Initialize a native channel layout from a bitmask indicating which channels
+ * are present.
+ */
+void av_channel_layout_from_mask(AVChannelLayout *channel_layout, uint64_t mask);
+
+/**
+ * Initialize a channel layout from a given string description.
+ * The input string can be represented by:
+ * - the formal channel layout name (returned by av_channel_layout_describe())
+ * - single or multiple channel names (returned by av_channel_name()
+ * or concatenated with "|")
+ * - a hexadecimal value of a channel layout (eg. "0x4")
+ * - the number of channels with default layout (eg. "5")
+ * - the number of unordered channels (eg. "4 channels")
+ *
+ * @param channel_layout input channel layout
+ * @param str string describing the channel layout
+ * @return 0 channel layout was detected, AVERROR_INVALIDATATA otherwise
+ */
+int av_channel_layout_from_string(AVChannelLayout *channel_layout,
+ const char *str);
+
+/**
+ * Get the default channel layout for a given number of channels.
+ */
+void av_channel_layout_default(AVChannelLayout *ch_layout, int nb_channels);
+
+/**
+ * Free any allocated data in the channel layout and reset the channel
+ * count to 0.
+ */
+void av_channel_layout_uninit(AVChannelLayout *channel_layout);
+
+/**
+ * Make a copy of a channel layout. This differs from just assigning src to dst
+ * in that it allocates and copies the map for AV_CHANNEL_ORDER_CUSTOM.
+ *
+ * @param dst destination channel layout
+ * @param src source channel layout
+ * @return 0 on success, a negative AVERROR on error.
+ */
+int av_channel_layout_copy(AVChannelLayout *dst, const AVChannelLayout *src);
+
+/**
+ * @return a string describing channel_layout or NULL on failure in the same
+ * format that is accepted by av_channel_layout_from_string(). The
+ * returned string allocated with av_malloc() and must be freed by the
+ * caller with av_free().
+ */
+char *av_channel_layout_describe(const AVChannelLayout *channel_layout);
+
+/**
+ * Get the channel with the given index in a channel layout.
+ *
+ * @return channel with the index idx in channel_layout on success or a negative
+ * AVERROR on failure (if idx is not valid or the channel order
+ * is unspecified)
+ */
+int av_channel_layout_get_channel(const AVChannelLayout *channel_layout, int idx);
+
+/**
+ * Get the index of a given channel in a channel layout.
+ *
+ * @return index of channel in channel_layout on success or a negative number if
+ * channel is not present in channel_layout.
+ */
+int av_channel_layout_channel_index(const AVChannelLayout *channel_layout,
+ enum AVChannel channel);
+
+/**
+ * Find out what channels from a given set are present in a channel layout,
+ * without regard for their positions.
+ *
+ * @param mask a combination of AV_CH_* representing a set of channels
+ * @return a bitfield representing all the channels from mask that are present
+ * in channel_layout
+ */
+uint64_t av_channel_layout_subset(const AVChannelLayout *channel_layout,
+ uint64_t mask);
+
+/**
+ * Check whether a channel layout is valid, i.e. can possibly describe audio
+ * data.
+ *
+ * @return 1 if channel_layout is valid, 0 otherwise.
+ */
+int av_channel_layout_check(const AVChannelLayout *channel_layout);
+
+/**
+ * Check whether two channel layouts are semantically the same, i.e. the same
+ * channels are present on the same positions in both.
+ *
+ * If one of the channel layouts is AV_CHANNEL_ORDER_UNSPEC, while the other is
+ * not, they are considered to be unequal. If both are AV_CHANNEL_ORDER_UNSPEC,
+ * they are considered equal iff the channel counts are the same in both.
+ *
+ * @return 0 if chl and chl1 are equal, 1 if they are not equal. A negative
+ * AVERROR code if one or both are invalid.
+ */
+int av_channel_layout_compare(const AVChannelLayout *chl, const AVChannelLayout *chl1);

/**
* @}
diff --git a/libavutil/version.h b/libavutil/version.h
index 2c85120b64..a882a68f6c 100644
--- a/libavutil/version.h
+++ b/libavutil/version.h
@@ -96,6 +96,9 @@
#ifndef FF_API_CRYPTO_SIZE_T
#define FF_API_CRYPTO_SIZE_T (LIBAVUTIL_VERSION_MAJOR < 57)
#endif
+#ifndef FF_API_OLD_CHANNEL_LAYOUT
+#define FF_API_OLD_CHANNEL_LAYOUT (LIBAVUTIL_VERSION_MAJOR < 57)
+#endif


/**
--
2.13.1
wm4
2017-06-29 09:14:37 UTC
Permalink
On Wed, 28 Jun 2017 18:10:45 -0400
Post by Vittorio Giovara
The new API is more extensible and allows for custom layouts.
More accurate information is exported, eg for decoders that do not
set a channel layout, lavc will not make one up for them.
Deprecate the old API working with just uint64_t bitmasks.
---
I guess this is essentially the final version, so I'm bikeshedding a
little bit harder. We'll probably have to live forever with this API,
anyway.
Post by Vittorio Giovara
/**
+ * An AVChannelLayout holds information about the channel layout of audio data.
+ *
+ * A channel layout here is defined as a set of channels ordered in a specific
+ * way (unless the channel order is AV_CHANNEL_ORDER_UNSPEC, in which case an
+ * AVChannelLayout carries only the channel count).
+ *
+ * Unlike most structures in Libav, sizeof(AVChannelLayout) is a part of the
+ * public ABI and may be used by the caller. E.g. it may be allocated on stack.
You should specify how it has to be handled. You can:
- default initialize it with {0} or by setting all used fields correctly
- using a predefined layout as initializer (AV_CHANNEL_LAYOUT_STEREO
etc.)
- initialize it with a constructor function
- must be uninitialized with av_channel_layout_uninit() (at least in
some situations, which is weird)
- copy via assigning is forbidden (probably?), av_channel_layout_copy()
must be used instead
Post by Vittorio Giovara
+ * No new fields may be added to it without a major version bump.
I think it's still intended that you can add new fields to the union?
So you will add new fields. You just won't change the size, or add
new fields which are mandatory for already defined layout types.
Post by Vittorio Giovara
+ *
+ * An AVChannelLayout can be constructed using the convenience function
+ * av_channel_layout_from_mask() / av_channel_layout_from_string(), or it can be
+ * built manually by the caller.
+ */
+typedef struct AVChannelLayout {
+ /**
+ * Channel order used in this layout.
+ */
("Mandatory field.")
Post by Vittorio Giovara
+ enum AVChannelOrder order;
+
+ /**
+ * Number of channels in this layout. Mandatory field.
+ */
+ int nb_channels;
+
+ /**
+ * Details about which channels are present in this layout.
+ * For AV_CHANNEL_ORDER_UNSPEC, this field is undefined and must not be
+ * used.
+ */
+ union {
+ /**
+ * This member must be used for AV_CHANNEL_ORDER_NATIVE.
+ * It is a bitmask, where the position of each set bit means that the
+ * AVChannel with the corresponding value is present.
+ *
+ * I.e. when (mask & (1 << AV_CHAN_FOO)) is non-zero, then AV_CHAN_FOO
+ * is present in the layout. Otherwise it is not present.
+ *
+ * modified manually (i.e. not using any of the av_channel_layout_*
+ * functions), the code doing it must ensure that the number of set bits
+ * is equal to nb_channels.
+ */
+ uint64_t mask;
+ /**
+ * This member must be used when the channel order is
+ * AV_CHANNEL_ORDER_CUSTOM. It is a nb_channels-sized array, with each
+ * element signalling the presend of the AVChannel with the
+ * corresponding value.
+ *
+ * I.e. when map[i] is equal to AV_CHAN_FOO, then AV_CH_FOO is the i-th
+ * channel in the audio data.
+ */
+ enum AVChannel *map;
Even if the channel map identifier is AV_CHAN_SILENCE? What does the
data contain then, actual silence or undefined contents?
Post by Vittorio Giovara
+ } u;
+} AVChannelLayout;
+
+#define AV_CHANNEL_LAYOUT_MONO \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 1, .u = { .mask = AV_CH_LAYOUT_MONO }}
+#define AV_CHANNEL_LAYOUT_STEREO \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 2, .u = { .mask = AV_CH_LAYOUT_STEREO }}
+#define AV_CHANNEL_LAYOUT_2POINT1 \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 3, .u = { .mask = AV_CH_LAYOUT_2POINT1 }}
+#define AV_CHANNEL_LAYOUT_2_1 \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 3, .u = { .mask = AV_CH_LAYOUT_2_1 }}
+#define AV_CHANNEL_LAYOUT_SURROUND \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 3, .u = { .mask = AV_CH_LAYOUT_SURROUND }}
+#define AV_CHANNEL_LAYOUT_3POINT1 \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 4, .u = { .mask = AV_CH_LAYOUT_3POINT1 }}
+#define AV_CHANNEL_LAYOUT_4POINT0 \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 4, .u = { .mask = AV_CH_LAYOUT_4POINT0 }}
+#define AV_CHANNEL_LAYOUT_4POINT1 \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 5, .u = { .mask = AV_CH_LAYOUT_4POINT1 }}
+#define AV_CHANNEL_LAYOUT_2_2 \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 4, .u = { .mask = AV_CH_LAYOUT_2_2 }}
+#define AV_CHANNEL_LAYOUT_QUAD \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 4, .u = { .mask = AV_CH_LAYOUT_QUAD }}
+#define AV_CHANNEL_LAYOUT_5POINT0 \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 5, .u = { .mask = AV_CH_LAYOUT_5POINT0 }}
+#define AV_CHANNEL_LAYOUT_5POINT1 \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 6, .u = { .mask = AV_CH_LAYOUT_5POINT1 }}
+#define AV_CHANNEL_LAYOUT_5POINT0_BACK \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 5, .u = { .mask = AV_CH_LAYOUT_5POINT0_BACK }}
+#define AV_CHANNEL_LAYOUT_5POINT1_BACK \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 6, .u = { .mask = AV_CH_LAYOUT_5POINT1_BACK }}
+#define AV_CHANNEL_LAYOUT_6POINT0 \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 6, .u = { .mask = AV_CH_LAYOUT_6POINT0 }}
+#define AV_CHANNEL_LAYOUT_6POINT0_FRONT \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 6, .u = { .mask = AV_CH_LAYOUT_6POINT0_FRONT }}
+#define AV_CHANNEL_LAYOUT_HEXAGONAL \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 6, .u = { .mask = AV_CH_LAYOUT_HEXAGONAL }}
+#define AV_CHANNEL_LAYOUT_6POINT1 \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 7, .u = { .mask = AV_CH_LAYOUT_6POINT1 }}
+#define AV_CHANNEL_LAYOUT_6POINT1_BACK \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 7, .u = { .mask = AV_CH_LAYOUT_6POINT1_BACK }}
+#define AV_CHANNEL_LAYOUT_6POINT1_FRONT \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 7, .u = { .mask = AV_CH_LAYOUT_6POINT1_FRONT }}
+#define AV_CHANNEL_LAYOUT_7POINT0 \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 7, .u = { .mask = AV_CH_LAYOUT_7POINT0 }}
+#define AV_CHANNEL_LAYOUT_7POINT0_FRONT \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 7, .u = { .mask = AV_CH_LAYOUT_7POINT0_FRONT }}
+#define AV_CHANNEL_LAYOUT_7POINT1 \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 8, .u = { .mask = AV_CH_LAYOUT_7POINT1 }}
+#define AV_CHANNEL_LAYOUT_7POINT1_WIDE \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 8, .u = { .mask = AV_CH_LAYOUT_7POINT1_WIDE }}
+#define AV_CHANNEL_LAYOUT_7POINT1_WIDE_BACK \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 8, .u = { .mask = AV_CH_LAYOUT_7POINT1_WIDE_BACK }}
+#define AV_CHANNEL_LAYOUT_OCTAGONAL \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 8, .u = { .mask = AV_CH_LAYOUT_OCTAGONAL }}
+#define AV_CHANNEL_LAYOUT_HEXADECAGONAL \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 16, .u = { .mask = AV_CH_LAYOUT_HEXAGONAL }}
+#define AV_CHANNEL_LAYOUT_STEREO_DOWNMIX \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 2, .u = { .mask = AV_CH_LAYOUT_STEREO_DOWNMIX }}
+
+#if FF_API_OLD_CHANNEL_LAYOUT
+/**
* Return a channel layout id that matches name, or 0 if no match is found.
*
* name can be one or several of the following notations,
@@ -134,7 +313,10 @@ enum AVMatrixEncoding {
* AV_CH_* macros).
*
* Example: "stereo+FC" = "2+FC" = "2c+1c" = "0x7"
+ *
*/
+attribute_deprecated
uint64_t av_get_channel_layout(const char *name);
/**
@@ -143,17 +325,24 @@ uint64_t av_get_channel_layout(const char *name);
*
*/
+attribute_deprecated
void av_get_channel_layout_string(char *buf, int buf_size, int nb_channels, uint64_t channel_layout);
/**
* Return the number of channels in the channel layout.
*/
+attribute_deprecated
int av_get_channel_layout_nb_channels(uint64_t channel_layout);
/**
* Return default channel layout for a given number of channels.
+ *
*/
+attribute_deprecated
uint64_t av_get_default_channel_layout(int nb_channels);
/**
@@ -164,21 +353,142 @@ uint64_t av_get_default_channel_layout(int nb_channels);
*
* on error.
+ *
*/
+attribute_deprecated
int av_get_channel_layout_channel_index(uint64_t channel_layout,
uint64_t channel);
/**
* Get the channel with the given index in channel_layout.
*/
+attribute_deprecated
uint64_t av_channel_layout_extract_channel(uint64_t channel_layout, int index);
/**
* Get the name of a given channel.
*
+ *
*/
+attribute_deprecated
const char *av_get_channel_name(uint64_t channel);
+#endif
+
+/**
+ */
+const char *av_channel_name(enum AVChannel channel);
What does it return for invalid channels?
Post by Vittorio Giovara
+
+/**
+ */
+int av_channel_from_string(const char *name);
Return what exactly? I guess AVChannel or negative error code. Could
also say it's the inverse of av_channel_name().
Post by Vittorio Giovara
+
+/**
+ * Initialize a native channel layout from a bitmask indicating which channels
+ * are present.
+ */
+void av_channel_layout_from_mask(AVChannelLayout *channel_layout, uint64_t mask);
What does it do if *channel_layout is not set to all 0 bytes?
Post by Vittorio Giovara
+
+/**
+ * Initialize a channel layout from a given string description.
+ * - the formal channel layout name (returned by av_channel_layout_describe())
+ * - single or multiple channel names (returned by av_channel_name()
+ * or concatenated with "|")
+ * - a hexadecimal value of a channel layout (eg. "0x4")
+ * - the number of channels with default layout (eg. "5")
+ * - the number of unordered channels (eg. "4 channels")
+ *
+ */
+int av_channel_layout_from_string(AVChannelLayout *channel_layout,
+ const char *str);
(Same question.)
Post by Vittorio Giovara
+
+/**
+ * Get the default channel layout for a given number of channels.
+ */
+void av_channel_layout_default(AVChannelLayout *ch_layout, int nb_channels);
(Same question.)
Post by Vittorio Giovara
+
+/**
+ * Free any allocated data in the channel layout and reset the channel
+ * count to 0.
+ */
+void av_channel_layout_uninit(AVChannelLayout *channel_layout);
Can the user assume that for defined channel orders, which do not use
allocated memory (like channel mask), this function can be skipped?
Post by Vittorio Giovara
+
+/**
+ * Make a copy of a channel layout. This differs from just assigning src to dst
+ * in that it allocates and copies the map for AV_CHANNEL_ORDER_CUSTOM.
+ *
+ */
+int av_channel_layout_copy(AVChannelLayout *dst, const AVChannelLayout *src);
Same question.
Post by Vittorio Giovara
+/**
+ * format that is accepted by av_channel_layout_from_string(). The
+ * returned string allocated with av_malloc() and must be freed by the
+ * caller with av_free().
+ */
+char *av_channel_layout_describe(const AVChannelLayout *channel_layout);
+
+/**
+ * Get the channel with the given index in a channel layout.
+ *
+ * AVERROR on failure (if idx is not valid or the channel order
+ * is unspecified)
+ */
+int av_channel_layout_get_channel(const AVChannelLayout *channel_layout, int idx);
+
+/**
+ * Get the index of a given channel in a channel layout.
+ *
+ * channel is not present in channel_layout.
+ */
+int av_channel_layout_channel_index(const AVChannelLayout *channel_layout,
+ enum AVChannel channel);
Returns the first index if there are multiple channels like this, I
suppose.
Post by Vittorio Giovara
+
+/**
+ * Find out what channels from a given set are present in a channel layout,
+ * without regard for their positions.
+ *
+ * in channel_layout
+ */
+uint64_t av_channel_layout_subset(const AVChannelLayout *channel_layout,
+ uint64_t mask);
No idea what's this for or what happens to AVChannel values that are
grater than 63.
Post by Vittorio Giovara
+/**
+ * Check whether a channel layout is valid, i.e. can possibly describe audio
+ * data.
+ *
+ */
+int av_channel_layout_check(const AVChannelLayout *channel_layout);
+
+/**
+ * Check whether two channel layouts are semantically the same, i.e. the same
+ * channels are present on the same positions in both.
+ *
+ * If one of the channel layouts is AV_CHANNEL_ORDER_UNSPEC, while the other is
+ * not, they are considered to be unequal. If both are AV_CHANNEL_ORDER_UNSPEC,
+ * they are considered equal iff the channel counts are the same in both.
+ *
+ * AVERROR code if one or both are invalid.
+ */
+int av_channel_layout_compare(const AVChannelLayout *chl, const AVChannelLayout *chl1);
/**
diff --git a/libavutil/version.h b/libavutil/version.h
index 2c85120b64..a882a68f6c 100644
--- a/libavutil/version.h
+++ b/libavutil/version.h
@@ -96,6 +96,9 @@
#ifndef FF_API_CRYPTO_SIZE_T
#define FF_API_CRYPTO_SIZE_T (LIBAVUTIL_VERSION_MAJOR < 57)
#endif
+#ifndef FF_API_OLD_CHANNEL_LAYOUT
+#define FF_API_OLD_CHANNEL_LAYOUT (LIBAVUTIL_VERSION_MAJOR < 57)
+#endif
/**
Vittorio Giovara
2017-06-29 21:17:06 UTC
Permalink
Post by wm4
On Wed, 28 Jun 2017 18:10:45 -0400
Post by Vittorio Giovara
/**
+ * An AVChannelLayout holds information about the channel layout of audio data.
+ *
+ * A channel layout here is defined as a set of channels ordered in a specific
+ * way (unless the channel order is AV_CHANNEL_ORDER_UNSPEC, in which case an
+ * AVChannelLayout carries only the channel count).
+ *
+ * Unlike most structures in Libav, sizeof(AVChannelLayout) is a part of the
+ * public ABI and may be used by the caller. E.g. it may be allocated on stack.
- default initialize it with {0} or by setting all used fields correctly
- using a predefined layout as initializer (AV_CHANNEL_LAYOUT_STEREO
etc.)
- initialize it with a constructor function
- must be uninitialized with av_channel_layout_uninit() (at least in
some situations, which is weird)
- copy via assigning is forbidden (probably?), av_channel_layout_copy()
must be used instead
Ok i'll add a verbatim of this description
Post by wm4
Post by Vittorio Giovara
+ * No new fields may be added to it without a major version bump.
I think it's still intended that you can add new fields to the union?
So you will add new fields. You just won't change the size, or add
new fields which are mandatory for already defined layout types.
ok I took it for granted, but mentioning it won't harm
Post by wm4
Post by Vittorio Giovara
+ * An AVChannelLayout can be constructed using the convenience function
+ * av_channel_layout_from_mask() / av_channel_layout_from_string(), or it can be
+ * built manually by the caller.
+ */
+typedef struct AVChannelLayout {
+ /**
+ * Channel order used in this layout.
+ */
("Mandatory field.")
It is but it defaults to NATIVE order. I'll mention it anyway.
Post by wm4
Post by Vittorio Giovara
+ enum AVChannelOrder order;
+
+ /**
+ * Number of channels in this layout. Mandatory field.
+ */
+ int nb_channels;
+
+ /**
+ * Details about which channels are present in this layout.
+ * For AV_CHANNEL_ORDER_UNSPEC, this field is undefined and must not be
+ * used.
+ */
+ union {
+ /**
+ * This member must be used for AV_CHANNEL_ORDER_NATIVE.
+ * It is a bitmask, where the position of each set bit means that the
+ * AVChannel with the corresponding value is present.
+ *
+ * I.e. when (mask & (1 << AV_CHAN_FOO)) is non-zero, then AV_CHAN_FOO
+ * is present in the layout. Otherwise it is not present.
+ *
+ * modified manually (i.e. not using any of the av_channel_layout_*
+ * functions), the code doing it must ensure that the number of set bits
+ * is equal to nb_channels.
+ */
+ uint64_t mask;
+ /**
+ * This member must be used when the channel order is
+ * AV_CHANNEL_ORDER_CUSTOM. It is a nb_channels-sized array, with each
+ * element signalling the presend of the AVChannel with the
+ * corresponding value.
+ *
+ * I.e. when map[i] is equal to AV_CHAN_FOO, then AV_CH_FOO is the i-th
+ * channel in the audio data.
+ */
+ enum AVChannel *map;
Even if the channel map identifier is AV_CHAN_SILENCE? What does the
data contain then, actual silence or undefined contents?
I suppose so, it will simply mean that the channel at position `i`
will be SILENCE.
I documented that channel as "empty", which is a little vague, do have
any suggestion?
Post by wm4
Post by Vittorio Giovara
+/**
+ */
+const char *av_channel_name(enum AVChannel channel);
What does it return for invalid channels?
it returns "?", I'll mention it in the docs
Post by wm4
Post by Vittorio Giovara
+
+/**
+ */
+int av_channel_from_string(const char *name);
Return what exactly? I guess AVChannel or negative error code. Could
also say it's the inverse of av_channel_name().
okay
Post by wm4
Post by Vittorio Giovara
+
+/**
+ * Initialize a native channel layout from a bitmask indicating which channels
+ * are present.
+ */
+void av_channel_layout_from_mask(AVChannelLayout *channel_layout, uint64_t mask);
What does it do if *channel_layout is not set to all 0 bytes?
Unpredictable. I'll mention that the input layout should be properly
initialized.
(same for the questions below)
Post by wm4
Post by Vittorio Giovara
+
+/**
+ * Free any allocated data in the channel layout and reset the channel
+ * count to 0.
+ */
+void av_channel_layout_uninit(AVChannelLayout *channel_layout);
Can the user assume that for defined channel orders, which do not use
allocated memory (like channel mask), this function can be skipped?
Post by Vittorio Giovara
+
+/**
+ * Make a copy of a channel layout. This differs from just assigning src to dst
+ * in that it allocates and copies the map for AV_CHANNEL_ORDER_CUSTOM.
+ *
+ */
+int av_channel_layout_copy(AVChannelLayout *dst, const AVChannelLayout *src);
Same question.
I don't think it applies here? I'll mention this function uninits dst.
Post by wm4
Post by Vittorio Giovara
+/**
+ * format that is accepted by av_channel_layout_from_string(). The
+ * returned string allocated with av_malloc() and must be freed by the
+ * caller with av_free().
+ */
+char *av_channel_layout_describe(const AVChannelLayout *channel_layout);
+
+/**
+ * Get the channel with the given index in a channel layout.
+ *
+ * AVERROR on failure (if idx is not valid or the channel order
+ * is unspecified)
+ */
+int av_channel_layout_get_channel(const AVChannelLayout *channel_layout, int idx);
+
+/**
+ * Get the index of a given channel in a channel layout.
+ *
+ * channel is not present in channel_layout.
+ */
+int av_channel_layout_channel_index(const AVChannelLayout *channel_layout,
+ enum AVChannel channel);
Returns the first index if there are multiple channels like this, I
suppose.
correct, I'll mentione it
Post by wm4
Post by Vittorio Giovara
+
+/**
+ * Find out what channels from a given set are present in a channel layout,
+ * without regard for their positions.
+ *
+ * in channel_layout
+ */
+uint64_t av_channel_layout_subset(const AVChannelLayout *channel_layout,
+ uint64_t mask);
No idea what's this for or what happens to AVChannel values that are
grater than 63.
It used in some filters to extract channel layouts from more complex structures.
If it goes over 63, it will return 0, which matches the documentation

Thanks for the review(s) on this set.
--
Vittorio
Vittorio Giovara
2017-06-29 21:28:51 UTC
Permalink
From: Anton Khirnov <***@khirnov.net>

The new API is more extensible and allows for custom layouts.
More accurate information is exported, eg for decoders that do not
set a channel layout, lavc will not make one up for them.

Deprecate the old API working with just uint64_t bitmasks.

Expanded and completed by Vittorio Giovara <***@gmail.com>.
Signed-off-by: Vittorio Giovara <***@gmail.com>
---
Changes to documentation as suggested by wm4, completed the doxygen
documentation for a couple of functions.
Vittorio

libavutil/channel_layout.c | 387 +++++++++++++++++++++++++++++++++++-------
libavutil/channel_layout.h | 408 ++++++++++++++++++++++++++++++++++++++++++---
libavutil/version.h | 3 +
3 files changed, 708 insertions(+), 90 deletions(-)

diff --git a/libavutil/channel_layout.c b/libavutil/channel_layout.c
index 41340ecdb6..285997446d 100644
--- a/libavutil/channel_layout.c
+++ b/libavutil/channel_layout.c
@@ -31,77 +31,90 @@
#include "common.h"

static const char * const channel_names[] = {
- [0] = "FL", /* front left */
- [1] = "FR", /* front right */
- [2] = "FC", /* front center */
- [3] = "LFE", /* low frequency */
- [4] = "BL", /* back left */
- [5] = "BR", /* back right */
- [6] = "FLC", /* front left-of-center */
- [7] = "FRC", /* front right-of-center */
- [8] = "BC", /* back-center */
- [9] = "SL", /* side left */
- [10] = "SR", /* side right */
- [11] = "TC", /* top center */
- [12] = "TFL", /* top front left */
- [13] = "TFC", /* top front center */
- [14] = "TFR", /* top front right */
- [15] = "TBL", /* top back left */
- [16] = "TBC", /* top back center */
- [17] = "TBR", /* top back right */
- [29] = "DL", /* downmix left */
- [30] = "DR", /* downmix right */
- [31] = "WL", /* wide left */
- [32] = "WR", /* wide right */
- [33] = "SDL", /* surround direct left */
- [34] = "SDR", /* surround direct right */
- [35] = "LFE2", /* low frequency 2 */
+ [AV_CHAN_FRONT_LEFT ] = "FL",
+ [AV_CHAN_FRONT_RIGHT ] = "FR",
+ [AV_CHAN_FRONT_CENTER ] = "FC",
+ [AV_CHAN_LOW_FREQUENCY ] = "LFE",
+ [AV_CHAN_BACK_LEFT ] = "BL",
+ [AV_CHAN_BACK_RIGHT ] = "BR",
+ [AV_CHAN_FRONT_LEFT_OF_CENTER ] = "FLC",
+ [AV_CHAN_FRONT_RIGHT_OF_CENTER ] = "FRC",
+ [AV_CHAN_BACK_CENTER ] = "BC",
+ [AV_CHAN_SIDE_LEFT ] = "SL",
+ [AV_CHAN_SIDE_RIGHT ] = "SR",
+ [AV_CHAN_TOP_CENTER ] = "TC",
+ [AV_CHAN_TOP_FRONT_LEFT ] = "TFL",
+ [AV_CHAN_TOP_FRONT_CENTER ] = "TFC",
+ [AV_CHAN_TOP_FRONT_RIGHT ] = "TFR",
+ [AV_CHAN_TOP_BACK_LEFT ] = "TBL",
+ [AV_CHAN_TOP_BACK_CENTER ] = "TBC",
+ [AV_CHAN_TOP_BACK_RIGHT ] = "TBR",
+ [AV_CHAN_STEREO_LEFT ] = "DL",
+ [AV_CHAN_STEREO_RIGHT ] = "DR",
+ [AV_CHAN_WIDE_LEFT ] = "WL",
+ [AV_CHAN_WIDE_RIGHT ] = "WR",
+ [AV_CHAN_SURROUND_DIRECT_LEFT ] = "SDL",
+ [AV_CHAN_SURROUND_DIRECT_RIGHT ] = "SDR",
+ [AV_CHAN_LOW_FREQUENCY_2 ] = "LFE2",
+ [AV_CHAN_SILENCE ] = "PAD",
};

-static const char *get_channel_name(int channel_id)
+const char *av_channel_name(enum AVChannel channel_id)
{
- if (channel_id < 0 || channel_id >= FF_ARRAY_ELEMS(channel_names))
- return NULL;
+ if ((unsigned) channel_id >= FF_ARRAY_ELEMS(channel_names))
+ return "?";
return channel_names[channel_id];
}

+int av_channel_from_string(const char *str)
+{
+ int i;
+ for (i = 0; i < FF_ARRAY_ELEMS(channel_names); i++) {
+ if (channel_names[i] && !strcmp(str, channel_names[i])) {
+ return i;
+ }
+ }
+ return AVERROR(EINVAL);
+}
+
static const struct {
const char *name;
- int nb_channels;
- uint64_t layout;
+ AVChannelLayout layout;
} channel_layout_map[] = {
- { "mono", 1, AV_CH_LAYOUT_MONO },
- { "stereo", 2, AV_CH_LAYOUT_STEREO },
- { "stereo", 2, AV_CH_LAYOUT_STEREO_DOWNMIX },
- { "2.1", 3, AV_CH_LAYOUT_2POINT1 },
- { "3.0", 3, AV_CH_LAYOUT_SURROUND },
- { "3.0(back)", 3, AV_CH_LAYOUT_2_1 },
- { "3.1", 4, AV_CH_LAYOUT_3POINT1 },
- { "4.0", 4, AV_CH_LAYOUT_4POINT0 },
- { "quad", 4, AV_CH_LAYOUT_QUAD },
- { "quad(side)", 4, AV_CH_LAYOUT_2_2 },
- { "4.1", 5, AV_CH_LAYOUT_4POINT1 },
- { "5.0", 5, AV_CH_LAYOUT_5POINT0 },
- { "5.0", 5, AV_CH_LAYOUT_5POINT0_BACK },
- { "5.1", 6, AV_CH_LAYOUT_5POINT1 },
- { "5.1", 6, AV_CH_LAYOUT_5POINT1_BACK },
- { "6.0", 6, AV_CH_LAYOUT_6POINT0 },
- { "6.0(front)", 6, AV_CH_LAYOUT_6POINT0_FRONT },
- { "hexagonal", 6, AV_CH_LAYOUT_HEXAGONAL },
- { "6.1", 7, AV_CH_LAYOUT_6POINT1 },
- { "6.1", 7, AV_CH_LAYOUT_6POINT1_BACK },
- { "6.1(front)", 7, AV_CH_LAYOUT_6POINT1_FRONT },
- { "7.0", 7, AV_CH_LAYOUT_7POINT0 },
- { "7.0(front)", 7, AV_CH_LAYOUT_7POINT0_FRONT },
- { "7.1", 8, AV_CH_LAYOUT_7POINT1 },
- { "7.1(wide)", 8, AV_CH_LAYOUT_7POINT1_WIDE },
- { "7.1(wide)", 8, AV_CH_LAYOUT_7POINT1_WIDE_BACK },
- { "octagonal", 8, AV_CH_LAYOUT_OCTAGONAL },
- { "hexadecagonal", 16, AV_CH_LAYOUT_HEXADECAGONAL },
- { "downmix", 2, AV_CH_LAYOUT_STEREO_DOWNMIX, },
+ { "mono", AV_CHANNEL_LAYOUT_MONO },
+ { "stereo", AV_CHANNEL_LAYOUT_STEREO },
+ { "stereo", AV_CHANNEL_LAYOUT_STEREO_DOWNMIX },
+ { "2.1", AV_CHANNEL_LAYOUT_2POINT1 },
+ { "3.0", AV_CHANNEL_LAYOUT_SURROUND },
+ { "3.0(back)", AV_CHANNEL_LAYOUT_2_1 },
+ { "3.1", AV_CHANNEL_LAYOUT_3POINT1 },
+ { "4.0", AV_CHANNEL_LAYOUT_4POINT0 },
+ { "quad", AV_CHANNEL_LAYOUT_QUAD },
+ { "quad(side)", AV_CHANNEL_LAYOUT_2_2 },
+ { "4.1", AV_CHANNEL_LAYOUT_4POINT1 },
+ { "5.0", AV_CHANNEL_LAYOUT_5POINT0 },
+ { "5.0(back)", AV_CHANNEL_LAYOUT_5POINT0_BACK },
+ { "5.1", AV_CHANNEL_LAYOUT_5POINT1 },
+ { "5.1(back)", AV_CHANNEL_LAYOUT_5POINT1_BACK },
+ { "6.0", AV_CHANNEL_LAYOUT_6POINT0 },
+ { "6.0(front)", AV_CHANNEL_LAYOUT_6POINT0_FRONT },
+ { "hexagonal", AV_CHANNEL_LAYOUT_HEXAGONAL },
+ { "6.1", AV_CHANNEL_LAYOUT_6POINT1 },
+ { "6.1(back)", AV_CHANNEL_LAYOUT_6POINT1_BACK },
+ { "6.1(front)", AV_CHANNEL_LAYOUT_6POINT1_FRONT },
+ { "7.0", AV_CHANNEL_LAYOUT_7POINT0 },
+ { "7.0(front)", AV_CHANNEL_LAYOUT_7POINT0_FRONT },
+ { "7.1", AV_CHANNEL_LAYOUT_7POINT1 },
+ { "7.1(wide)", AV_CHANNEL_LAYOUT_7POINT1_WIDE },
+ { "7.1(wide-back)", AV_CHANNEL_LAYOUT_7POINT1_WIDE_BACK },
+ { "octagonal", AV_CHANNEL_LAYOUT_OCTAGONAL },
+ { "hexadecagonal", AV_CHANNEL_LAYOUT_HEXADECAGONAL },
+ { "downmix", AV_CHANNEL_LAYOUT_STEREO_DOWNMIX, },
{ 0 }
};

+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
static uint64_t get_channel_layout_single(const char *name, int name_len)
{
int i;
@@ -111,7 +124,7 @@ static uint64_t get_channel_layout_single(const char *name, int name_len)
for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map) - 1; i++) {
if (strlen(channel_layout_map[i].name) == name_len &&
!memcmp(channel_layout_map[i].name, name, name_len))
- return channel_layout_map[i].layout;
+ return channel_layout_map[i].layout.u.mask;
}
for (i = 0; i < FF_ARRAY_ELEMS(channel_names); i++)
if (channel_names[i] &&
@@ -153,8 +166,8 @@ void av_get_channel_layout_string(char *buf, int buf_size,
nb_channels = av_get_channel_layout_nb_channels(channel_layout);

for (i = 0; channel_layout_map[i].name; i++)
- if (nb_channels == channel_layout_map[i].nb_channels &&
- channel_layout == channel_layout_map[i].layout) {
+ if (nb_channels == channel_layout_map[i].layout.nb_channels &&
+ channel_layout == channel_layout_map[i].layout.u.mask) {
av_strlcpy(buf, channel_layout_map[i].name, buf_size);
return;
}
@@ -165,7 +178,7 @@ void av_get_channel_layout_string(char *buf, int buf_size,
av_strlcat(buf, " (", buf_size);
for (i = 0, ch = 0; i < 64; i++) {
if ((channel_layout & (UINT64_C(1) << i))) {
- const char *name = get_channel_name(i);
+ const char *name = av_channel_name(i);
if (name) {
if (ch > 0)
av_strlcat(buf, "|", buf_size);
@@ -216,7 +229,7 @@ const char *av_get_channel_name(uint64_t channel)
return NULL;
for (i = 0; i < 64; i++)
if ((1ULL<<i) & channel)
- return get_channel_name(i);
+ return av_channel_name(i);
return NULL;
}

@@ -233,3 +246,249 @@ uint64_t av_channel_layout_extract_channel(uint64_t channel_layout, int index)
}
return 0;
}
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+
+void av_channel_layout_from_mask(AVChannelLayout *channel_layout,
+ uint64_t mask)
+{
+ channel_layout->order = AV_CHANNEL_ORDER_NATIVE;
+ channel_layout->nb_channels = av_popcount64(mask);
+ channel_layout->u.mask = mask;
+}
+
+int av_channel_layout_from_string(AVChannelLayout *channel_layout,
+ const char *str)
+{
+ int i, channels;
+ const char *dup = str;
+ uint64_t mask = 0;
+
+ /* channel layout names */
+ for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); i++) {
+ if (channel_layout_map[i].name && !strcmp(str, channel_layout_map[i].name)) {
+ *channel_layout = channel_layout_map[i].layout;
+ return 0;
+ }
+ }
+
+ /* channel names */
+ while (*dup) {
+ char *chname = av_get_token(&dup, "|");
+ if (!chname)
+ return AVERROR(ENOMEM);
+ if (*dup)
+ dup++; // skip separator
+ for (i = 0; i < FF_ARRAY_ELEMS(channel_names); i++) {
+ if (channel_names[i] && !strcmp(chname, channel_names[i])) {
+ mask |= 1ULL << i;
+ }
+ }
+ av_free(chname);
+ }
+ if (mask) {
+ av_channel_layout_from_mask(channel_layout, mask);
+ return 0;
+ }
+
+ /* channel layout mask */
+ if (!strncmp(str, "0x", 2) && sscanf(str, "%llx", &mask) == 1) {
+ av_channel_layout_from_mask(channel_layout, mask);
+ return 0;
+ }
+
+ /* number of channels */
+ if (sscanf(str, "%d", &channels) == 1) {
+ av_channel_layout_default(channel_layout, channels);
+ return 0;
+ }
+
+ /* number of unordered channels */
+ if (sscanf(str, "%d channels", &channel_layout->nb_channels) == 1) {
+ channel_layout->order = AV_CHANNEL_ORDER_UNSPEC;
+ return 0;
+ }
+
+ return AVERROR_INVALIDDATA;
+}
+
+void av_channel_layout_uninit(AVChannelLayout *channel_layout)
+{
+ if (channel_layout->order == AV_CHANNEL_ORDER_CUSTOM)
+ av_freep(&channel_layout->u.map);
+ memset(channel_layout, 0, sizeof(*channel_layout));
+}
+
+int av_channel_layout_copy(AVChannelLayout *dst, const AVChannelLayout *src)
+{
+ av_channel_layout_uninit(dst);
+ *dst = *src;
+ if (src->order == AV_CHANNEL_ORDER_CUSTOM) {
+ dst->u.map = av_malloc(src->nb_channels * sizeof(*dst->u.map));
+ if (!dst->u.map)
+ return AVERROR(ENOMEM);
+ memcpy(dst->u.map, src->u.map, src->nb_channels * sizeof(*src->u.map));
+ }
+ return 0;
+}
+
+char *av_channel_layout_describe(const AVChannelLayout *channel_layout)
+{
+ int i;
+
+ switch (channel_layout->order) {
+ case AV_CHANNEL_ORDER_NATIVE:
+ for (i = 0; channel_layout_map[i].name; i++)
+ if (channel_layout->u.mask == channel_layout_map[i].layout.u.mask)
+ return av_strdup(channel_layout_map[i].name);
+ // fall-through
+ case AV_CHANNEL_ORDER_CUSTOM: {
+ // max 4 bytes for channel name + a separator
+ int size = 5 * channel_layout->nb_channels + 1;
+ char *ret;
+
+ ret = av_mallocz(size);
+ if (!ret)
+ return NULL;
+
+ for (i = 0; i < channel_layout->nb_channels; i++) {
+ enum AVChannel ch = av_channel_layout_get_channel(channel_layout, i);
+ const char *ch_name = av_channel_name(ch);
+
+ if (i)
+ av_strlcat(ret, "|", size);
+ av_strlcat(ret, ch_name, size);
+ }
+ return ret;
+ }
+ case AV_CHANNEL_ORDER_UNSPEC: {
+ char buf[64];
+ snprintf(buf, sizeof(buf), "%d channels", channel_layout->nb_channels);
+ return av_strdup(buf);
+ }
+ default:
+ return NULL;
+ }
+}
+
+int av_channel_layout_get_channel(const AVChannelLayout *channel_layout, int idx)
+{
+ int i;
+
+ if (idx < 0 || idx >= channel_layout->nb_channels)
+ return AVERROR(EINVAL);
+
+ switch (channel_layout->order) {
+ case AV_CHANNEL_ORDER_CUSTOM:
+ return channel_layout->u.map[idx];
+ case AV_CHANNEL_ORDER_NATIVE:
+ for (i = 0; i < 64; i++) {
+ if ((1ULL << i) & channel_layout->u.mask && !idx--)
+ return i;
+ }
+ default:
+ return AVERROR(EINVAL);
+ }
+}
+
+int av_channel_layout_channel_index(const AVChannelLayout *channel_layout,
+ enum AVChannel channel)
+{
+ int i;
+
+ switch (channel_layout->order) {
+ case AV_CHANNEL_ORDER_CUSTOM:
+ for (i = 0; i < channel_layout->nb_channels; i++)
+ if (channel_layout->u.map[i] == channel)
+ return i;
+ return AVERROR(EINVAL);
+ case AV_CHANNEL_ORDER_NATIVE: {
+ uint64_t mask = channel_layout->u.mask;
+ if (!(mask & (1ULL << channel)))
+ return AVERROR(EINVAL);
+ mask &= (1ULL << channel) - 1;
+ return av_popcount64(mask);
+ }
+ default:
+ return AVERROR(EINVAL);
+ }
+}
+
+int av_channel_layout_check(const AVChannelLayout *channel_layout)
+{
+ if (!channel_layout || channel_layout->nb_channels <= 0)
+ return 0;
+
+ switch (channel_layout->order) {
+ case AV_CHANNEL_ORDER_NATIVE:
+ return av_popcount64(channel_layout->u.mask) == channel_layout->nb_channels;
+ case AV_CHANNEL_ORDER_CUSTOM:
+ return !!channel_layout->u.map;
+ case AV_CHANNEL_ORDER_UNSPEC:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+int av_channel_layout_compare(const AVChannelLayout *chl, const AVChannelLayout *chl1)
+{
+ int i;
+
+ /* different channel counts -> not equal */
+ if (chl->nb_channels != chl1->nb_channels)
+ return 1;
+
+ /* if only one is unspecified -> not equal */
+ if ((chl->order == AV_CHANNEL_ORDER_UNSPEC) !=
+ (chl1->order == AV_CHANNEL_ORDER_UNSPEC))
+ return 1;
+ /* both are unspecified -> equal */
+ else if (chl->order == AV_CHANNEL_ORDER_UNSPEC)
+ return 0;
+
+ /* can compare masks directly */
+ if (chl->order != AV_CHANNEL_ORDER_CUSTOM &&
+ chl->order == chl1->order)
+ return chl->u.mask != chl1->u.mask;
+
+ /* compare channel by channel */
+ for (i = 0; i < chl->nb_channels; i++)
+ if (av_channel_layout_get_channel(chl, i) !=
+ av_channel_layout_get_channel(chl1, i))
+ return 1;
+ return 0;
+}
+
+void av_channel_layout_default(AVChannelLayout *ch_layout, int nb_channels)
+{
+ switch (nb_channels) {
+ case 1: *ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; break;
+ case 2: *ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; break;
+ case 3: *ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_SURROUND; break;
+ case 4: *ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_QUAD; break;
+ case 5: *ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT0; break;
+ case 6: *ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1; break;
+ case 7: *ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_6POINT1; break;
+ case 8: *ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_7POINT1; break;
+ default:
+ ch_layout->order = AV_CHANNEL_ORDER_UNSPEC;
+ ch_layout->nb_channels = nb_channels;
+ }
+}
+
+uint64_t av_channel_layout_subset(const AVChannelLayout *channel_layout,
+ uint64_t mask)
+{
+ uint64_t ret = 0;
+ int i;
+
+ if (channel_layout->order == AV_CHANNEL_ORDER_NATIVE)
+ return channel_layout->u.mask & mask;
+
+ for (i = 0; i < 64; i++)
+ if (mask & (1ULL << i) && av_channel_layout_channel_index(channel_layout, i) >= 0)
+ ret |= (1ULL << i);
+
+ return ret;
+}
diff --git a/libavutil/channel_layout.h b/libavutil/channel_layout.h
index 5bd0c2ce6e..04094ee101 100644
--- a/libavutil/channel_layout.h
+++ b/libavutil/channel_layout.h
@@ -24,6 +24,9 @@

#include <stdint.h>

+#include "version.h"
+#include "attributes.h"
+
/**
* @file
* audio channel layout utility functions
@@ -34,40 +37,99 @@
* @{
*/

+enum AVChannel {
+ AV_CHAN_FRONT_LEFT,
+ AV_CHAN_FRONT_RIGHT,
+ AV_CHAN_FRONT_CENTER,
+ AV_CHAN_LOW_FREQUENCY,
+ AV_CHAN_BACK_LEFT,
+ AV_CHAN_BACK_RIGHT,
+ AV_CHAN_FRONT_LEFT_OF_CENTER,
+ AV_CHAN_FRONT_RIGHT_OF_CENTER,
+ AV_CHAN_BACK_CENTER,
+ AV_CHAN_SIDE_LEFT,
+ AV_CHAN_SIDE_RIGHT,
+ AV_CHAN_TOP_CENTER,
+ AV_CHAN_TOP_FRONT_LEFT,
+ AV_CHAN_TOP_FRONT_CENTER,
+ AV_CHAN_TOP_FRONT_RIGHT,
+ AV_CHAN_TOP_BACK_LEFT,
+ AV_CHAN_TOP_BACK_CENTER,
+ AV_CHAN_TOP_BACK_RIGHT,
+ /** Stereo downmix. */
+ AV_CHAN_STEREO_LEFT = 29,
+ /** See above. */
+ AV_CHAN_STEREO_RIGHT,
+ AV_CHAN_WIDE_LEFT,
+ AV_CHAN_WIDE_RIGHT,
+ AV_CHAN_SURROUND_DIRECT_LEFT,
+ AV_CHAN_SURROUND_DIRECT_RIGHT,
+ AV_CHAN_LOW_FREQUENCY_2,
+
+ /** Channel is empty can be safely skipped. */
+ AV_CHAN_SILENCE = 64,
+};
+
+enum AVChannelOrder {
+ /**
+ * The native channel order, i.e. the channels are in the same order in
+ * which they are defined in the AVChannel enum. This supports up to 63
+ * different channels.
+ */
+ AV_CHANNEL_ORDER_NATIVE,
+ /**
+ * The channel order does not correspond to any other predefined order and
+ * is stored as an explicit map. For example, this could be used to support
+ * layouts with 64 or more channels, or with channels that could be skipped.
+ */
+ AV_CHANNEL_ORDER_CUSTOM,
+ /**
+ * Only the channel count is specified, without any further information
+ * about the channel order.
+ */
+ AV_CHANNEL_ORDER_UNSPEC,
+};
+
+
/**
* @defgroup channel_masks Audio channel masks
* @{
*/
-#define AV_CH_FRONT_LEFT 0x00000001
-#define AV_CH_FRONT_RIGHT 0x00000002
-#define AV_CH_FRONT_CENTER 0x00000004
-#define AV_CH_LOW_FREQUENCY 0x00000008
-#define AV_CH_BACK_LEFT 0x00000010
-#define AV_CH_BACK_RIGHT 0x00000020
-#define AV_CH_FRONT_LEFT_OF_CENTER 0x00000040
-#define AV_CH_FRONT_RIGHT_OF_CENTER 0x00000080
-#define AV_CH_BACK_CENTER 0x00000100
-#define AV_CH_SIDE_LEFT 0x00000200
-#define AV_CH_SIDE_RIGHT 0x00000400
-#define AV_CH_TOP_CENTER 0x00000800
-#define AV_CH_TOP_FRONT_LEFT 0x00001000
-#define AV_CH_TOP_FRONT_CENTER 0x00002000
-#define AV_CH_TOP_FRONT_RIGHT 0x00004000
-#define AV_CH_TOP_BACK_LEFT 0x00008000
-#define AV_CH_TOP_BACK_CENTER 0x00010000
-#define AV_CH_TOP_BACK_RIGHT 0x00020000
-#define AV_CH_STEREO_LEFT 0x20000000 ///< Stereo downmix.
-#define AV_CH_STEREO_RIGHT 0x40000000 ///< See AV_CH_STEREO_LEFT.
-#define AV_CH_WIDE_LEFT 0x0000000080000000ULL
-#define AV_CH_WIDE_RIGHT 0x0000000100000000ULL
-#define AV_CH_SURROUND_DIRECT_LEFT 0x0000000200000000ULL
-#define AV_CH_SURROUND_DIRECT_RIGHT 0x0000000400000000ULL
-#define AV_CH_LOW_FREQUENCY_2 0x0000000800000000ULL
+#define AV_CH_FRONT_LEFT (1ULL << AV_CHAN_FRONT_LEFT )
+#define AV_CH_FRONT_RIGHT (1ULL << AV_CHAN_FRONT_RIGHT )
+#define AV_CH_FRONT_CENTER (1ULL << AV_CHAN_FRONT_CENTER )
+#define AV_CH_LOW_FREQUENCY (1ULL << AV_CHAN_LOW_FREQUENCY )
+#define AV_CH_BACK_LEFT (1ULL << AV_CHAN_BACK_LEFT )
+#define AV_CH_BACK_RIGHT (1ULL << AV_CHAN_BACK_RIGHT )
+#define AV_CH_FRONT_LEFT_OF_CENTER (1ULL << AV_CHAN_FRONT_LEFT_OF_CENTER )
+#define AV_CH_FRONT_RIGHT_OF_CENTER (1ULL << AV_CHAN_FRONT_RIGHT_OF_CENTER)
+#define AV_CH_BACK_CENTER (1ULL << AV_CHAN_BACK_CENTER )
+#define AV_CH_SIDE_LEFT (1ULL << AV_CHAN_SIDE_LEFT )
+#define AV_CH_SIDE_RIGHT (1ULL << AV_CHAN_SIDE_RIGHT )
+#define AV_CH_TOP_CENTER (1ULL << AV_CHAN_TOP_CENTER )
+#define AV_CH_TOP_FRONT_LEFT (1ULL << AV_CHAN_TOP_FRONT_LEFT )
+#define AV_CH_TOP_FRONT_CENTER (1ULL << AV_CHAN_TOP_FRONT_CENTER )
+#define AV_CH_TOP_FRONT_RIGHT (1ULL << AV_CHAN_TOP_FRONT_RIGHT )
+#define AV_CH_TOP_BACK_LEFT (1ULL << AV_CHAN_TOP_BACK_LEFT )
+#define AV_CH_TOP_BACK_CENTER (1ULL << AV_CHAN_TOP_BACK_CENTER )
+#define AV_CH_TOP_BACK_RIGHT (1ULL << AV_CHAN_TOP_BACK_RIGHT )
+#define AV_CH_STEREO_LEFT (1ULL << AV_CHAN_STEREO_LEFT )
+#define AV_CH_STEREO_RIGHT (1ULL << AV_CHAN_STEREO_RIGHT )
+#define AV_CH_WIDE_LEFT (1ULL << AV_CHAN_WIDE_LEFT )
+#define AV_CH_WIDE_RIGHT (1ULL << AV_CHAN_WIDE_RIGHT )
+#define AV_CH_SURROUND_DIRECT_LEFT (1ULL << AV_CHAN_SURROUND_DIRECT_LEFT )
+#define AV_CH_SURROUND_DIRECT_RIGHT (1ULL << AV_CHAN_SURROUND_DIRECT_RIGHT)
+#define AV_CH_LOW_FREQUENCY_2 (1ULL << AV_CHAN_LOW_FREQUENCY_2 )

+#if FF_API_OLD_CHANNEL_LAYOUT
/** Channel mask value used for AVCodecContext.request_channel_layout
to indicate that the user requests the channel order of the decoder output
- to be the native codec channel order. */
+ to be the native codec channel order.
+ @deprecated channel order is now indicated in a special field in
+ AVChannelLayout
+ */
#define AV_CH_LAYOUT_NATIVE 0x8000000000000000ULL
+#endif

/**
* @}
@@ -119,6 +181,135 @@ enum AVMatrixEncoding {
*/

/**
+ * An AVChannelLayout holds information about the channel layout of audio data.
+ *
+ * A channel layout here is defined as a set of channels ordered in a specific
+ * way (unless the channel order is AV_CHANNEL_ORDER_UNSPEC, in which case an
+ * AVChannelLayout carries only the channel count).
+ *
+ * Unlike most structures in Libav, sizeof(AVChannelLayout) is a part of the
+ * public ABI and may be used by the caller. E.g. it may be allocated on stack.
+ * In particular, this structure can be initialized as follows:
+ * - default initialization with {0} or by setting all used fields correctly
+ * - with predefined layout as initializer (AV_CHANNEL_LAYOUT_STEREO, etc.)
+ * - with a constructor function such as av_channel_layout_default()
+ * On that note, this also applies:
+ * - copy via assigning is forbidden, av_channel_layout_copy() must be used
+ * instead (and its return value should be checked)
+ * - if order is AV_CHANNEL_ORDER_CUSTOM, then it must be uninitialized with
+ * av_channel_layout_uninit().
+ *
+ * No new fields may be added to it without a major version bump, except for
+ * new elements of the union fitting in sizeof(uint64_t).
+ *
+ * An AVChannelLayout can be constructed using the convenience function
+ * av_channel_layout_from_mask() / av_channel_layout_from_string(), or it can be
+ * built manually by the caller.
+ */
+typedef struct AVChannelLayout {
+ /**
+ * Channel order used in this layout.
+ * This is a mandatory field, will default to AV_CHANNEL_ORDER_NATIVE.
+ */
+ enum AVChannelOrder order;
+
+ /**
+ * Number of channels in this layout. Mandatory field.
+ */
+ int nb_channels;
+
+ /**
+ * Details about which channels are present in this layout.
+ * For AV_CHANNEL_ORDER_UNSPEC, this field is undefined and must not be
+ * used.
+ */
+ union {
+ /**
+ * This member must be used for AV_CHANNEL_ORDER_NATIVE.
+ * It is a bitmask, where the position of each set bit means that the
+ * AVChannel with the corresponding value is present.
+ *
+ * I.e. when (mask & (1 << AV_CHAN_FOO)) is non-zero, then AV_CHAN_FOO
+ * is present in the layout. Otherwise it is not present.
+ *
+ * @note when a channel layout using a bitmask is constructed or
+ * modified manually (i.e. not using any of the av_channel_layout_*
+ * functions), the code doing it must ensure that the number of set bits
+ * is equal to nb_channels.
+ */
+ uint64_t mask;
+ /**
+ * This member must be used when the channel order is
+ * AV_CHANNEL_ORDER_CUSTOM. It is a nb_channels-sized array, with each
+ * element signalling the presend of the AVChannel with the
+ * corresponding value.
+ *
+ * I.e. when map[i] is equal to AV_CHAN_FOO, then AV_CH_FOO is the i-th
+ * channel in the audio data.
+ */
+ enum AVChannel *map;
+ } u;
+} AVChannelLayout;
+
+#define AV_CHANNEL_LAYOUT_MONO \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 1, .u = { .mask = AV_CH_LAYOUT_MONO }}
+#define AV_CHANNEL_LAYOUT_STEREO \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 2, .u = { .mask = AV_CH_LAYOUT_STEREO }}
+#define AV_CHANNEL_LAYOUT_2POINT1 \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 3, .u = { .mask = AV_CH_LAYOUT_2POINT1 }}
+#define AV_CHANNEL_LAYOUT_2_1 \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 3, .u = { .mask = AV_CH_LAYOUT_2_1 }}
+#define AV_CHANNEL_LAYOUT_SURROUND \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 3, .u = { .mask = AV_CH_LAYOUT_SURROUND }}
+#define AV_CHANNEL_LAYOUT_3POINT1 \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 4, .u = { .mask = AV_CH_LAYOUT_3POINT1 }}
+#define AV_CHANNEL_LAYOUT_4POINT0 \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 4, .u = { .mask = AV_CH_LAYOUT_4POINT0 }}
+#define AV_CHANNEL_LAYOUT_4POINT1 \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 5, .u = { .mask = AV_CH_LAYOUT_4POINT1 }}
+#define AV_CHANNEL_LAYOUT_2_2 \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 4, .u = { .mask = AV_CH_LAYOUT_2_2 }}
+#define AV_CHANNEL_LAYOUT_QUAD \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 4, .u = { .mask = AV_CH_LAYOUT_QUAD }}
+#define AV_CHANNEL_LAYOUT_5POINT0 \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 5, .u = { .mask = AV_CH_LAYOUT_5POINT0 }}
+#define AV_CHANNEL_LAYOUT_5POINT1 \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 6, .u = { .mask = AV_CH_LAYOUT_5POINT1 }}
+#define AV_CHANNEL_LAYOUT_5POINT0_BACK \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 5, .u = { .mask = AV_CH_LAYOUT_5POINT0_BACK }}
+#define AV_CHANNEL_LAYOUT_5POINT1_BACK \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 6, .u = { .mask = AV_CH_LAYOUT_5POINT1_BACK }}
+#define AV_CHANNEL_LAYOUT_6POINT0 \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 6, .u = { .mask = AV_CH_LAYOUT_6POINT0 }}
+#define AV_CHANNEL_LAYOUT_6POINT0_FRONT \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 6, .u = { .mask = AV_CH_LAYOUT_6POINT0_FRONT }}
+#define AV_CHANNEL_LAYOUT_HEXAGONAL \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 6, .u = { .mask = AV_CH_LAYOUT_HEXAGONAL }}
+#define AV_CHANNEL_LAYOUT_6POINT1 \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 7, .u = { .mask = AV_CH_LAYOUT_6POINT1 }}
+#define AV_CHANNEL_LAYOUT_6POINT1_BACK \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 7, .u = { .mask = AV_CH_LAYOUT_6POINT1_BACK }}
+#define AV_CHANNEL_LAYOUT_6POINT1_FRONT \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 7, .u = { .mask = AV_CH_LAYOUT_6POINT1_FRONT }}
+#define AV_CHANNEL_LAYOUT_7POINT0 \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 7, .u = { .mask = AV_CH_LAYOUT_7POINT0 }}
+#define AV_CHANNEL_LAYOUT_7POINT0_FRONT \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 7, .u = { .mask = AV_CH_LAYOUT_7POINT0_FRONT }}
+#define AV_CHANNEL_LAYOUT_7POINT1 \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 8, .u = { .mask = AV_CH_LAYOUT_7POINT1 }}
+#define AV_CHANNEL_LAYOUT_7POINT1_WIDE \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 8, .u = { .mask = AV_CH_LAYOUT_7POINT1_WIDE }}
+#define AV_CHANNEL_LAYOUT_7POINT1_WIDE_BACK \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 8, .u = { .mask = AV_CH_LAYOUT_7POINT1_WIDE_BACK }}
+#define AV_CHANNEL_LAYOUT_OCTAGONAL \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 8, .u = { .mask = AV_CH_LAYOUT_OCTAGONAL }}
+#define AV_CHANNEL_LAYOUT_HEXADECAGONAL \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 16, .u = { .mask = AV_CH_LAYOUT_HEXAGONAL }}
+#define AV_CHANNEL_LAYOUT_STEREO_DOWNMIX \
+ { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 2, .u = { .mask = AV_CH_LAYOUT_STEREO_DOWNMIX }}
+
+#if FF_API_OLD_CHANNEL_LAYOUT
+/**
* Return a channel layout id that matches name, or 0 if no match is found.
*
* name can be one or several of the following notations,
@@ -134,7 +325,10 @@ enum AVMatrixEncoding {
* AV_CH_* macros).
*
* Example: "stereo+FC" = "2+FC" = "2c+1c" = "0x7"
+ *
+ * @deprecated use av_channel_layout_from_string()
*/
+attribute_deprecated
uint64_t av_get_channel_layout(const char *name);

/**
@@ -143,17 +337,24 @@ uint64_t av_get_channel_layout(const char *name);
*
* @param buf put here the string containing the channel layout
* @param buf_size size in bytes of the buffer
+ * @deprecated use av_channel_layout_describe()
*/
+attribute_deprecated
void av_get_channel_layout_string(char *buf, int buf_size, int nb_channels, uint64_t channel_layout);

/**
* Return the number of channels in the channel layout.
+ * @deprecated use AVChannelLayout.nb_channels
*/
+attribute_deprecated
int av_get_channel_layout_nb_channels(uint64_t channel_layout);

/**
* Return default channel layout for a given number of channels.
+ *
+ * @deprecated use av_channel_layout_default()
*/
+attribute_deprecated
uint64_t av_get_default_channel_layout(int nb_channels);

/**
@@ -164,21 +365,176 @@ uint64_t av_get_default_channel_layout(int nb_channels);
*
* @return index of channel in channel_layout on success, a negative AVERROR
* on error.
+ *
+ * @deprecated use av_channel_layout_channel_index()
*/
+attribute_deprecated
int av_get_channel_layout_channel_index(uint64_t channel_layout,
uint64_t channel);

/**
* Get the channel with the given index in channel_layout.
+ * @deprecated use av_channel_layout_get_channel()
*/
+attribute_deprecated
uint64_t av_channel_layout_extract_channel(uint64_t channel_layout, int index);

/**
* Get the name of a given channel.
*
* @return channel name on success, NULL on error.
+ *
+ * @deprecated use av_channel_name()
*/
+attribute_deprecated
const char *av_get_channel_name(uint64_t channel);
+#endif
+
+/**
+ * This is the inverse function of @ref av_channel_from_string().
+ *
+ * @return a string describing a given channel, "?" if not found.
+ */
+const char *av_channel_name(enum AVChannel channel);
+
+/**
+ * This is the inverse function of @ref av_channel_name().
+ *
+ * @return a channel described by the given string, or a negative AVERROR value.
+ */
+int av_channel_from_string(const char *name);
+
+/**
+ * Initialize a native channel layout from a bitmask indicating which channels
+ * are present.
+ *
+ * @note channel_layout should be properly allocated as described above.
+ *
+ * @param channel_layout the layout structure to be initialized
+ * @param mask bitmask describing the channel layout
+ */
+void av_channel_layout_from_mask(AVChannelLayout *channel_layout, uint64_t mask);
+
+/**
+ * Initialize a channel layout from a given string description.
+ * The input string can be represented by:
+ * - the formal channel layout name (returned by av_channel_layout_describe())
+ * - single or multiple channel names (returned by av_channel_name()
+ * or concatenated with "|")
+ * - a hexadecimal value of a channel layout (eg. "0x4")
+ * - the number of channels with default layout (eg. "5")
+ * - the number of unordered channels (eg. "4 channels")
+ *
+ * @note channel_layout should be properly allocated as described above.
+ *
+ * @param channel_layout input channel layout
+ * @param str string describing the channel layout
+ * @return 0 channel layout was detected, AVERROR_INVALIDATATA otherwise
+ */
+int av_channel_layout_from_string(AVChannelLayout *channel_layout,
+ const char *str);
+
+/**
+ * Get the default channel layout for a given number of channels.
+ *
+ * @note channel_layout should be properly allocated as described above.
+ *
+ * @param channel_layout the layout structure to be initialized
+ * @param nb_channels number of channels
+ */
+void av_channel_layout_default(AVChannelLayout *ch_layout, int nb_channels);
+
+/**
+ * Free any allocated data in the channel layout and reset the channel
+ * count to 0.
+ *
+ * @note this only used for structure initialization and for freeing the
+ * allocated memory for AV_CHANNEL_ORDER_CUSTOM order.
+ *
+ * @param channel_layout the layout structure to be uninitialized
+ */
+void av_channel_layout_uninit(AVChannelLayout *channel_layout);
+
+/**
+ * Make a copy of a channel layout. This differs from just assigning src to dst
+ * in that it allocates and copies the map for AV_CHANNEL_ORDER_CUSTOM.
+ *
+ * @note the destination channel_layout will be always uninitialized before copy.
+ *
+ * @param dst destination channel layout
+ * @param src source channel layout
+ * @return 0 on success, a negative AVERROR on error.
+ */
+int av_channel_layout_copy(AVChannelLayout *dst, const AVChannelLayout *src);
+
+/**
+ * Get a human-readable string describing the channel layout properties.
+ *
+ * @note The returned string is allocated with av_malloc(),
+ * and must be freed by the caller with av_free().
+ *
+ * @param channel_layout channel layout to be described
+ * @return a string describing the structure or NULL on failure in the same
+ * format that is accepted by @ref av_channel_layout_from_string().
+ */
+char *av_channel_layout_describe(const AVChannelLayout *channel_layout);
+
+/**
+ * Get the channel with the given index in a channel layout.
+ *
+ * @param channel_layout input channel layout
+ * @return channel with the index idx in channel_layout on success or a negative
+ * AVERROR on failure (if idx is not valid or the channel order
+ * is unspecified)
+ */
+int av_channel_layout_get_channel(const AVChannelLayout *channel_layout, int idx);
+
+/**
+ * Get the index of a given channel in a channel layout. In case multiple
+ * channels are found, only the first match will be returned.
+ *
+ * @param channel_layout input channel layout
+ * @return index of channel in channel_layout on success or a negative number if
+ * channel is not present in channel_layout.
+ */
+int av_channel_layout_channel_index(const AVChannelLayout *channel_layout,
+ enum AVChannel channel);
+
+/**
+ * Find out what channels from a given set are present in a channel layout,
+ * without regard for their positions.
+ *
+ * @param channel_layout input channel layout
+ * @param mask a combination of AV_CH_* representing a set of channels
+ * @return a bitfield representing all the channels from mask that are present
+ * in channel_layout
+ */
+uint64_t av_channel_layout_subset(const AVChannelLayout *channel_layout,
+ uint64_t mask);
+
+/**
+ * Check whether a channel layout is valid, i.e. can possibly describe audio
+ * data.
+ *
+ * @param channel_layout input channel layout
+ * @return 1 if channel_layout is valid, 0 otherwise.
+ */
+int av_channel_layout_check(const AVChannelLayout *channel_layout);
+
+/**
+ * Check whether two channel layouts are semantically the same, i.e. the same
+ * channels are present on the same positions in both.
+ *
+ * If one of the channel layouts is AV_CHANNEL_ORDER_UNSPEC, while the other is
+ * not, they are considered to be unequal. If both are AV_CHANNEL_ORDER_UNSPEC,
+ * they are considered equal iff the channel counts are the same in both.
+ *
+ * @param chl input channel layout
+ * @param chl1 input channel layout
+ * @return 0 if chl and chl1 are equal, 1 if they are not equal. A negative
+ * AVERROR code if one or both are invalid.
+ */
+int av_channel_layout_compare(const AVChannelLayout *chl, const AVChannelLayout *chl1);

/**
* @}
diff --git a/libavutil/version.h b/libavutil/version.h
index 2c85120b64..a882a68f6c 100644
--- a/libavutil/version.h
+++ b/libavutil/version.h
@@ -96,6 +96,9 @@
#ifndef FF_API_CRYPTO_SIZE_T
#define FF_API_CRYPTO_SIZE_T (LIBAVUTIL_VERSION_MAJOR < 57)
#endif
+#ifndef FF_API_OLD_CHANNEL_LAYOUT
+#define FF_API_OLD_CHANNEL_LAYOUT (LIBAVUTIL_VERSION_MAJOR < 57)
+#endif


/**
--
2.13.1
wm4
2017-06-30 08:38:42 UTC
Permalink
On Thu, 29 Jun 2017 17:28:51 -0400
Post by Vittorio Giovara
The new API is more extensible and allows for custom layouts.
More accurate information is exported, eg for decoders that do not
set a channel layout, lavc will not make one up for them.
Deprecate the old API working with just uint64_t bitmasks.
---
+
+/**
+ * Initialize a channel layout from a given string description.
+ * - the formal channel layout name (returned by av_channel_layout_describe())
+ * - single or multiple channel names (returned by av_channel_name()
+ * or concatenated with "|")
+ * - a hexadecimal value of a channel layout (eg. "0x4")
+ * - the number of channels with default layout (eg. "5")
+ * - the number of unordered channels (eg. "4 channels")
+ *
Above, where?
Post by Vittorio Giovara
+ *
+ */
+int av_channel_layout_from_string(AVChannelLayout *channel_layout,
+ const char *str);
I still think you need to describe in what state channel_layout should
be.

Why is this so hard? It's always the same with Libav API docs. AVFrame
sort of has the same problem.
Post by Vittorio Giovara
+/**
+ * Get the default channel layout for a given number of channels.
+ *
+ *
+ */
+void av_channel_layout_default(AVChannelLayout *ch_layout, int nb_channels);
+
+/**
+ * Free any allocated data in the channel layout and reset the channel
+ * count to 0.
+ *
+ * allocated memory for AV_CHANNEL_ORDER_CUSTOM order.
+ *
+ */
+void av_channel_layout_uninit(AVChannelLayout *channel_layout);
+
+/**
+ * Make a copy of a channel layout. This differs from just assigning src to dst
+ * in that it allocates and copies the map for AV_CHANNEL_ORDER_CUSTOM.
+ *
What does this statement even mean? Does it call

av_channel_layout_uninit(dst);

as first line?

(Again, documentation issue, not source code issue.)
Post by Vittorio Giovara
+ *
+ */
+int av_channel_layout_copy(AVChannelLayout *dst, const AVChannelLayout *src);
+
Otherwise ok.
Vittorio Giovara
2017-06-30 16:51:16 UTC
Permalink
Post by wm4
On Thu, 29 Jun 2017 17:28:51 -0400
Post by Vittorio Giovara
The new API is more extensible and allows for custom layouts.
More accurate information is exported, eg for decoders that do not
set a channel layout, lavc will not make one up for them.
Deprecate the old API working with just uint64_t bitmasks.
---
+
+/**
+ * Initialize a channel layout from a given string description.
+ * - the formal channel layout name (returned by av_channel_layout_describe())
+ * - single or multiple channel names (returned by av_channel_name()
+ * or concatenated with "|")
+ * - a hexadecimal value of a channel layout (eg. "0x4")
+ * - the number of channels with default layout (eg. "5")
+ * - the number of unordered channels (eg. "4 channels")
+ *
Above, where?
in the structure description, I'll add this locally
Post by wm4
Post by Vittorio Giovara
+ *
+ */
+int av_channel_layout_from_string(AVChannelLayout *channel_layout,
+ const char *str);
I still think you need to describe in what state channel_layout should
be.
Why is this so hard? It's always the same with Libav API docs. AVFrame
sort of has the same problem.
ok if you insist ^^
Post by wm4
Post by Vittorio Giovara
+/**
+ * Get the default channel layout for a given number of channels.
+ *
+ *
+ */
+void av_channel_layout_default(AVChannelLayout *ch_layout, int nb_channels);
+
+/**
+ * Free any allocated data in the channel layout and reset the channel
+ * count to 0.
+ *
+ * allocated memory for AV_CHANNEL_ORDER_CUSTOM order.
+ *
+ */
+void av_channel_layout_uninit(AVChannelLayout *channel_layout);
+
+/**
+ * Make a copy of a channel layout. This differs from just assigning src to dst
+ * in that it allocates and copies the map for AV_CHANNEL_ORDER_CUSTOM.
+ *
What does this statement even mean? Does it call
av_channel_layout_uninit(dst);
as first line?
Correct, is that unclear? How would you phrase it?
Post by wm4
Post by Vittorio Giovara
+ *
+ */
+int av_channel_layout_copy(AVChannelLayout *dst, const AVChannelLayout *src);
+
Otherwise ok.
\o/
--
Vittorio
wm4
2017-07-05 18:53:54 UTC
Permalink
On Fri, 30 Jun 2017 12:51:16 -0400
Post by Vittorio Giovara
Post by wm4
On Thu, 29 Jun 2017 17:28:51 -0400
Post by Vittorio Giovara
The new API is more extensible and allows for custom layouts.
More accurate information is exported, eg for decoders that do not
set a channel layout, lavc will not make one up for them.
Deprecate the old API working with just uint64_t bitmasks.
---
+
+/**
+ * Initialize a channel layout from a given string description.
+ * - the formal channel layout name (returned by av_channel_layout_describe())
+ * - single or multiple channel names (returned by av_channel_name()
+ * or concatenated with "|")
+ * - a hexadecimal value of a channel layout (eg. "0x4")
+ * - the number of channels with default layout (eg. "5")
+ * - the number of unordered channels (eg. "4 channels")
+ *
Above, where?
in the structure description, I'll add this locally
Post by wm4
Post by Vittorio Giovara
+ *
+ */
+int av_channel_layout_from_string(AVChannelLayout *channel_layout,
+ const char *str);
I still think you need to describe in what state channel_layout should
be.
Why is this so hard? It's always the same with Libav API docs. AVFrame
sort of has the same problem.
ok if you insist ^^
Post by wm4
Post by Vittorio Giovara
+/**
+ * Get the default channel layout for a given number of channels.
+ *
+ *
+ */
+void av_channel_layout_default(AVChannelLayout *ch_layout, int nb_channels);
+
+/**
+ * Free any allocated data in the channel layout and reset the channel
+ * count to 0.
+ *
+ * allocated memory for AV_CHANNEL_ORDER_CUSTOM order.
+ *
+ */
+void av_channel_layout_uninit(AVChannelLayout *channel_layout);
+
+/**
+ * Make a copy of a channel layout. This differs from just assigning src to dst
+ * in that it allocates and copies the map for AV_CHANNEL_ORDER_CUSTOM.
+ *
What does this statement even mean? Does it call
av_channel_layout_uninit(dst);
as first line?
Correct, is that unclear? How would you phrase it?
Well, the situation is that memory allocations are involved, and the
state of the dst argument is unclear. You have to define exactly in
what state it has to be, or the user is inevitably going to make
mistakes, unless he reads the source code and makes assumptions about
the API based on it.

In such a case, there are about the following choices:

1. The function will blindly overwrite dst, and not ever read from it.
In this case, the API user doesn't need to care what is in dst as
long as he made sure that there are no allocations that would leak.
The user can put uninitialized (i.e. random) data into dst before
calling the function.
2. The function explicitly uninitializes the dst argument before it
writes to it. The API user must make sure that dst is somehow valid.
I suppose at least in this case, both passing zerod-out memory, or
something created with a constructor function is fine.
3. Something in-between, like requiring zerod-out memory, and having
undefined behavior if it's a valid allocation (yes there are
functions like this in Libav).

Your implementation is 2., but you write something about how it's
"uninitialized" (now that I read it again, I think it says in English
that av_channel_layout_uninit(dst); is called).

The docs should be as explicit as possible here. Even better if we had
(or have?) some sort of consistent standard terminology for these
things. And maybe consistent API behavior.

I for one tend to have to look up which behavior a given function
expects.
Anton Khirnov
2017-07-22 07:56:21 UTC
Permalink
Quoting wm4 (2017-07-05 20:53:54)
Post by wm4
On Fri, 30 Jun 2017 12:51:16 -0400
Post by Vittorio Giovara
Post by wm4
On Thu, 29 Jun 2017 17:28:51 -0400
Post by Vittorio Giovara
The new API is more extensible and allows for custom layouts.
More accurate information is exported, eg for decoders that do not
set a channel layout, lavc will not make one up for them.
Deprecate the old API working with just uint64_t bitmasks.
---
+
+/**
+ * Initialize a channel layout from a given string description.
+ * - the formal channel layout name (returned by av_channel_layout_describe())
+ * - single or multiple channel names (returned by av_channel_name()
+ * or concatenated with "|")
+ * - a hexadecimal value of a channel layout (eg. "0x4")
+ * - the number of channels with default layout (eg. "5")
+ * - the number of unordered channels (eg. "4 channels")
+ *
Above, where?
in the structure description, I'll add this locally
Post by wm4
Post by Vittorio Giovara
+ *
+ */
+int av_channel_layout_from_string(AVChannelLayout *channel_layout,
+ const char *str);
I still think you need to describe in what state channel_layout should
be.
Why is this so hard? It's always the same with Libav API docs. AVFrame
sort of has the same problem.
ok if you insist ^^
Post by wm4
Post by Vittorio Giovara
+/**
+ * Get the default channel layout for a given number of channels.
+ *
+ *
+ */
+void av_channel_layout_default(AVChannelLayout *ch_layout, int nb_channels);
+
+/**
+ * Free any allocated data in the channel layout and reset the channel
+ * count to 0.
+ *
+ * allocated memory for AV_CHANNEL_ORDER_CUSTOM order.
+ *
+ */
+void av_channel_layout_uninit(AVChannelLayout *channel_layout);
+
+/**
+ * Make a copy of a channel layout. This differs from just assigning src to dst
+ * in that it allocates and copies the map for AV_CHANNEL_ORDER_CUSTOM.
+ *
What does this statement even mean? Does it call
av_channel_layout_uninit(dst);
as first line?
Correct, is that unclear? How would you phrase it?
Well, the situation is that memory allocations are involved, and the
state of the dst argument is unclear. You have to define exactly in
what state it has to be, or the user is inevitably going to make
mistakes, unless he reads the source code and makes assumptions about
the API based on it.
1. The function will blindly overwrite dst, and not ever read from it.
In this case, the API user doesn't need to care what is in dst as
long as he made sure that there are no allocations that would leak.
The user can put uninitialized (i.e. random) data into dst before
calling the function.
2. The function explicitly uninitializes the dst argument before it
writes to it. The API user must make sure that dst is somehow valid.
I suppose at least in this case, both passing zerod-out memory, or
something created with a constructor function is fine.
3. Something in-between, like requiring zerod-out memory, and having
undefined behavior if it's a valid allocation (yes there are
functions like this in Libav).
Your implementation is 2., but you write something about how it's
"uninitialized" (now that I read it again, I think it says in English
that av_channel_layout_uninit(dst); is called).
The docs should be as explicit as possible here. Even better if we had
(or have?) some sort of consistent standard terminology for these
things. And maybe consistent API behavior.
I fully agree with you about consistent API behaviour, but the one
that's consistent across Libav is with no implicit frees. So 1. from
your list.
--
Anton Khirnov
Anton Khirnov
2017-07-22 07:55:01 UTC
Permalink
Quoting Vittorio Giovara (2017-06-29 00:10:45)
Post by Vittorio Giovara
+
+enum AVChannelOrder {
+ /**
+ * The native channel order, i.e. the channels are in the same order in
+ * which they are defined in the AVChannel enum. This supports up to 63
+ * different channels.
+ */
+ AV_CHANNEL_ORDER_NATIVE,
+ /**
+ * The channel order does not correspond to any other predefined order and
+ * is stored as an explicit map. For example, this could be used to support
+ * layouts with 64 or more channels, or with channels that could be skipped.
+ */
+ AV_CHANNEL_ORDER_CUSTOM,
+ /**
+ * Only the channel count is specified, without any further information
+ * about the channel order.
This used to be just 'about the channels', and I think that was more
correct -- here we lack any informations about what the channels are,
not just their ordering. Alternatively 'about the channel order or
semantics'.
Post by Vittorio Giovara
+
+/**
+ * Initialize a channel layout from a given string description.
+ * - the formal channel layout name (returned by av_channel_layout_describe())
+ * - single or multiple channel names (returned by av_channel_name()
+ * or concatenated with "|")
Shouldn't this be
- single or multiple channel names (returned by av_channel_name())
concatenated with "|"
--
Anton Khirnov
Vittorio Giovara
2017-06-28 22:10:47 UTC
Permalink
From: Anton Khirnov <***@khirnov.net>

They are incompatible with the new channel layout scheme and no decoder
uses them.

Signed-off-by: Vittorio Giovara <***@gmail.com>
---
libavcodec/avcodec.h | 5 +++++
libavcodec/decode.c | 4 ++++
libavformat/dump.c | 9 ++++++++-
libavformat/utils.c | 9 +++++++++
4 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 162f1abe4b..4089c08a24 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -1165,8 +1165,13 @@ typedef struct AVPacket {
#define AV_PKT_FLAG_CORRUPT 0x0002 ///< The packet content is corrupted

enum AVSideDataParamChangeFlags {
+#if FF_API_OLD_CHANNEL_LAYOUT
+ /**
+ * @deprecated those are not used by any decoder
+ */
AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT = 0x0001,
AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT = 0x0002,
+#endif
AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE = 0x0004,
AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS = 0x0008,
};
diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index 175a6fae4c..a49cd77e51 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -60,6 +60,8 @@ static int apply_param_change(AVCodecContext *avctx, AVPacket *avpkt)
flags = bytestream_get_le32(&data);
size -= 4;

+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
if (flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT) {
if (size < 4)
goto fail;
@@ -72,6 +74,8 @@ static int apply_param_change(AVCodecContext *avctx, AVPacket *avpkt)
avctx->channel_layout = bytestream_get_le64(&data);
size -= 8;
}
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
if (flags & AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE) {
if (size < 4)
goto fail;
diff --git a/libavformat/dump.c b/libavformat/dump.c
index 261e21efd3..e1f6848547 100644
--- a/libavformat/dump.c
+++ b/libavformat/dump.c
@@ -142,8 +142,11 @@ static void dump_paramchange(void *ctx, AVPacketSideData *sd)
{
int size = sd->size;
const uint8_t *data = sd->data;
- uint32_t flags, channels, sample_rate, width, height;
+ uint32_t flags, sample_rate, width, height;
+#if FF_API_OLD_CHANNEL_LAYOUT
+ uint32_t channels;
uint64_t layout;
+#endif

if (!data || sd->size < 4)
goto fail;
@@ -152,6 +155,8 @@ static void dump_paramchange(void *ctx, AVPacketSideData *sd)
data += 4;
size -= 4;

+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
if (flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT) {
if (size < 4)
goto fail;
@@ -169,6 +174,8 @@ static void dump_paramchange(void *ctx, AVPacketSideData *sd)
av_log(ctx, AV_LOG_INFO,
"channel layout: %s, ", av_get_channel_name(layout));
}
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif /* FF_API_OLD_CHANNEL_LAYOUT */
if (flags & AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE) {
if (size < 4)
goto fail;
diff --git a/libavformat/utils.c b/libavformat/utils.c
index eaba473914..c8bb04aa70 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -3234,6 +3234,9 @@ int ff_add_param_change(AVPacket *pkt, int32_t channels,
uint8_t *data;
if (!pkt)
return AVERROR(EINVAL);
+
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
if (channels) {
size += 4;
flags |= AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT;
@@ -3242,6 +3245,8 @@ int ff_add_param_change(AVPacket *pkt, int32_t channels,
size += 8;
flags |= AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT;
}
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
if (sample_rate) {
size += 4;
flags |= AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE;
@@ -3254,10 +3259,14 @@ int ff_add_param_change(AVPacket *pkt, int32_t channels,
if (!data)
return AVERROR(ENOMEM);
bytestream_put_le32(&data, flags);
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
if (channels)
bytestream_put_le32(&data, channels);
if (channel_layout)
bytestream_put_le64(&data, channel_layout);
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
if (sample_rate)
bytestream_put_le32(&data, sample_rate);
if (width || height) {
--
2.13.1
Luca Barbato
2017-07-04 10:48:14 UTC
Permalink
Post by Vittorio Giovara
They are incompatible with the new channel layout scheme and no decoder
uses them.
---
libavcodec/avcodec.h | 5 +++++
libavcodec/decode.c | 4 ++++
libavformat/dump.c | 9 ++++++++-
libavformat/utils.c | 9 +++++++++
4 files changed, 26 insertions(+), 1 deletion(-)
Seems ok, if/when we need the functionality we can introduce something
later.
Vittorio Giovara
2017-06-28 22:10:49 UTC
Permalink
---
avtools/avconv.c | 2 +-
avtools/avconv_filter.c | 2 +-
avtools/avplay.c | 4 ++--
3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/avtools/avconv.c b/avtools/avconv.c
index 8dd11bb5fc..42cbfef592 100644
--- a/avtools/avconv.c
+++ b/avtools/avconv.c
@@ -1209,7 +1209,7 @@ static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame)
switch (ifilter->ist->st->codecpar->codec_type) {
case AVMEDIA_TYPE_AUDIO:
need_reinit |= ifilter->sample_rate != frame->sample_rate ||
- ifilter->channel_layout != frame->channel_layout;
+ ifilter->channel_layout != frame->ch_layout.u.mask;
break;
case AVMEDIA_TYPE_VIDEO:
need_reinit |= ifilter->width != frame->width ||
diff --git a/avtools/avconv_filter.c b/avtools/avconv_filter.c
index 884478da27..e719c06658 100644
--- a/avtools/avconv_filter.c
+++ b/avtools/avconv_filter.c
@@ -798,7 +798,7 @@ int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame)
ifilter->sample_aspect_ratio = frame->sample_aspect_ratio;

ifilter->sample_rate = frame->sample_rate;
- ifilter->channel_layout = frame->channel_layout;
+ ifilter->channel_layout = frame->ch_layout.u.mask;

if (frame->hw_frames_ctx) {
ifilter->hw_frames_ctx = av_buffer_ref(frame->hw_frames_ctx);
diff --git a/avtools/avplay.c b/avtools/avplay.c
index b6dbc52cf7..6cc63258fc 100644
--- a/avtools/avplay.c
+++ b/avtools/avplay.c
@@ -1837,11 +1837,11 @@ static int audio_decode_frame(PlayerState *is, double *pts_ptr)
is->frame->format, 1);

audio_resample = is->frame->format != is->sdl_sample_fmt ||
- is->frame->channel_layout != is->sdl_channel_layout ||
+ is->frame->ch_layout.u.mask != is->sdl_channel_layout ||
is->frame->sample_rate != is->sdl_sample_rate;

resample_changed = is->frame->format != is->resample_sample_fmt ||
- is->frame->channel_layout != is->resample_channel_layout ||
+ is->frame->ch_layout.u.mask != is->resample_channel_layout ||
is->frame->sample_rate != is->resample_sample_rate;

if ((!is->avr && audio_resample) || resample_changed) {
--
2.13.1
Luca Barbato
2017-07-04 10:50:56 UTC
Permalink
Post by Vittorio Giovara
---
avtools/avconv.c | 2 +-
avtools/avconv_filter.c | 2 +-
avtools/avplay.c | 4 ++--
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/avtools/avconv.c b/avtools/avconv.c
index 8dd11bb5fc..42cbfef592 100644
--- a/avtools/avconv.c
+++ b/avtools/avconv.c
@@ -1209,7 +1209,7 @@ static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame)
switch (ifilter->ist->st->codecpar->codec_type) {
need_reinit |= ifilter->sample_rate != frame->sample_rate ||
- ifilter->channel_layout != frame->channel_layout;
+ ifilter->channel_layout != frame->ch_layout.u.mask;
break;
need_reinit |= ifilter->width != frame->width ||
diff --git a/avtools/avconv_filter.c b/avtools/avconv_filter.c
index 884478da27..e719c06658 100644
--- a/avtools/avconv_filter.c
+++ b/avtools/avconv_filter.c
@@ -798,7 +798,7 @@ int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame)
ifilter->sample_aspect_ratio = frame->sample_aspect_ratio;
ifilter->sample_rate = frame->sample_rate;
- ifilter->channel_layout = frame->channel_layout;
+ ifilter->channel_layout = frame->ch_layout.u.mask;
if (frame->hw_frames_ctx) {
ifilter->hw_frames_ctx = av_buffer_ref(frame->hw_frames_ctx);
diff --git a/avtools/avplay.c b/avtools/avplay.c
index b6dbc52cf7..6cc63258fc 100644
--- a/avtools/avplay.c
+++ b/avtools/avplay.c
@@ -1837,11 +1837,11 @@ static int audio_decode_frame(PlayerState *is, double *pts_ptr)
is->frame->format, 1);
audio_resample = is->frame->format != is->sdl_sample_fmt ||
- is->frame->channel_layout != is->sdl_channel_layout ||
+ is->frame->ch_layout.u.mask != is->sdl_channel_layout ||
is->frame->sample_rate != is->sdl_sample_rate;
resample_changed = is->frame->format != is->resample_sample_fmt ||
- is->frame->channel_layout != is->resample_channel_layout ||
+ is->frame->ch_layout.u.mask != is->resample_channel_layout ||
is->frame->sample_rate != is->resample_sample_rate;
if ((!is->avr && audio_resample) || resample_changed) {
Doesn't hurt, but might be folded with patch 16.
Vittorio Giovara
2017-07-04 16:18:03 UTC
Permalink
Post by Luca Barbato
Post by Vittorio Giovara
---
avtools/avconv.c | 2 +-
avtools/avconv_filter.c | 2 +-
avtools/avplay.c | 4 ++--
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/avtools/avconv.c b/avtools/avconv.c
index 8dd11bb5fc..42cbfef592 100644
--- a/avtools/avconv.c
+++ b/avtools/avconv.c
@@ -1209,7 +1209,7 @@ static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame)
switch (ifilter->ist->st->codecpar->codec_type) {
need_reinit |= ifilter->sample_rate != frame->sample_rate ||
- ifilter->channel_layout != frame->channel_layout;
+ ifilter->channel_layout != frame->ch_layout.u.mask;
break;
need_reinit |= ifilter->width != frame->width ||
diff --git a/avtools/avconv_filter.c b/avtools/avconv_filter.c
index 884478da27..e719c06658 100644
--- a/avtools/avconv_filter.c
+++ b/avtools/avconv_filter.c
@@ -798,7 +798,7 @@ int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame)
ifilter->sample_aspect_ratio = frame->sample_aspect_ratio;
ifilter->sample_rate = frame->sample_rate;
- ifilter->channel_layout = frame->channel_layout;
+ ifilter->channel_layout = frame->ch_layout.u.mask;
if (frame->hw_frames_ctx) {
ifilter->hw_frames_ctx = av_buffer_ref(frame->hw_frames_ctx);
diff --git a/avtools/avplay.c b/avtools/avplay.c
index b6dbc52cf7..6cc63258fc 100644
--- a/avtools/avplay.c
+++ b/avtools/avplay.c
@@ -1837,11 +1837,11 @@ static int audio_decode_frame(PlayerState *is, double *pts_ptr)
is->frame->format, 1);
audio_resample = is->frame->format != is->sdl_sample_fmt ||
- is->frame->channel_layout != is->sdl_channel_layout ||
+ is->frame->ch_layout.u.mask != is->sdl_channel_layout ||
is->frame->sample_rate != is->sdl_sample_rate;
resample_changed = is->frame->format != is->resample_sample_fmt ||
- is->frame->channel_layout != is->resample_channel_layout ||
+ is->frame->ch_layout.u.mask != is->resample_channel_layout ||
is->frame->sample_rate != is->resample_sample_rate;
if ((!is->avr && audio_resample) || resample_changed) {
Doesn't hurt, but might be folded with patch 16.
patch 16 is for supplementary parts, such as examples or tests, I'd
rather keep the main tools patches separated
--
Vittorio
Luca Barbato
2017-07-04 18:16:30 UTC
Permalink
Post by Vittorio Giovara
Post by Luca Barbato
Post by Vittorio Giovara
---
avtools/avconv.c | 2 +-
avtools/avconv_filter.c | 2 +-
avtools/avplay.c | 4 ++--
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/avtools/avconv.c b/avtools/avconv.c
index 8dd11bb5fc..42cbfef592 100644
--- a/avtools/avconv.c
+++ b/avtools/avconv.c
@@ -1209,7 +1209,7 @@ static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame)
switch (ifilter->ist->st->codecpar->codec_type) {
need_reinit |= ifilter->sample_rate != frame->sample_rate ||
- ifilter->channel_layout != frame->channel_layout;
+ ifilter->channel_layout != frame->ch_layout.u.mask;
break;
need_reinit |= ifilter->width != frame->width ||
diff --git a/avtools/avconv_filter.c b/avtools/avconv_filter.c
index 884478da27..e719c06658 100644
--- a/avtools/avconv_filter.c
+++ b/avtools/avconv_filter.c
@@ -798,7 +798,7 @@ int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame)
ifilter->sample_aspect_ratio = frame->sample_aspect_ratio;
ifilter->sample_rate = frame->sample_rate;
- ifilter->channel_layout = frame->channel_layout;
+ ifilter->channel_layout = frame->ch_layout.u.mask;
if (frame->hw_frames_ctx) {
ifilter->hw_frames_ctx = av_buffer_ref(frame->hw_frames_ctx);
diff --git a/avtools/avplay.c b/avtools/avplay.c
index b6dbc52cf7..6cc63258fc 100644
--- a/avtools/avplay.c
+++ b/avtools/avplay.c
@@ -1837,11 +1837,11 @@ static int audio_decode_frame(PlayerState *is, double *pts_ptr)
is->frame->format, 1);
audio_resample = is->frame->format != is->sdl_sample_fmt ||
- is->frame->channel_layout != is->sdl_channel_layout ||
+ is->frame->ch_layout.u.mask != is->sdl_channel_layout ||
is->frame->sample_rate != is->sdl_sample_rate;
resample_changed = is->frame->format != is->resample_sample_fmt ||
- is->frame->channel_layout != is->resample_channel_layout ||
+ is->frame->ch_layout.u.mask != is->resample_channel_layout ||
is->frame->sample_rate != is->resample_sample_rate;
if ((!is->avr && audio_resample) || resample_changed) {
Doesn't hurt, but might be folded with patch 16.
patch 16 is for supplementary parts, such as examples or tests, I'd
rather keep the main tools patches separated
As you prefer, I do not have strong opinions about it.
Anton Khirnov
2017-07-22 08:15:00 UTC
Permalink
Quoting Vittorio Giovara (2017-06-29 00:10:49)
Post by Vittorio Giovara
---
avtools/avconv.c | 2 +-
avtools/avconv_filter.c | 2 +-
avtools/avplay.c | 4 ++--
3 files changed, 4 insertions(+), 4 deletions(-)
Again, seems premature. The switch should be done at the end. If it
needs to be done here, then your compatibility layer is broken.
--
Anton Khirnov
Vittorio Giovara
2018-01-19 20:34:34 UTC
Permalink
Post by Anton Khirnov
Quoting Vittorio Giovara (2017-06-29 00:10:49)
Post by Vittorio Giovara
---
avtools/avconv.c | 2 +-
avtools/avconv_filter.c | 2 +-
avtools/avplay.c | 4 ++--
3 files changed, 4 insertions(+), 4 deletions(-)
Again, seems premature. The switch should be done at the end. If it
needs to be done here, then your compatibility layer is broken.
ok I'll move tools-related changes to the end
--
Vittorio
Vittorio Giovara
2017-06-28 22:10:48 UTC
Permalink
From: Anton Khirnov <***@khirnov.net>

Signed-off-by: Vittorio Giovara <***@gmail.com>
---
libavcodec/decode.c | 67 ++++++++++++++++++++++++++++------------
libavcodec/encode.c | 9 ++++++
libavutil/frame.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++------
libavutil/frame.h | 12 +++++++-
4 files changed, 146 insertions(+), 30 deletions(-)

diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index a49cd77e51..b0d6b9fb33 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -132,7 +132,7 @@ static int unrefcount_frame(AVCodecInternal *avci, AVFrame *frame)
memcpy(frame->data, avci->to_free->data, sizeof(frame->data));
memcpy(frame->linesize, avci->to_free->linesize, sizeof(frame->linesize));
if (avci->to_free->extended_data != avci->to_free->data) {
- int planes = av_get_channel_layout_nb_channels(avci->to_free->channel_layout);
+ int planes = avci->to_free->ch_layout.nb_channels;
int size = planes * sizeof(*frame->extended_data);

if (!size) {
@@ -153,9 +153,19 @@ static int unrefcount_frame(AVCodecInternal *avci, AVFrame *frame)
frame->format = avci->to_free->format;
frame->width = avci->to_free->width;
frame->height = avci->to_free->height;
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
frame->channel_layout = avci->to_free->channel_layout;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
frame->nb_samples = avci->to_free->nb_samples;

+ ret = av_channel_layout_copy(&frame->ch_layout, &avci->to_free->ch_layout);
+ if (ret < 0) {
+ av_frame_unref(frame);
+ return ret;
+ }
+
return 0;
}

@@ -887,10 +897,20 @@ static int update_frame_pool(AVCodecContext *avctx, AVFrame *frame)
break;
}
case AVMEDIA_TYPE_AUDIO: {
- int ch = av_get_channel_layout_nb_channels(frame->channel_layout);
+ int ch = frame->ch_layout.nb_channels;
int planar = av_sample_fmt_is_planar(frame->format);
int planes = planar ? ch : 1;

+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+ if (!ch && frame->channel_layout) {
+ av_channel_layout_from_mask(&frame->ch_layout, frame->channel_layout);
+ ch = frame->ch_layout.nb_channels;
+ planes = planar ? ch : 1;
+ }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+
if (pool->format == frame->format && pool->planes == planes &&
pool->channels == ch && frame->nb_samples == pool->samples)
return 0;
@@ -1111,28 +1131,35 @@ 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 (!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);
+ }
+#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 (avctx->channel_layout) {
- if (av_get_channel_layout_nb_channels(avctx->channel_layout) !=
- avctx->channels) {
- av_log(avctx, AV_LOG_ERROR, "Inconsistent channel "
- "configuration.\n");
- return AVERROR(EINVAL);
- }
-
- frame->channel_layout = avctx->channel_layout;
- } else {
- if (avctx->channels > FF_SANE_NB_CHANNELS) {
- av_log(avctx, AV_LOG_ERROR, "Too many channels: %d.\n",
- avctx->channels);
- return AVERROR(ENOSYS);
- }
-
- frame->channel_layout = av_get_default_channel_layout(avctx->channels);
+ 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 << avctx->channels) - 1;
+ frame->channel_layout = (1ULL << frame->ch_layout.nb_channels) - 1;
}
}
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+ if (!av_channel_layout_check(&frame->ch_layout)) {
+ av_log(avctx, AV_LOG_ERROR, "Invalid channel layout.\n");
+ return AVERROR_INVALIDDATA;
+ }
break;
default: return AVERROR(EINVAL);
}
diff --git a/libavcodec/encode.c b/libavcodec/encode.c
index 9bb7ae5bde..cf77fa7cff 100644
--- a/libavcodec/encode.c
+++ b/libavcodec/encode.c
@@ -60,8 +60,17 @@ static int pad_last_frame(AVCodecContext *s, AVFrame **dst, const AVFrame *src)
return AVERROR(ENOMEM);

frame->format = src->format;
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
frame->channel_layout = src->channel_layout;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
frame->nb_samples = s->frame_size;
+
+ ret = av_channel_layout_copy(&frame->ch_layout, &src->ch_layout);
+ if (ret < 0)
+ goto fail;
+
ret = av_frame_get_buffer(frame, 32);
if (ret < 0)
goto fail;
diff --git a/libavutil/frame.c b/libavutil/frame.c
index 9cd5f9ab37..ad1a5273f6 100644
--- a/libavutil/frame.c
+++ b/libavutil/frame.c
@@ -140,11 +140,20 @@ fail:

static int get_audio_buffer(AVFrame *frame, int align)
{
- int channels = av_get_channel_layout_nb_channels(frame->channel_layout);
+ int channels = frame->ch_layout.nb_channels;
int planar = av_sample_fmt_is_planar(frame->format);
int planes = planar ? channels : 1;
int ret, i;

+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+ if (!channels) {
+ av_channel_layout_from_mask(&frame->ch_layout, frame->channel_layout);
+ channels = frame->ch_layout.nb_channels;
+ planes = planar ? channels : 1;
+ }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
if (!frame->linesize[0]) {
ret = av_samples_get_buffer_size(&frame->linesize[0], channels,
frame->nb_samples, frame->format,
@@ -194,7 +203,14 @@ int av_frame_get_buffer(AVFrame *frame, int align)

if (frame->width > 0 && frame->height > 0)
return get_video_buffer(frame, align);
- else if (frame->nb_samples > 0 && frame->channel_layout)
+ else if (frame->nb_samples > 0 &&
+ (av_channel_layout_check(&frame->ch_layout)
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+ || frame->channel_layout
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+ ))
return get_audio_buffer(frame, align);

return AVERROR(EINVAL);
@@ -207,13 +223,26 @@ int av_frame_ref(AVFrame *dst, const AVFrame *src)
dst->format = src->format;
dst->width = src->width;
dst->height = src->height;
- dst->channel_layout = src->channel_layout;
dst->nb_samples = src->nb_samples;
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+ dst->channel_layout = src->channel_layout;
+ if (!av_channel_layout_check(&src->ch_layout))
+ av_channel_layout_from_mask(&dst->ch_layout, src->channel_layout);
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif

ret = av_frame_copy_props(dst, src);
if (ret < 0)
return ret;

+ // this check is needed only until FF_API_OLD_CHANNEL_LAYOUT is out
+ if (av_channel_layout_check(&src->ch_layout)) {
+ ret = av_channel_layout_copy(&dst->ch_layout, &src->ch_layout);
+ if (ret < 0)
+ goto fail;
+ }
+
/* duplicate the frame data if it's not refcounted */
if (!src->buf[0]) {
ret = av_frame_get_buffer(dst, 32);
@@ -264,7 +293,7 @@ int av_frame_ref(AVFrame *dst, const AVFrame *src)

/* duplicate extended data */
if (src->extended_data != src->data) {
- int ch = av_get_channel_layout_nb_channels(src->channel_layout);
+ int ch = dst->ch_layout.nb_channels;

if (!ch) {
ret = AVERROR(EINVAL);
@@ -319,6 +348,8 @@ void av_frame_unref(AVFrame *frame)

av_buffer_unref(&frame->opaque_ref);

+ av_channel_layout_uninit(&frame->ch_layout);
+
get_frame_defaults(frame);
}

@@ -362,8 +393,18 @@ int av_frame_make_writable(AVFrame *frame)
tmp.format = frame->format;
tmp.width = frame->width;
tmp.height = frame->height;
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
tmp.channel_layout = frame->channel_layout;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
tmp.nb_samples = frame->nb_samples;
+ ret = av_channel_layout_copy(&tmp.ch_layout, &frame->ch_layout);
+ if (ret < 0) {
+ av_frame_unref(&tmp);
+ return ret;
+ }
+
ret = av_frame_get_buffer(&tmp, 32);
if (ret < 0)
return ret;
@@ -458,7 +499,14 @@ AVBufferRef *av_frame_get_plane_buffer(AVFrame *frame, int plane)
int planes, i;

if (frame->nb_samples) {
- int channels = av_get_channel_layout_nb_channels(frame->channel_layout);
+ int channels = frame->ch_layout.nb_channels;
+
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+ if (!channels)
+ channels = av_get_channel_layout_nb_channels(frame->channel_layout);
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
if (!channels)
return NULL;
planes = av_sample_fmt_is_planar(frame->format) ? channels : 1;
@@ -552,12 +600,27 @@ static int frame_copy_video(AVFrame *dst, const AVFrame *src)
static int frame_copy_audio(AVFrame *dst, const AVFrame *src)
{
int planar = av_sample_fmt_is_planar(dst->format);
- int channels = av_get_channel_layout_nb_channels(dst->channel_layout);
+ int channels = dst->ch_layout.nb_channels;
int planes = planar ? channels : 1;
int i;

- if (dst->nb_samples != src->nb_samples ||
- dst->channel_layout != src->channel_layout)
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+ if (!channels) {
+ channels = av_get_channel_layout_nb_channels(dst->channel_layout);
+ planes = planar ? channels : 1;
+ }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+
+ if (dst->nb_samples != src->nb_samples ||
+ av_channel_layout_compare(&dst->ch_layout, &src->ch_layout)
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+ || dst->channel_layout != src->channel_layout
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+ )
return AVERROR(EINVAL);

for (i = 0; i < planes; i++)
@@ -577,7 +640,14 @@ int av_frame_copy(AVFrame *dst, const AVFrame *src)

if (dst->width > 0 && dst->height > 0)
return frame_copy_video(dst, src);
- else if (dst->nb_samples > 0 && dst->channel_layout)
+ else if (dst->nb_samples > 0 &&
+ (av_channel_layout_check(&dst->ch_layout)
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+ || dst->channel_layout
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+ ))
return frame_copy_audio(dst, src);

return AVERROR(EINVAL);
diff --git a/libavutil/frame.h b/libavutil/frame.h
index f9ffb5bbbf..afa655026f 100644
--- a/libavutil/frame.h
+++ b/libavutil/frame.h
@@ -30,6 +30,7 @@

#include "avutil.h"
#include "buffer.h"
+#include "channel_layout.h"
#include "dict.h"
#include "rational.h"
#include "samplefmt.h"
@@ -304,10 +305,14 @@ typedef struct AVFrame {
*/
int sample_rate;

+#if FF_API_OLD_CHANNEL_LAYOUT
/**
* Channel layout of the audio data.
+ * @deprecated use ch_layout instead
*/
+ attribute_deprecated
uint64_t channel_layout;
+#endif

/**
* AVBuffer references backing the data for this frame. If all elements of
@@ -406,6 +411,11 @@ typedef struct AVFrame {
* purpose.
*/
AVBufferRef *opaque_ref;
+
+ /**
+ * Channel layout of the audio data.
+ */
+ AVChannelLayout ch_layout;
} AVFrame;

/**
@@ -475,7 +485,7 @@ void av_frame_move_ref(AVFrame *dst, AVFrame *src);
* The following fields must be set on frame before calling this function:
* - format (pixel format for video, sample format for audio)
* - width and height for video
- * - nb_samples and channel_layout for audio
+ * - nb_samples and ch_layout for audio
*
* This function will fill AVFrame.data and AVFrame.buf arrays and, if
* necessary, allocate and fill AVFrame.extended_data and AVFrame.extended_buf.
--
2.13.1
Luca Barbato
2017-07-04 10:48:35 UTC
Permalink
Post by Vittorio Giovara
---
libavcodec/decode.c | 67 ++++++++++++++++++++++++++++------------
libavcodec/encode.c | 9 ++++++
libavutil/frame.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++------
libavutil/frame.h | 12 +++++++-
4 files changed, 146 insertions(+), 30 deletions(-)
Seems fine.
Anton Khirnov
2017-07-22 08:02:09 UTC
Permalink
Quoting Vittorio Giovara (2017-06-29 00:10:48)
Post by Vittorio Giovara
---
libavcodec/decode.c | 67 ++++++++++++++++++++++++++++------------
libavcodec/encode.c | 9 ++++++
Why are there lavc changes in this patch. Should they not come after
lavc conversion? I'd expect this patch to break FATE.
--
Anton Khirnov
Vittorio Giovara
2018-01-19 19:47:33 UTC
Permalink
Post by Anton Khirnov
Quoting Vittorio Giovara (2017-06-29 00:10:48)
Post by Vittorio Giovara
---
libavcodec/decode.c | 67 ++++++++++++++++++++++++++++------------
libavcodec/encode.c | 9 ++++++
Why are there lavc changes in this patch. Should they not come after
lavc conversion? I'd expect this patch to break FATE.
I'll split this patch in two. No this does not break FATE in the current
incarnation.
--
Vittorio
Anton Khirnov
2017-07-22 08:13:45 UTC
Permalink
Quoting Vittorio Giovara (2017-06-29 00:10:48)
Post by Vittorio Giovara
---
libavcodec/decode.c | 67 ++++++++++++++++++++++++++++------------
libavcodec/encode.c | 9 ++++++
libavutil/frame.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++------
libavutil/frame.h | 12 +++++++-
4 files changed, 146 insertions(+), 30 deletions(-)
diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index a49cd77e51..b0d6b9fb33 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -132,7 +132,7 @@ static int unrefcount_frame(AVCodecInternal *avci, AVFrame *frame)
memcpy(frame->data, avci->to_free->data, sizeof(frame->data));
memcpy(frame->linesize, avci->to_free->linesize, sizeof(frame->linesize));
if (avci->to_free->extended_data != avci->to_free->data) {
- int planes = av_get_channel_layout_nb_channels(avci->to_free->channel_layout);
+ int planes = avci->to_free->ch_layout.nb_channels;
int size = planes * sizeof(*frame->extended_data);
if (!size) {
@@ -153,9 +153,19 @@ static int unrefcount_frame(AVCodecInternal *avci, AVFrame *frame)
frame->format = avci->to_free->format;
frame->width = avci->to_free->width;
frame->height = avci->to_free->height;
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
frame->channel_layout = avci->to_free->channel_layout;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
frame->nb_samples = avci->to_free->nb_samples;
+ ret = av_channel_layout_copy(&frame->ch_layout, &avci->to_free->ch_layout);
+ if (ret < 0) {
+ av_frame_unref(frame);
+ return ret;
+ }
+
return 0;
}
@@ -887,10 +897,20 @@ static int update_frame_pool(AVCodecContext *avctx, AVFrame *frame)
break;
}
case AVMEDIA_TYPE_AUDIO: {
- int ch = av_get_channel_layout_nb_channels(frame->channel_layout);
+ int ch = frame->ch_layout.nb_channels;
int planar = av_sample_fmt_is_planar(frame->format);
int planes = planar ? ch : 1;
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+ if (!ch && frame->channel_layout) {
+ av_channel_layout_from_mask(&frame->ch_layout, frame->channel_layout);
+ ch = frame->ch_layout.nb_channels;
+ planes = planar ? ch : 1;
+ }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
What is this for? This code is the internal get_buffer2()
implementation, so the new channel layout API should always be used.
Post by Vittorio Giovara
+
if (pool->format == frame->format && pool->planes == planes &&
pool->channels == ch && frame->nb_samples == pool->samples)
return 0;
@@ -1111,28 +1131,35 @@ 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 (!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);
+ }
Same, why the deprecated API use.
--
Anton Khirnov
Vittorio Giovara
2018-01-19 20:33:23 UTC
Permalink
Post by Anton Khirnov
Quoting Vittorio Giovara (2017-06-29 00:10:48)
Post by Vittorio Giovara
---
libavcodec/decode.c | 67 ++++++++++++++++++++++++++++------------
libavcodec/encode.c | 9 ++++++
libavutil/frame.c | 88 ++++++++++++++++++++++++++++++
+++++++++++++++++------
Post by Vittorio Giovara
libavutil/frame.h | 12 +++++++-
4 files changed, 146 insertions(+), 30 deletions(-)
diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index a49cd77e51..b0d6b9fb33 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -132,7 +132,7 @@ static int unrefcount_frame(AVCodecInternal *avci,
AVFrame *frame)
Post by Vittorio Giovara
memcpy(frame->data, avci->to_free->data,
sizeof(frame->data));
Post by Vittorio Giovara
memcpy(frame->linesize, avci->to_free->linesize,
sizeof(frame->linesize));
Post by Vittorio Giovara
if (avci->to_free->extended_data != avci->to_free->data) {
- int planes = av_get_channel_layout_nb_channels(avci->to_free->
channel_layout);
Post by Vittorio Giovara
+ int planes = avci->to_free->ch_layout.nb_channels;
int size = planes * sizeof(*frame->extended_data);
if (!size) {
@@ -153,9 +153,19 @@ static int unrefcount_frame(AVCodecInternal *avci,
AVFrame *frame)
Post by Vittorio Giovara
frame->format = avci->to_free->format;
frame->width = avci->to_free->width;
frame->height = avci->to_free->height;
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
frame->channel_layout = avci->to_free->channel_layout;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
frame->nb_samples = avci->to_free->nb_samples;
+ ret = av_channel_layout_copy(&frame->ch_layout,
&avci->to_free->ch_layout);
Post by Vittorio Giovara
+ if (ret < 0) {
+ av_frame_unref(frame);
+ return ret;
+ }
+
return 0;
}
@@ -887,10 +897,20 @@ static int update_frame_pool(AVCodecContext
*avctx, AVFrame *frame)
Post by Vittorio Giovara
break;
}
case AVMEDIA_TYPE_AUDIO: {
- int ch = av_get_channel_layout_nb_channels(frame->channel_
layout);
Post by Vittorio Giovara
+ int ch = frame->ch_layout.nb_channels;
int planar = av_sample_fmt_is_planar(frame->format);
int planes = planar ? ch : 1;
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+ if (!ch && frame->channel_layout) {
+ av_channel_layout_from_mask(&frame->ch_layout,
frame->channel_layout);
Post by Vittorio Giovara
+ ch = frame->ch_layout.nb_channels;
+ planes = planar ? ch : 1;
+ }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
What is this for? This code is the internal get_buffer2()
implementation, so the new channel layout API should always be used.
Yes this chunk is unneeded I'll drop it.
Post by Anton Khirnov
Post by Vittorio Giovara
+
if (pool->format == frame->format && pool->planes == planes &&
pool->channels == ch && frame->nb_samples == pool->samples)
return 0;
@@ -1111,28 +1131,35 @@ int ff_get_buffer(AVCodecContext *avctx, AVFrame
*frame, int flags)
Post by Vittorio Giovara
frame->sample_rate = avctx->sample_rate;
if (frame->format < 0)
frame->format = avctx->sample_fmt;
+ if (!frame->ch_layout.nb_channels) {
+ if (avctx->channel_layout)
+ av_channel_layout_from_mask(&frame->ch_layout,
avctx->channel_layout);
Post by Vittorio Giovara
+ else
+ av_channel_layout_default(&frame->ch_layout,
avctx->channels);
Post by Vittorio Giovara
+ }
Same, why the deprecated API use.
This chunk is actually needed because some decoders don't set the channel
layout fully before ff_get_buffer.
Besides this use is going to be dropped in a later patch, as the
AVCodecContext is fully ported to the new API.
--
Vittorio
Vittorio Giovara
2017-06-28 22:10:51 UTC
Permalink
Signed-off-by: Vittorio Giovara <***@gmail.com>
---
libavfilter/audio.c | 17 +++++++++++++--
libavfilter/avfilter.c | 9 ++++----
libavfilter/avfilter.h | 13 ++++++++++-
libavfilter/avfiltergraph.c | 35 +++++++++++++++++++++++-------
libavfilter/buffersink.c | 2 +-
libavfilter/buffersrc.c | 53 ++++++++++++++++++++++++++++-----------------
libavfilter/buffersrc.h | 12 +++++++++-
libavfilter/fifo.c | 7 +++---
8 files changed, 106 insertions(+), 42 deletions(-)

diff --git a/libavfilter/audio.c b/libavfilter/audio.c
index 5fe9da95c3..afd8bdc169 100644
--- a/libavfilter/audio.c
+++ b/libavfilter/audio.c
@@ -31,7 +31,7 @@ AVFrame *ff_null_get_audio_buffer(AVFilterLink *link, int nb_samples)
AVFrame *ff_default_get_audio_buffer(AVFilterLink *link, int nb_samples)
{
AVFrame *frame = av_frame_alloc();
- int channels = av_get_channel_layout_nb_channels(link->channel_layout);
+ int channels = link->ch_layout.nb_channels;
int ret;

if (!frame)
@@ -39,7 +39,20 @@ AVFrame *ff_default_get_audio_buffer(AVFilterLink *link, int nb_samples)

frame->nb_samples = nb_samples;
frame->format = link->format;
- frame->channel_layout = link->channel_layout;
+
+ ret = av_channel_layout_copy(&frame->ch_layout, &link->ch_layout);
+ if (ret < 0) {
+ av_frame_free(&frame);
+ return NULL;
+ }
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+ if (link->ch_layout.order == AV_CHANNEL_ORDER_NATIVE ||
+ link->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC)
+ frame->channel_layout = link->channel_layout;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+
frame->sample_rate = link->sample_rate;
ret = av_frame_get_buffer(frame, 0);
if (ret < 0) {
diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c
index 83c1a7c20d..f2adefff3d 100644
--- a/libavfilter/avfilter.c
+++ b/libavfilter/avfilter.c
@@ -247,16 +247,15 @@ void ff_dlog_link(void *ctx, AVFilterLink *link, int end)
link->dst ? link->dst->filter->name : "",
end ? "\n" : "");
} else {
- char buf[128];
- av_get_channel_layout_string(buf, sizeof(buf), -1, link->channel_layout);
-
+ char *chlstr = av_channel_layout_describe(&link->ch_layout);
av_log(ctx, AV_LOG_TRACE,
"link[%p r:%d cl:%s fmt:%-16s %-16s->%-16s]%s",
- link, link->sample_rate, buf,
+ link, link->sample_rate, chlstr,
av_get_sample_fmt_name(link->format),
link->src ? link->src->filter->name : "",
link->dst ? link->dst->filter->name : "",
end ? "\n" : "");
+ av_free(chlstr);
}
}

@@ -683,7 +682,7 @@ int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
case AVMEDIA_TYPE_AUDIO:
av_samples_copy(out->extended_data, frame->extended_data,
0, 0, frame->nb_samples,
- av_get_channel_layout_nb_channels(frame->channel_layout),
+ frame->ch_layout.nb_channels,
frame->format);
break;
default:
diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h
index 6df69dbbbf..5d5edf0ed3 100644
--- a/libavfilter/avfilter.h
+++ b/libavfilter/avfilter.h
@@ -36,6 +36,7 @@
#include "libavutil/attributes.h"
#include "libavutil/avutil.h"
#include "libavutil/buffer.h"
+#include "libavutil/channel_layout.h"
#include "libavutil/frame.h"
#include "libavutil/log.h"
#include "libavutil/samplefmt.h"
@@ -334,7 +335,12 @@ struct AVFilterLink {
int h; ///< agreed upon image height
AVRational sample_aspect_ratio; ///< agreed upon sample aspect ratio
/* These two parameters apply only to audio */
- uint64_t channel_layout; ///< channel layout of current buffer (see libavutil/channel_layout.h)
+#if FF_API_OLD_CHANNEL_LAYOUT
+ /**
+ * @deprecated use ch_layout instead
+ */
+ attribute_deprecated uint64_t channel_layout;
+#endif
int sample_rate; ///< samples per second

int format; ///< agreed upon media format
@@ -405,6 +411,11 @@ struct AVFilterLink {
* AVHWFramesContext describing the frames.
*/
AVBufferRef *hw_frames_ctx;
+
+ /**
+ * Channel layout of current buffer.
+ */
+ AVChannelLayout ch_layout;
};

/**
diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c
index a0f797e283..c72016d2c8 100644
--- a/libavfilter/avfiltergraph.c
+++ b/libavfilter/avfiltergraph.c
@@ -397,7 +397,13 @@ static int pick_format(AVFilterLink *link)
return AVERROR(EINVAL);
}
link->in_channel_layouts->nb_channel_layouts = 1;
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
link->channel_layout = link->in_channel_layouts->channel_layouts[0];
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+ av_channel_layout_from_mask(&link->ch_layout,
+ link->in_channel_layouts->channel_layouts[0]);
}

ff_formats_unref(&link->in_formats);
@@ -578,23 +584,33 @@ static void swap_channel_layouts_on_filter(AVFilterContext *filter)
for (j = 0; j < outlink->in_channel_layouts->nb_channel_layouts; j++) {
uint64_t in_chlayout = link->out_channel_layouts->channel_layouts[0];
uint64_t out_chlayout = outlink->in_channel_layouts->channel_layouts[j];
- int in_channels = av_get_channel_layout_nb_channels(in_chlayout);
- int out_channels = av_get_channel_layout_nb_channels(out_chlayout);
- int count_diff = out_channels - in_channels;
+ int in_channels;
+ int out_channels;
+ int count_diff;
int matched_channels, extra_channels;
int score = 0;
+ AVChannelLayout in_ch_layout = {0};
+ AVChannelLayout out_ch_layout = {0};
+
+ av_channel_layout_from_mask( &in_ch_layout, in_chlayout);
+ av_channel_layout_from_mask(&out_ch_layout, out_chlayout);
+ in_channels = in_ch_layout.nb_channels;
+ out_channels = out_ch_layout.nb_channels;
+ count_diff = out_channels - in_channels;

/* channel substitution */
for (k = 0; k < FF_ARRAY_ELEMS(ch_subst); k++) {
uint64_t cmp0 = ch_subst[k][0];
uint64_t cmp1 = ch_subst[k][1];
+ AVChannelLayout tmp = {0};
if (( in_chlayout & cmp0) && (!(out_chlayout & cmp0)) &&
(out_chlayout & cmp1) && (!( in_chlayout & cmp1))) {
in_chlayout &= ~cmp0;
out_chlayout &= ~cmp1;
/* add score for channel match, minus a deduction for
having to do the substitution */
- score += 10 * av_get_channel_layout_nb_channels(cmp1) - 2;
+ av_channel_layout_from_mask(&tmp, cmp1);
+ score += 10 * tmp.nb_channels - 2;
}
}

@@ -605,10 +621,13 @@ static void swap_channel_layouts_on_filter(AVFilterContext *filter)
in_chlayout &= ~AV_CH_LOW_FREQUENCY;
out_chlayout &= ~AV_CH_LOW_FREQUENCY;

- matched_channels = av_get_channel_layout_nb_channels(in_chlayout &
- out_chlayout);
- extra_channels = av_get_channel_layout_nb_channels(out_chlayout &
- (~in_chlayout));
+ av_channel_layout_uninit( &in_ch_layout);
+ av_channel_layout_uninit(&out_ch_layout);
+ av_channel_layout_from_mask( &in_ch_layout, in_chlayout & out_chlayout);
+ av_channel_layout_from_mask(&out_ch_layout, out_chlayout & (~in_chlayout));
+
+ matched_channels = in_ch_layout.nb_channels;
+ extra_channels = out_ch_layout.nb_channels;
score += 10 * matched_channels - 5 * extra_channels;

if (score > best_score ||
diff --git a/libavfilter/buffersink.c b/libavfilter/buffersink.c
index 3b4d285ffd..1c2d912ad4 100644
--- a/libavfilter/buffersink.c
+++ b/libavfilter/buffersink.c
@@ -107,7 +107,7 @@ int attribute_align_arg av_buffersink_get_samples(AVFilterContext *ctx,
int ret = 0;

if (!s->audio_fifo) {
- int nb_channels = av_get_channel_layout_nb_channels(link->channel_layout);
+ int nb_channels = link->ch_layout.nb_channels;
if (!(s->audio_fifo = av_audio_fifo_alloc(link->format, nb_channels, nb_samples)))
return AVERROR(ENOMEM);
}
diff --git a/libavfilter/buffersrc.c b/libavfilter/buffersrc.c
index df00971514..838e3ac08d 100644
--- a/libavfilter/buffersrc.c
+++ b/libavfilter/buffersrc.c
@@ -58,8 +58,7 @@ typedef struct BufferSourceContext {
int sample_rate;
enum AVSampleFormat sample_fmt;
char *sample_fmt_str;
- uint64_t channel_layout;
- char *channel_layout_str;
+ AVChannelLayout ch_layout;

int got_format_from_params;
int eof;
@@ -71,9 +70,9 @@ typedef struct BufferSourceContext {
return AVERROR(EINVAL);\
}

-#define CHECK_AUDIO_PARAM_CHANGE(s, c, srate, ch_layout, format)\
+#define CHECK_AUDIO_PARAM_CHANGE(s, c, srate, chlayout, format)\
if (c->sample_fmt != format || c->sample_rate != srate ||\
- c->channel_layout != ch_layout) {\
+ av_channel_layout_compare(&c->ch_layout, &chlayout)) {\
av_log(s, AV_LOG_ERROR, "Changing frame properties on the fly is not supported.\n");\
return AVERROR(EINVAL);\
}
@@ -92,6 +91,7 @@ AVBufferSrcParameters *av_buffersrc_parameters_alloc(void)
int av_buffersrc_parameters_set(AVFilterContext *ctx, AVBufferSrcParameters *param)
{
BufferSourceContext *s = ctx->priv;
+ int ret;

if (param->time_base.num > 0 && param->time_base.den > 0)
s->time_base = param->time_base;
@@ -124,8 +124,17 @@ int av_buffersrc_parameters_set(AVFilterContext *ctx, AVBufferSrcParameters *par
}
if (param->sample_rate > 0)
s->sample_rate = param->sample_rate;
- if (param->channel_layout)
- s->channel_layout = param->channel_layout;
+
+ ret = av_channel_layout_copy(&s->ch_layout, &param->ch_layout);
+ if (ret < 0)
+ return ret;
+
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+ if (!av_channel_layout_check(&s->ch_layout))
+ av_channel_layout_from_mask(&s->ch_layout, param->channel_layout);
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
break;
default:
return AVERROR_BUG;
@@ -170,7 +179,7 @@ int attribute_align_arg av_buffersrc_add_frame(AVFilterContext *ctx,
frame->format);
break;
case AVMEDIA_TYPE_AUDIO:
- CHECK_AUDIO_PARAM_CHANGE(ctx, s, frame->sample_rate, frame->channel_layout,
+ CHECK_AUDIO_PARAM_CHANGE(ctx, s, frame->sample_rate, frame->ch_layout,
frame->format);
break;
default:
@@ -261,7 +270,7 @@ static const AVOption audio_options[] = {
{ "time_base", NULL, OFFSET(time_base), AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, INT_MAX, A },
{ "sample_rate", NULL, OFFSET(sample_rate), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, A },
{ "sample_fmt", NULL, OFFSET(sample_fmt_str), AV_OPT_TYPE_STRING, .flags = A },
- { "channel_layout", NULL, OFFSET(channel_layout_str), AV_OPT_TYPE_STRING, .flags = A },
+ { "channel_layout", NULL, OFFSET(ch_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, .flags = A },
{ NULL },
};

@@ -275,6 +284,7 @@ static const AVClass abuffer_class = {
static av_cold int init_audio(AVFilterContext *ctx)
{
BufferSourceContext *s = ctx->priv;
+ char *chlstr;
int ret = 0;

if (!(s->sample_fmt_str || s->got_format_from_params)) {
@@ -290,24 +300,17 @@ static av_cold int init_audio(AVFilterContext *ctx)
return AVERROR(EINVAL);
}

- if (s->channel_layout_str)
- s->channel_layout = av_get_channel_layout(s->channel_layout_str);
-
- if (!s->channel_layout) {
- av_log(ctx, AV_LOG_ERROR, "Invalid channel layout %s.\n",
- s->channel_layout_str);
- return AVERROR(EINVAL);
- }
-
if (!(s->fifo = av_fifo_alloc(sizeof(AVFrame*))))
return AVERROR(ENOMEM);

if (!s->time_base.num)
s->time_base = (AVRational){1, s->sample_rate};

+ chlstr = av_channel_layout_describe(&s->ch_layout);
av_log(ctx, AV_LOG_VERBOSE, "tb:%d/%d samplefmt:%s samplerate: %d "
"ch layout:%s\n", s->time_base.num, s->time_base.den, s->sample_fmt_str,
- s->sample_rate, s->channel_layout_str);
+ s->sample_rate, chlstr);
+ av_free(chlstr);

return ret;
}
@@ -344,7 +347,7 @@ static int query_formats(AVFilterContext *ctx)
ff_add_format(&samplerates, c->sample_rate);
ff_set_common_samplerates(ctx, samplerates);

- ff_add_channel_layout(&channel_layouts, c->channel_layout);
+ ff_add_channel_layout(&channel_layouts, c->ch_layout.u.mask);
ff_set_common_channel_layouts(ctx, channel_layouts);
break;
default:
@@ -357,6 +360,7 @@ static int query_formats(AVFilterContext *ctx)
static int config_props(AVFilterLink *link)
{
BufferSourceContext *c = link->src->priv;
+ int ret;

switch (link->type) {
case AVMEDIA_TYPE_VIDEO:
@@ -371,7 +375,16 @@ static int config_props(AVFilterLink *link)
}
break;
case AVMEDIA_TYPE_AUDIO:
- link->channel_layout = c->channel_layout;
+ ret = av_channel_layout_copy(&link->ch_layout, &c->ch_layout);
+ if (ret < 0)
+ return ret;
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+ if (c->ch_layout.order == AV_CHANNEL_ORDER_NATIVE ||
+ c->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC)
+ link->channel_layout = c->ch_layout.u.mask;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
link->sample_rate = c->sample_rate;
break;
default:
diff --git a/libavfilter/buffersrc.h b/libavfilter/buffersrc.h
index dcea3da79b..ac1631cdff 100644
--- a/libavfilter/buffersrc.h
+++ b/libavfilter/buffersrc.h
@@ -25,6 +25,8 @@
* Memory buffer source API.
*/

+#include "libavutil/channel_layout.h"
+
#include "avfilter.h"

/**
@@ -80,10 +82,18 @@ typedef struct AVBufferSrcParameters {
*/
int sample_rate;

+#if FF_API_OLD_CHANNEL_LAYOUT
/**
- * Audio only, the audio channel layout
+ * @deprecated use ch_layout instead
*/
+ attribute_deprecated
uint64_t channel_layout;
+#endif
+
+ /**
+ * Audio only, the audio channel layout
+ */
+ AVChannelLayout ch_layout;
} AVBufferSrcParameters;

/**
diff --git a/libavfilter/fifo.c b/libavfilter/fifo.c
index a414585ece..85730cccd7 100644
--- a/libavfilter/fifo.c
+++ b/libavfilter/fifo.c
@@ -104,7 +104,7 @@ static void queue_pop(FifoContext *s)
static void buffer_offset(AVFilterLink *link, AVFrame *frame,
int offset)
{
- int nb_channels = av_get_channel_layout_nb_channels(link->channel_layout);
+ int nb_channels = link->ch_layout.nb_channels;
int planar = av_sample_fmt_is_planar(link->format);
int planes = planar ? nb_channels : 1;
int block_align = av_get_bytes_per_sample(link->format) * (planar ? 1 : nb_channels);
@@ -128,8 +128,7 @@ static void buffer_offset(AVFilterLink *link, AVFrame *frame,

static int calc_ptr_alignment(AVFrame *frame)
{
- int planes = av_sample_fmt_is_planar(frame->format) ?
- av_get_channel_layout_nb_channels(frame->channel_layout) : 1;
+ int planes = av_sample_fmt_is_planar(frame->format) ? frame->ch_layout.nb_channels : 1;
int min_align = 128;
int p;

@@ -170,7 +169,7 @@ static int return_audio_frame(AVFilterContext *ctx)
buffer_offset(link, head, link->request_samples);
}
} else {
- int nb_channels = av_get_channel_layout_nb_channels(link->channel_layout);
+ int nb_channels = link->ch_layout.nb_channels;

if (!s->out) {
s->out = ff_get_audio_buffer(link, link->request_samples);
--
2.13.1
Luca Barbato
2017-07-11 09:29:12 UTC
Permalink
Post by Vittorio Giovara
+ ret = av_channel_layout_copy(&s->ch_layout, &param->ch_layout);
Ok assuming this function wipes the destination before copying.

lu
Anton Khirnov
2017-07-22 10:02:59 UTC
Permalink
Quoting Vittorio Giovara (2017-06-29 00:10:51)
Post by Vittorio Giovara
---
libavfilter/audio.c | 17 +++++++++++++--
libavfilter/avfilter.c | 9 ++++----
libavfilter/avfilter.h | 13 ++++++++++-
libavfilter/avfiltergraph.c | 35 +++++++++++++++++++++++-------
libavfilter/buffersink.c | 2 +-
libavfilter/buffersrc.c | 53 ++++++++++++++++++++++++++++-----------------
libavfilter/buffersrc.h | 12 +++++++++-
libavfilter/fifo.c | 7 +++---
8 files changed, 106 insertions(+), 42 deletions(-)
diff --git a/libavfilter/audio.c b/libavfilter/audio.c
index 5fe9da95c3..afd8bdc169 100644
--- a/libavfilter/audio.c
+++ b/libavfilter/audio.c
@@ -31,7 +31,7 @@ AVFrame *ff_null_get_audio_buffer(AVFilterLink *link, int nb_samples)
AVFrame *ff_default_get_audio_buffer(AVFilterLink *link, int nb_samples)
{
AVFrame *frame = av_frame_alloc();
- int channels = av_get_channel_layout_nb_channels(link->channel_layout);
+ int channels = link->ch_layout.nb_channels;
int ret;
if (!frame)
@@ -39,7 +39,20 @@ AVFrame *ff_default_get_audio_buffer(AVFilterLink *link, int nb_samples)
frame->nb_samples = nb_samples;
frame->format = link->format;
- frame->channel_layout = link->channel_layout;
+
+ ret = av_channel_layout_copy(&frame->ch_layout, &link->ch_layout);
+ if (ret < 0) {
+ av_frame_free(&frame);
+ return NULL;
+ }
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+ if (link->ch_layout.order == AV_CHANNEL_ORDER_NATIVE ||
+ link->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC)
+ frame->channel_layout = link->channel_layout;
This is incomplete, the channel layout should always be set, at least to
(1<<count) - 1.
Post by Vittorio Giovara
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+
frame->sample_rate = link->sample_rate;
ret = av_frame_get_buffer(frame, 0);
if (ret < 0) {
diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c
index 83c1a7c20d..f2adefff3d 100644
--- a/libavfilter/avfilter.c
+++ b/libavfilter/avfilter.c
@@ -247,16 +247,15 @@ void ff_dlog_link(void *ctx, AVFilterLink *link, int end)
link->dst ? link->dst->filter->name : "",
end ? "\n" : "");
} else {
- char buf[128];
- av_get_channel_layout_string(buf, sizeof(buf), -1, link->channel_layout);
-
+ char *chlstr = av_channel_layout_describe(&link->ch_layout);
av_log(ctx, AV_LOG_TRACE,
"link[%p r:%d cl:%s fmt:%-16s %-16s->%-16s]%s",
- link, link->sample_rate, buf,
+ link, link->sample_rate, chlstr,
av_get_sample_fmt_name(link->format),
link->src ? link->src->filter->name : "",
link->dst ? link->dst->filter->name : "",
end ? "\n" : "");
+ av_free(chlstr);
}
}
@@ -683,7 +682,7 @@ int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
av_samples_copy(out->extended_data, frame->extended_data,
0, 0, frame->nb_samples,
- av_get_channel_layout_nb_channels(frame->channel_layout),
+ frame->ch_layout.nb_channels,
frame->format);
break;
diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h
index 6df69dbbbf..5d5edf0ed3 100644
--- a/libavfilter/avfilter.h
+++ b/libavfilter/avfilter.h
@@ -36,6 +36,7 @@
#include "libavutil/attributes.h"
#include "libavutil/avutil.h"
#include "libavutil/buffer.h"
+#include "libavutil/channel_layout.h"
#include "libavutil/frame.h"
#include "libavutil/log.h"
#include "libavutil/samplefmt.h"
@@ -334,7 +335,12 @@ struct AVFilterLink {
int h; ///< agreed upon image height
AVRational sample_aspect_ratio; ///< agreed upon sample aspect ratio
/* These two parameters apply only to audio */
- uint64_t channel_layout; ///< channel layout of current buffer (see libavutil/channel_layout.h)
+#if FF_API_OLD_CHANNEL_LAYOUT
+ /**
+ */
+ attribute_deprecated uint64_t channel_layout;
+#endif
int sample_rate; ///< samples per second
int format; ///< agreed upon media format
@@ -405,6 +411,11 @@ struct AVFilterLink {
* AVHWFramesContext describing the frames.
*/
AVBufferRef *hw_frames_ctx;
+
+ /**
+ * Channel layout of current buffer.
What 'current buffer' is this talking about?
Post by Vittorio Giovara
+ */
+ AVChannelLayout ch_layout;
};
/**
diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c
index a0f797e283..c72016d2c8 100644
--- a/libavfilter/avfiltergraph.c
+++ b/libavfilter/avfiltergraph.c
@@ -397,7 +397,13 @@ static int pick_format(AVFilterLink *link)
return AVERROR(EINVAL);
}
link->in_channel_layouts->nb_channel_layouts = 1;
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
link->channel_layout = link->in_channel_layouts->channel_layouts[0];
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+ av_channel_layout_from_mask(&link->ch_layout,
+ link->in_channel_layouts->channel_layouts[0]);
}
ff_formats_unref(&link->in_formats);
@@ -578,23 +584,33 @@ static void swap_channel_layouts_on_filter(AVFilterContext *filter)
for (j = 0; j < outlink->in_channel_layouts->nb_channel_layouts; j++) {
uint64_t in_chlayout = link->out_channel_layouts->channel_layouts[0];
uint64_t out_chlayout = outlink->in_channel_layouts->channel_layouts[j];
- int in_channels = av_get_channel_layout_nb_channels(in_chlayout);
- int out_channels = av_get_channel_layout_nb_channels(out_chlayout);
- int count_diff = out_channels - in_channels;
+ int in_channels;
+ int out_channels;
+ int count_diff;
int matched_channels, extra_channels;
int score = 0;
+ AVChannelLayout in_ch_layout = {0};
+ AVChannelLayout out_ch_layout = {0};
+
+ av_channel_layout_from_mask( &in_ch_layout, in_chlayout);
+ av_channel_layout_from_mask(&out_ch_layout, out_chlayout);
+ in_channels = in_ch_layout.nb_channels;
+ out_channels = out_ch_layout.nb_channels;
+ count_diff = out_channels - in_channels;
/* channel substitution */
for (k = 0; k < FF_ARRAY_ELEMS(ch_subst); k++) {
uint64_t cmp0 = ch_subst[k][0];
uint64_t cmp1 = ch_subst[k][1];
+ AVChannelLayout tmp = {0};
if (( in_chlayout & cmp0) && (!(out_chlayout & cmp0)) &&
(out_chlayout & cmp1) && (!( in_chlayout & cmp1))) {
in_chlayout &= ~cmp0;
out_chlayout &= ~cmp1;
/* add score for channel match, minus a deduction for
having to do the substitution */
- score += 10 * av_get_channel_layout_nb_channels(cmp1) - 2;
+ av_channel_layout_from_mask(&tmp, cmp1);
+ score += 10 * tmp.nb_channels - 2;
}
}
@@ -605,10 +621,13 @@ static void swap_channel_layouts_on_filter(AVFilterContext *filter)
in_chlayout &= ~AV_CH_LOW_FREQUENCY;
out_chlayout &= ~AV_CH_LOW_FREQUENCY;
- matched_channels = av_get_channel_layout_nb_channels(in_chlayout &
- out_chlayout);
- extra_channels = av_get_channel_layout_nb_channels(out_chlayout &
- (~in_chlayout));
+ av_channel_layout_uninit( &in_ch_layout);
+ av_channel_layout_uninit(&out_ch_layout);
+ av_channel_layout_from_mask( &in_ch_layout, in_chlayout & out_chlayout);
+ av_channel_layout_from_mask(&out_ch_layout, out_chlayout & (~in_chlayout));
+
+ matched_channels = in_ch_layout.nb_channels;
+ extra_channels = out_ch_layout.nb_channels;
score += 10 * matched_channels - 5 * extra_channels;
if (score > best_score ||
diff --git a/libavfilter/buffersink.c b/libavfilter/buffersink.c
index 3b4d285ffd..1c2d912ad4 100644
--- a/libavfilter/buffersink.c
+++ b/libavfilter/buffersink.c
@@ -107,7 +107,7 @@ int attribute_align_arg av_buffersink_get_samples(AVFilterContext *ctx,
int ret = 0;
if (!s->audio_fifo) {
- int nb_channels = av_get_channel_layout_nb_channels(link->channel_layout);
+ int nb_channels = link->ch_layout.nb_channels;
if (!(s->audio_fifo = av_audio_fifo_alloc(link->format, nb_channels, nb_samples)))
return AVERROR(ENOMEM);
}
diff --git a/libavfilter/buffersrc.c b/libavfilter/buffersrc.c
index df00971514..838e3ac08d 100644
--- a/libavfilter/buffersrc.c
+++ b/libavfilter/buffersrc.c
@@ -58,8 +58,7 @@ typedef struct BufferSourceContext {
int sample_rate;
enum AVSampleFormat sample_fmt;
char *sample_fmt_str;
- uint64_t channel_layout;
- char *channel_layout_str;
+ AVChannelLayout ch_layout;
int got_format_from_params;
int eof;
@@ -71,9 +70,9 @@ typedef struct BufferSourceContext {
return AVERROR(EINVAL);\
}
-#define CHECK_AUDIO_PARAM_CHANGE(s, c, srate, ch_layout, format)\
+#define CHECK_AUDIO_PARAM_CHANGE(s, c, srate, chlayout, format)\
if (c->sample_fmt != format || c->sample_rate != srate ||\
- c->channel_layout != ch_layout) {\
+ av_channel_layout_compare(&c->ch_layout, &chlayout)) {\
av_log(s, AV_LOG_ERROR, "Changing frame properties on the fly is not supported.\n");\
return AVERROR(EINVAL);\
}
@@ -92,6 +91,7 @@ AVBufferSrcParameters *av_buffersrc_parameters_alloc(void)
int av_buffersrc_parameters_set(AVFilterContext *ctx, AVBufferSrcParameters *param)
{
BufferSourceContext *s = ctx->priv;
+ int ret;
if (param->time_base.num > 0 && param->time_base.den > 0)
s->time_base = param->time_base;
@@ -124,8 +124,17 @@ int av_buffersrc_parameters_set(AVFilterContext *ctx, AVBufferSrcParameters *par
}
if (param->sample_rate > 0)
s->sample_rate = param->sample_rate;
- if (param->channel_layout)
- s->channel_layout = param->channel_layout;
+
+ ret = av_channel_layout_copy(&s->ch_layout, &param->ch_layout);
+ if (ret < 0)
+ return ret;
+
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+ if (!av_channel_layout_check(&s->ch_layout))
+ av_channel_layout_from_mask(&s->ch_layout, param->channel_layout);
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
I think it would be more consistent to always prefer the deprecated
channel_layout if it is set.
Post by Vittorio Giovara
break;
return AVERROR_BUG;
@@ -170,7 +179,7 @@ int attribute_align_arg av_buffersrc_add_frame(AVFilterContext *ctx,
frame->format);
break;
- CHECK_AUDIO_PARAM_CHANGE(ctx, s, frame->sample_rate, frame->channel_layout,
+ CHECK_AUDIO_PARAM_CHANGE(ctx, s, frame->sample_rate, frame->ch_layout,
frame->format);
break;
@@ -261,7 +270,7 @@ static const AVOption audio_options[] = {
{ "time_base", NULL, OFFSET(time_base), AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, INT_MAX, A },
{ "sample_rate", NULL, OFFSET(sample_rate), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, A },
{ "sample_fmt", NULL, OFFSET(sample_fmt_str), AV_OPT_TYPE_STRING, .flags = A },
- { "channel_layout", NULL, OFFSET(channel_layout_str), AV_OPT_TYPE_STRING, .flags = A },
+ { "channel_layout", NULL, OFFSET(ch_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, .flags = A },
{ NULL },
};
@@ -275,6 +284,7 @@ static const AVClass abuffer_class = {
static av_cold int init_audio(AVFilterContext *ctx)
{
BufferSourceContext *s = ctx->priv;
+ char *chlstr;
int ret = 0;
if (!(s->sample_fmt_str || s->got_format_from_params)) {
@@ -290,24 +300,17 @@ static av_cold int init_audio(AVFilterContext *ctx)
return AVERROR(EINVAL);
}
- if (s->channel_layout_str)
- s->channel_layout = av_get_channel_layout(s->channel_layout_str);
-
- if (!s->channel_layout) {
- av_log(ctx, AV_LOG_ERROR, "Invalid channel layout %s.\n",
- s->channel_layout_str);
- return AVERROR(EINVAL);
- }
-
if (!(s->fifo = av_fifo_alloc(sizeof(AVFrame*))))
return AVERROR(ENOMEM);
if (!s->time_base.num)
s->time_base = (AVRational){1, s->sample_rate};
+ chlstr = av_channel_layout_describe(&s->ch_layout);
av_log(ctx, AV_LOG_VERBOSE, "tb:%d/%d samplefmt:%s samplerate: %d "
"ch layout:%s\n", s->time_base.num, s->time_base.den, s->sample_fmt_str,
- s->sample_rate, s->channel_layout_str);
+ s->sample_rate, chlstr);
+ av_free(chlstr);
return ret;
}
@@ -344,7 +347,7 @@ static int query_formats(AVFilterContext *ctx)
ff_add_format(&samplerates, c->sample_rate);
ff_set_common_samplerates(ctx, samplerates);
- ff_add_channel_layout(&channel_layouts, c->channel_layout);
+ ff_add_channel_layout(&channel_layouts, c->ch_layout.u.mask);
ff_set_common_channel_layouts(ctx, channel_layouts);
break;
@@ -357,6 +360,7 @@ static int query_formats(AVFilterContext *ctx)
static int config_props(AVFilterLink *link)
{
BufferSourceContext *c = link->src->priv;
+ int ret;
switch (link->type) {
@@ -371,7 +375,16 @@ static int config_props(AVFilterLink *link)
}
break;
- link->channel_layout = c->channel_layout;
+ ret = av_channel_layout_copy(&link->ch_layout, &c->ch_layout);
+ if (ret < 0)
+ return ret;
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+ if (c->ch_layout.order == AV_CHANNEL_ORDER_NATIVE ||
+ c->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC)
+ link->channel_layout = c->ch_layout.u.mask;
Same as above.
--
Anton Khirnov
Vittorio Giovara
2018-01-19 22:31:37 UTC
Permalink
Post by Anton Khirnov
Quoting Vittorio Giovara (2017-06-29 00:10:51)
Post by Vittorio Giovara
---
libavfilter/audio.c | 17 +++++++++++++--
libavfilter/avfilter.c | 9 ++++----
libavfilter/avfilter.h | 13 ++++++++++-
libavfilter/avfiltergraph.c | 35 +++++++++++++++++++++++-------
libavfilter/buffersink.c | 2 +-
libavfilter/buffersrc.c | 53 ++++++++++++++++++++++++++++--
---------------
Post by Vittorio Giovara
libavfilter/buffersrc.h | 12 +++++++++-
libavfilter/fifo.c | 7 +++---
8 files changed, 106 insertions(+), 42 deletions(-)
diff --git a/libavfilter/audio.c b/libavfilter/audio.c
index 5fe9da95c3..afd8bdc169 100644
--- a/libavfilter/audio.c
+++ b/libavfilter/audio.c
@@ -31,7 +31,7 @@ AVFrame *ff_null_get_audio_buffer(AVFilterLink *link,
int nb_samples)
Post by Vittorio Giovara
AVFrame *ff_default_get_audio_buffer(AVFilterLink *link, int
nb_samples)
Post by Vittorio Giovara
{
AVFrame *frame = av_frame_alloc();
- int channels = av_get_channel_layout_nb_
channels(link->channel_layout);
Post by Vittorio Giovara
+ int channels = link->ch_layout.nb_channels;
int ret;
if (!frame)
@@ -39,7 +39,20 @@ AVFrame *ff_default_get_audio_buffer(AVFilterLink
*link, int nb_samples)
Post by Vittorio Giovara
frame->nb_samples = nb_samples;
frame->format = link->format;
- frame->channel_layout = link->channel_layout;
+
+ ret = av_channel_layout_copy(&frame->ch_layout, &link->ch_layout);
+ if (ret < 0) {
+ av_frame_free(&frame);
+ return NULL;
+ }
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+ if (link->ch_layout.order == AV_CHANNEL_ORDER_NATIVE ||
+ link->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC)
+ frame->channel_layout = link->channel_layout;
This is incomplete, the channel layout should always be set, at least to
(1<<count) - 1.
Right, I added this else as you suggested.

else
frame->channel_layout = (1 << channels) - 1;
Post by Anton Khirnov
Post by Vittorio Giovara
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+
frame->sample_rate = link->sample_rate;
ret = av_frame_get_buffer(frame, 0);
if (ret < 0) {
diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c
index 83c1a7c20d..f2adefff3d 100644
--- a/libavfilter/avfilter.c
+++ b/libavfilter/avfilter.c
@@ -247,16 +247,15 @@ void ff_dlog_link(void *ctx, AVFilterLink *link,
int end)
Post by Vittorio Giovara
link->dst ? link->dst->filter->name : "",
end ? "\n" : "");
} else {
- char buf[128];
- av_get_channel_layout_string(buf, sizeof(buf), -1,
link->channel_layout);
Post by Vittorio Giovara
-
+ char *chlstr = av_channel_layout_describe(&link->ch_layout);
av_log(ctx, AV_LOG_TRACE,
"link[%p r:%d cl:%s fmt:%-16s %-16s->%-16s]%s",
- link, link->sample_rate, buf,
+ link, link->sample_rate, chlstr,
av_get_sample_fmt_name(link->format),
link->src ? link->src->filter->name : "",
link->dst ? link->dst->filter->name : "",
end ? "\n" : "");
+ av_free(chlstr);
}
}
@@ -683,7 +682,7 @@ int ff_filter_frame(AVFilterLink *link, AVFrame
*frame)
Post by Vittorio Giovara
av_samples_copy(out->extended_data, frame->extended_data,
0, 0, frame->nb_samples,
- av_get_channel_layout_nb_
channels(frame->channel_layout),
Post by Vittorio Giovara
+ frame->ch_layout.nb_channels,
frame->format);
break;
diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h
index 6df69dbbbf..5d5edf0ed3 100644
--- a/libavfilter/avfilter.h
+++ b/libavfilter/avfilter.h
@@ -36,6 +36,7 @@
#include "libavutil/attributes.h"
#include "libavutil/avutil.h"
#include "libavutil/buffer.h"
+#include "libavutil/channel_layout.h"
#include "libavutil/frame.h"
#include "libavutil/log.h"
#include "libavutil/samplefmt.h"
@@ -334,7 +335,12 @@ struct AVFilterLink {
int h; ///< agreed upon image height
AVRational sample_aspect_ratio; ///< agreed upon sample aspect ratio
/* These two parameters apply only to audio */
- uint64_t channel_layout; ///< channel layout of current buffer
(see libavutil/channel_layout.h)
Post by Vittorio Giovara
+#if FF_API_OLD_CHANNEL_LAYOUT
+ /**
+ */
+ attribute_deprecated uint64_t channel_layout;
+#endif
int sample_rate; ///< samples per second
int format; ///< agreed upon media format
@@ -405,6 +411,11 @@ struct AVFilterLink {
* AVHWFramesContext describing the frames.
*/
AVBufferRef *hw_frames_ctx;
+
+ /**
+ * Channel layout of current buffer.
What 'current buffer' is this talking about?
I mostly moved the existing documentation, I believe this refers to the
avframe buffer that is being passed through the link.
BTW, I noticed that this field is in the wrong section of AVFilterLink,
I'll move it above after time_base.
Post by Anton Khirnov
Post by Vittorio Giovara
+ */
+ AVChannelLayout ch_layout;
};
/**
diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c
index a0f797e283..c72016d2c8 100644
--- a/libavfilter/avfiltergraph.c
+++ b/libavfilter/avfiltergraph.c
[...]
Post by Anton Khirnov
Post by Vittorio Giovara
@@ -124,8 +124,17 @@ int av_buffersrc_parameters_set(AVFilterContext
*ctx, AVBufferSrcParameters *par
Post by Vittorio Giovara
}
if (param->sample_rate > 0)
s->sample_rate = param->sample_rate;
- if (param->channel_layout)
- s->channel_layout = param->channel_layout;
+
+ ret = av_channel_layout_copy(&s->ch_layout, &param->ch_layout);
+ if (ret < 0)
+ return ret;
+
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+ if (!av_channel_layout_check(&s->ch_layout))
+ av_channel_layout_from_mask(&s->ch_layout,
param->channel_layout);
Post by Vittorio Giovara
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
I think it would be more consistent to always prefer the deprecated
channel_layout if it is set.
Post by Vittorio Giovara
break;
return AVERROR_BUG;
[...]
Post by Anton Khirnov
Post by Vittorio Giovara
@@ -371,7 +375,16 @@ static int config_props(AVFilterLink *link)
}
break;
- link->channel_layout = c->channel_layout;
+ ret = av_channel_layout_copy(&link->ch_layout, &c->ch_layout);
+ if (ret < 0)
+ return ret;
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+ if (c->ch_layout.order == AV_CHANNEL_ORDER_NATIVE ||
+ c->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC)
+ link->channel_layout = c->ch_layout.u.mask;
Same as above
And leave it unset if the old channel_layout is unset? Won't that affect
the transition period for any lavfi API caller?
I also dropped the old channel_layout in BufferSourceContext so that I
could only validate one field only.
Unless I'm misunderstanding your suggestion, I'd rather move everything to
the new API and guarantee compatibility deriving from it, instead of
lingering on the old one.
--
Vittorio
Vittorio Giovara
2017-06-28 22:10:50 UTC
Permalink
From: Anton Khirnov <***@khirnov.net>

Signed-off-by: Vittorio Giovara <***@gmail.com>
---
libavresample/audio_mix.c | 148 ++++++------
libavresample/audio_mix_matrix.c | 477 ++++++++++++++++++++++-----------------
libavresample/avresample.h | 42 +++-
libavresample/internal.h | 10 +-
libavresample/options.c | 8 +
libavresample/tests/avresample.c | 26 +--
libavresample/utils.c | 127 +++++++----
7 files changed, 504 insertions(+), 334 deletions(-)

diff --git a/libavresample/audio_mix.c b/libavresample/audio_mix.c
index 89ecc6ba71..36dff2b979 100644
--- a/libavresample/audio_mix.c
+++ b/libavresample/audio_mix.c
@@ -20,6 +20,7 @@

#include <stdint.h>

+#include "libavutil/channel_layout.h"
#include "libavutil/common.h"
#include "libavutil/libm.h"
#include "libavutil/samplefmt.h"
@@ -34,10 +35,8 @@ struct AudioMix {
AVAudioResampleContext *avr;
enum AVSampleFormat fmt;
enum AVMixCoeffType coeff_type;
- uint64_t in_layout;
- uint64_t out_layout;
- int in_channels;
- int out_channels;
+ AVChannelLayout in_layout;
+ AVChannelLayout out_layout;

int ptr_align;
int samples_align;
@@ -331,8 +330,8 @@ static av_cold int mix_function_init(AudioMix *am)
if (!am->mix) {
av_log(am->avr, AV_LOG_ERROR, "audio_mix: NO FUNCTION FOUND: [fmt=%s] "
"[c=%s] [%d to %d]\n", av_get_sample_fmt_name(am->fmt),
- coeff_type_names[am->coeff_type], am->in_channels,
- am->out_channels);
+ coeff_type_names[am->coeff_type], am->in_layout.nb_channels,
+ am->out_layout.nb_channels);
return AVERROR_PATCHWELCOME;
}
return 0;
@@ -358,38 +357,42 @@ AudioMix *ff_audio_mix_alloc(AVAudioResampleContext *avr)

am->fmt = avr->internal_sample_fmt;
am->coeff_type = avr->mix_coeff_type;
- am->in_layout = avr->in_channel_layout;
- am->out_layout = avr->out_channel_layout;
- am->in_channels = avr->in_channels;
- am->out_channels = avr->out_channels;
+
+ ret = av_channel_layout_copy(&am->in_layout, &avr->in_ch_layout);
+ if (ret < 0)
+ goto error;
+ ret = av_channel_layout_copy(&am->out_layout, &avr->out_ch_layout);
+ if (ret < 0)
+ goto error;

/* build matrix if the user did not already set one */
if (avr->mix_matrix) {
- ret = ff_audio_mix_set_matrix(am, avr->mix_matrix, avr->in_channels);
+ ret = ff_audio_mix_set_matrix(am, avr->mix_matrix, avr->in_ch_layout.nb_channels);
if (ret < 0)
goto error;
av_freep(&avr->mix_matrix);
} else {
- double *matrix_dbl = av_mallocz(avr->out_channels * avr->in_channels *
+ double *matrix_dbl = av_mallocz(avr->out_ch_layout.nb_channels *
+ avr->in_ch_layout.nb_channels *
sizeof(*matrix_dbl));
if (!matrix_dbl)
goto error;

- ret = avresample_build_matrix(avr->in_channel_layout,
- avr->out_channel_layout,
- avr->center_mix_level,
- avr->surround_mix_level,
- avr->lfe_mix_level,
- avr->normalize_mix_level,
- matrix_dbl,
- avr->in_channels,
- avr->matrix_encoding);
+ ret = avresample_build_matrix2(&avr->in_ch_layout,
+ &avr->out_ch_layout,
+ avr->center_mix_level,
+ avr->surround_mix_level,
+ avr->lfe_mix_level,
+ avr->normalize_mix_level,
+ matrix_dbl,
+ avr->in_ch_layout.nb_channels,
+ avr->matrix_encoding);
if (ret < 0) {
av_free(matrix_dbl);
goto error;
}

- ret = ff_audio_mix_set_matrix(am, matrix_dbl, avr->in_channels);
+ ret = ff_audio_mix_set_matrix(am, matrix_dbl, avr->in_ch_layout.nb_channels);
if (ret < 0) {
av_log(avr, AV_LOG_ERROR, "error setting mix matrix\n");
av_free(matrix_dbl);
@@ -402,7 +405,7 @@ AudioMix *ff_audio_mix_alloc(AVAudioResampleContext *avr)
return am;

error:
- av_free(am);
+ ff_audio_mix_free(&am);
return NULL;
}

@@ -422,11 +425,16 @@ void ff_audio_mix_free(AudioMix **am_p)
memset(am->matrix_q15, 0, sizeof(am->matrix_q15));
memset(am->matrix_flt, 0, sizeof(am->matrix_flt));

+ av_channel_layout_uninit(&am->in_layout);
+ av_channel_layout_uninit(&am->out_layout);
+
av_freep(am_p);
}

int ff_audio_mix(AudioMix *am, AudioData *src)
{
+ int in_channels = am->in_layout.nb_channels;
+ int out_channels = am->out_layout.nb_channels;
int use_generic = 1;
int len = src->nb_samples;
int i, j;
@@ -442,16 +450,16 @@ int ff_audio_mix(AudioMix *am, AudioData *src)
}
}
av_log(am->avr, AV_LOG_TRACE, "audio_mix: %d samples - %d to %d channels (%s)\n",
- src->nb_samples, am->in_channels, am->out_channels,
+ src->nb_samples, in_channels, out_channels,
use_generic ? am->func_descr_generic : am->func_descr);

if (am->in_matrix_channels && am->out_matrix_channels) {
uint8_t **data;
uint8_t *data0[AVRESAMPLE_MAX_CHANNELS] = { NULL };

- if (am->out_matrix_channels < am->out_channels ||
- am->in_matrix_channels < am->in_channels) {
- for (i = 0, j = 0; i < FFMAX(am->in_channels, am->out_channels); i++) {
+ if (am->out_matrix_channels < out_channels ||
+ am->in_matrix_channels < in_channels) {
+ for (i = 0, j = 0; i < FFMAX(in_channels, out_channels); i++) {
if (am->input_skip[i] || am->output_skip[i] || am->output_zero[i])
continue;
data0[j++] = src->data[i];
@@ -469,23 +477,25 @@ int ff_audio_mix(AudioMix *am, AudioData *src)
am->in_matrix_channels);
}

- if (am->out_matrix_channels < am->out_channels) {
- for (i = 0; i < am->out_channels; i++)
+ if (am->out_matrix_channels < out_channels) {
+ for (i = 0; i < out_channels; i++)
if (am->output_zero[i])
av_samples_set_silence(&src->data[i], 0, len, 1, am->fmt);
}

- ff_audio_data_set_channels(src, am->out_channels);
+ ff_audio_data_set_channels(src, out_channels);

return 0;
}

int ff_audio_mix_get_matrix(AudioMix *am, double *matrix, int stride)
{
+ int in_channels = am->in_layout.nb_channels;
+ int out_channels = am->out_layout.nb_channels;
int i, o, i0, o0;

- if ( am->in_channels <= 0 || am->in_channels > AVRESAMPLE_MAX_CHANNELS ||
- am->out_channels <= 0 || am->out_channels > AVRESAMPLE_MAX_CHANNELS) {
+ if (in_channels <= 0 || in_channels > AVRESAMPLE_MAX_CHANNELS ||
+ out_channels <= 0 || out_channels > AVRESAMPLE_MAX_CHANNELS) {
av_log(am->avr, AV_LOG_ERROR, "Invalid channel counts\n");
return AVERROR(EINVAL);
}
@@ -495,8 +505,8 @@ int ff_audio_mix_get_matrix(AudioMix *am, double *matrix, int stride)
av_log(am->avr, AV_LOG_ERROR, "matrix is not set\n"); \
return AVERROR(EINVAL); \
} \
- for (o = 0, o0 = 0; o < am->out_channels; o++) { \
- for (i = 0, i0 = 0; i < am->in_channels; i++) { \
+ for (o = 0, o0 = 0; o < out_channels; o++) { \
+ for (i = 0, i0 = 0; i < in_channels; i++) { \
if (am->input_skip[i] || am->output_zero[o]) \
matrix[o * stride + i] = 0.0; \
else \
@@ -529,6 +539,8 @@ int ff_audio_mix_get_matrix(AudioMix *am, double *matrix, int stride)

static void reduce_matrix(AudioMix *am, const double *matrix, int stride)
{
+ int in_channels = am->in_layout.nb_channels;
+ int out_channels = am->out_layout.nb_channels;
int i, o;

memset(am->output_zero, 0, sizeof(am->output_zero));
@@ -536,11 +548,11 @@ static void reduce_matrix(AudioMix *am, const double *matrix, int stride)
memset(am->output_skip, 0, sizeof(am->output_skip));

/* exclude output channels if they can be zeroed instead of mixed */
- for (o = 0; o < am->out_channels; o++) {
+ for (o = 0; o < out_channels; o++) {
int zero = 1;

/* check if the output is always silent */
- for (i = 0; i < am->in_channels; i++) {
+ for (i = 0; i < in_channels; i++) {
if (matrix[o * stride + i] != 0.0) {
zero = 0;
break;
@@ -548,8 +560,8 @@ static void reduce_matrix(AudioMix *am, const double *matrix, int stride)
}
/* check if the corresponding input channel makes a contribution to
any output channel */
- if (o < am->in_channels) {
- for (i = 0; i < am->out_channels; i++) {
+ if (o < in_channels) {
+ for (i = 0; i < out_channels; i++) {
if (matrix[i * stride + o] != 0.0) {
zero = 0;
break;
@@ -559,7 +571,7 @@ static void reduce_matrix(AudioMix *am, const double *matrix, int stride)
if (zero) {
am->output_zero[o] = 1;
am->out_matrix_channels--;
- if (o < am->in_channels)
+ if (o < in_channels)
am->in_matrix_channels--;
}
}
@@ -571,10 +583,10 @@ static void reduce_matrix(AudioMix *am, const double *matrix, int stride)

/* skip input channels that contribute fully only to the corresponding
output channel */
- for (i = 0; i < FFMIN(am->in_channels, am->out_channels); i++) {
+ for (i = 0; i < FFMIN(in_channels, out_channels); i++) {
int skip = 1;

- for (o = 0; o < am->out_channels; o++) {
+ for (o = 0; o < out_channels; o++) {
int i0;
if ((o != i && matrix[o * stride + i] != 0.0) ||
(o == i && matrix[o * stride + i] != 1.0)) {
@@ -584,7 +596,7 @@ static void reduce_matrix(AudioMix *am, const double *matrix, int stride)
/* if the input contributes fully to the output, also check that no
other inputs contribute to this output */
if (o == i) {
- for (i0 = 0; i0 < am->in_channels; i0++) {
+ for (i0 = 0; i0 < in_channels; i0++) {
if (i0 != i && matrix[o * stride + i0] != 0.0) {
skip = 0;
break;
@@ -598,10 +610,10 @@ static void reduce_matrix(AudioMix *am, const double *matrix, int stride)
}
}
/* skip input channels that do not contribute to any output channel */
- for (; i < am->in_channels; i++) {
+ for (; i < in_channels; i++) {
int contrib = 0;

- for (o = 0; o < am->out_channels; o++) {
+ for (o = 0; o < out_channels; o++) {
if (matrix[o * stride + i] != 0.0) {
contrib = 1;
break;
@@ -619,11 +631,11 @@ static void reduce_matrix(AudioMix *am, const double *matrix, int stride)

/* skip output channels that only get full contribution from the
corresponding input channel */
- for (o = 0; o < FFMIN(am->in_channels, am->out_channels); o++) {
+ for (o = 0; o < FFMIN(in_channels, out_channels); o++) {
int skip = 1;
int o0;

- for (i = 0; i < am->in_channels; i++) {
+ for (i = 0; i < in_channels; i++) {
if ((o != i && matrix[o * stride + i] != 0.0) ||
(o == i && matrix[o * stride + i] != 1.0)) {
skip = 0;
@@ -633,7 +645,7 @@ static void reduce_matrix(AudioMix *am, const double *matrix, int stride)
/* check if the corresponding input channel makes a contribution to
any other output channel */
i = o;
- for (o0 = 0; o0 < am->out_channels; o0++) {
+ for (o0 = 0; o0 < out_channels; o0++) {
if (o0 != i && matrix[o0 * stride + i] != 0.0) {
skip = 0;
break;
@@ -653,11 +665,15 @@ static void reduce_matrix(AudioMix *am, const double *matrix, int stride)
int ff_audio_mix_set_matrix(AudioMix *am, const double *matrix, int stride)
{
int i, o, i0, o0, ret;
- char in_layout_name[128];
- char out_layout_name[128];
-
- if ( am->in_channels <= 0 || am->in_channels > AVRESAMPLE_MAX_CHANNELS ||
- am->out_channels <= 0 || am->out_channels > AVRESAMPLE_MAX_CHANNELS) {
+ int in_channels = am->in_layout.nb_channels;
+ int out_channels = am->out_layout.nb_channels;
+ char *in_layout_name;
+ char *out_layout_name;
+
+ if (!av_channel_layout_check(&am->in_layout) ||
+ !av_channel_layout_check(&am->out_layout) ||
+ am->in_layout.nb_channels > AVRESAMPLE_MAX_CHANNELS ||
+ am->out_layout.nb_channels > AVRESAMPLE_MAX_CHANNELS) {
av_log(am->avr, AV_LOG_ERROR, "Invalid channel counts\n");
return AVERROR(EINVAL);
}
@@ -667,8 +683,8 @@ int ff_audio_mix_set_matrix(AudioMix *am, const double *matrix, int stride)
am->matrix = NULL;
}

- am->in_matrix_channels = am->in_channels;
- am->out_matrix_channels = am->out_channels;
+ am->in_matrix_channels = am->in_layout.nb_channels;
+ am->out_matrix_channels = am->out_layout.nb_channels;

reduce_matrix(am, matrix, stride);

@@ -678,13 +694,13 @@ int ff_audio_mix_set_matrix(AudioMix *am, const double *matrix, int stride)
sizeof(*am->matrix_## type[0])); \
if (!am->matrix_## type[0]) \
return AVERROR(ENOMEM); \
- for (o = 0, o0 = 0; o < am->out_channels; o++) { \
+ for (o = 0, o0 = 0; o < out_channels; o++) { \
if (am->output_zero[o] || am->output_skip[o]) \
continue; \
if (o0 > 0) \
am->matrix_## type[o0] = am->matrix_## type[o0 - 1] + \
am->in_matrix_channels; \
- for (i = 0, i0 = 0; i < am->in_channels; i++) { \
+ for (i = 0, i0 = 0; i < in_channels; i++) { \
double v; \
if (am->input_skip[i] || am->output_zero[i]) \
continue; \
@@ -717,26 +733,28 @@ int ff_audio_mix_set_matrix(AudioMix *am, const double *matrix, int stride)
if (ret < 0)
return ret;

- av_get_channel_layout_string(in_layout_name, sizeof(in_layout_name),
- am->in_channels, am->in_layout);
- av_get_channel_layout_string(out_layout_name, sizeof(out_layout_name),
- am->out_channels, am->out_layout);
- av_log(am->avr, AV_LOG_DEBUG, "audio_mix: %s to %s\n",
- in_layout_name, out_layout_name);
+ in_layout_name = av_channel_layout_describe(&am->in_layout);
+ out_layout_name = av_channel_layout_describe(&am->out_layout);
+ if (in_layout_name && out_layout_name)
+ av_log(am->avr, AV_LOG_DEBUG, "audio_mix: %s to %s\n",
+ in_layout_name, out_layout_name);
av_log(am->avr, AV_LOG_DEBUG, "matrix size: %d x %d\n",
am->in_matrix_channels, am->out_matrix_channels);
- for (o = 0; o < am->out_channels; o++) {
- for (i = 0; i < am->in_channels; i++) {
+ for (o = 0; o < out_channels; o++) {
+ for (i = 0; i < in_channels; i++) {
if (am->output_zero[o])
av_log(am->avr, AV_LOG_DEBUG, " (ZERO)");
else if (am->input_skip[i] || am->output_zero[i] || am->output_skip[o])
av_log(am->avr, AV_LOG_DEBUG, " (SKIP)");
else
av_log(am->avr, AV_LOG_DEBUG, " %0.3f ",
- matrix[o * am->in_channels + i]);
+ matrix[o * in_channels + i]);
}
av_log(am->avr, AV_LOG_DEBUG, "\n");
}

+ av_freep(&in_layout_name);
+ av_freep(&out_layout_name);
+
return 0;
}
diff --git a/libavresample/audio_mix_matrix.c b/libavresample/audio_mix_matrix.c
index 5182ae1bf9..a5a16edca1 100644
--- a/libavresample/audio_mix_matrix.c
+++ b/libavresample/audio_mix_matrix.c
@@ -21,6 +21,7 @@

#include <stdint.h>

+#include "libavutil/channel_layout.h"
#include "libavutil/common.h"
#include "libavutil/libm.h"
#include "libavutil/samplefmt.h"
@@ -29,33 +30,6 @@
#include "audio_data.h"
#include "audio_mix.h"

-/* channel positions */
-#define FRONT_LEFT 0
-#define FRONT_RIGHT 1
-#define FRONT_CENTER 2
-#define LOW_FREQUENCY 3
-#define BACK_LEFT 4
-#define BACK_RIGHT 5
-#define FRONT_LEFT_OF_CENTER 6
-#define FRONT_RIGHT_OF_CENTER 7
-#define BACK_CENTER 8
-#define SIDE_LEFT 9
-#define SIDE_RIGHT 10
-#define TOP_CENTER 11
-#define TOP_FRONT_LEFT 12
-#define TOP_FRONT_CENTER 13
-#define TOP_FRONT_RIGHT 14
-#define TOP_BACK_LEFT 15
-#define TOP_BACK_CENTER 16
-#define TOP_BACK_RIGHT 17
-#define STEREO_LEFT 29
-#define STEREO_RIGHT 30
-#define WIDE_LEFT 31
-#define WIDE_RIGHT 32
-#define SURROUND_DIRECT_LEFT 33
-#define SURROUND_DIRECT_RIGHT 34
-#define LOW_FREQUENCY_2 35
-
#define SQRT3_2 1.22474487139158904909 /* sqrt(3/2) */

static av_always_inline int even(uint64_t layout)
@@ -63,232 +37,313 @@ static av_always_inline int even(uint64_t layout)
return (!layout || !!(layout & (layout - 1)));
}

-static int sane_layout(uint64_t layout)
+static int sane_layout(const AVChannelLayout *layout)
{
/* check that there is at least 1 front speaker */
- if (!(layout & AV_CH_LAYOUT_SURROUND))
+ if (!av_channel_layout_subset(layout, AV_CH_LAYOUT_SURROUND))
return 0;

/* check for left/right symmetry */
- if (!even(layout & (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT)) ||
- !even(layout & (AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT)) ||
- !even(layout & (AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT)) ||
- !even(layout & (AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER)) ||
- !even(layout & (AV_CH_TOP_FRONT_LEFT | AV_CH_TOP_FRONT_RIGHT)) ||
- !even(layout & (AV_CH_TOP_BACK_LEFT | AV_CH_TOP_BACK_RIGHT)) ||
- !even(layout & (AV_CH_STEREO_LEFT | AV_CH_STEREO_RIGHT)) ||
- !even(layout & (AV_CH_WIDE_LEFT | AV_CH_WIDE_RIGHT)) ||
- !even(layout & (AV_CH_SURROUND_DIRECT_LEFT | AV_CH_SURROUND_DIRECT_RIGHT)))
+ if (!even(av_channel_layout_subset(layout, (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT))) ||
+ !even(av_channel_layout_subset(layout, (AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT))) ||
+ !even(av_channel_layout_subset(layout, (AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT))) ||
+ !even(av_channel_layout_subset(layout, (AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER))) ||
+ !even(av_channel_layout_subset(layout, (AV_CH_TOP_FRONT_LEFT | AV_CH_TOP_FRONT_RIGHT))) ||
+ !even(av_channel_layout_subset(layout, (AV_CH_TOP_BACK_LEFT | AV_CH_TOP_BACK_RIGHT))) ||
+ !even(av_channel_layout_subset(layout, (AV_CH_STEREO_LEFT | AV_CH_STEREO_RIGHT))) ||
+ !even(av_channel_layout_subset(layout, (AV_CH_WIDE_LEFT | AV_CH_WIDE_RIGHT))) ||
+ !even(av_channel_layout_subset(layout, (AV_CH_SURROUND_DIRECT_LEFT | AV_CH_SURROUND_DIRECT_RIGHT))))
return 0;

return 1;
}

-int avresample_build_matrix(uint64_t in_layout, uint64_t out_layout,
- double center_mix_level, double surround_mix_level,
- double lfe_mix_level, int normalize,
- double *matrix_out, int stride,
- enum AVMatrixEncoding matrix_encoding)
+#define IDX_OUT(ch) (av_channel_layout_channel_index(out_layout, ch))
+
+int avresample_build_matrix2(const AVChannelLayout *in_layout,
+ const AVChannelLayout *out_layout,
+ double center_mix_level, double surround_mix_level,
+ double lfe_mix_level, int normalize,
+ double *matrix, int stride,
+ enum AVMatrixEncoding matrix_encoding)
{
- int i, j, out_i, out_j;
- double matrix[64][64] = {{0}};
- int64_t unaccounted;
+ static const AVChannelLayout stereo = AV_CHANNEL_LAYOUT_STEREO;
+ int i, j;
double maxcoef = 0;
- int in_channels, out_channels;
-
- if ((out_layout & AV_CH_LAYOUT_STEREO_DOWNMIX) == AV_CH_LAYOUT_STEREO_DOWNMIX) {
- out_layout = AV_CH_LAYOUT_STEREO;
- }
-
- unaccounted = in_layout & ~out_layout;
-
- in_channels = av_get_channel_layout_nb_channels( in_layout);
- out_channels = av_get_channel_layout_nb_channels(out_layout);
-
- memset(matrix_out, 0, out_channels * stride * sizeof(*matrix_out));
+ int idx_in, idx_out, idx_r, idx_l;
+ int in_channels = in_layout->nb_channels;
+ int out_channels = out_layout->nb_channels;;

/* check if layouts are supported */
- if (!in_layout || in_channels > AVRESAMPLE_MAX_CHANNELS)
+ if (!av_channel_layout_check(in_layout) ||
+ in_channels > AVRESAMPLE_MAX_CHANNELS)
return AVERROR(EINVAL);
- if (!out_layout || out_channels > AVRESAMPLE_MAX_CHANNELS)
+ if (!av_channel_layout_check(out_layout) ||
+ out_channels > AVRESAMPLE_MAX_CHANNELS)
return AVERROR(EINVAL);

/* check if layouts are unbalanced or abnormal */
if (!sane_layout(in_layout) || !sane_layout(out_layout))
return AVERROR_PATCHWELCOME;

- /* route matching input/output channels */
- for (i = 0; i < 64; i++) {
- if (in_layout & out_layout & (1ULL << i))
- matrix[i][i] = 1.0;
- }
+ if (out_channels == 2 &&
+ IDX_OUT(AV_CHAN_STEREO_LEFT) >= 0 &&
+ IDX_OUT(AV_CHAN_STEREO_RIGHT) >= 0)
+ out_layout = &stereo;
+
+ memset(matrix, 0, out_channels * stride * sizeof(*matrix));

- /* mix front center to front left/right */
- if (unaccounted & AV_CH_FRONT_CENTER) {
- if ((out_layout & AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO) {
- if ((in_layout & AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO) {
- matrix[FRONT_LEFT ][FRONT_CENTER] += center_mix_level;
- matrix[FRONT_RIGHT][FRONT_CENTER] += center_mix_level;
+ for (idx_in = 0; idx_in < in_channels; idx_in++) {
+ enum AVChannel in_ch = av_channel_layout_get_channel(in_layout, idx_in);
+
+ idx_out = IDX_OUT(in_ch);
+
+ /* check if the input channel is also present in output */
+ if (idx_out >= 0) {
+ if (in_ch == AV_CHAN_FRONT_CENTER &&
+ av_channel_layout_subset(in_layout, AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO &&
+ !av_channel_layout_subset(out_layout, AV_CH_LAYOUT_STEREO)) {
+ /* mix left/right/center to center */
+ matrix[idx_out * stride + idx_in] = center_mix_level * M_SQRT2;
} else {
- matrix[FRONT_LEFT ][FRONT_CENTER] += M_SQRT1_2;
- matrix[FRONT_RIGHT][FRONT_CENTER] += M_SQRT1_2;
+ /* just copy it */
+ matrix[idx_out * stride + idx_in] = 1.0;
}
- } else
- return AVERROR_PATCHWELCOME;
- }
- /* mix front left/right to center */
- if (unaccounted & AV_CH_LAYOUT_STEREO) {
- if (out_layout & AV_CH_FRONT_CENTER) {
- matrix[FRONT_CENTER][FRONT_LEFT ] += M_SQRT1_2;
- matrix[FRONT_CENTER][FRONT_RIGHT] += M_SQRT1_2;
- /* mix left/right/center to center */
- if (in_layout & AV_CH_FRONT_CENTER)
- matrix[FRONT_CENTER][FRONT_CENTER] = center_mix_level * M_SQRT2;
- } else
- return AVERROR_PATCHWELCOME;
- }
- /* mix back center to back, side, or front */
- if (unaccounted & AV_CH_BACK_CENTER) {
- if (out_layout & AV_CH_BACK_LEFT) {
- matrix[BACK_LEFT ][BACK_CENTER] += M_SQRT1_2;
- matrix[BACK_RIGHT][BACK_CENTER] += M_SQRT1_2;
- } else if (out_layout & AV_CH_SIDE_LEFT) {
- matrix[SIDE_LEFT ][BACK_CENTER] += M_SQRT1_2;
- matrix[SIDE_RIGHT][BACK_CENTER] += M_SQRT1_2;
- } else if (out_layout & AV_CH_FRONT_LEFT) {
- if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY ||
- matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
- if (unaccounted & (AV_CH_BACK_LEFT | AV_CH_SIDE_LEFT)) {
- matrix[FRONT_LEFT ][BACK_CENTER] -= surround_mix_level * M_SQRT1_2;
- matrix[FRONT_RIGHT][BACK_CENTER] += surround_mix_level * M_SQRT1_2;
+
+ continue;
+ }
+
+ /* the input channel is not present in the output layout */
+
+ /* mix front center to front left/right */
+ if (in_ch == AV_CHAN_FRONT_CENTER) {
+ int idx_l = IDX_OUT(AV_CHAN_FRONT_LEFT);
+ int idx_r = IDX_OUT(AV_CHAN_FRONT_RIGHT);
+ if (idx_l >= 0 && idx_r >= 0) {
+ matrix[idx_l * stride + idx_in] += M_SQRT1_2;
+ matrix[idx_r * stride + idx_in] += M_SQRT1_2;
+ }
+ }
+
+ /* mix front left/right to center */
+ if (in_ch == AV_CHAN_FRONT_LEFT || in_ch == AV_CHAN_FRONT_RIGHT) {
+ idx_out = IDX_OUT(AV_CHAN_FRONT_CENTER);
+ if (idx_out >= 0)
+ matrix[idx_out * stride + idx_in] += M_SQRT1_2;
+ }
+
+ /* mix back center to back, side, or front */
+ if (in_ch == AV_CHAN_BACK_CENTER) {
+ int idx_l = IDX_OUT(AV_CHAN_BACK_LEFT);
+ int idx_r = IDX_OUT(AV_CHAN_BACK_RIGHT);
+ if (idx_l >= 0 && idx_r >= 0) {
+ matrix[idx_l * stride + idx_in] += M_SQRT1_2;
+ matrix[idx_r * stride + idx_in] += M_SQRT1_2;
+ continue;
+ }
+
+ idx_l = IDX_OUT(AV_CHAN_SIDE_LEFT);
+ idx_r = IDX_OUT(AV_CHAN_SIDE_RIGHT);
+ if (idx_l >= 0 && idx_r >= 0) {
+ matrix[idx_l * stride + idx_in] += M_SQRT1_2;
+ matrix[idx_r * stride + idx_in] += M_SQRT1_2;
+ continue;
+ }
+
+ idx_l = IDX_OUT(AV_CHAN_FRONT_LEFT);
+ idx_r = IDX_OUT(AV_CHAN_FRONT_RIGHT);
+ if (idx_l >= 0 && idx_r >= 0) {
+ if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY ||
+ matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
+ if (!av_channel_layout_subset(out_layout, AV_CH_BACK_LEFT | AV_CH_SIDE_LEFT) &&
+ av_channel_layout_subset(in_layout, AV_CH_BACK_LEFT | AV_CH_SIDE_LEFT)) {
+ matrix[idx_l * stride + idx_in] -= surround_mix_level * M_SQRT1_2;
+ matrix[idx_r * stride + idx_in] += surround_mix_level * M_SQRT1_2;
+ } else {
+ matrix[idx_l * stride + idx_in] -= surround_mix_level;
+ matrix[idx_r * stride + idx_in] += surround_mix_level;
+ }
} else {
- matrix[FRONT_LEFT ][BACK_CENTER] -= surround_mix_level;
- matrix[FRONT_RIGHT][BACK_CENTER] += surround_mix_level;
+ matrix[idx_l * stride + idx_in] += surround_mix_level * M_SQRT1_2;
+ matrix[idx_r * stride + idx_in] += surround_mix_level * M_SQRT1_2;
}
- } else {
- matrix[FRONT_LEFT ][BACK_CENTER] += surround_mix_level * M_SQRT1_2;
- matrix[FRONT_RIGHT][BACK_CENTER] += surround_mix_level * M_SQRT1_2;
+ continue;
}
- } else if (out_layout & AV_CH_FRONT_CENTER) {
- matrix[FRONT_CENTER][BACK_CENTER] += surround_mix_level * M_SQRT1_2;
- } else
- return AVERROR_PATCHWELCOME;
- }
- /* mix back left/right to back center, side, or front */
- if (unaccounted & AV_CH_BACK_LEFT) {
- if (out_layout & AV_CH_BACK_CENTER) {
- matrix[BACK_CENTER][BACK_LEFT ] += M_SQRT1_2;
- matrix[BACK_CENTER][BACK_RIGHT] += M_SQRT1_2;
- } else if (out_layout & AV_CH_SIDE_LEFT) {
- /* if side channels do not exist in the input, just copy back
- channels to side channels, otherwise mix back into side */
- if (in_layout & AV_CH_SIDE_LEFT) {
- matrix[SIDE_LEFT ][BACK_LEFT ] += M_SQRT1_2;
- matrix[SIDE_RIGHT][BACK_RIGHT] += M_SQRT1_2;
- } else {
- matrix[SIDE_LEFT ][BACK_LEFT ] += 1.0;
- matrix[SIDE_RIGHT][BACK_RIGHT] += 1.0;
+
+ idx_out = IDX_OUT(AV_CHAN_FRONT_CENTER);
+ if (idx_out >= 0) {
+ matrix[idx_out * stride + idx_in] += surround_mix_level * M_SQRT1_2;
+ continue;
}
- } else if (out_layout & AV_CH_FRONT_LEFT) {
- if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) {
- matrix[FRONT_LEFT ][BACK_LEFT ] -= surround_mix_level * M_SQRT1_2;
- matrix[FRONT_LEFT ][BACK_RIGHT] -= surround_mix_level * M_SQRT1_2;
- matrix[FRONT_RIGHT][BACK_LEFT ] += surround_mix_level * M_SQRT1_2;
- matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level * M_SQRT1_2;
- } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
- matrix[FRONT_LEFT ][BACK_LEFT ] -= surround_mix_level * SQRT3_2;
- matrix[FRONT_LEFT ][BACK_RIGHT] -= surround_mix_level * M_SQRT1_2;
- matrix[FRONT_RIGHT][BACK_LEFT ] += surround_mix_level * M_SQRT1_2;
- matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level * SQRT3_2;
- } else {
- matrix[FRONT_LEFT ][BACK_LEFT ] += surround_mix_level;
- matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level;
+ }
+
+ /* mix back left/right to back center, side, or front */
+ if (in_ch == AV_CHAN_BACK_LEFT || in_ch == AV_CHAN_BACK_RIGHT) {
+ idx_out = IDX_OUT(AV_CHAN_BACK_CENTER);
+ if (idx_out >= 0) {
+ matrix[idx_out * stride + idx_in] += M_SQRT1_2;
+ continue;
}
- } else if (out_layout & AV_CH_FRONT_CENTER) {
- matrix[FRONT_CENTER][BACK_LEFT ] += surround_mix_level * M_SQRT1_2;
- matrix[FRONT_CENTER][BACK_RIGHT] += surround_mix_level * M_SQRT1_2;
- } else
- return AVERROR_PATCHWELCOME;
- }
- /* mix side left/right into back or front */
- if (unaccounted & AV_CH_SIDE_LEFT) {
- if (out_layout & AV_CH_BACK_LEFT) {
- /* if back channels do not exist in the input, just copy side
- channels to back channels, otherwise mix side into back */
- if (in_layout & AV_CH_BACK_LEFT) {
- matrix[BACK_LEFT ][SIDE_LEFT ] += M_SQRT1_2;
- matrix[BACK_RIGHT][SIDE_RIGHT] += M_SQRT1_2;
- } else {
- matrix[BACK_LEFT ][SIDE_LEFT ] += 1.0;
- matrix[BACK_RIGHT][SIDE_RIGHT] += 1.0;
+
+ idx_out = IDX_OUT(in_ch == AV_CHAN_BACK_LEFT ? AV_CHAN_SIDE_LEFT :
+ AV_CHAN_SIDE_RIGHT);
+ if (idx_out >= 0) {
+ /* if side channels do not exist in the input, just copy back
+ channels to side channels, otherwise mix back into side */
+ if (av_channel_layout_subset(in_layout, AV_CH_SIDE_LEFT))
+ matrix[idx_out * stride + idx_in] += M_SQRT1_2;
+ else
+ matrix[idx_out * stride + idx_in] += 1.0;
+
+ continue;
}
- } else if (out_layout & AV_CH_BACK_CENTER) {
- matrix[BACK_CENTER][SIDE_LEFT ] += M_SQRT1_2;
- matrix[BACK_CENTER][SIDE_RIGHT] += M_SQRT1_2;
- } else if (out_layout & AV_CH_FRONT_LEFT) {
- if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) {
- matrix[FRONT_LEFT ][SIDE_LEFT ] -= surround_mix_level * M_SQRT1_2;
- matrix[FRONT_LEFT ][SIDE_RIGHT] -= surround_mix_level * M_SQRT1_2;
- matrix[FRONT_RIGHT][SIDE_LEFT ] += surround_mix_level * M_SQRT1_2;
- matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level * M_SQRT1_2;
- } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
- matrix[FRONT_LEFT ][SIDE_LEFT ] -= surround_mix_level * SQRT3_2;
- matrix[FRONT_LEFT ][SIDE_RIGHT] -= surround_mix_level * M_SQRT1_2;
- matrix[FRONT_RIGHT][SIDE_LEFT ] += surround_mix_level * M_SQRT1_2;
- matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level * SQRT3_2;
- } else {
- matrix[FRONT_LEFT ][SIDE_LEFT ] += surround_mix_level;
- matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level;
+
+ idx_l = IDX_OUT(AV_CHAN_FRONT_LEFT);
+ idx_r = IDX_OUT(AV_CHAN_FRONT_RIGHT);
+ if (idx_l >= 0 && idx_r >= 0) {
+ if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) {
+ matrix[idx_l * stride + idx_in] -= surround_mix_level * M_SQRT1_2;
+ matrix[idx_r * stride + idx_in] += surround_mix_level * M_SQRT1_2;
+ } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
+ if (in_ch == AV_CHAN_BACK_LEFT) {
+ matrix[idx_l * stride + idx_in] -= surround_mix_level * SQRT3_2;
+ matrix[idx_r * stride + idx_in] += surround_mix_level * M_SQRT1_2;
+ } else {
+ matrix[idx_l * stride + idx_in] -= surround_mix_level * M_SQRT1_2;
+ matrix[idx_r * stride + idx_in] += surround_mix_level * SQRT3_2;
+ }
+ } else {
+ idx_out = (in_ch == AV_CHAN_BACK_LEFT) ? idx_l : idx_r;
+ matrix[idx_out * stride + idx_in] += surround_mix_level;
+ }
+
+ continue;
}
- } else if (out_layout & AV_CH_FRONT_CENTER) {
- matrix[FRONT_CENTER][SIDE_LEFT ] += surround_mix_level * M_SQRT1_2;
- matrix[FRONT_CENTER][SIDE_RIGHT] += surround_mix_level * M_SQRT1_2;
- } else
- return AVERROR_PATCHWELCOME;
- }
- /* mix left-of-center/right-of-center into front left/right or center */
- if (unaccounted & AV_CH_FRONT_LEFT_OF_CENTER) {
- if (out_layout & AV_CH_FRONT_LEFT) {
- matrix[FRONT_LEFT ][FRONT_LEFT_OF_CENTER ] += 1.0;
- matrix[FRONT_RIGHT][FRONT_RIGHT_OF_CENTER] += 1.0;
- } else if (out_layout & AV_CH_FRONT_CENTER) {
- matrix[FRONT_CENTER][FRONT_LEFT_OF_CENTER ] += M_SQRT1_2;
- matrix[FRONT_CENTER][FRONT_RIGHT_OF_CENTER] += M_SQRT1_2;
- } else
- return AVERROR_PATCHWELCOME;
- }
- /* mix LFE into front left/right or center */
- if (unaccounted & AV_CH_LOW_FREQUENCY) {
- if (out_layout & AV_CH_FRONT_CENTER) {
- matrix[FRONT_CENTER][LOW_FREQUENCY] += lfe_mix_level;
- } else if (out_layout & AV_CH_FRONT_LEFT) {
- matrix[FRONT_LEFT ][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2;
- matrix[FRONT_RIGHT][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2;
- } else
- return AVERROR_PATCHWELCOME;
+
+ idx_out = IDX_OUT(AV_CHAN_FRONT_CENTER);
+ if (idx_out >= 0) {
+ matrix[idx_out * stride + idx_in] += surround_mix_level * M_SQRT1_2;
+ continue;
+ }
+ }
+
+ /* mix side left/right into back or front */
+ if (in_ch == AV_CHAN_SIDE_LEFT || in_ch == AV_CHAN_SIDE_RIGHT) {
+ idx_out = IDX_OUT(in_ch == AV_CHAN_SIDE_LEFT ? AV_CHAN_BACK_LEFT :
+ AV_CHAN_BACK_RIGHT);
+ if (idx_out >= 0) {
+ /* if back channels do not exist in the input, just copy side
+ channels to back channels, otherwise mix side into back */
+ if (av_channel_layout_subset(in_layout, AV_CH_BACK_LEFT))
+ matrix[idx_out * stride + idx_in] += M_SQRT1_2;
+ else
+ matrix[idx_out * stride + idx_in] += 1.0;
+
+ continue;
+ }
+
+ idx_out = IDX_OUT(AV_CHAN_BACK_CENTER);
+ if (idx_out >= 0) {
+ matrix[idx_out * stride + idx_in] += M_SQRT1_2;
+ continue;
+ }
+
+
+ idx_l = IDX_OUT(AV_CHAN_FRONT_LEFT);
+ idx_r = IDX_OUT(AV_CHAN_FRONT_RIGHT);
+ if (idx_l >= 0 && idx_r >= 0) {
+ if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) {
+ matrix[idx_l * stride + idx_in] -= surround_mix_level * M_SQRT1_2;
+ matrix[idx_r * stride + idx_in] += surround_mix_level * M_SQRT1_2;
+ } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
+ if (in_ch == AV_CHAN_SIDE_LEFT) {
+ matrix[idx_l * stride + idx_in] -= surround_mix_level * SQRT3_2;
+ matrix[idx_r * stride + idx_in] += surround_mix_level * M_SQRT1_2;
+ } else {
+ matrix[idx_l * stride + idx_in] -= surround_mix_level * M_SQRT1_2;
+ matrix[idx_r * stride + idx_in] += surround_mix_level * SQRT3_2;
+ }
+ } else {
+ idx_out = (in_ch == AV_CHAN_SIDE_LEFT) ? idx_l : idx_r;
+ matrix[idx_out * stride + idx_in] += surround_mix_level;
+ }
+
+ continue;
+ }
+
+ idx_out = IDX_OUT(AV_CHAN_FRONT_CENTER);
+ if (idx_out >= 0) {
+ matrix[idx_out * stride + idx_in] += surround_mix_level * M_SQRT1_2;
+ continue;
+ }
+ }
+
+ /* mix left-of-center/right-of-center into front left/right or center */
+ if (in_ch == AV_CHAN_FRONT_LEFT_OF_CENTER ||
+ in_ch == AV_CHAN_FRONT_RIGHT_OF_CENTER) {
+ idx_out = IDX_OUT(in_ch == AV_CHAN_FRONT_LEFT_OF_CENTER ?
+ AV_CHAN_FRONT_LEFT : AV_CHAN_FRONT_RIGHT);
+ if (idx_out >= 0) {
+ matrix[idx_out * stride + idx_in] += 1.0;
+ continue;
+ }
+
+ idx_out = IDX_OUT(AV_CHAN_FRONT_CENTER);
+ if (idx_out >= 0) {
+ matrix[idx_out * stride + idx_in] += M_SQRT1_2;
+ continue;
+ }
+ }
+
+ /* mix LFE into front left/right or center */
+ if (in_ch == AV_CHAN_LOW_FREQUENCY) {
+ idx_out = IDX_OUT(AV_CHAN_FRONT_CENTER);
+ if (idx_out >= 0) {
+ matrix[idx_out * stride + idx_in] += lfe_mix_level;
+ continue;
+ }
+
+ idx_l = IDX_OUT(AV_CHAN_FRONT_LEFT);
+ idx_r = IDX_OUT(AV_CHAN_FRONT_RIGHT);
+ if (idx_l >= 0 && idx_r >= 0) {
+ matrix[idx_l * stride + idx_in] += lfe_mix_level * M_SQRT1_2;
+ matrix[idx_r * stride + idx_in] += lfe_mix_level * M_SQRT1_2;
+ continue;
+ }
+ }
}

- /* transfer internal matrix to output matrix and calculate maximum
- per-channel coefficient sum */
- for (out_i = i = 0; out_i < out_channels && i < 64; i++) {
+ /* calculate maximum per-channel coefficient sum */
+ for (idx_out = 0; idx_out < out_channels; idx_out++) {
double sum = 0;
- for (out_j = j = 0; out_j < in_channels && j < 64; j++) {
- matrix_out[out_i * stride + out_j] = matrix[i][j];
- sum += fabs(matrix[i][j]);
- if (in_layout & (1ULL << j))
- out_j++;
- }
+ for (idx_in = 0; idx_in < in_channels; idx_in++)
+ sum += fabs(matrix[idx_out * stride + idx_in]);
maxcoef = FFMAX(maxcoef, sum);
- if (out_layout & (1ULL << i))
- out_i++;
}

/* normalize */
if (normalize && maxcoef > 1.0) {
for (i = 0; i < out_channels; i++)
for (j = 0; j < in_channels; j++)
- matrix_out[i * stride + j] /= maxcoef;
+ matrix[i * stride + j] /= maxcoef;
}

return 0;
}
+
+#if FF_API_OLD_CHANNEL_LAYOUT
+int avresample_build_matrix(uint64_t in_layout, uint64_t out_layout,
+ double center_mix_level, double surround_mix_level,
+ double lfe_mix_level, int normalize,
+ double *matrix_out, int stride,
+ enum AVMatrixEncoding matrix_encoding)
+{
+ AVChannelLayout in_chl, out_chl;
+
+ av_channel_layout_from_mask(&in_chl, in_layout);
+ av_channel_layout_from_mask(&out_chl, out_layout);
+ return avresample_build_matrix2(&in_chl, &out_chl, center_mix_level,
+ surround_mix_level, lfe_mix_level, normalize,
+ matrix_out, stride, matrix_encoding);
+}
+#endif
diff --git a/libavresample/avresample.h b/libavresample/avresample.h
index 3f9b9433c1..5a60423470 100644
--- a/libavresample/avresample.h
+++ b/libavresample/avresample.h
@@ -44,8 +44,10 @@
* matrix):
* @code
* AVAudioResampleContext *avr = avresample_alloc_context();
- * av_opt_set_int(avr, "in_channel_layout", AV_CH_LAYOUT_5POINT1, 0);
- * av_opt_set_int(avr, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0);
+ * AVChannelLayout in_ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1;
+ * AVChannelLayout out_ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
+ * av_opt_set_channel_layout(avr, "in_ch_layout", &in_ch_layout, 0);
+ * av_opt_set_channel_layout(avr, "out_ch_layout", &out_ch_layout, 0);
* av_opt_set_int(avr, "in_sample_rate", 48000, 0);
* av_opt_set_int(avr, "out_sample_rate", 44100, 0);
* av_opt_set_int(avr, "in_sample_fmt", AV_SAMPLE_FMT_FLTP, 0);
@@ -92,6 +94,7 @@
* avresample_free().
*/

+#include "libavutil/attributes.h"
#include "libavutil/avutil.h"
#include "libavutil/channel_layout.h"
#include "libavutil/dict.h"
@@ -167,7 +170,7 @@ AVAudioResampleContext *avresample_alloc_context(void);
/**
* Initialize AVAudioResampleContext.
* @note The context must be configured using the AVOption API.
- * @note The fields "in_channel_layout", "out_channel_layout",
+ * @note The fields "in_ch_layout", "out_ch_layout",
* "in_sample_rate", "out_sample_rate", "in_sample_fmt",
* "out_sample_fmt" must be set.
*
@@ -212,6 +215,7 @@ void avresample_close(AVAudioResampleContext *avr);
*/
void avresample_free(AVAudioResampleContext **avr);

+#if FF_API_OLD_CHANNEL_LAYOUT
/**
* Generate a channel mixing matrix.
*
@@ -233,11 +237,43 @@ void avresample_free(AVAudioResampleContext **avr);
* matrix array
* @param matrix_encoding matrixed stereo downmix mode (e.g. dplii)
* @return 0 on success, negative AVERROR code on failure
+ *
+ * @deprecated use avresample_build_matrix2()
*/
+attribute_deprecated
int avresample_build_matrix(uint64_t in_layout, uint64_t out_layout,
double center_mix_level, double surround_mix_level,
double lfe_mix_level, int normalize, double *matrix,
int stride, enum AVMatrixEncoding matrix_encoding);
+#endif
+
+/**
+ * Generate a channel mixing matrix.
+ *
+ * This function is the one used internally by libavresample for building the
+ * default mixing matrix. It is made public just as a utility function for
+ * building custom matrices.
+ *
+ * @param in_layout input channel layout
+ * @param out_layout output channel layout
+ * @param center_mix_level mix level for the center channel
+ * @param surround_mix_level mix level for the surround channel(s)
+ * @param lfe_mix_level mix level for the low-frequency effects channel
+ * @param normalize if 1, coefficients will be normalized to prevent
+ * overflow. if 0, coefficients will not be
+ * normalized.
+ * @param[out] matrix mixing coefficients; matrix[i + stride * o] is
+ * the weight of input channel i in output channel o.
+ * @param stride distance between adjacent input channels in the
+ * matrix array
+ * @param matrix_encoding matrixed stereo downmix mode (e.g. dplii)
+ * @return 0 on success, negative AVERROR code on failure
+ */
+int avresample_build_matrix2(const AVChannelLayout *in_layout,
+ const AVChannelLayout *out_layout,
+ double center_mix_level, double surround_mix_level,
+ double lfe_mix_level, int normalize, double *matrix,
+ int stride, enum AVMatrixEncoding matrix_encoding);

/**
* Get the current channel mixing matrix.
diff --git a/libavresample/internal.h b/libavresample/internal.h
index b88b7587aa..a6bf2d400e 100644
--- a/libavresample/internal.h
+++ b/libavresample/internal.h
@@ -22,6 +22,7 @@
#define AVRESAMPLE_INTERNAL_H

#include "libavutil/audio_fifo.h"
+#include "libavutil/channel_layout.h"
#include "libavutil/log.h"
#include "libavutil/opt.h"
#include "libavutil/samplefmt.h"
@@ -53,10 +54,17 @@ typedef struct ChannelMapInfo {
struct AVAudioResampleContext {
const AVClass *av_class; /**< AVClass for logging and AVOptions */

+#if FF_API_OLD_CHANNEL_LAYOUT
uint64_t in_channel_layout; /**< input channel layout */
+#endif
+ AVChannelLayout in_ch_layout; /**< input channel layout */
+
enum AVSampleFormat in_sample_fmt; /**< input sample format */
int in_sample_rate; /**< input sample rate */
+#if FF_API_OLD_CHANNEL_LAYOUT
uint64_t out_channel_layout; /**< output channel layout */
+#endif
+ AVChannelLayout out_ch_layout; /**< output channel layout */
enum AVSampleFormat out_sample_fmt; /**< output sample format */
int out_sample_rate; /**< output sample rate */
enum AVSampleFormat internal_sample_fmt; /**< internal sample format */
@@ -74,8 +82,6 @@ struct AVAudioResampleContext {
int kaiser_beta; /**< beta value for Kaiser window (only applicable if filter_type == AV_FILTER_TYPE_KAISER) */
enum AVResampleDitherMethod dither_method; /**< dither method */

- int in_channels; /**< number of input channels */
- int out_channels; /**< number of output channels */
int resample_channels; /**< number of channels used for resampling */
int downmix_needed; /**< downmixing is needed */
int upmix_needed; /**< upmixing is needed */
diff --git a/libavresample/options.c b/libavresample/options.c
index 6249f90115..78af61a6e1 100644
--- a/libavresample/options.c
+++ b/libavresample/options.c
@@ -36,10 +36,18 @@
#define PARAM AV_OPT_FLAG_AUDIO_PARAM

static const AVOption avresample_options[] = {
+#if FF_API_OLD_CHANNEL_LAYOUT
{ "in_channel_layout", "Input Channel Layout", OFFSET(in_channel_layout), AV_OPT_TYPE_INT64, { .i64 = 0 }, INT64_MIN, INT64_MAX, PARAM },
+#endif
+ { "in_ch_layout", "Input Channel Layout", OFFSET(in_ch_layout), AV_OPT_TYPE_CHANNEL_LAYOUT,
+ { .str = NULL }, .flags = PARAM },
{ "in_sample_fmt", "Input Sample Format", OFFSET(in_sample_fmt), AV_OPT_TYPE_INT, { .i64 = AV_SAMPLE_FMT_S16 }, AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_NB-1, PARAM },
{ "in_sample_rate", "Input Sample Rate", OFFSET(in_sample_rate), AV_OPT_TYPE_INT, { .i64 = 48000 }, 1, INT_MAX, PARAM },
+#if FF_API_OLD_CHANNEL_LAYOUT
{ "out_channel_layout", "Output Channel Layout", OFFSET(out_channel_layout), AV_OPT_TYPE_INT64, { .i64 = 0 }, INT64_MIN, INT64_MAX, PARAM },
+#endif
+ { "out_ch_layout", "Output Channel Layout", OFFSET(out_ch_layout), AV_OPT_TYPE_CHANNEL_LAYOUT,
+ { .str = NULL }, .flags = PARAM },
{ "out_sample_fmt", "Output Sample Format", OFFSET(out_sample_fmt), AV_OPT_TYPE_INT, { .i64 = AV_SAMPLE_FMT_S16 }, AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_NB-1, PARAM },
{ "out_sample_rate", "Output Sample Rate", OFFSET(out_sample_rate), AV_OPT_TYPE_INT, { .i64 = 48000 }, 1, INT_MAX, PARAM },
{ "internal_sample_fmt", "Internal Sample Format", OFFSET(internal_sample_fmt), AV_OPT_TYPE_INT, { .i64 = AV_SAMPLE_FMT_NONE }, AV_SAMPLE_FMT_NONE, AV_SAMPLE_FMT_NB-1, PARAM, "internal_sample_fmt" },
diff --git a/libavresample/tests/avresample.c b/libavresample/tests/avresample.c
index 77599960f8..19027b2df1 100644
--- a/libavresample/tests/avresample.c
+++ b/libavresample/tests/avresample.c
@@ -179,11 +179,11 @@ static const int rates[] = {
16000
};

-static const uint64_t layouts[] = {
- AV_CH_LAYOUT_STEREO,
- AV_CH_LAYOUT_MONO,
- AV_CH_LAYOUT_5POINT1,
- AV_CH_LAYOUT_7POINT1,
+static const AVChannelLayout layouts[] = {
+ AV_CHANNEL_LAYOUT_STEREO,
+ AV_CHANNEL_LAYOUT_MONO,
+ AV_CHANNEL_LAYOUT_5POINT1,
+ AV_CHANNEL_LAYOUT_7POINT1,
};

int main(int argc, char **argv)
@@ -199,12 +199,8 @@ int main(int argc, char **argv)
uint8_t *out_data[AVRESAMPLE_MAX_CHANNELS] = { 0 };
int in_linesize;
int out_linesize;
- uint64_t in_ch_layout;
- int in_channels;
enum AVSampleFormat in_fmt;
int in_rate;
- uint64_t out_ch_layout;
- int out_channels;
enum AVSampleFormat out_fmt;
int out_rate;
int num_formats, num_rates, num_layouts;
@@ -257,8 +253,8 @@ int main(int argc, char **argv)
for (i = 0; i < num_formats; i++) {
in_fmt = formats[i];
for (k = 0; k < num_layouts; k++) {
- in_ch_layout = layouts[k];
- in_channels = av_get_channel_layout_nb_channels(in_ch_layout);
+ AVChannelLayout in_ch_layout = layouts[k];
+ int in_channels = in_ch_layout.nb_channels;
for (m = 0; m < num_rates; m++) {
in_rate = rates[m];

@@ -274,8 +270,8 @@ int main(int argc, char **argv)
for (j = 0; j < num_formats; j++) {
out_fmt = formats[j];
for (l = 0; l < num_layouts; l++) {
- out_ch_layout = layouts[l];
- out_channels = av_get_channel_layout_nb_channels(out_ch_layout);
+ AVChannelLayout out_ch_layout = layouts[l];
+ int out_channels = out_ch_layout.nb_channels;
for (n = 0; n < num_rates; n++) {
out_rate = rates[n];

@@ -291,10 +287,10 @@ int main(int argc, char **argv)
goto end;
}

- av_opt_set_int(s, "in_channel_layout", in_ch_layout, 0);
+ av_opt_set_channel_layout(s, "in_ch_layout", &in_ch_layout, 0);
+ av_opt_set_channel_layout(s, "out_ch_layout", &out_ch_layout, 0);
av_opt_set_int(s, "in_sample_fmt", in_fmt, 0);
av_opt_set_int(s, "in_sample_rate", in_rate, 0);
- av_opt_set_int(s, "out_channel_layout", out_ch_layout, 0);
av_opt_set_int(s, "out_sample_fmt", out_fmt, 0);
av_opt_set_int(s, "out_sample_rate", out_rate, 0);

diff --git a/libavresample/utils.c b/libavresample/utils.c
index bab2153b4b..15c827efbe 100644
--- a/libavresample/utils.c
+++ b/libavresample/utils.c
@@ -18,6 +18,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

+#include "libavutil/channel_layout.h"
#include "libavutil/common.h"
#include "libavutil/dict.h"
#include "libavutil/error.h"
@@ -35,6 +36,7 @@

int avresample_open(AVAudioResampleContext *avr)
{
+ int in_ch, out_ch;
int ret;

if (avresample_is_open(avr)) {
@@ -42,24 +44,67 @@ int avresample_open(AVAudioResampleContext *avr)
return AVERROR(EINVAL);
}

+ if ( avr->in_ch_layout.order == AV_CHANNEL_ORDER_CUSTOM ||
+ avr->out_ch_layout.order == AV_CHANNEL_ORDER_CUSTOM) {
+ av_log(avr, AV_LOG_ERROR,
+ "Resampling a custom channel layout order is not supported.\n");
+ return AVERROR(ENOSYS);
+ }
+
+ if (avr->in_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) {
+ if (avr->in_ch_layout.nb_channels > 63) {
+ av_log(avr, AV_LOG_ERROR,
+ "Unspecified channel layout order is supported only for up "
+ "to 63 channels (got %d).\n", avr->in_ch_layout.nb_channels);
+ return AVERROR(ENOSYS);
+ }
+ av_channel_layout_default(&avr->in_ch_layout, avr->in_ch_layout.nb_channels);
+ }
+ if (avr->out_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) {
+ if (avr->out_ch_layout.nb_channels > 63) {
+ av_log(avr, AV_LOG_ERROR,
+ "Unspecified channel layout order is supported only for up "
+ "to 63 channels (got %d).\n", avr->out_ch_layout.nb_channels);
+ return AVERROR(ENOSYS);
+ }
+ av_channel_layout_default(&avr->out_ch_layout, avr->out_ch_layout.nb_channels);
+ }
+
/* set channel mixing parameters */
- avr->in_channels = av_get_channel_layout_nb_channels(avr->in_channel_layout);
- if (avr->in_channels <= 0 || avr->in_channels > AVRESAMPLE_MAX_CHANNELS) {
- av_log(avr, AV_LOG_ERROR, "Invalid input channel layout: %"PRIu64"\n",
- avr->in_channel_layout);
+#if FF_API_OLD_CHANNEL_LAYOUT
+ if (avr->in_channel_layout) {
+ av_log(avr, AV_LOG_WARNING, "Setting the input channel layout with the "
+ "'in_channel_layout' option is deprecated, use the "
+ "'in_ch_layout' option instead].\n");
+ av_channel_layout_uninit(&avr->in_ch_layout);
+ av_channel_layout_from_mask(&avr->in_ch_layout, avr->in_channel_layout);
+ }
+ if (avr->out_channel_layout) {
+ av_log(avr, AV_LOG_WARNING, "Setting the output channel layout with the "
+ "'out_channel_layout' option is deprecated, use the "
+ "'out_ch_layout' option instead].\n");
+ av_channel_layout_uninit(&avr->out_ch_layout);
+ av_channel_layout_from_mask(&avr->out_ch_layout, avr->out_channel_layout);
+ }
+#endif
+ in_ch = avr->in_ch_layout.nb_channels;
+ out_ch = avr->out_ch_layout.nb_channels;
+ if (!av_channel_layout_check(&avr->in_ch_layout) ||
+ in_ch > AVRESAMPLE_MAX_CHANNELS) {
+ av_log(avr, AV_LOG_ERROR, "Invalid input channel layout.\n");
return AVERROR(EINVAL);
}
- avr->out_channels = av_get_channel_layout_nb_channels(avr->out_channel_layout);
- if (avr->out_channels <= 0 || avr->out_channels > AVRESAMPLE_MAX_CHANNELS) {
- av_log(avr, AV_LOG_ERROR, "Invalid output channel layout: %"PRIu64"\n",
- avr->out_channel_layout);
+ if (!av_channel_layout_check(&avr->out_ch_layout) ||
+ out_ch > AVRESAMPLE_MAX_CHANNELS) {
+ av_log(avr, AV_LOG_ERROR, "Invalid output channel layout.\n");
return AVERROR(EINVAL);
}
- avr->resample_channels = FFMIN(avr->in_channels, avr->out_channels);
- avr->downmix_needed = avr->in_channels > avr->out_channels;
- avr->upmix_needed = avr->out_channels > avr->in_channels ||
+ avr->resample_channels = FFMIN(in_ch, out_ch);
+ avr->downmix_needed = in_ch > out_ch;
+ avr->upmix_needed = out_ch > in_ch ||
(!avr->downmix_needed && (avr->mix_matrix ||
- avr->in_channel_layout != avr->out_channel_layout));
+ av_channel_layout_compare(&avr->in_ch_layout,
+ &avr->out_ch_layout)));
avr->mixing_needed = avr->downmix_needed || avr->upmix_needed;

/* set resampling parameters */
@@ -105,7 +150,7 @@ int avresample_open(AVAudioResampleContext *avr)
/* we may need to add an extra conversion in order to remap channels if
the output format is not planar */
if (avr->use_channel_map && !avr->mixing_needed && !avr->resample_needed &&
- !ff_sample_fmt_is_planar(avr->out_sample_fmt, avr->out_channels)) {
+ !ff_sample_fmt_is_planar(avr->out_sample_fmt, avr->out_ch_layout.nb_channels)) {
avr->internal_sample_fmt = av_get_planar_sample_fmt(avr->out_sample_fmt);
}

@@ -114,7 +159,8 @@ int avresample_open(AVAudioResampleContext *avr)
avr->in_convert_needed = avr->in_sample_fmt != avr->internal_sample_fmt;
else
avr->in_convert_needed = avr->use_channel_map &&
- !ff_sample_fmt_is_planar(avr->out_sample_fmt, avr->out_channels);
+ !ff_sample_fmt_is_planar(avr->out_sample_fmt,
+ avr->out_ch_layout.nb_channels);

if (avr->resample_needed || avr->mixing_needed || avr->in_convert_needed)
avr->out_convert_needed = avr->internal_sample_fmt != avr->out_sample_fmt;
@@ -144,27 +190,27 @@ int avresample_open(AVAudioResampleContext *avr)
int ch;
av_log(avr, AV_LOG_TRACE, "output map: ");
if (avr->ch_map_info.do_remap)
- for (ch = 0; ch < avr->in_channels; ch++)
+ for (ch = 0; ch < in_ch; ch++)
av_log(avr, AV_LOG_TRACE, " % 2d", avr->ch_map_info.channel_map[ch]);
else
av_log(avr, AV_LOG_TRACE, "n/a");
av_log(avr, AV_LOG_TRACE, "\n");
av_log(avr, AV_LOG_TRACE, "copy map: ");
if (avr->ch_map_info.do_copy)
- for (ch = 0; ch < avr->in_channels; ch++)
+ for (ch = 0; ch < in_ch; ch++)
av_log(avr, AV_LOG_TRACE, " % 2d", avr->ch_map_info.channel_copy[ch]);
else
av_log(avr, AV_LOG_TRACE, "n/a");
av_log(avr, AV_LOG_TRACE, "\n");
av_log(avr, AV_LOG_TRACE, "zero map: ");
if (avr->ch_map_info.do_zero)
- for (ch = 0; ch < avr->in_channels; ch++)
+ for (ch = 0; ch < in_ch; ch++)
av_log(avr, AV_LOG_TRACE, " % 2d", avr->ch_map_info.channel_zero[ch]);
else
av_log(avr, AV_LOG_TRACE, "n/a");
av_log(avr, AV_LOG_TRACE, "\n");
av_log(avr, AV_LOG_TRACE, "input map: ");
- for (ch = 0; ch < avr->in_channels; ch++)
+ for (ch = 0; ch < in_ch; ch++)
av_log(avr, AV_LOG_TRACE, " % 2d", avr->ch_map_info.input_map[ch]);
av_log(avr, AV_LOG_TRACE, "\n");
}
@@ -174,7 +220,7 @@ int avresample_open(AVAudioResampleContext *avr)

/* allocate buffers */
if (avr->in_copy_needed || avr->in_convert_needed) {
- avr->in_buffer = ff_audio_data_alloc(FFMAX(avr->in_channels, avr->out_channels),
+ avr->in_buffer = ff_audio_data_alloc(FFMAX(in_ch, out_ch),
0, avr->internal_sample_fmt,
"in_buffer");
if (!avr->in_buffer) {
@@ -183,7 +229,7 @@ int avresample_open(AVAudioResampleContext *avr)
}
}
if (avr->resample_needed) {
- avr->resample_out_buffer = ff_audio_data_alloc(avr->out_channels,
+ avr->resample_out_buffer = ff_audio_data_alloc(out_ch,
1024, avr->internal_sample_fmt,
"resample_out_buffer");
if (!avr->resample_out_buffer) {
@@ -192,15 +238,14 @@ int avresample_open(AVAudioResampleContext *avr)
}
}
if (avr->out_convert_needed) {
- avr->out_buffer = ff_audio_data_alloc(avr->out_channels, 0,
+ avr->out_buffer = ff_audio_data_alloc(out_ch, 0,
avr->out_sample_fmt, "out_buffer");
if (!avr->out_buffer) {
ret = AVERROR(EINVAL);
goto error;
}
}
- avr->out_fifo = av_audio_fifo_alloc(avr->out_sample_fmt, avr->out_channels,
- 1024);
+ avr->out_fifo = av_audio_fifo_alloc(avr->out_sample_fmt, out_ch, 1024);
if (!avr->out_fifo) {
ret = AVERROR(ENOMEM);
goto error;
@@ -209,7 +254,7 @@ int avresample_open(AVAudioResampleContext *avr)
/* setup contexts */
if (avr->in_convert_needed) {
avr->ac_in = ff_audio_convert_alloc(avr, avr->internal_sample_fmt,
- avr->in_sample_fmt, avr->in_channels,
+ avr->in_sample_fmt, in_ch,
avr->in_sample_rate,
avr->remap_point == REMAP_IN_CONVERT);
if (!avr->ac_in) {
@@ -224,7 +269,7 @@ int avresample_open(AVAudioResampleContext *avr)
else
src_fmt = avr->in_sample_fmt;
avr->ac_out = ff_audio_convert_alloc(avr, avr->out_sample_fmt, src_fmt,
- avr->out_channels,
+ out_ch,
avr->out_sample_rate,
avr->remap_point == REMAP_OUT_CONVERT);
if (!avr->ac_out) {
@@ -361,7 +406,7 @@ int attribute_align_arg avresample_convert(AVAudioResampleContext *avr,
direct_output = output && av_audio_fifo_size(avr->out_fifo) == 0;
if (output) {
ret = ff_audio_data_init(&output_buffer, output, out_plane_size,
- avr->out_channels, out_samples,
+ avr->out_ch_layout.nb_channels, out_samples,
avr->out_sample_fmt, 0, "output");
if (ret < 0)
return ret;
@@ -371,7 +416,7 @@ int attribute_align_arg avresample_convert(AVAudioResampleContext *avr,
if (input) {
/* initialize input_buffer with input data */
ret = ff_audio_data_init(&input_buffer, input, in_plane_size,
- avr->in_channels, in_samples,
+ avr->in_ch_layout.nb_channels, in_samples,
avr->in_sample_fmt, 1, "input");
if (ret < 0)
return ret;
@@ -420,7 +465,7 @@ int attribute_align_arg avresample_convert(AVAudioResampleContext *avr,
if (ret < 0)
return ret;
}
- ff_audio_data_set_channels(avr->in_buffer, avr->in_channels);
+ ff_audio_data_set_channels(avr->in_buffer, avr->in_ch_layout.nb_channels);
if (avr->downmix_needed) {
av_log(avr, AV_LOG_TRACE, "[downmix] in_buffer\n");
ret = ff_audio_mix(avr->am, avr->in_buffer);
@@ -504,18 +549,24 @@ int attribute_align_arg avresample_convert(AVAudioResampleContext *avr,

int avresample_config(AVAudioResampleContext *avr, AVFrame *out, AVFrame *in)
{
+ int ret;
+
if (avresample_is_open(avr)) {
avresample_close(avr);
}

if (in) {
- avr->in_channel_layout = in->channel_layout;
+ ret = av_channel_layout_copy(&avr->in_ch_layout, &in->ch_layout);
+ if (ret < 0)
+ return ret;
avr->in_sample_rate = in->sample_rate;
avr->in_sample_fmt = in->format;
}

if (out) {
- avr->out_channel_layout = out->channel_layout;
+ ret = av_channel_layout_copy(&avr->out_ch_layout, &out->ch_layout);
+ if (ret < 0)
+ return ret;
avr->out_sample_rate = out->sample_rate;
avr->out_sample_fmt = out->format;
}
@@ -529,7 +580,7 @@ static int config_changed(AVAudioResampleContext *avr,
int ret = 0;

if (in) {
- if (avr->in_channel_layout != in->channel_layout ||
+ if (av_channel_layout_compare(&avr->in_ch_layout, &in->ch_layout) ||
avr->in_sample_rate != in->sample_rate ||
avr->in_sample_fmt != in->format) {
ret |= AVERROR_INPUT_CHANGED;
@@ -537,7 +588,7 @@ static int config_changed(AVAudioResampleContext *avr,
}

if (out) {
- if (avr->out_channel_layout != out->channel_layout ||
+ if (av_channel_layout_compare(&avr->out_ch_layout, &out->ch_layout) ||
avr->out_sample_rate != out->sample_rate ||
avr->out_sample_fmt != out->format) {
ret |= AVERROR_OUTPUT_CHANGED;
@@ -595,7 +646,7 @@ static inline int available_samples(AVFrame *out)
if (av_sample_fmt_is_planar(out->format)) {
return samples;
} else {
- int channels = av_get_channel_layout_nb_channels(out->channel_layout);
+ int channels = out->ch_layout.nb_channels;
return samples / channels;
}
}
@@ -642,8 +693,8 @@ int avresample_get_matrix(AVAudioResampleContext *avr, double *matrix,
if (avr->am)
return ff_audio_mix_get_matrix(avr->am, matrix, stride);

- in_channels = av_get_channel_layout_nb_channels(avr->in_channel_layout);
- out_channels = av_get_channel_layout_nb_channels(avr->out_channel_layout);
+ in_channels = avr->in_ch_layout.nb_channels;
+ out_channels = avr->out_ch_layout.nb_channels;

if ( in_channels <= 0 || in_channels > AVRESAMPLE_MAX_CHANNELS ||
out_channels <= 0 || out_channels > AVRESAMPLE_MAX_CHANNELS) {
@@ -671,8 +722,8 @@ int avresample_set_matrix(AVAudioResampleContext *avr, const double *matrix,
if (avr->am)
return ff_audio_mix_set_matrix(avr->am, matrix, stride);

- in_channels = av_get_channel_layout_nb_channels(avr->in_channel_layout);
- out_channels = av_get_channel_layout_nb_channels(avr->out_channel_layout);
+ in_channels = avr->in_ch_layout.nb_channels;
+ out_channels = avr->out_ch_layout.nb_channels;

if ( in_channels <= 0 || in_channels > AVRESAMPLE_MAX_CHANNELS ||
out_channels <= 0 || out_channels > AVRESAMPLE_MAX_CHANNELS) {
@@ -700,7 +751,7 @@ int avresample_set_channel_mapping(AVAudioResampleContext *avr,
ChannelMapInfo *info = &avr->ch_map_info;
int in_channels, ch, i;

- in_channels = av_get_channel_layout_nb_channels(avr->in_channel_layout);
+ in_channels = avr->in_ch_layout.nb_channels;
if (in_channels <= 0 || in_channels > AVRESAMPLE_MAX_CHANNELS) {
av_log(avr, AV_LOG_ERROR, "Invalid input channel layout\n");
return AVERROR(EINVAL);
--
2.13.1
Vittorio Giovara
2017-06-29 20:17:14 UTC
Permalink
From: Anton Khirnov <***@khirnov.net>

Set a whitelist of supported channel order.

Signed-off-by: Vittorio Giovara <***@gmail.com>
---
libavresample/audio_mix.c | 148 ++++++------
libavresample/audio_mix_matrix.c | 477 ++++++++++++++++++++++-----------------
libavresample/avresample.h | 42 +++-
libavresample/internal.h | 10 +-
libavresample/options.c | 8 +
libavresample/tests/avresample.c | 26 +--
libavresample/utils.c | 130 +++++++----
7 files changed, 507 insertions(+), 334 deletions(-)

diff --git a/libavresample/audio_mix.c b/libavresample/audio_mix.c
index 89ecc6ba71..36dff2b979 100644
--- a/libavresample/audio_mix.c
+++ b/libavresample/audio_mix.c
@@ -20,6 +20,7 @@

#include <stdint.h>

+#include "libavutil/channel_layout.h"
#include "libavutil/common.h"
#include "libavutil/libm.h"
#include "libavutil/samplefmt.h"
@@ -34,10 +35,8 @@ struct AudioMix {
AVAudioResampleContext *avr;
enum AVSampleFormat fmt;
enum AVMixCoeffType coeff_type;
- uint64_t in_layout;
- uint64_t out_layout;
- int in_channels;
- int out_channels;
+ AVChannelLayout in_layout;
+ AVChannelLayout out_layout;

int ptr_align;
int samples_align;
@@ -331,8 +330,8 @@ static av_cold int mix_function_init(AudioMix *am)
if (!am->mix) {
av_log(am->avr, AV_LOG_ERROR, "audio_mix: NO FUNCTION FOUND: [fmt=%s] "
"[c=%s] [%d to %d]\n", av_get_sample_fmt_name(am->fmt),
- coeff_type_names[am->coeff_type], am->in_channels,
- am->out_channels);
+ coeff_type_names[am->coeff_type], am->in_layout.nb_channels,
+ am->out_layout.nb_channels);
return AVERROR_PATCHWELCOME;
}
return 0;
@@ -358,38 +357,42 @@ AudioMix *ff_audio_mix_alloc(AVAudioResampleContext *avr)

am->fmt = avr->internal_sample_fmt;
am->coeff_type = avr->mix_coeff_type;
- am->in_layout = avr->in_channel_layout;
- am->out_layout = avr->out_channel_layout;
- am->in_channels = avr->in_channels;
- am->out_channels = avr->out_channels;
+
+ ret = av_channel_layout_copy(&am->in_layout, &avr->in_ch_layout);
+ if (ret < 0)
+ goto error;
+ ret = av_channel_layout_copy(&am->out_layout, &avr->out_ch_layout);
+ if (ret < 0)
+ goto error;

/* build matrix if the user did not already set one */
if (avr->mix_matrix) {
- ret = ff_audio_mix_set_matrix(am, avr->mix_matrix, avr->in_channels);
+ ret = ff_audio_mix_set_matrix(am, avr->mix_matrix, avr->in_ch_layout.nb_channels);
if (ret < 0)
goto error;
av_freep(&avr->mix_matrix);
} else {
- double *matrix_dbl = av_mallocz(avr->out_channels * avr->in_channels *
+ double *matrix_dbl = av_mallocz(avr->out_ch_layout.nb_channels *
+ avr->in_ch_layout.nb_channels *
sizeof(*matrix_dbl));
if (!matrix_dbl)
goto error;

- ret = avresample_build_matrix(avr->in_channel_layout,
- avr->out_channel_layout,
- avr->center_mix_level,
- avr->surround_mix_level,
- avr->lfe_mix_level,
- avr->normalize_mix_level,
- matrix_dbl,
- avr->in_channels,
- avr->matrix_encoding);
+ ret = avresample_build_matrix2(&avr->in_ch_layout,
+ &avr->out_ch_layout,
+ avr->center_mix_level,
+ avr->surround_mix_level,
+ avr->lfe_mix_level,
+ avr->normalize_mix_level,
+ matrix_dbl,
+ avr->in_ch_layout.nb_channels,
+ avr->matrix_encoding);
if (ret < 0) {
av_free(matrix_dbl);
goto error;
}

- ret = ff_audio_mix_set_matrix(am, matrix_dbl, avr->in_channels);
+ ret = ff_audio_mix_set_matrix(am, matrix_dbl, avr->in_ch_layout.nb_channels);
if (ret < 0) {
av_log(avr, AV_LOG_ERROR, "error setting mix matrix\n");
av_free(matrix_dbl);
@@ -402,7 +405,7 @@ AudioMix *ff_audio_mix_alloc(AVAudioResampleContext *avr)
return am;

error:
- av_free(am);
+ ff_audio_mix_free(&am);
return NULL;
}

@@ -422,11 +425,16 @@ void ff_audio_mix_free(AudioMix **am_p)
memset(am->matrix_q15, 0, sizeof(am->matrix_q15));
memset(am->matrix_flt, 0, sizeof(am->matrix_flt));

+ av_channel_layout_uninit(&am->in_layout);
+ av_channel_layout_uninit(&am->out_layout);
+
av_freep(am_p);
}

int ff_audio_mix(AudioMix *am, AudioData *src)
{
+ int in_channels = am->in_layout.nb_channels;
+ int out_channels = am->out_layout.nb_channels;
int use_generic = 1;
int len = src->nb_samples;
int i, j;
@@ -442,16 +450,16 @@ int ff_audio_mix(AudioMix *am, AudioData *src)
}
}
av_log(am->avr, AV_LOG_TRACE, "audio_mix: %d samples - %d to %d channels (%s)\n",
- src->nb_samples, am->in_channels, am->out_channels,
+ src->nb_samples, in_channels, out_channels,
use_generic ? am->func_descr_generic : am->func_descr);

if (am->in_matrix_channels && am->out_matrix_channels) {
uint8_t **data;
uint8_t *data0[AVRESAMPLE_MAX_CHANNELS] = { NULL };

- if (am->out_matrix_channels < am->out_channels ||
- am->in_matrix_channels < am->in_channels) {
- for (i = 0, j = 0; i < FFMAX(am->in_channels, am->out_channels); i++) {
+ if (am->out_matrix_channels < out_channels ||
+ am->in_matrix_channels < in_channels) {
+ for (i = 0, j = 0; i < FFMAX(in_channels, out_channels); i++) {
if (am->input_skip[i] || am->output_skip[i] || am->output_zero[i])
continue;
data0[j++] = src->data[i];
@@ -469,23 +477,25 @@ int ff_audio_mix(AudioMix *am, AudioData *src)
am->in_matrix_channels);
}

- if (am->out_matrix_channels < am->out_channels) {
- for (i = 0; i < am->out_channels; i++)
+ if (am->out_matrix_channels < out_channels) {
+ for (i = 0; i < out_channels; i++)
if (am->output_zero[i])
av_samples_set_silence(&src->data[i], 0, len, 1, am->fmt);
}

- ff_audio_data_set_channels(src, am->out_channels);
+ ff_audio_data_set_channels(src, out_channels);

return 0;
}

int ff_audio_mix_get_matrix(AudioMix *am, double *matrix, int stride)
{
+ int in_channels = am->in_layout.nb_channels;
+ int out_channels = am->out_layout.nb_channels;
int i, o, i0, o0;

- if ( am->in_channels <= 0 || am->in_channels > AVRESAMPLE_MAX_CHANNELS ||
- am->out_channels <= 0 || am->out_channels > AVRESAMPLE_MAX_CHANNELS) {
+ if (in_channels <= 0 || in_channels > AVRESAMPLE_MAX_CHANNELS ||
+ out_channels <= 0 || out_channels > AVRESAMPLE_MAX_CHANNELS) {
av_log(am->avr, AV_LOG_ERROR, "Invalid channel counts\n");
return AVERROR(EINVAL);
}
@@ -495,8 +505,8 @@ int ff_audio_mix_get_matrix(AudioMix *am, double *matrix, int stride)
av_log(am->avr, AV_LOG_ERROR, "matrix is not set\n"); \
return AVERROR(EINVAL); \
} \
- for (o = 0, o0 = 0; o < am->out_channels; o++) { \
- for (i = 0, i0 = 0; i < am->in_channels; i++) { \
+ for (o = 0, o0 = 0; o < out_channels; o++) { \
+ for (i = 0, i0 = 0; i < in_channels; i++) { \
if (am->input_skip[i] || am->output_zero[o]) \
matrix[o * stride + i] = 0.0; \
else \
@@ -529,6 +539,8 @@ int ff_audio_mix_get_matrix(AudioMix *am, double *matrix, int stride)

static void reduce_matrix(AudioMix *am, const double *matrix, int stride)
{
+ int in_channels = am->in_layout.nb_channels;
+ int out_channels = am->out_layout.nb_channels;
int i, o;

memset(am->output_zero, 0, sizeof(am->output_zero));
@@ -536,11 +548,11 @@ static void reduce_matrix(AudioMix *am, const double *matrix, int stride)
memset(am->output_skip, 0, sizeof(am->output_skip));

/* exclude output channels if they can be zeroed instead of mixed */
- for (o = 0; o < am->out_channels; o++) {
+ for (o = 0; o < out_channels; o++) {
int zero = 1;

/* check if the output is always silent */
- for (i = 0; i < am->in_channels; i++) {
+ for (i = 0; i < in_channels; i++) {
if (matrix[o * stride + i] != 0.0) {
zero = 0;
break;
@@ -548,8 +560,8 @@ static void reduce_matrix(AudioMix *am, const double *matrix, int stride)
}
/* check if the corresponding input channel makes a contribution to
any output channel */
- if (o < am->in_channels) {
- for (i = 0; i < am->out_channels; i++) {
+ if (o < in_channels) {
+ for (i = 0; i < out_channels; i++) {
if (matrix[i * stride + o] != 0.0) {
zero = 0;
break;
@@ -559,7 +571,7 @@ static void reduce_matrix(AudioMix *am, const double *matrix, int stride)
if (zero) {
am->output_zero[o] = 1;
am->out_matrix_channels--;
- if (o < am->in_channels)
+ if (o < in_channels)
am->in_matrix_channels--;
}
}
@@ -571,10 +583,10 @@ static void reduce_matrix(AudioMix *am, const double *matrix, int stride)

/* skip input channels that contribute fully only to the corresponding
output channel */
- for (i = 0; i < FFMIN(am->in_channels, am->out_channels); i++) {
+ for (i = 0; i < FFMIN(in_channels, out_channels); i++) {
int skip = 1;

- for (o = 0; o < am->out_channels; o++) {
+ for (o = 0; o < out_channels; o++) {
int i0;
if ((o != i && matrix[o * stride + i] != 0.0) ||
(o == i && matrix[o * stride + i] != 1.0)) {
@@ -584,7 +596,7 @@ static void reduce_matrix(AudioMix *am, const double *matrix, int stride)
/* if the input contributes fully to the output, also check that no
other inputs contribute to this output */
if (o == i) {
- for (i0 = 0; i0 < am->in_channels; i0++) {
+ for (i0 = 0; i0 < in_channels; i0++) {
if (i0 != i && matrix[o * stride + i0] != 0.0) {
skip = 0;
break;
@@ -598,10 +610,10 @@ static void reduce_matrix(AudioMix *am, const double *matrix, int stride)
}
}
/* skip input channels that do not contribute to any output channel */
- for (; i < am->in_channels; i++) {
+ for (; i < in_channels; i++) {
int contrib = 0;

- for (o = 0; o < am->out_channels; o++) {
+ for (o = 0; o < out_channels; o++) {
if (matrix[o * stride + i] != 0.0) {
contrib = 1;
break;
@@ -619,11 +631,11 @@ static void reduce_matrix(AudioMix *am, const double *matrix, int stride)

/* skip output channels that only get full contribution from the
corresponding input channel */
- for (o = 0; o < FFMIN(am->in_channels, am->out_channels); o++) {
+ for (o = 0; o < FFMIN(in_channels, out_channels); o++) {
int skip = 1;
int o0;

- for (i = 0; i < am->in_channels; i++) {
+ for (i = 0; i < in_channels; i++) {
if ((o != i && matrix[o * stride + i] != 0.0) ||
(o == i && matrix[o * stride + i] != 1.0)) {
skip = 0;
@@ -633,7 +645,7 @@ static void reduce_matrix(AudioMix *am, const double *matrix, int stride)
/* check if the corresponding input channel makes a contribution to
any other output channel */
i = o;
- for (o0 = 0; o0 < am->out_channels; o0++) {
+ for (o0 = 0; o0 < out_channels; o0++) {
if (o0 != i && matrix[o0 * stride + i] != 0.0) {
skip = 0;
break;
@@ -653,11 +665,15 @@ static void reduce_matrix(AudioMix *am, const double *matrix, int stride)
int ff_audio_mix_set_matrix(AudioMix *am, const double *matrix, int stride)
{
int i, o, i0, o0, ret;
- char in_layout_name[128];
- char out_layout_name[128];
-
- if ( am->in_channels <= 0 || am->in_channels > AVRESAMPLE_MAX_CHANNELS ||
- am->out_channels <= 0 || am->out_channels > AVRESAMPLE_MAX_CHANNELS) {
+ int in_channels = am->in_layout.nb_channels;
+ int out_channels = am->out_layout.nb_channels;
+ char *in_layout_name;
+ char *out_layout_name;
+
+ if (!av_channel_layout_check(&am->in_layout) ||
+ !av_channel_layout_check(&am->out_layout) ||
+ am->in_layout.nb_channels > AVRESAMPLE_MAX_CHANNELS ||
+ am->out_layout.nb_channels > AVRESAMPLE_MAX_CHANNELS) {
av_log(am->avr, AV_LOG_ERROR, "Invalid channel counts\n");
return AVERROR(EINVAL);
}
@@ -667,8 +683,8 @@ int ff_audio_mix_set_matrix(AudioMix *am, const double *matrix, int stride)
am->matrix = NULL;
}

- am->in_matrix_channels = am->in_channels;
- am->out_matrix_channels = am->out_channels;
+ am->in_matrix_channels = am->in_layout.nb_channels;
+ am->out_matrix_channels = am->out_layout.nb_channels;

reduce_matrix(am, matrix, stride);

@@ -678,13 +694,13 @@ int ff_audio_mix_set_matrix(AudioMix *am, const double *matrix, int stride)
sizeof(*am->matrix_## type[0])); \
if (!am->matrix_## type[0]) \
return AVERROR(ENOMEM); \
- for (o = 0, o0 = 0; o < am->out_channels; o++) { \
+ for (o = 0, o0 = 0; o < out_channels; o++) { \
if (am->output_zero[o] || am->output_skip[o]) \
continue; \
if (o0 > 0) \
am->matrix_## type[o0] = am->matrix_## type[o0 - 1] + \
am->in_matrix_channels; \
- for (i = 0, i0 = 0; i < am->in_channels; i++) { \
+ for (i = 0, i0 = 0; i < in_channels; i++) { \
double v; \
if (am->input_skip[i] || am->output_zero[i]) \
continue; \
@@ -717,26 +733,28 @@ int ff_audio_mix_set_matrix(AudioMix *am, const double *matrix, int stride)
if (ret < 0)
return ret;

- av_get_channel_layout_string(in_layout_name, sizeof(in_layout_name),
- am->in_channels, am->in_layout);
- av_get_channel_layout_string(out_layout_name, sizeof(out_layout_name),
- am->out_channels, am->out_layout);
- av_log(am->avr, AV_LOG_DEBUG, "audio_mix: %s to %s\n",
- in_layout_name, out_layout_name);
+ in_layout_name = av_channel_layout_describe(&am->in_layout);
+ out_layout_name = av_channel_layout_describe(&am->out_layout);
+ if (in_layout_name && out_layout_name)
+ av_log(am->avr, AV_LOG_DEBUG, "audio_mix: %s to %s\n",
+ in_layout_name, out_layout_name);
av_log(am->avr, AV_LOG_DEBUG, "matrix size: %d x %d\n",
am->in_matrix_channels, am->out_matrix_channels);
- for (o = 0; o < am->out_channels; o++) {
- for (i = 0; i < am->in_channels; i++) {
+ for (o = 0; o < out_channels; o++) {
+ for (i = 0; i < in_channels; i++) {
if (am->output_zero[o])
av_log(am->avr, AV_LOG_DEBUG, " (ZERO)");
else if (am->input_skip[i] || am->output_zero[i] || am->output_skip[o])
av_log(am->avr, AV_LOG_DEBUG, " (SKIP)");
else
av_log(am->avr, AV_LOG_DEBUG, " %0.3f ",
- matrix[o * am->in_channels + i]);
+ matrix[o * in_channels + i]);
}
av_log(am->avr, AV_LOG_DEBUG, "\n");
}

+ av_freep(&in_layout_name);
+ av_freep(&out_layout_name);
+
return 0;
}
diff --git a/libavresample/audio_mix_matrix.c b/libavresample/audio_mix_matrix.c
index 5182ae1bf9..a5a16edca1 100644
--- a/libavresample/audio_mix_matrix.c
+++ b/libavresample/audio_mix_matrix.c
@@ -21,6 +21,7 @@

#include <stdint.h>

+#include "libavutil/channel_layout.h"
#include "libavutil/common.h"
#include "libavutil/libm.h"
#include "libavutil/samplefmt.h"
@@ -29,33 +30,6 @@
#include "audio_data.h"
#include "audio_mix.h"

-/* channel positions */
-#define FRONT_LEFT 0
-#define FRONT_RIGHT 1
-#define FRONT_CENTER 2
-#define LOW_FREQUENCY 3
-#define BACK_LEFT 4
-#define BACK_RIGHT 5
-#define FRONT_LEFT_OF_CENTER 6
-#define FRONT_RIGHT_OF_CENTER 7
-#define BACK_CENTER 8
-#define SIDE_LEFT 9
-#define SIDE_RIGHT 10
-#define TOP_CENTER 11
-#define TOP_FRONT_LEFT 12
-#define TOP_FRONT_CENTER 13
-#define TOP_FRONT_RIGHT 14
-#define TOP_BACK_LEFT 15
-#define TOP_BACK_CENTER 16
-#define TOP_BACK_RIGHT 17
-#define STEREO_LEFT 29
-#define STEREO_RIGHT 30
-#define WIDE_LEFT 31
-#define WIDE_RIGHT 32
-#define SURROUND_DIRECT_LEFT 33
-#define SURROUND_DIRECT_RIGHT 34
-#define LOW_FREQUENCY_2 35
-
#define SQRT3_2 1.22474487139158904909 /* sqrt(3/2) */

static av_always_inline int even(uint64_t layout)
@@ -63,232 +37,313 @@ static av_always_inline int even(uint64_t layout)
return (!layout || !!(layout & (layout - 1)));
}

-static int sane_layout(uint64_t layout)
+static int sane_layout(const AVChannelLayout *layout)
{
/* check that there is at least 1 front speaker */
- if (!(layout & AV_CH_LAYOUT_SURROUND))
+ if (!av_channel_layout_subset(layout, AV_CH_LAYOUT_SURROUND))
return 0;

/* check for left/right symmetry */
- if (!even(layout & (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT)) ||
- !even(layout & (AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT)) ||
- !even(layout & (AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT)) ||
- !even(layout & (AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER)) ||
- !even(layout & (AV_CH_TOP_FRONT_LEFT | AV_CH_TOP_FRONT_RIGHT)) ||
- !even(layout & (AV_CH_TOP_BACK_LEFT | AV_CH_TOP_BACK_RIGHT)) ||
- !even(layout & (AV_CH_STEREO_LEFT | AV_CH_STEREO_RIGHT)) ||
- !even(layout & (AV_CH_WIDE_LEFT | AV_CH_WIDE_RIGHT)) ||
- !even(layout & (AV_CH_SURROUND_DIRECT_LEFT | AV_CH_SURROUND_DIRECT_RIGHT)))
+ if (!even(av_channel_layout_subset(layout, (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT))) ||
+ !even(av_channel_layout_subset(layout, (AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT))) ||
+ !even(av_channel_layout_subset(layout, (AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT))) ||
+ !even(av_channel_layout_subset(layout, (AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER))) ||
+ !even(av_channel_layout_subset(layout, (AV_CH_TOP_FRONT_LEFT | AV_CH_TOP_FRONT_RIGHT))) ||
+ !even(av_channel_layout_subset(layout, (AV_CH_TOP_BACK_LEFT | AV_CH_TOP_BACK_RIGHT))) ||
+ !even(av_channel_layout_subset(layout, (AV_CH_STEREO_LEFT | AV_CH_STEREO_RIGHT))) ||
+ !even(av_channel_layout_subset(layout, (AV_CH_WIDE_LEFT | AV_CH_WIDE_RIGHT))) ||
+ !even(av_channel_layout_subset(layout, (AV_CH_SURROUND_DIRECT_LEFT | AV_CH_SURROUND_DIRECT_RIGHT))))
return 0;

return 1;
}

-int avresample_build_matrix(uint64_t in_layout, uint64_t out_layout,
- double center_mix_level, double surround_mix_level,
- double lfe_mix_level, int normalize,
- double *matrix_out, int stride,
- enum AVMatrixEncoding matrix_encoding)
+#define IDX_OUT(ch) (av_channel_layout_channel_index(out_layout, ch))
+
+int avresample_build_matrix2(const AVChannelLayout *in_layout,
+ const AVChannelLayout *out_layout,
+ double center_mix_level, double surround_mix_level,
+ double lfe_mix_level, int normalize,
+ double *matrix, int stride,
+ enum AVMatrixEncoding matrix_encoding)
{
- int i, j, out_i, out_j;
- double matrix[64][64] = {{0}};
- int64_t unaccounted;
+ static const AVChannelLayout stereo = AV_CHANNEL_LAYOUT_STEREO;
+ int i, j;
double maxcoef = 0;
- int in_channels, out_channels;
-
- if ((out_layout & AV_CH_LAYOUT_STEREO_DOWNMIX) == AV_CH_LAYOUT_STEREO_DOWNMIX) {
- out_layout = AV_CH_LAYOUT_STEREO;
- }
-
- unaccounted = in_layout & ~out_layout;
-
- in_channels = av_get_channel_layout_nb_channels( in_layout);
- out_channels = av_get_channel_layout_nb_channels(out_layout);
-
- memset(matrix_out, 0, out_channels * stride * sizeof(*matrix_out));
+ int idx_in, idx_out, idx_r, idx_l;
+ int in_channels = in_layout->nb_channels;
+ int out_channels = out_layout->nb_channels;;

/* check if layouts are supported */
- if (!in_layout || in_channels > AVRESAMPLE_MAX_CHANNELS)
+ if (!av_channel_layout_check(in_layout) ||
+ in_channels > AVRESAMPLE_MAX_CHANNELS)
return AVERROR(EINVAL);
- if (!out_layout || out_channels > AVRESAMPLE_MAX_CHANNELS)
+ if (!av_channel_layout_check(out_layout) ||
+ out_channels > AVRESAMPLE_MAX_CHANNELS)
return AVERROR(EINVAL);

/* check if layouts are unbalanced or abnormal */
if (!sane_layout(in_layout) || !sane_layout(out_layout))
return AVERROR_PATCHWELCOME;

- /* route matching input/output channels */
- for (i = 0; i < 64; i++) {
- if (in_layout & out_layout & (1ULL << i))
- matrix[i][i] = 1.0;
- }
+ if (out_channels == 2 &&
+ IDX_OUT(AV_CHAN_STEREO_LEFT) >= 0 &&
+ IDX_OUT(AV_CHAN_STEREO_RIGHT) >= 0)
+ out_layout = &stereo;
+
+ memset(matrix, 0, out_channels * stride * sizeof(*matrix));

- /* mix front center to front left/right */
- if (unaccounted & AV_CH_FRONT_CENTER) {
- if ((out_layout & AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO) {
- if ((in_layout & AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO) {
- matrix[FRONT_LEFT ][FRONT_CENTER] += center_mix_level;
- matrix[FRONT_RIGHT][FRONT_CENTER] += center_mix_level;
+ for (idx_in = 0; idx_in < in_channels; idx_in++) {
+ enum AVChannel in_ch = av_channel_layout_get_channel(in_layout, idx_in);
+
+ idx_out = IDX_OUT(in_ch);
+
+ /* check if the input channel is also present in output */
+ if (idx_out >= 0) {
+ if (in_ch == AV_CHAN_FRONT_CENTER &&
+ av_channel_layout_subset(in_layout, AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO &&
+ !av_channel_layout_subset(out_layout, AV_CH_LAYOUT_STEREO)) {
+ /* mix left/right/center to center */
+ matrix[idx_out * stride + idx_in] = center_mix_level * M_SQRT2;
} else {
- matrix[FRONT_LEFT ][FRONT_CENTER] += M_SQRT1_2;
- matrix[FRONT_RIGHT][FRONT_CENTER] += M_SQRT1_2;
+ /* just copy it */
+ matrix[idx_out * stride + idx_in] = 1.0;
}
- } else
- return AVERROR_PATCHWELCOME;
- }
- /* mix front left/right to center */
- if (unaccounted & AV_CH_LAYOUT_STEREO) {
- if (out_layout & AV_CH_FRONT_CENTER) {
- matrix[FRONT_CENTER][FRONT_LEFT ] += M_SQRT1_2;
- matrix[FRONT_CENTER][FRONT_RIGHT] += M_SQRT1_2;
- /* mix left/right/center to center */
- if (in_layout & AV_CH_FRONT_CENTER)
- matrix[FRONT_CENTER][FRONT_CENTER] = center_mix_level * M_SQRT2;
- } else
- return AVERROR_PATCHWELCOME;
- }
- /* mix back center to back, side, or front */
- if (unaccounted & AV_CH_BACK_CENTER) {
- if (out_layout & AV_CH_BACK_LEFT) {
- matrix[BACK_LEFT ][BACK_CENTER] += M_SQRT1_2;
- matrix[BACK_RIGHT][BACK_CENTER] += M_SQRT1_2;
- } else if (out_layout & AV_CH_SIDE_LEFT) {
- matrix[SIDE_LEFT ][BACK_CENTER] += M_SQRT1_2;
- matrix[SIDE_RIGHT][BACK_CENTER] += M_SQRT1_2;
- } else if (out_layout & AV_CH_FRONT_LEFT) {
- if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY ||
- matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
- if (unaccounted & (AV_CH_BACK_LEFT | AV_CH_SIDE_LEFT)) {
- matrix[FRONT_LEFT ][BACK_CENTER] -= surround_mix_level * M_SQRT1_2;
- matrix[FRONT_RIGHT][BACK_CENTER] += surround_mix_level * M_SQRT1_2;
+
+ continue;
+ }
+
+ /* the input channel is not present in the output layout */
+
+ /* mix front center to front left/right */
+ if (in_ch == AV_CHAN_FRONT_CENTER) {
+ int idx_l = IDX_OUT(AV_CHAN_FRONT_LEFT);
+ int idx_r = IDX_OUT(AV_CHAN_FRONT_RIGHT);
+ if (idx_l >= 0 && idx_r >= 0) {
+ matrix[idx_l * stride + idx_in] += M_SQRT1_2;
+ matrix[idx_r * stride + idx_in] += M_SQRT1_2;
+ }
+ }
+
+ /* mix front left/right to center */
+ if (in_ch == AV_CHAN_FRONT_LEFT || in_ch == AV_CHAN_FRONT_RIGHT) {
+ idx_out = IDX_OUT(AV_CHAN_FRONT_CENTER);
+ if (idx_out >= 0)
+ matrix[idx_out * stride + idx_in] += M_SQRT1_2;
+ }
+
+ /* mix back center to back, side, or front */
+ if (in_ch == AV_CHAN_BACK_CENTER) {
+ int idx_l = IDX_OUT(AV_CHAN_BACK_LEFT);
+ int idx_r = IDX_OUT(AV_CHAN_BACK_RIGHT);
+ if (idx_l >= 0 && idx_r >= 0) {
+ matrix[idx_l * stride + idx_in] += M_SQRT1_2;
+ matrix[idx_r * stride + idx_in] += M_SQRT1_2;
+ continue;
+ }
+
+ idx_l = IDX_OUT(AV_CHAN_SIDE_LEFT);
+ idx_r = IDX_OUT(AV_CHAN_SIDE_RIGHT);
+ if (idx_l >= 0 && idx_r >= 0) {
+ matrix[idx_l * stride + idx_in] += M_SQRT1_2;
+ matrix[idx_r * stride + idx_in] += M_SQRT1_2;
+ continue;
+ }
+
+ idx_l = IDX_OUT(AV_CHAN_FRONT_LEFT);
+ idx_r = IDX_OUT(AV_CHAN_FRONT_RIGHT);
+ if (idx_l >= 0 && idx_r >= 0) {
+ if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY ||
+ matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
+ if (!av_channel_layout_subset(out_layout, AV_CH_BACK_LEFT | AV_CH_SIDE_LEFT) &&
+ av_channel_layout_subset(in_layout, AV_CH_BACK_LEFT | AV_CH_SIDE_LEFT)) {
+ matrix[idx_l * stride + idx_in] -= surround_mix_level * M_SQRT1_2;
+ matrix[idx_r * stride + idx_in] += surround_mix_level * M_SQRT1_2;
+ } else {
+ matrix[idx_l * stride + idx_in] -= surround_mix_level;
+ matrix[idx_r * stride + idx_in] += surround_mix_level;
+ }
} else {
- matrix[FRONT_LEFT ][BACK_CENTER] -= surround_mix_level;
- matrix[FRONT_RIGHT][BACK_CENTER] += surround_mix_level;
+ matrix[idx_l * stride + idx_in] += surround_mix_level * M_SQRT1_2;
+ matrix[idx_r * stride + idx_in] += surround_mix_level * M_SQRT1_2;
}
- } else {
- matrix[FRONT_LEFT ][BACK_CENTER] += surround_mix_level * M_SQRT1_2;
- matrix[FRONT_RIGHT][BACK_CENTER] += surround_mix_level * M_SQRT1_2;
+ continue;
}
- } else if (out_layout & AV_CH_FRONT_CENTER) {
- matrix[FRONT_CENTER][BACK_CENTER] += surround_mix_level * M_SQRT1_2;
- } else
- return AVERROR_PATCHWELCOME;
- }
- /* mix back left/right to back center, side, or front */
- if (unaccounted & AV_CH_BACK_LEFT) {
- if (out_layout & AV_CH_BACK_CENTER) {
- matrix[BACK_CENTER][BACK_LEFT ] += M_SQRT1_2;
- matrix[BACK_CENTER][BACK_RIGHT] += M_SQRT1_2;
- } else if (out_layout & AV_CH_SIDE_LEFT) {
- /* if side channels do not exist in the input, just copy back
- channels to side channels, otherwise mix back into side */
- if (in_layout & AV_CH_SIDE_LEFT) {
- matrix[SIDE_LEFT ][BACK_LEFT ] += M_SQRT1_2;
- matrix[SIDE_RIGHT][BACK_RIGHT] += M_SQRT1_2;
- } else {
- matrix[SIDE_LEFT ][BACK_LEFT ] += 1.0;
- matrix[SIDE_RIGHT][BACK_RIGHT] += 1.0;
+
+ idx_out = IDX_OUT(AV_CHAN_FRONT_CENTER);
+ if (idx_out >= 0) {
+ matrix[idx_out * stride + idx_in] += surround_mix_level * M_SQRT1_2;
+ continue;
}
- } else if (out_layout & AV_CH_FRONT_LEFT) {
- if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) {
- matrix[FRONT_LEFT ][BACK_LEFT ] -= surround_mix_level * M_SQRT1_2;
- matrix[FRONT_LEFT ][BACK_RIGHT] -= surround_mix_level * M_SQRT1_2;
- matrix[FRONT_RIGHT][BACK_LEFT ] += surround_mix_level * M_SQRT1_2;
- matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level * M_SQRT1_2;
- } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
- matrix[FRONT_LEFT ][BACK_LEFT ] -= surround_mix_level * SQRT3_2;
- matrix[FRONT_LEFT ][BACK_RIGHT] -= surround_mix_level * M_SQRT1_2;
- matrix[FRONT_RIGHT][BACK_LEFT ] += surround_mix_level * M_SQRT1_2;
- matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level * SQRT3_2;
- } else {
- matrix[FRONT_LEFT ][BACK_LEFT ] += surround_mix_level;
- matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level;
+ }
+
+ /* mix back left/right to back center, side, or front */
+ if (in_ch == AV_CHAN_BACK_LEFT || in_ch == AV_CHAN_BACK_RIGHT) {
+ idx_out = IDX_OUT(AV_CHAN_BACK_CENTER);
+ if (idx_out >= 0) {
+ matrix[idx_out * stride + idx_in] += M_SQRT1_2;
+ continue;
}
- } else if (out_layout & AV_CH_FRONT_CENTER) {
- matrix[FRONT_CENTER][BACK_LEFT ] += surround_mix_level * M_SQRT1_2;
- matrix[FRONT_CENTER][BACK_RIGHT] += surround_mix_level * M_SQRT1_2;
- } else
- return AVERROR_PATCHWELCOME;
- }
- /* mix side left/right into back or front */
- if (unaccounted & AV_CH_SIDE_LEFT) {
- if (out_layout & AV_CH_BACK_LEFT) {
- /* if back channels do not exist in the input, just copy side
- channels to back channels, otherwise mix side into back */
- if (in_layout & AV_CH_BACK_LEFT) {
- matrix[BACK_LEFT ][SIDE_LEFT ] += M_SQRT1_2;
- matrix[BACK_RIGHT][SIDE_RIGHT] += M_SQRT1_2;
- } else {
- matrix[BACK_LEFT ][SIDE_LEFT ] += 1.0;
- matrix[BACK_RIGHT][SIDE_RIGHT] += 1.0;
+
+ idx_out = IDX_OUT(in_ch == AV_CHAN_BACK_LEFT ? AV_CHAN_SIDE_LEFT :
+ AV_CHAN_SIDE_RIGHT);
+ if (idx_out >= 0) {
+ /* if side channels do not exist in the input, just copy back
+ channels to side channels, otherwise mix back into side */
+ if (av_channel_layout_subset(in_layout, AV_CH_SIDE_LEFT))
+ matrix[idx_out * stride + idx_in] += M_SQRT1_2;
+ else
+ matrix[idx_out * stride + idx_in] += 1.0;
+
+ continue;
}
- } else if (out_layout & AV_CH_BACK_CENTER) {
- matrix[BACK_CENTER][SIDE_LEFT ] += M_SQRT1_2;
- matrix[BACK_CENTER][SIDE_RIGHT] += M_SQRT1_2;
- } else if (out_layout & AV_CH_FRONT_LEFT) {
- if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) {
- matrix[FRONT_LEFT ][SIDE_LEFT ] -= surround_mix_level * M_SQRT1_2;
- matrix[FRONT_LEFT ][SIDE_RIGHT] -= surround_mix_level * M_SQRT1_2;
- matrix[FRONT_RIGHT][SIDE_LEFT ] += surround_mix_level * M_SQRT1_2;
- matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level * M_SQRT1_2;
- } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
- matrix[FRONT_LEFT ][SIDE_LEFT ] -= surround_mix_level * SQRT3_2;
- matrix[FRONT_LEFT ][SIDE_RIGHT] -= surround_mix_level * M_SQRT1_2;
- matrix[FRONT_RIGHT][SIDE_LEFT ] += surround_mix_level * M_SQRT1_2;
- matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level * SQRT3_2;
- } else {
- matrix[FRONT_LEFT ][SIDE_LEFT ] += surround_mix_level;
- matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level;
+
+ idx_l = IDX_OUT(AV_CHAN_FRONT_LEFT);
+ idx_r = IDX_OUT(AV_CHAN_FRONT_RIGHT);
+ if (idx_l >= 0 && idx_r >= 0) {
+ if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) {
+ matrix[idx_l * stride + idx_in] -= surround_mix_level * M_SQRT1_2;
+ matrix[idx_r * stride + idx_in] += surround_mix_level * M_SQRT1_2;
+ } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
+ if (in_ch == AV_CHAN_BACK_LEFT) {
+ matrix[idx_l * stride + idx_in] -= surround_mix_level * SQRT3_2;
+ matrix[idx_r * stride + idx_in] += surround_mix_level * M_SQRT1_2;
+ } else {
+ matrix[idx_l * stride + idx_in] -= surround_mix_level * M_SQRT1_2;
+ matrix[idx_r * stride + idx_in] += surround_mix_level * SQRT3_2;
+ }
+ } else {
+ idx_out = (in_ch == AV_CHAN_BACK_LEFT) ? idx_l : idx_r;
+ matrix[idx_out * stride + idx_in] += surround_mix_level;
+ }
+
+ continue;
}
- } else if (out_layout & AV_CH_FRONT_CENTER) {
- matrix[FRONT_CENTER][SIDE_LEFT ] += surround_mix_level * M_SQRT1_2;
- matrix[FRONT_CENTER][SIDE_RIGHT] += surround_mix_level * M_SQRT1_2;
- } else
- return AVERROR_PATCHWELCOME;
- }
- /* mix left-of-center/right-of-center into front left/right or center */
- if (unaccounted & AV_CH_FRONT_LEFT_OF_CENTER) {
- if (out_layout & AV_CH_FRONT_LEFT) {
- matrix[FRONT_LEFT ][FRONT_LEFT_OF_CENTER ] += 1.0;
- matrix[FRONT_RIGHT][FRONT_RIGHT_OF_CENTER] += 1.0;
- } else if (out_layout & AV_CH_FRONT_CENTER) {
- matrix[FRONT_CENTER][FRONT_LEFT_OF_CENTER ] += M_SQRT1_2;
- matrix[FRONT_CENTER][FRONT_RIGHT_OF_CENTER] += M_SQRT1_2;
- } else
- return AVERROR_PATCHWELCOME;
- }
- /* mix LFE into front left/right or center */
- if (unaccounted & AV_CH_LOW_FREQUENCY) {
- if (out_layout & AV_CH_FRONT_CENTER) {
- matrix[FRONT_CENTER][LOW_FREQUENCY] += lfe_mix_level;
- } else if (out_layout & AV_CH_FRONT_LEFT) {
- matrix[FRONT_LEFT ][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2;
- matrix[FRONT_RIGHT][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2;
- } else
- return AVERROR_PATCHWELCOME;
+
+ idx_out = IDX_OUT(AV_CHAN_FRONT_CENTER);
+ if (idx_out >= 0) {
+ matrix[idx_out * stride + idx_in] += surround_mix_level * M_SQRT1_2;
+ continue;
+ }
+ }
+
+ /* mix side left/right into back or front */
+ if (in_ch == AV_CHAN_SIDE_LEFT || in_ch == AV_CHAN_SIDE_RIGHT) {
+ idx_out = IDX_OUT(in_ch == AV_CHAN_SIDE_LEFT ? AV_CHAN_BACK_LEFT :
+ AV_CHAN_BACK_RIGHT);
+ if (idx_out >= 0) {
+ /* if back channels do not exist in the input, just copy side
+ channels to back channels, otherwise mix side into back */
+ if (av_channel_layout_subset(in_layout, AV_CH_BACK_LEFT))
+ matrix[idx_out * stride + idx_in] += M_SQRT1_2;
+ else
+ matrix[idx_out * stride + idx_in] += 1.0;
+
+ continue;
+ }
+
+ idx_out = IDX_OUT(AV_CHAN_BACK_CENTER);
+ if (idx_out >= 0) {
+ matrix[idx_out * stride + idx_in] += M_SQRT1_2;
+ continue;
+ }
+
+
+ idx_l = IDX_OUT(AV_CHAN_FRONT_LEFT);
+ idx_r = IDX_OUT(AV_CHAN_FRONT_RIGHT);
+ if (idx_l >= 0 && idx_r >= 0) {
+ if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) {
+ matrix[idx_l * stride + idx_in] -= surround_mix_level * M_SQRT1_2;
+ matrix[idx_r * stride + idx_in] += surround_mix_level * M_SQRT1_2;
+ } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
+ if (in_ch == AV_CHAN_SIDE_LEFT) {
+ matrix[idx_l * stride + idx_in] -= surround_mix_level * SQRT3_2;
+ matrix[idx_r * stride + idx_in] += surround_mix_level * M_SQRT1_2;
+ } else {
+ matrix[idx_l * stride + idx_in] -= surround_mix_level * M_SQRT1_2;
+ matrix[idx_r * stride + idx_in] += surround_mix_level * SQRT3_2;
+ }
+ } else {
+ idx_out = (in_ch == AV_CHAN_SIDE_LEFT) ? idx_l : idx_r;
+ matrix[idx_out * stride + idx_in] += surround_mix_level;
+ }
+
+ continue;
+ }
+
+ idx_out = IDX_OUT(AV_CHAN_FRONT_CENTER);
+ if (idx_out >= 0) {
+ matrix[idx_out * stride + idx_in] += surround_mix_level * M_SQRT1_2;
+ continue;
+ }
+ }
+
+ /* mix left-of-center/right-of-center into front left/right or center */
+ if (in_ch == AV_CHAN_FRONT_LEFT_OF_CENTER ||
+ in_ch == AV_CHAN_FRONT_RIGHT_OF_CENTER) {
+ idx_out = IDX_OUT(in_ch == AV_CHAN_FRONT_LEFT_OF_CENTER ?
+ AV_CHAN_FRONT_LEFT : AV_CHAN_FRONT_RIGHT);
+ if (idx_out >= 0) {
+ matrix[idx_out * stride + idx_in] += 1.0;
+ continue;
+ }
+
+ idx_out = IDX_OUT(AV_CHAN_FRONT_CENTER);
+ if (idx_out >= 0) {
+ matrix[idx_out * stride + idx_in] += M_SQRT1_2;
+ continue;
+ }
+ }
+
+ /* mix LFE into front left/right or center */
+ if (in_ch == AV_CHAN_LOW_FREQUENCY) {
+ idx_out = IDX_OUT(AV_CHAN_FRONT_CENTER);
+ if (idx_out >= 0) {
+ matrix[idx_out * stride + idx_in] += lfe_mix_level;
+ continue;
+ }
+
+ idx_l = IDX_OUT(AV_CHAN_FRONT_LEFT);
+ idx_r = IDX_OUT(AV_CHAN_FRONT_RIGHT);
+ if (idx_l >= 0 && idx_r >= 0) {
+ matrix[idx_l * stride + idx_in] += lfe_mix_level * M_SQRT1_2;
+ matrix[idx_r * stride + idx_in] += lfe_mix_level * M_SQRT1_2;
+ continue;
+ }
+ }
}

- /* transfer internal matrix to output matrix and calculate maximum
- per-channel coefficient sum */
- for (out_i = i = 0; out_i < out_channels && i < 64; i++) {
+ /* calculate maximum per-channel coefficient sum */
+ for (idx_out = 0; idx_out < out_channels; idx_out++) {
double sum = 0;
- for (out_j = j = 0; out_j < in_channels && j < 64; j++) {
- matrix_out[out_i * stride + out_j] = matrix[i][j];
- sum += fabs(matrix[i][j]);
- if (in_layout & (1ULL << j))
- out_j++;
- }
+ for (idx_in = 0; idx_in < in_channels; idx_in++)
+ sum += fabs(matrix[idx_out * stride + idx_in]);
maxcoef = FFMAX(maxcoef, sum);
- if (out_layout & (1ULL << i))
- out_i++;
}

/* normalize */
if (normalize && maxcoef > 1.0) {
for (i = 0; i < out_channels; i++)
for (j = 0; j < in_channels; j++)
- matrix_out[i * stride + j] /= maxcoef;
+ matrix[i * stride + j] /= maxcoef;
}

return 0;
}
+
+#if FF_API_OLD_CHANNEL_LAYOUT
+int avresample_build_matrix(uint64_t in_layout, uint64_t out_layout,
+ double center_mix_level, double surround_mix_level,
+ double lfe_mix_level, int normalize,
+ double *matrix_out, int stride,
+ enum AVMatrixEncoding matrix_encoding)
+{
+ AVChannelLayout in_chl, out_chl;
+
+ av_channel_layout_from_mask(&in_chl, in_layout);
+ av_channel_layout_from_mask(&out_chl, out_layout);
+ return avresample_build_matrix2(&in_chl, &out_chl, center_mix_level,
+ surround_mix_level, lfe_mix_level, normalize,
+ matrix_out, stride, matrix_encoding);
+}
+#endif
diff --git a/libavresample/avresample.h b/libavresample/avresample.h
index 3f9b9433c1..5a60423470 100644
--- a/libavresample/avresample.h
+++ b/libavresample/avresample.h
@@ -44,8 +44,10 @@
* matrix):
* @code
* AVAudioResampleContext *avr = avresample_alloc_context();
- * av_opt_set_int(avr, "in_channel_layout", AV_CH_LAYOUT_5POINT1, 0);
- * av_opt_set_int(avr, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0);
+ * AVChannelLayout in_ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1;
+ * AVChannelLayout out_ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
+ * av_opt_set_channel_layout(avr, "in_ch_layout", &in_ch_layout, 0);
+ * av_opt_set_channel_layout(avr, "out_ch_layout", &out_ch_layout, 0);
* av_opt_set_int(avr, "in_sample_rate", 48000, 0);
* av_opt_set_int(avr, "out_sample_rate", 44100, 0);
* av_opt_set_int(avr, "in_sample_fmt", AV_SAMPLE_FMT_FLTP, 0);
@@ -92,6 +94,7 @@
* avresample_free().
*/

+#include "libavutil/attributes.h"
#include "libavutil/avutil.h"
#include "libavutil/channel_layout.h"
#include "libavutil/dict.h"
@@ -167,7 +170,7 @@ AVAudioResampleContext *avresample_alloc_context(void);
/**
* Initialize AVAudioResampleContext.
* @note The context must be configured using the AVOption API.
- * @note The fields "in_channel_layout", "out_channel_layout",
+ * @note The fields "in_ch_layout", "out_ch_layout",
* "in_sample_rate", "out_sample_rate", "in_sample_fmt",
* "out_sample_fmt" must be set.
*
@@ -212,6 +215,7 @@ void avresample_close(AVAudioResampleContext *avr);
*/
void avresample_free(AVAudioResampleContext **avr);

+#if FF_API_OLD_CHANNEL_LAYOUT
/**
* Generate a channel mixing matrix.
*
@@ -233,11 +237,43 @@ void avresample_free(AVAudioResampleContext **avr);
* matrix array
* @param matrix_encoding matrixed stereo downmix mode (e.g. dplii)
* @return 0 on success, negative AVERROR code on failure
+ *
+ * @deprecated use avresample_build_matrix2()
*/
+attribute_deprecated
int avresample_build_matrix(uint64_t in_layout, uint64_t out_layout,
double center_mix_level, double surround_mix_level,
double lfe_mix_level, int normalize, double *matrix,
int stride, enum AVMatrixEncoding matrix_encoding);
+#endif
+
+/**
+ * Generate a channel mixing matrix.
+ *
+ * This function is the one used internally by libavresample for building the
+ * default mixing matrix. It is made public just as a utility function for
+ * building custom matrices.
+ *
+ * @param in_layout input channel layout
+ * @param out_layout output channel layout
+ * @param center_mix_level mix level for the center channel
+ * @param surround_mix_level mix level for the surround channel(s)
+ * @param lfe_mix_level mix level for the low-frequency effects channel
+ * @param normalize if 1, coefficients will be normalized to prevent
+ * overflow. if 0, coefficients will not be
+ * normalized.
+ * @param[out] matrix mixing coefficients; matrix[i + stride * o] is
+ * the weight of input channel i in output channel o.
+ * @param stride distance between adjacent input channels in the
+ * matrix array
+ * @param matrix_encoding matrixed stereo downmix mode (e.g. dplii)
+ * @return 0 on success, negative AVERROR code on failure
+ */
+int avresample_build_matrix2(const AVChannelLayout *in_layout,
+ const AVChannelLayout *out_layout,
+ double center_mix_level, double surround_mix_level,
+ double lfe_mix_level, int normalize, double *matrix,
+ int stride, enum AVMatrixEncoding matrix_encoding);

/**
* Get the current channel mixing matrix.
diff --git a/libavresample/internal.h b/libavresample/internal.h
index b88b7587aa..a6bf2d400e 100644
--- a/libavresample/internal.h
+++ b/libavresample/internal.h
@@ -22,6 +22,7 @@
#define AVRESAMPLE_INTERNAL_H

#include "libavutil/audio_fifo.h"
+#include "libavutil/channel_layout.h"
#include "libavutil/log.h"
#include "libavutil/opt.h"
#include "libavutil/samplefmt.h"
@@ -53,10 +54,17 @@ typedef struct ChannelMapInfo {
struct AVAudioResampleContext {
const AVClass *av_class; /**< AVClass for logging and AVOptions */

+#if FF_API_OLD_CHANNEL_LAYOUT
uint64_t in_channel_layout; /**< input channel layout */
+#endif
+ AVChannelLayout in_ch_layout; /**< input channel layout */
+
enum AVSampleFormat in_sample_fmt; /**< input sample format */
int in_sample_rate; /**< input sample rate */
+#if FF_API_OLD_CHANNEL_LAYOUT
uint64_t out_channel_layout; /**< output channel layout */
+#endif
+ AVChannelLayout out_ch_layout; /**< output channel layout */
enum AVSampleFormat out_sample_fmt; /**< output sample format */
int out_sample_rate; /**< output sample rate */
enum AVSampleFormat internal_sample_fmt; /**< internal sample format */
@@ -74,8 +82,6 @@ struct AVAudioResampleContext {
int kaiser_beta; /**< beta value for Kaiser window (only applicable if filter_type == AV_FILTER_TYPE_KAISER) */
enum AVResampleDitherMethod dither_method; /**< dither method */

- int in_channels; /**< number of input channels */
- int out_channels; /**< number of output channels */
int resample_channels; /**< number of channels used for resampling */
int downmix_needed; /**< downmixing is needed */
int upmix_needed; /**< upmixing is needed */
diff --git a/libavresample/options.c b/libavresample/options.c
index 6249f90115..78af61a6e1 100644
--- a/libavresample/options.c
+++ b/libavresample/options.c
@@ -36,10 +36,18 @@
#define PARAM AV_OPT_FLAG_AUDIO_PARAM

static const AVOption avresample_options[] = {
+#if FF_API_OLD_CHANNEL_LAYOUT
{ "in_channel_layout", "Input Channel Layout", OFFSET(in_channel_layout), AV_OPT_TYPE_INT64, { .i64 = 0 }, INT64_MIN, INT64_MAX, PARAM },
+#endif
+ { "in_ch_layout", "Input Channel Layout", OFFSET(in_ch_layout), AV_OPT_TYPE_CHANNEL_LAYOUT,
+ { .str = NULL }, .flags = PARAM },
{ "in_sample_fmt", "Input Sample Format", OFFSET(in_sample_fmt), AV_OPT_TYPE_INT, { .i64 = AV_SAMPLE_FMT_S16 }, AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_NB-1, PARAM },
{ "in_sample_rate", "Input Sample Rate", OFFSET(in_sample_rate), AV_OPT_TYPE_INT, { .i64 = 48000 }, 1, INT_MAX, PARAM },
+#if FF_API_OLD_CHANNEL_LAYOUT
{ "out_channel_layout", "Output Channel Layout", OFFSET(out_channel_layout), AV_OPT_TYPE_INT64, { .i64 = 0 }, INT64_MIN, INT64_MAX, PARAM },
+#endif
+ { "out_ch_layout", "Output Channel Layout", OFFSET(out_ch_layout), AV_OPT_TYPE_CHANNEL_LAYOUT,
+ { .str = NULL }, .flags = PARAM },
{ "out_sample_fmt", "Output Sample Format", OFFSET(out_sample_fmt), AV_OPT_TYPE_INT, { .i64 = AV_SAMPLE_FMT_S16 }, AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_NB-1, PARAM },
{ "out_sample_rate", "Output Sample Rate", OFFSET(out_sample_rate), AV_OPT_TYPE_INT, { .i64 = 48000 }, 1, INT_MAX, PARAM },
{ "internal_sample_fmt", "Internal Sample Format", OFFSET(internal_sample_fmt), AV_OPT_TYPE_INT, { .i64 = AV_SAMPLE_FMT_NONE }, AV_SAMPLE_FMT_NONE, AV_SAMPLE_FMT_NB-1, PARAM, "internal_sample_fmt" },
diff --git a/libavresample/tests/avresample.c b/libavresample/tests/avresample.c
index 77599960f8..19027b2df1 100644
--- a/libavresample/tests/avresample.c
+++ b/libavresample/tests/avresample.c
@@ -179,11 +179,11 @@ static const int rates[] = {
16000
};

-static const uint64_t layouts[] = {
- AV_CH_LAYOUT_STEREO,
- AV_CH_LAYOUT_MONO,
- AV_CH_LAYOUT_5POINT1,
- AV_CH_LAYOUT_7POINT1,
+static const AVChannelLayout layouts[] = {
+ AV_CHANNEL_LAYOUT_STEREO,
+ AV_CHANNEL_LAYOUT_MONO,
+ AV_CHANNEL_LAYOUT_5POINT1,
+ AV_CHANNEL_LAYOUT_7POINT1,
};

int main(int argc, char **argv)
@@ -199,12 +199,8 @@ int main(int argc, char **argv)
uint8_t *out_data[AVRESAMPLE_MAX_CHANNELS] = { 0 };
int in_linesize;
int out_linesize;
- uint64_t in_ch_layout;
- int in_channels;
enum AVSampleFormat in_fmt;
int in_rate;
- uint64_t out_ch_layout;
- int out_channels;
enum AVSampleFormat out_fmt;
int out_rate;
int num_formats, num_rates, num_layouts;
@@ -257,8 +253,8 @@ int main(int argc, char **argv)
for (i = 0; i < num_formats; i++) {
in_fmt = formats[i];
for (k = 0; k < num_layouts; k++) {
- in_ch_layout = layouts[k];
- in_channels = av_get_channel_layout_nb_channels(in_ch_layout);
+ AVChannelLayout in_ch_layout = layouts[k];
+ int in_channels = in_ch_layout.nb_channels;
for (m = 0; m < num_rates; m++) {
in_rate = rates[m];

@@ -274,8 +270,8 @@ int main(int argc, char **argv)
for (j = 0; j < num_formats; j++) {
out_fmt = formats[j];
for (l = 0; l < num_layouts; l++) {
- out_ch_layout = layouts[l];
- out_channels = av_get_channel_layout_nb_channels(out_ch_layout);
+ AVChannelLayout out_ch_layout = layouts[l];
+ int out_channels = out_ch_layout.nb_channels;
for (n = 0; n < num_rates; n++) {
out_rate = rates[n];

@@ -291,10 +287,10 @@ int main(int argc, char **argv)
goto end;
}

- av_opt_set_int(s, "in_channel_layout", in_ch_layout, 0);
+ av_opt_set_channel_layout(s, "in_ch_layout", &in_ch_layout, 0);
+ av_opt_set_channel_layout(s, "out_ch_layout", &out_ch_layout, 0);
av_opt_set_int(s, "in_sample_fmt", in_fmt, 0);
av_opt_set_int(s, "in_sample_rate", in_rate, 0);
- av_opt_set_int(s, "out_channel_layout", out_ch_layout, 0);
av_opt_set_int(s, "out_sample_fmt", out_fmt, 0);
av_opt_set_int(s, "out_sample_rate", out_rate, 0);

diff --git a/libavresample/utils.c b/libavresample/utils.c
index bab2153b4b..5e4a9f3ac3 100644
--- a/libavresample/utils.c
+++ b/libavresample/utils.c
@@ -18,6 +18,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

+#include "libavutil/channel_layout.h"
#include "libavutil/common.h"
#include "libavutil/dict.h"
#include "libavutil/error.h"
@@ -35,6 +36,7 @@

int avresample_open(AVAudioResampleContext *avr)
{
+ int in_ch, out_ch;
int ret;

if (avresample_is_open(avr)) {
@@ -42,24 +44,70 @@ int avresample_open(AVAudioResampleContext *avr)
return AVERROR(EINVAL);
}

+ /* whitelist allowed channel orders */
+ if ( (avr->in_ch_layout.order != AV_CHANNEL_ORDER_NATIVE &&
+ avr->in_ch_layout.order != AV_CHANNEL_ORDER_UNSPEC) ||
+ (avr->out_ch_layout.order != AV_CHANNEL_ORDER_NATIVE &&
+ avr->out_ch_layout.order != AV_CHANNEL_ORDER_UNSPEC)) {
+ av_log(avr, AV_LOG_ERROR,
+ "Input or ouput channel order is not supported.\n");
+ return AVERROR(ENOSYS);
+ }
+
+ if (avr->in_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) {
+ if (avr->in_ch_layout.nb_channels > 63) {
+ av_log(avr, AV_LOG_ERROR,
+ "Unspecified channel layout order is supported only for up "
+ "to 63 channels (got %d).\n", avr->in_ch_layout.nb_channels);
+ return AVERROR(ENOSYS);
+ }
+ av_channel_layout_default(&avr->in_ch_layout, avr->in_ch_layout.nb_channels);
+ }
+ if (avr->out_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) {
+ if (avr->out_ch_layout.nb_channels > 63) {
+ av_log(avr, AV_LOG_ERROR,
+ "Unspecified channel layout order is supported only for up "
+ "to 63 channels (got %d).\n", avr->out_ch_layout.nb_channels);
+ return AVERROR(ENOSYS);
+ }
+ av_channel_layout_default(&avr->out_ch_layout, avr->out_ch_layout.nb_channels);
+ }
+
/* set channel mixing parameters */
- avr->in_channels = av_get_channel_layout_nb_channels(avr->in_channel_layout);
- if (avr->in_channels <= 0 || avr->in_channels > AVRESAMPLE_MAX_CHANNELS) {
- av_log(avr, AV_LOG_ERROR, "Invalid input channel layout: %"PRIu64"\n",
- avr->in_channel_layout);
+#if FF_API_OLD_CHANNEL_LAYOUT
+ if (avr->in_channel_layout) {
+ av_log(avr, AV_LOG_WARNING, "Setting the input channel layout with the "
+ "'in_channel_layout' option is deprecated, use the "
+ "'in_ch_layout' option instead].\n");
+ av_channel_layout_uninit(&avr->in_ch_layout);
+ av_channel_layout_from_mask(&avr->in_ch_layout, avr->in_channel_layout);
+ }
+ if (avr->out_channel_layout) {
+ av_log(avr, AV_LOG_WARNING, "Setting the output channel layout with the "
+ "'out_channel_layout' option is deprecated, use the "
+ "'out_ch_layout' option instead].\n");
+ av_channel_layout_uninit(&avr->out_ch_layout);
+ av_channel_layout_from_mask(&avr->out_ch_layout, avr->out_channel_layout);
+ }
+#endif
+ in_ch = avr->in_ch_layout.nb_channels;
+ out_ch = avr->out_ch_layout.nb_channels;
+ if (!av_channel_layout_check(&avr->in_ch_layout) ||
+ in_ch > AVRESAMPLE_MAX_CHANNELS) {
+ av_log(avr, AV_LOG_ERROR, "Invalid input channel layout.\n");
return AVERROR(EINVAL);
}
- avr->out_channels = av_get_channel_layout_nb_channels(avr->out_channel_layout);
- if (avr->out_channels <= 0 || avr->out_channels > AVRESAMPLE_MAX_CHANNELS) {
- av_log(avr, AV_LOG_ERROR, "Invalid output channel layout: %"PRIu64"\n",
- avr->out_channel_layout);
+ if (!av_channel_layout_check(&avr->out_ch_layout) ||
+ out_ch > AVRESAMPLE_MAX_CHANNELS) {
+ av_log(avr, AV_LOG_ERROR, "Invalid output channel layout.\n");
return AVERROR(EINVAL);
}
- avr->resample_channels = FFMIN(avr->in_channels, avr->out_channels);
- avr->downmix_needed = avr->in_channels > avr->out_channels;
- avr->upmix_needed = avr->out_channels > avr->in_channels ||
+ avr->resample_channels = FFMIN(in_ch, out_ch);
+ avr->downmix_needed = in_ch > out_ch;
+ avr->upmix_needed = out_ch > in_ch ||
(!avr->downmix_needed && (avr->mix_matrix ||
- avr->in_channel_layout != avr->out_channel_layout));
+ av_channel_layout_compare(&avr->in_ch_layout,
+ &avr->out_ch_layout)));
avr->mixing_needed = avr->downmix_needed || avr->upmix_needed;

/* set resampling parameters */
@@ -105,7 +153,7 @@ int avresample_open(AVAudioResampleContext *avr)
/* we may need to add an extra conversion in order to remap channels if
the output format is not planar */
if (avr->use_channel_map && !avr->mixing_needed && !avr->resample_needed &&
- !ff_sample_fmt_is_planar(avr->out_sample_fmt, avr->out_channels)) {
+ !ff_sample_fmt_is_planar(avr->out_sample_fmt, avr->out_ch_layout.nb_channels)) {
avr->internal_sample_fmt = av_get_planar_sample_fmt(avr->out_sample_fmt);
}

@@ -114,7 +162,8 @@ int avresample_open(AVAudioResampleContext *avr)
avr->in_convert_needed = avr->in_sample_fmt != avr->internal_sample_fmt;
else
avr->in_convert_needed = avr->use_channel_map &&
- !ff_sample_fmt_is_planar(avr->out_sample_fmt, avr->out_channels);
+ !ff_sample_fmt_is_planar(avr->out_sample_fmt,
+ avr->out_ch_layout.nb_channels);

if (avr->resample_needed || avr->mixing_needed || avr->in_convert_needed)
avr->out_convert_needed = avr->internal_sample_fmt != avr->out_sample_fmt;
@@ -144,27 +193,27 @@ int avresample_open(AVAudioResampleContext *avr)
int ch;
av_log(avr, AV_LOG_TRACE, "output map: ");
if (avr->ch_map_info.do_remap)
- for (ch = 0; ch < avr->in_channels; ch++)
+ for (ch = 0; ch < in_ch; ch++)
av_log(avr, AV_LOG_TRACE, " % 2d", avr->ch_map_info.channel_map[ch]);
else
av_log(avr, AV_LOG_TRACE, "n/a");
av_log(avr, AV_LOG_TRACE, "\n");
av_log(avr, AV_LOG_TRACE, "copy map: ");
if (avr->ch_map_info.do_copy)
- for (ch = 0; ch < avr->in_channels; ch++)
+ for (ch = 0; ch < in_ch; ch++)
av_log(avr, AV_LOG_TRACE, " % 2d", avr->ch_map_info.channel_copy[ch]);
else
av_log(avr, AV_LOG_TRACE, "n/a");
av_log(avr, AV_LOG_TRACE, "\n");
av_log(avr, AV_LOG_TRACE, "zero map: ");
if (avr->ch_map_info.do_zero)
- for (ch = 0; ch < avr->in_channels; ch++)
+ for (ch = 0; ch < in_ch; ch++)
av_log(avr, AV_LOG_TRACE, " % 2d", avr->ch_map_info.channel_zero[ch]);
else
av_log(avr, AV_LOG_TRACE, "n/a");
av_log(avr, AV_LOG_TRACE, "\n");
av_log(avr, AV_LOG_TRACE, "input map: ");
- for (ch = 0; ch < avr->in_channels; ch++)
+ for (ch = 0; ch < in_ch; ch++)
av_log(avr, AV_LOG_TRACE, " % 2d", avr->ch_map_info.input_map[ch]);
av_log(avr, AV_LOG_TRACE, "\n");
}
@@ -174,7 +223,7 @@ int avresample_open(AVAudioResampleContext *avr)

/* allocate buffers */
if (avr->in_copy_needed || avr->in_convert_needed) {
- avr->in_buffer = ff_audio_data_alloc(FFMAX(avr->in_channels, avr->out_channels),
+ avr->in_buffer = ff_audio_data_alloc(FFMAX(in_ch, out_ch),
0, avr->internal_sample_fmt,
"in_buffer");
if (!avr->in_buffer) {
@@ -183,7 +232,7 @@ int avresample_open(AVAudioResampleContext *avr)
}
}
if (avr->resample_needed) {
- avr->resample_out_buffer = ff_audio_data_alloc(avr->out_channels,
+ avr->resample_out_buffer = ff_audio_data_alloc(out_ch,
1024, avr->internal_sample_fmt,
"resample_out_buffer");
if (!avr->resample_out_buffer) {
@@ -192,15 +241,14 @@ int avresample_open(AVAudioResampleContext *avr)
}
}
if (avr->out_convert_needed) {
- avr->out_buffer = ff_audio_data_alloc(avr->out_channels, 0,
+ avr->out_buffer = ff_audio_data_alloc(out_ch, 0,
avr->out_sample_fmt, "out_buffer");
if (!avr->out_buffer) {
ret = AVERROR(EINVAL);
goto error;
}
}
- avr->out_fifo = av_audio_fifo_alloc(avr->out_sample_fmt, avr->out_channels,
- 1024);
+ avr->out_fifo = av_audio_fifo_alloc(avr->out_sample_fmt, out_ch, 1024);
if (!avr->out_fifo) {
ret = AVERROR(ENOMEM);
goto error;
@@ -209,7 +257,7 @@ int avresample_open(AVAudioResampleContext *avr)
/* setup contexts */
if (avr->in_convert_needed) {
avr->ac_in = ff_audio_convert_alloc(avr, avr->internal_sample_fmt,
- avr->in_sample_fmt, avr->in_channels,
+ avr->in_sample_fmt, in_ch,
avr->in_sample_rate,
avr->remap_point == REMAP_IN_CONVERT);
if (!avr->ac_in) {
@@ -224,7 +272,7 @@ int avresample_open(AVAudioResampleContext *avr)
else
src_fmt = avr->in_sample_fmt;
avr->ac_out = ff_audio_convert_alloc(avr, avr->out_sample_fmt, src_fmt,
- avr->out_channels,
+ out_ch,
avr->out_sample_rate,
avr->remap_point == REMAP_OUT_CONVERT);
if (!avr->ac_out) {
@@ -361,7 +409,7 @@ int attribute_align_arg avresample_convert(AVAudioResampleContext *avr,
direct_output = output && av_audio_fifo_size(avr->out_fifo) == 0;
if (output) {
ret = ff_audio_data_init(&output_buffer, output, out_plane_size,
- avr->out_channels, out_samples,
+ avr->out_ch_layout.nb_channels, out_samples,
avr->out_sample_fmt, 0, "output");
if (ret < 0)
return ret;
@@ -371,7 +419,7 @@ int attribute_align_arg avresample_convert(AVAudioResampleContext *avr,
if (input) {
/* initialize input_buffer with input data */
ret = ff_audio_data_init(&input_buffer, input, in_plane_size,
- avr->in_channels, in_samples,
+ avr->in_ch_layout.nb_channels, in_samples,
avr->in_sample_fmt, 1, "input");
if (ret < 0)
return ret;
@@ -420,7 +468,7 @@ int attribute_align_arg avresample_convert(AVAudioResampleContext *avr,
if (ret < 0)
return ret;
}
- ff_audio_data_set_channels(avr->in_buffer, avr->in_channels);
+ ff_audio_data_set_channels(avr->in_buffer, avr->in_ch_layout.nb_channels);
if (avr->downmix_needed) {
av_log(avr, AV_LOG_TRACE, "[downmix] in_buffer\n");
ret = ff_audio_mix(avr->am, avr->in_buffer);
@@ -504,18 +552,24 @@ int attribute_align_arg avresample_convert(AVAudioResampleContext *avr,

int avresample_config(AVAudioResampleContext *avr, AVFrame *out, AVFrame *in)
{
+ int ret;
+
if (avresample_is_open(avr)) {
avresample_close(avr);
}

if (in) {
- avr->in_channel_layout = in->channel_layout;
+ ret = av_channel_layout_copy(&avr->in_ch_layout, &in->ch_layout);
+ if (ret < 0)
+ return ret;
avr->in_sample_rate = in->sample_rate;
avr->in_sample_fmt = in->format;
}

if (out) {
- avr->out_channel_layout = out->channel_layout;
+ ret = av_channel_layout_copy(&avr->out_ch_layout, &out->ch_layout);
+ if (ret < 0)
+ return ret;
avr->out_sample_rate = out->sample_rate;
avr->out_sample_fmt = out->format;
}
@@ -529,7 +583,7 @@ static int config_changed(AVAudioResampleContext *avr,
int ret = 0;

if (in) {
- if (avr->in_channel_layout != in->channel_layout ||
+ if (av_channel_layout_compare(&avr->in_ch_layout, &in->ch_layout) ||
avr->in_sample_rate != in->sample_rate ||
avr->in_sample_fmt != in->format) {
ret |= AVERROR_INPUT_CHANGED;
@@ -537,7 +591,7 @@ static int config_changed(AVAudioResampleContext *avr,
}

if (out) {
- if (avr->out_channel_layout != out->channel_layout ||
+ if (av_channel_layout_compare(&avr->out_ch_layout, &out->ch_layout) ||
avr->out_sample_rate != out->sample_rate ||
avr->out_sample_fmt != out->format) {
ret |= AVERROR_OUTPUT_CHANGED;
@@ -595,7 +649,7 @@ static inline int available_samples(AVFrame *out)
if (av_sample_fmt_is_planar(out->format)) {
return samples;
} else {
- int channels = av_get_channel_layout_nb_channels(out->channel_layout);
+ int channels = out->ch_layout.nb_channels;
return samples / channels;
}
}
@@ -642,8 +696,8 @@ int avresample_get_matrix(AVAudioResampleContext *avr, double *matrix,
if (avr->am)
return ff_audio_mix_get_matrix(avr->am, matrix, stride);

- in_channels = av_get_channel_layout_nb_channels(avr->in_channel_layout);
- out_channels = av_get_channel_layout_nb_channels(avr->out_channel_layout);
+ in_channels = avr->in_ch_layout.nb_channels;
+ out_channels = avr->out_ch_layout.nb_channels;

if ( in_channels <= 0 || in_channels > AVRESAMPLE_MAX_CHANNELS ||
out_channels <= 0 || out_channels > AVRESAMPLE_MAX_CHANNELS) {
@@ -671,8 +725,8 @@ int avresample_set_matrix(AVAudioResampleContext *avr, const double *matrix,
if (avr->am)
return ff_audio_mix_set_matrix(avr->am, matrix, stride);

- in_channels = av_get_channel_layout_nb_channels(avr->in_channel_layout);
- out_channels = av_get_channel_layout_nb_channels(avr->out_channel_layout);
+ in_channels = avr->in_ch_layout.nb_channels;
+ out_channels = avr->out_ch_layout.nb_channels;

if ( in_channels <= 0 || in_channels > AVRESAMPLE_MAX_CHANNELS ||
out_channels <= 0 || out_channels > AVRESAMPLE_MAX_CHANNELS) {
@@ -700,7 +754,7 @@ int avresample_set_channel_mapping(AVAudioResampleContext *avr,
ChannelMapInfo *info = &avr->ch_map_info;
int in_channels, ch, i;

- in_channels = av_get_channel_layout_nb_channels(avr->in_channel_layout);
+ in_channels = avr->in_ch_layout.nb_channels;
if (in_channels <= 0 || in_channels > AVRESAMPLE_MAX_CHANNELS) {
av_log(avr, AV_LOG_ERROR, "Invalid input channel layout\n");
return AVERROR(EINVAL);
--
2.13.1
Luca Barbato
2017-07-04 10:49:51 UTC
Permalink
Post by Vittorio Giovara
Set a whitelist of supported channel order.
---
libavresample/audio_mix.c | 148 ++++++------
libavresample/audio_mix_matrix.c | 477 ++++++++++++++++++++++-----------------
libavresample/avresample.h | 42 +++-
libavresample/internal.h | 10 +-
libavresample/options.c | 8 +
libavresample/tests/avresample.c | 26 +--
libavresample/utils.c | 130 +++++++----
7 files changed, 507 insertions(+), 334 deletions(-)
Seems fine.
Anton Khirnov
2017-07-22 08:40:25 UTC
Permalink
Quoting Vittorio Giovara (2017-06-29 00:10:50)
Post by Vittorio Giovara
diff --git a/libavresample/utils.c b/libavresample/utils.c
index bab2153b4b..15c827efbe 100644
--- a/libavresample/utils.c
+++ b/libavresample/utils.c
@@ -18,6 +18,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include "libavutil/channel_layout.h"
#include "libavutil/common.h"
#include "libavutil/dict.h"
#include "libavutil/error.h"
@@ -35,6 +36,7 @@
int avresample_open(AVAudioResampleContext *avr)
{
+ int in_ch, out_ch;
int ret;
if (avresample_is_open(avr)) {
@@ -42,24 +44,67 @@ int avresample_open(AVAudioResampleContext *avr)
return AVERROR(EINVAL);
}
+ if ( avr->in_ch_layout.order == AV_CHANNEL_ORDER_CUSTOM ||
+ avr->out_ch_layout.order == AV_CHANNEL_ORDER_CUSTOM) {
+ av_log(avr, AV_LOG_ERROR,
+ "Resampling a custom channel layout order is not supported.\n");
+ return AVERROR(ENOSYS);
Why? I don't remember if I tested it properly back then, but IIRC the
matrix building code should work custom orders just fine.
Post by Vittorio Giovara
+ }
+
+ if (avr->in_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) {
+ if (avr->in_ch_layout.nb_channels > 63) {
+ av_log(avr, AV_LOG_ERROR,
+ "Unspecified channel layout order is supported only for up "
+ "to 63 channels (got %d).\n", avr->in_ch_layout.nb_channels);
+ return AVERROR(ENOSYS);
+ }
+ av_channel_layout_default(&avr->in_ch_layout, avr->in_ch_layout.nb_channels);
+ }
+ if (avr->out_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) {
+ if (avr->out_ch_layout.nb_channels > 63) {
+ av_log(avr, AV_LOG_ERROR,
+ "Unspecified channel layout order is supported only for up "
+ "to 63 channels (got %d).\n", avr->out_ch_layout.nb_channels);
+ return AVERROR(ENOSYS);
+ }
+ av_channel_layout_default(&avr->out_ch_layout, avr->out_ch_layout.nb_channels);
+ }
Why are those needed? Seems they are redundant given the other checks
right below.
--
Anton Khirnov
Vittorio Giovara
2018-01-19 19:46:16 UTC
Permalink
Post by Anton Khirnov
Quoting Vittorio Giovara (2017-06-29 00:10:50)
Post by Vittorio Giovara
diff --git a/libavresample/utils.c b/libavresample/utils.c
index bab2153b4b..15c827efbe 100644
--- a/libavresample/utils.c
+++ b/libavresample/utils.c
@@ -18,6 +18,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
Post by Vittorio Giovara
*/
+#include "libavutil/channel_layout.h"
#include "libavutil/common.h"
#include "libavutil/dict.h"
#include "libavutil/error.h"
@@ -35,6 +36,7 @@
int avresample_open(AVAudioResampleContext *avr)
{
+ int in_ch, out_ch;
int ret;
if (avresample_is_open(avr)) {
@@ -42,24 +44,67 @@ int avresample_open(AVAudioResampleContext *avr)
return AVERROR(EINVAL);
}
+ if ( avr->in_ch_layout.order == AV_CHANNEL_ORDER_CUSTOM ||
+ avr->out_ch_layout.order == AV_CHANNEL_ORDER_CUSTOM) {
+ av_log(avr, AV_LOG_ERROR,
+ "Resampling a custom channel layout order is not
supported.\n");
Post by Vittorio Giovara
+ return AVERROR(ENOSYS);
Why? I don't remember if I tested it properly back then, but IIRC the
matrix building code should work custom orders just fine.
Post by Vittorio Giovara
+ }
+
+ if (avr->in_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) {
+ if (avr->in_ch_layout.nb_channels > 63) {
+ av_log(avr, AV_LOG_ERROR,
+ "Unspecified channel layout order is supported only
for up "
Post by Vittorio Giovara
+ "to 63 channels (got %d).\n",
avr->in_ch_layout.nb_channels);
Post by Vittorio Giovara
+ return AVERROR(ENOSYS);
+ }
+ av_channel_layout_default(&avr->in_ch_layout,
avr->in_ch_layout.nb_channels);
Post by Vittorio Giovara
+ }
+ if (avr->out_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) {
+ if (avr->out_ch_layout.nb_channels > 63) {
+ av_log(avr, AV_LOG_ERROR,
+ "Unspecified channel layout order is supported only
for up "
Post by Vittorio Giovara
+ "to 63 channels (got %d).\n", avr->out_ch_layout.nb_
channels);
Post by Vittorio Giovara
+ return AVERROR(ENOSYS);
+ }
+ av_channel_layout_default(&avr->out_ch_layout,
avr->out_ch_layout.nb_channels);
Post by Vittorio Giovara
+ }
Why are those needed? Seems they are redundant given the other checks
right below.
You are right on both points, the code is fine (and simpler) without these
checks.
--
Vittorio
Vittorio Giovara
2017-06-28 22:10:53 UTC
Permalink
Signed-off-by: Vittorio Giovara <***@gmail.com>
---
libavfilter/af_aformat.c | 30 +++++++++---
libavfilter/af_channelmap.c | 2 +-
libavfilter/af_channelsplit.c | 6 ++-
libavfilter/af_join.c | 2 +-
libavfilter/avfiltergraph.c | 109 +++++++++++++++++++++++++++++++-----------
libavfilter/buffersrc.c | 2 +-
libavfilter/formats.c | 45 +++++++++++++++--
libavfilter/formats.h | 4 +-
8 files changed, 153 insertions(+), 47 deletions(-)

diff --git a/libavfilter/af_aformat.c b/libavfilter/af_aformat.c
index c5aa4f7148..259ece4c0b 100644
--- a/libavfilter/af_aformat.c
+++ b/libavfilter/af_aformat.c
@@ -94,11 +94,29 @@ static int get_sample_rate(const char *samplerate)
return FFMAX(ret, 0);
}

-static int get_channel_layout(const char *channel_layout)
+static int parse_channel_layout_string(AVFilterContext *ctx)
{
- AVChannelLayout ch_layout = {0};
- av_channel_layout_from_string(&ch_layout, channel_layout);
- return ch_layout.u.mask;
+ AFormatContext *s = ctx->priv;
+ char *next, *cur = s->channel_layouts_str, sep = '|';
+ int ret;
+
+ while (cur) {
+ AVChannelLayout fmt = {0};
+ next = strchr(cur, sep);
+ if (next)
+ *next++ = 0;
+
+ ret = av_channel_layout_from_string(&fmt, cur);
+ if (ret < 0) {
+ av_log(ctx, AV_LOG_ERROR, "Error parsing channel layout: %s.\n", cur);\
+ return ret;
+ }
+ ff_add_channel_layout(&s->channel_layouts, &fmt);
+
+ cur = next;
+ }
+
+ return 0;
}

static av_cold int init(AVFilterContext *ctx)
@@ -109,10 +127,8 @@ static av_cold int init(AVFilterContext *ctx)
ff_add_format, av_get_sample_fmt, AV_SAMPLE_FMT_NONE, "sample format");
PARSE_FORMATS(s->sample_rates_str, int, s->sample_rates, ff_add_format,
get_sample_rate, 0, "sample rate");
- PARSE_FORMATS(s->channel_layouts_str, uint64_t, s->channel_layouts,
- ff_add_channel_layout, get_channel_layout, 0, "channel layout");

- return 0;
+ return parse_channel_layout_string(ctx);
}

static int query_formats(AVFilterContext *ctx)
diff --git a/libavfilter/af_channelmap.c b/libavfilter/af_channelmap.c
index 939f056d6f..54ff146c5b 100644
--- a/libavfilter/af_channelmap.c
+++ b/libavfilter/af_channelmap.c
@@ -296,7 +296,7 @@ static int channelmap_query_formats(AVFilterContext *ctx)
ChannelMapContext *s = ctx->priv;
AVFilterChannelLayouts *channel_layouts = NULL;

- ff_add_channel_layout(&channel_layouts, s->ch_layout.u.mask);
+ ff_add_channel_layout(&channel_layouts, &s->ch_layout);

ff_set_common_formats(ctx, ff_planar_sample_fmts());
ff_set_common_samplerates(ctx, ff_all_samplerates());
diff --git a/libavfilter/af_channelsplit.c b/libavfilter/af_channelsplit.c
index 41b3051c8c..b13919cdf0 100644
--- a/libavfilter/af_channelsplit.c
+++ b/libavfilter/af_channelsplit.c
@@ -85,16 +85,18 @@ static int query_formats(AVFilterContext *ctx)
ff_set_common_formats (ctx, ff_planar_sample_fmts());
ff_set_common_samplerates(ctx, ff_all_samplerates());

- ff_add_channel_layout(&in_layouts, s->ch_layout.u.mask);
+ ff_add_channel_layout(&in_layouts, &s->ch_layout);
ff_channel_layouts_ref(in_layouts, &ctx->inputs[0]->out_channel_layouts);

for (i = 0; i < ctx->nb_outputs; i++) {
AVFilterChannelLayouts *out_layouts = NULL;
+ AVChannelLayout tmp = {0};
int ret = av_channel_layout_get_channel(&s->ch_layout, i);
if (ret < 0)
return ret;

- ff_add_channel_layout(&out_layouts, 1ULL << ret);
+ av_channel_layout_from_mask(&tmp, 1ULL << ret);
+ ff_add_channel_layout(&out_layouts, &tmp);
ff_channel_layouts_ref(out_layouts, &ctx->outputs[i]->in_channel_layouts);
}

diff --git a/libavfilter/af_join.c b/libavfilter/af_join.c
index 6c000b9257..70dc2d00d7 100644
--- a/libavfilter/af_join.c
+++ b/libavfilter/af_join.c
@@ -234,7 +234,7 @@ static int join_query_formats(AVFilterContext *ctx)
AVFilterChannelLayouts *layouts = NULL;
int i;

- ff_add_channel_layout(&layouts, s->ch_layout.u.mask);
+ ff_add_channel_layout(&layouts, &s->ch_layout);
ff_channel_layouts_ref(layouts, &ctx->outputs[0]->in_channel_layouts);

for (i = 0; i < ctx->nb_inputs; i++)
diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c
index c72016d2c8..936a791175 100644
--- a/libavfilter/avfiltergraph.c
+++ b/libavfilter/avfiltergraph.c
@@ -374,6 +374,8 @@ static int query_formats(AVFilterGraph *graph, AVClass *log_ctx)

static int pick_format(AVFilterLink *link)
{
+ int ret;
+
if (!link || !link->in_formats)
return 0;

@@ -399,11 +401,15 @@ static int pick_format(AVFilterLink *link)
link->in_channel_layouts->nb_channel_layouts = 1;
#if FF_API_OLD_CHANNEL_LAYOUT
FF_DISABLE_DEPRECATION_WARNINGS
- link->channel_layout = link->in_channel_layouts->channel_layouts[0];
+ if (link->in_channel_layouts->channel_layouts[0].order == AV_CHANNEL_ORDER_NATIVE ||
+ link->in_channel_layouts->channel_layouts[0].order == AV_CHANNEL_ORDER_UNSPEC)
+ link->channel_layout = link->in_channel_layouts->channel_layouts[0].u.mask;
FF_ENABLE_DEPRECATION_WARNINGS
#endif
- av_channel_layout_from_mask(&link->ch_layout,
- link->in_channel_layouts->channel_layouts[0]);
+ ret = av_channel_layout_copy(&link->ch_layout,
+ &link->in_channel_layouts->channel_layouts[0]);
+ if (ret < 0)
+ return ret;
}

ff_formats_unref(&link->in_formats);
@@ -451,6 +457,47 @@ do { \
} \
} while (0)

+static int reduce_formats_channel_layout(AVFilterContext *filter)
+{
+ int i, j, k, ret = 0;
+
+ for (i = 0; i < filter->nb_inputs; i++) {
+ AVFilterLink *link = filter->inputs[i];
+ AVChannelLayout *fmt;
+
+ if (!link->out_channel_layouts || link->out_channel_layouts->nb_channel_layouts != 1)
+ continue;
+ fmt = &link->out_channel_layouts->channel_layouts[0];
+
+ for (j = 0; j < filter->nb_outputs; j++) {
+ AVFilterLink *out_link = filter->outputs[j];
+ AVFilterChannelLayouts *fmts;
+
+ if (link->type != out_link->type ||
+ out_link->in_channel_layouts->nb_channel_layouts == 1)
+ continue;
+ fmts = out_link->in_channel_layouts;
+
+ if (!out_link->in_channel_layouts->nb_channel_layouts) {
+ ff_add_channel_layout(&out_link->in_channel_layouts, fmt);
+ break;
+ }
+
+ for (k = 0; k < out_link->in_channel_layouts->nb_channel_layouts; k++)
+ if (!av_channel_layout_compare(&fmts->channel_layouts[k], fmt)) {
+ ret = av_channel_layout_copy(&fmts->channel_layouts[0], fmt);
+ if (ret < 0)
+ return ret;
+ fmts->nb_channel_layouts = 1;
+ ret = 1;
+ break;
+ }
+ }
+ }
+
+ return ret;
+}
+
static int reduce_formats_on_filter(AVFilterContext *filter)
{
int i, j, k, ret = 0;
@@ -459,10 +506,11 @@ static int reduce_formats_on_filter(AVFilterContext *filter)
nb_formats, ff_add_format);
REDUCE_FORMATS(int, AVFilterFormats, samplerates, formats,
nb_formats, ff_add_format);
- REDUCE_FORMATS(uint64_t, AVFilterChannelLayouts, channel_layouts,
- channel_layouts, nb_channel_layouts, ff_add_channel_layout);

- return ret;
+ if (ret < 0)
+ return ret;
+
+ return reduce_formats_channel_layout(filter);
}

static void reduce_formats(AVFilterGraph *graph)
@@ -582,20 +630,22 @@ static void swap_channel_layouts_on_filter(AVFilterContext *filter)
continue;

for (j = 0; j < outlink->in_channel_layouts->nb_channel_layouts; j++) {
- uint64_t in_chlayout = link->out_channel_layouts->channel_layouts[0];
- uint64_t out_chlayout = outlink->in_channel_layouts->channel_layouts[j];
+ AVChannelLayout *in_ch_layout = &link->out_channel_layouts->channel_layouts[0];
+ AVChannelLayout *out_ch_layout = &outlink->in_channel_layouts->channel_layouts[j];
+ AVChannelLayout in = {0}, out = {0};
int in_channels;
int out_channels;
+ uint64_t in_mask = 0, out_mask = 0;
int count_diff;
int matched_channels, extra_channels;
int score = 0;
- AVChannelLayout in_ch_layout = {0};
- AVChannelLayout out_ch_layout = {0};

- av_channel_layout_from_mask( &in_ch_layout, in_chlayout);
- av_channel_layout_from_mask(&out_ch_layout, out_chlayout);
- in_channels = in_ch_layout.nb_channels;
- out_channels = out_ch_layout.nb_channels;
+ in_channels = in_ch_layout->nb_channels;
+ out_channels = out_ch_layout->nb_channels;
+ if ( in_ch_layout->order == AV_CHANNEL_ORDER_NATIVE)
+ in_mask = in_ch_layout->u.mask;
+ if (out_ch_layout->order == AV_CHANNEL_ORDER_NATIVE)
+ out_mask = out_ch_layout->u.mask;
count_diff = out_channels - in_channels;

/* channel substitution */
@@ -603,10 +653,13 @@ static void swap_channel_layouts_on_filter(AVFilterContext *filter)
uint64_t cmp0 = ch_subst[k][0];
uint64_t cmp1 = ch_subst[k][1];
AVChannelLayout tmp = {0};
- if (( in_chlayout & cmp0) && (!(out_chlayout & cmp0)) &&
- (out_chlayout & cmp1) && (!( in_chlayout & cmp1))) {
- in_chlayout &= ~cmp0;
- out_chlayout &= ~cmp1;
+
+ if ( av_channel_layout_subset( in_ch_layout, cmp0) &&
+ !av_channel_layout_subset(out_ch_layout, cmp0) &&
+ av_channel_layout_subset(out_ch_layout, cmp1) &&
+ !av_channel_layout_subset( in_ch_layout, cmp1)) {
+ in_mask &= ~cmp0;
+ out_mask &= ~cmp1;
/* add score for channel match, minus a deduction for
having to do the substitution */
av_channel_layout_from_mask(&tmp, cmp1);
@@ -615,19 +668,17 @@ static void swap_channel_layouts_on_filter(AVFilterContext *filter)
}

/* no penalty for LFE channel mismatch */
- if ( (in_chlayout & AV_CH_LOW_FREQUENCY) &&
- (out_chlayout & AV_CH_LOW_FREQUENCY))
+ if (av_channel_layout_subset( in_ch_layout, AV_CH_LOW_FREQUENCY) &&
+ av_channel_layout_subset(out_ch_layout, AV_CH_LOW_FREQUENCY))
score += 10;
- in_chlayout &= ~AV_CH_LOW_FREQUENCY;
- out_chlayout &= ~AV_CH_LOW_FREQUENCY;
+ in_mask &= ~AV_CH_LOW_FREQUENCY;
+ out_mask &= ~AV_CH_LOW_FREQUENCY;

- av_channel_layout_uninit( &in_ch_layout);
- av_channel_layout_uninit(&out_ch_layout);
- av_channel_layout_from_mask( &in_ch_layout, in_chlayout & out_chlayout);
- av_channel_layout_from_mask(&out_ch_layout, out_chlayout & (~in_chlayout));
+ av_channel_layout_from_mask( &in, in_mask & out_mask);
+ av_channel_layout_from_mask(&out, out_mask & (~in_mask));

- matched_channels = in_ch_layout.nb_channels;
- extra_channels = out_ch_layout.nb_channels;
+ matched_channels = in.nb_channels;
+ extra_channels = out.nb_channels;
score += 10 * matched_channels - 5 * extra_channels;

if (score > best_score ||
@@ -638,7 +689,7 @@ static void swap_channel_layouts_on_filter(AVFilterContext *filter)
}
}
av_assert0(best_idx >= 0);
- FFSWAP(uint64_t, outlink->in_channel_layouts->channel_layouts[0],
+ FFSWAP(AVChannelLayout, outlink->in_channel_layouts->channel_layouts[0],
outlink->in_channel_layouts->channel_layouts[best_idx]);
}

diff --git a/libavfilter/buffersrc.c b/libavfilter/buffersrc.c
index 838e3ac08d..9f4e8dbf8a 100644
--- a/libavfilter/buffersrc.c
+++ b/libavfilter/buffersrc.c
@@ -347,7 +347,7 @@ static int query_formats(AVFilterContext *ctx)
ff_add_format(&samplerates, c->sample_rate);
ff_set_common_samplerates(ctx, samplerates);

- ff_add_channel_layout(&channel_layouts, c->ch_layout.u.mask);
+ ff_add_channel_layout(&channel_layouts, &c->ch_layout);
ff_set_common_channel_layouts(ctx, channel_layouts);
break;
default:
diff --git a/libavfilter/formats.c b/libavfilter/formats.c
index 7b5a93c325..251df0d721 100644
--- a/libavfilter/formats.c
+++ b/libavfilter/formats.c
@@ -131,8 +131,31 @@ AVFilterChannelLayouts *ff_merge_channel_layouts(AVFilterChannelLayouts *a,
if (a == b) return a;

if (a->nb_channel_layouts && b->nb_channel_layouts) {
- MERGE_FORMATS(ret, a, b, channel_layouts, nb_channel_layouts,
- AVFilterChannelLayouts, fail);
+ int i, j, k = 0, count = FFMIN(a->nb_channel_layouts, b->nb_channel_layouts);
+
+ if (!(ret = av_mallocz(sizeof(*ret))))
+ goto fail;
+
+ if (count) {
+ if (!(ret->channel_layouts = av_malloc(sizeof(*ret->channel_layouts) * count)))
+ goto fail;
+ for (i = 0; i < a->nb_channel_layouts; i++)
+ for (j = 0; j < b->nb_channel_layouts; j++)
+ if (!av_channel_layout_compare(&a->channel_layouts[i],
+ &b->channel_layouts[j]))
+ if (av_channel_layout_copy(&ret->channel_layouts[k++],
+ &a->channel_layouts[i]) < 0)
+ goto fail;
+
+ ret->nb_channel_layouts = k;
+ }
+ /* check that there was at least one common format */
+ if (!ret->nb_channel_layouts)
+ goto fail;
+
+ MERGE_REF(ret, a, channel_layouts, AVFilterChannelLayouts, fail);
+ MERGE_REF(ret, b, channel_layouts, AVFilterChannelLayouts, fail);
+
} else if (a->nb_channel_layouts) {
MERGE_REF(a, b, channel_layouts, AVFilterChannelLayouts, fail);
ret = a;
@@ -210,9 +233,23 @@ int ff_add_format(AVFilterFormats **avff, int fmt)
ADD_FORMAT(avff, fmt, int, formats, nb_formats);
}

-int ff_add_channel_layout(AVFilterChannelLayouts **l, uint64_t channel_layout)
+int ff_add_channel_layout(AVFilterChannelLayouts **f, AVChannelLayout *channel_layout)
{
- ADD_FORMAT(l, channel_layout, uint64_t, channel_layouts, nb_channel_layouts);
+ AVChannelLayout *fmts;
+
+ if (!(*f) && !(*f = av_mallocz(sizeof(**f))))
+ return AVERROR(ENOMEM);
+
+ fmts = av_realloc((*f)->channel_layouts,
+ sizeof(*(*f)->channel_layouts) * ((*f)->nb_channel_layouts + 1));\
+ if (!fmts) {
+ av_freep(&f);
+ return AVERROR(ENOMEM);
+ }
+
+ (*f)->channel_layouts = fmts;
+ return av_channel_layout_copy(&(*f)->channel_layouts[(*f)->nb_channel_layouts++],
+ channel_layout);
}

AVFilterFormats *ff_all_formats(enum AVMediaType type)
diff --git a/libavfilter/formats.h b/libavfilter/formats.h
index b273f8aa03..157ef757b3 100644
--- a/libavfilter/formats.h
+++ b/libavfilter/formats.h
@@ -70,7 +70,7 @@ struct AVFilterFormats {
};

typedef struct AVFilterChannelLayouts {
- uint64_t *channel_layouts; ///< list of channel layouts
+ AVChannelLayout *channel_layouts; ///< list of channel layouts
int nb_channel_layouts; ///< number of channel layouts

unsigned refcount; ///< number of references to this list
@@ -114,7 +114,7 @@ void ff_set_common_samplerates(AVFilterContext *ctx,
*/
void ff_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats);

-int ff_add_channel_layout(AVFilterChannelLayouts **l, uint64_t channel_layout);
+int ff_add_channel_layout(AVFilterChannelLayouts **l, AVChannelLayout *channel_layout);

/**
* Add *ref as a new reference to f.
--
2.13.1
Vittorio Giovara
2017-06-28 22:10:52 UTC
Permalink
This patch contains the following commits:

avtools: Use the new channel layout API in libavfilter

af_aformat: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

af_amix: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

af_ashowinfo: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

af_asyncts: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

af_atrim: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

af_channelmap: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

af_channelsplit: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

af_compand: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

af_hdcd: convert to new channel layout API

af_join: convert to new channel layout API

af_resample: convert to new channel layout API

af_volume: convert to new channel layout
---
avtools/avconv.c | 2 +-
avtools/avconv_filter.c | 4 +-
libavfilter/af_aformat.c | 10 ++++-
libavfilter/af_amix.c | 11 ++++--
libavfilter/af_ashowinfo.c | 12 +++---
libavfilter/af_asyncts.c | 6 +--
libavfilter/af_channelmap.c | 92 ++++++++++++++++++++++++-------------------
libavfilter/af_channelsplit.c | 38 +++++++++---------
libavfilter/af_compand.c | 8 ++--
libavfilter/af_hdcd.c | 2 +-
libavfilter/af_join.c | 84 ++++++++++++++++++---------------------
libavfilter/af_resample.c | 33 +++++++++-------
libavfilter/af_volume.c | 2 +-
libavfilter/trim.c | 3 +-
14 files changed, 163 insertions(+), 144 deletions(-)

diff --git a/avtools/avconv.c b/avtools/avconv.c
index 42cbfef592..a1427e0cb4 100644
--- a/avtools/avconv.c
+++ b/avtools/avconv.c
@@ -1998,7 +1998,7 @@ static int init_output_stream_encode(OutputStream *ost)
case AVMEDIA_TYPE_AUDIO:
enc_ctx->sample_fmt = ost->filter->filter->inputs[0]->format;
enc_ctx->sample_rate = ost->filter->filter->inputs[0]->sample_rate;
- enc_ctx->channel_layout = ost->filter->filter->inputs[0]->channel_layout;
+ enc_ctx->channel_layout = ost->filter->filter->inputs[0]->ch_layout.u.mask;
enc_ctx->channels = av_get_channel_layout_nb_channels(enc_ctx->channel_layout);
enc_ctx->time_base = (AVRational){ 1, enc_ctx->sample_rate };
break;
diff --git a/avtools/avconv_filter.c b/avtools/avconv_filter.c
index e719c06658..7df64c647a 100644
--- a/avtools/avconv_filter.c
+++ b/avtools/avconv_filter.c
@@ -591,7 +591,7 @@ static int configure_input_audio_filter(FilterGraph *fg, InputFilter *ifilter,
par->time_base = (AVRational){ 1, ifilter->sample_rate };
par->sample_rate = ifilter->sample_rate;
par->format = ifilter->format;
- par->channel_layout = ifilter->channel_layout;
+ av_channel_layout_from_mask(&par->ch_layout, ifilter->channel_layout);

ret = av_buffersrc_parameters_set(ifilter->filter, par);
av_freep(&par);
@@ -758,7 +758,7 @@ int configure_filtergraph(FilterGraph *fg)
ofilter->height = link->h;

ofilter->sample_rate = link->sample_rate;
- ofilter->channel_layout = link->channel_layout;
+ ofilter->channel_layout = link->ch_layout.u.mask;
}

for (i = 0; i < fg->nb_inputs; i++) {
diff --git a/libavfilter/af_aformat.c b/libavfilter/af_aformat.c
index f0746737dc..c5aa4f7148 100644
--- a/libavfilter/af_aformat.c
+++ b/libavfilter/af_aformat.c
@@ -94,6 +94,13 @@ static int get_sample_rate(const char *samplerate)
return FFMAX(ret, 0);
}

+static int get_channel_layout(const char *channel_layout)
+{
+ AVChannelLayout ch_layout = {0};
+ av_channel_layout_from_string(&ch_layout, channel_layout);
+ return ch_layout.u.mask;
+}
+
static av_cold int init(AVFilterContext *ctx)
{
AFormatContext *s = ctx->priv;
@@ -103,8 +110,7 @@ static av_cold int init(AVFilterContext *ctx)
PARSE_FORMATS(s->sample_rates_str, int, s->sample_rates, ff_add_format,
get_sample_rate, 0, "sample rate");
PARSE_FORMATS(s->channel_layouts_str, uint64_t, s->channel_layouts,
- ff_add_channel_layout, av_get_channel_layout, 0,
- "channel layout");
+ ff_add_channel_layout, get_channel_layout, 0, "channel layout");

return 0;
}
diff --git a/libavfilter/af_amix.c b/libavfilter/af_amix.c
index bfba1504ea..a35e04530f 100644
--- a/libavfilter/af_amix.c
+++ b/libavfilter/af_amix.c
@@ -226,7 +226,7 @@ static int config_output(AVFilterLink *outlink)
AVFilterContext *ctx = outlink->src;
MixContext *s = ctx->priv;
int i;
- char buf[64];
+ char *chlstr;

s->planar = av_sample_fmt_is_planar(outlink->format);
s->sample_rate = outlink->sample_rate;
@@ -241,7 +241,7 @@ static int config_output(AVFilterLink *outlink)
if (!s->fifos)
return AVERROR(ENOMEM);

- s->nb_channels = av_get_channel_layout_nb_channels(outlink->channel_layout);
+ s->nb_channels = outlink->ch_layout.nb_channels;
for (i = 0; i < s->nb_inputs; i++) {
s->fifos[i] = av_audio_fifo_alloc(outlink->format, s->nb_channels, 1024);
if (!s->fifos[i])
@@ -260,11 +260,14 @@ static int config_output(AVFilterLink *outlink)
s->scale_norm = s->active_inputs;
calculate_scales(s, 0);

- av_get_channel_layout_string(buf, sizeof(buf), -1, outlink->channel_layout);
+ chlstr = av_channel_layout_describe(&outlink->ch_layout);
+ if (!chlstr)
+ return AVERROR(ENOMEM);

av_log(ctx, AV_LOG_VERBOSE,
"inputs:%d fmt:%s srate:%d cl:%s\n", s->nb_inputs,
- av_get_sample_fmt_name(outlink->format), outlink->sample_rate, buf);
+ av_get_sample_fmt_name(outlink->format), outlink->sample_rate, chlstr);
+ av_free(chlstr);

return 0;
}
diff --git a/libavfilter/af_ashowinfo.c b/libavfilter/af_ashowinfo.c
index 5f0e2549ff..dd25c64d69 100644
--- a/libavfilter/af_ashowinfo.c
+++ b/libavfilter/af_ashowinfo.c
@@ -57,7 +57,7 @@ typedef struct AShowInfoContext {
static int config_input(AVFilterLink *inlink)
{
AShowInfoContext *s = inlink->dst->priv;
- int channels = av_get_channel_layout_nb_channels(inlink->channel_layout);
+ int channels = inlink->ch_layout.nb_channels;
s->plane_checksums = av_malloc(channels * sizeof(*s->plane_checksums));
if (!s->plane_checksums)
return AVERROR(ENOMEM);
@@ -192,9 +192,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
{
AVFilterContext *ctx = inlink->dst;
AShowInfoContext *s = ctx->priv;
- char chlayout_str[128];
+ char *chlayout_str;
uint32_t checksum = 0;
- int channels = av_get_channel_layout_nb_channels(buf->channel_layout);
+ int channels = buf->ch_layout.nb_channels;
int planar = av_sample_fmt_is_planar(buf->format);
int block_align = av_get_bytes_per_sample(buf->format) * (planar ? 1 : channels);
int data_size = buf->nb_samples * block_align;
@@ -209,8 +209,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
s->plane_checksums[0];
}

- av_get_channel_layout_string(chlayout_str, sizeof(chlayout_str), -1,
- buf->channel_layout);
+ chlayout_str = av_channel_layout_describe(&buf->ch_layout);
+ if (!chlayout_str)
+ return AVERROR(ENOMEM);

av_log(ctx, AV_LOG_INFO,
"n:%"PRIu64" pts:%"PRId64" pts_time:%f "
@@ -220,6 +221,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
av_get_sample_fmt_name(buf->format), chlayout_str,
buf->sample_rate, buf->nb_samples,
checksum);
+ av_free(chlayout_str);

av_log(ctx, AV_LOG_INFO, "plane_checksums: [ ");
for (i = 0; i < planes; i++)
diff --git a/libavfilter/af_asyncts.c b/libavfilter/af_asyncts.c
index 862b7a8cbd..ac983edca9 100644
--- a/libavfilter/af_asyncts.c
+++ b/libavfilter/af_asyncts.c
@@ -99,8 +99,8 @@ static int config_props(AVFilterLink *link)
if (!s->avr)
return AVERROR(ENOMEM);

- av_opt_set_int(s->avr, "in_channel_layout", link->channel_layout, 0);
- av_opt_set_int(s->avr, "out_channel_layout", link->channel_layout, 0);
+ av_opt_set_channel_layout(s->avr, "in_ch_layout", &link->ch_layout, 0);
+ av_opt_set_channel_layout(s->avr, "out_ch_layout", &link->ch_layout, 0);
av_opt_set_int(s->avr, "in_sample_fmt", link->format, 0);
av_opt_set_int(s->avr, "out_sample_fmt", link->format, 0);
av_opt_set_int(s->avr, "in_sample_rate", link->sample_rate, 0);
@@ -183,7 +183,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
AVFilterContext *ctx = inlink->dst;
ASyncContext *s = ctx->priv;
AVFilterLink *outlink = ctx->outputs[0];
- int nb_channels = av_get_channel_layout_nb_channels(buf->channel_layout);
+ int nb_channels = buf->ch_layout.nb_channels;
int64_t pts = (buf->pts == AV_NOPTS_VALUE) ? buf->pts :
av_rescale_q(buf->pts, inlink->time_base, outlink->time_base);
int out_size, ret;
diff --git a/libavfilter/af_channelmap.c b/libavfilter/af_channelmap.c
index e214bdbcc1..939f056d6f 100644
--- a/libavfilter/af_channelmap.c
+++ b/libavfilter/af_channelmap.c
@@ -38,8 +38,8 @@
#include "internal.h"

struct ChannelMap {
- uint64_t in_channel;
- uint64_t out_channel;
+ enum AVChannel in_channel;
+ enum AVChannel out_channel;
int in_channel_idx;
int out_channel_idx;
};
@@ -59,7 +59,7 @@ typedef struct ChannelMapContext {
const AVClass *class;
char *mapping_str;
char *channel_layout_str;
- uint64_t output_layout;
+ AVChannelLayout ch_layout;
struct ChannelMap map[MAX_CH];
int nch;
enum MappingMode mode;
@@ -106,14 +106,19 @@ static int get_channel_idx(char **map, int *ch, char delim, int max_ch)
return 0;
}

-static int get_channel(char **map, uint64_t *ch, char delim)
+static int get_channel(char **map, enum AVChannel *ch, char delim)
{
char *next = split(*map, delim);
+ int ret;
+
if (!next && delim == '-')
return AVERROR(EINVAL);
- *ch = av_get_channel_layout(*map);
- if (av_get_channel_layout_nb_channels(*ch) != 1)
- return AVERROR(EINVAL);
+
+ ret = av_channel_from_string(*map);
+ if (ret < 0)
+ return ret;
+
+ *ch = ret;
*map = next;
return 0;
}
@@ -123,7 +128,6 @@ static av_cold int channelmap_init(AVFilterContext *ctx)
ChannelMapContext *s = ctx->priv;
char *mapping, separator = '|';
int map_entries = 0;
- char buf[256];
enum MappingMode mode;
uint64_t out_ch_mask = 0;
int i;
@@ -168,7 +172,7 @@ static av_cold int channelmap_init(AVFilterContext *ctx)

for (i = 0; i < map_entries; i++) {
int in_ch_idx = -1, out_ch_idx = -1;
- uint64_t in_ch = 0, out_ch = 0;
+ enum AVChannel in_ch = 0, out_ch = 0;
static const char err[] = "Failed to parse channel map\n";
switch (mode) {
case MAP_ONE_INT:
@@ -199,13 +203,13 @@ static av_cold int channelmap_init(AVFilterContext *ctx)
case MAP_PAIR_INT_STR:
if (get_channel_idx(&mapping, &in_ch_idx, '-', MAX_CH) < 0 ||
get_channel(&mapping, &out_ch, separator) < 0 ||
- out_ch & out_ch_mask) {
+ (1ULL << out_ch) & out_ch_mask) {
av_log(ctx, AV_LOG_ERROR, err);
return AVERROR(EINVAL);
}
s->map[i].in_channel_idx = in_ch_idx;
s->map[i].out_channel = out_ch;
- out_ch_mask |= out_ch;
+ out_ch_mask |= (1ULL << out_ch);
break;
case MAP_PAIR_STR_INT:
if (get_channel(&mapping, &in_ch, '-') < 0 ||
@@ -219,50 +223,59 @@ static av_cold int channelmap_init(AVFilterContext *ctx)
case MAP_PAIR_STR_STR:
if (get_channel(&mapping, &in_ch, '-') < 0 ||
get_channel(&mapping, &out_ch, separator) < 0 ||
- out_ch & out_ch_mask) {
+ (1ULL << out_ch) & out_ch_mask) {
av_log(ctx, AV_LOG_ERROR, err);
return AVERROR(EINVAL);
}
s->map[i].in_channel = in_ch;
s->map[i].out_channel = out_ch;
- out_ch_mask |= out_ch;
+ out_ch_mask |= (1ULL << out_ch);
break;
}
}
s->mode = mode;
s->nch = map_entries;
- s->output_layout = out_ch_mask ? out_ch_mask :
- av_get_default_channel_layout(map_entries);
+
+ av_channel_layout_uninit(&s->ch_layout);
+ if (out_ch_mask)
+ av_channel_layout_from_mask(&s->ch_layout, out_ch_mask);
+ else
+ av_channel_layout_default(&s->ch_layout, map_entries);

if (s->channel_layout_str) {
- uint64_t fmt;
- if ((fmt = av_get_channel_layout(s->channel_layout_str)) == 0) {
+ int ret;
+ AVChannelLayout fmt = {0};
+ ret = av_channel_layout_from_string(&fmt, s->channel_layout_str);
+ if (ret < 0) {
av_log(ctx, AV_LOG_ERROR, "Error parsing channel layout: '%s'.\n",
s->channel_layout_str);
return AVERROR(EINVAL);
}
if (mode == MAP_NONE) {
int i;
- s->nch = av_get_channel_layout_nb_channels(fmt);
+ s->nch = fmt.nb_channels;
for (i = 0; i < s->nch; i++) {
s->map[i].in_channel_idx = i;
s->map[i].out_channel_idx = i;
}
- } else if (out_ch_mask && out_ch_mask != fmt) {
- av_get_channel_layout_string(buf, sizeof(buf), 0, out_ch_mask);
+ } else if (out_ch_mask && av_channel_layout_compare(&s->ch_layout, &fmt)) {
+ char *chlstr = av_channel_layout_describe(&s->ch_layout);
av_log(ctx, AV_LOG_ERROR,
"Output channel layout '%s' does not match the list of channel mapped: '%s'.\n",
- s->channel_layout_str, buf);
+ s->channel_layout_str, chlstr);
+ av_free(chlstr);
return AVERROR(EINVAL);
- } else if (s->nch != av_get_channel_layout_nb_channels(fmt)) {
+ } else if (s->nch != fmt.nb_channels) {
av_log(ctx, AV_LOG_ERROR,
"Output channel layout %s does not match the number of channels mapped %d.\n",
s->channel_layout_str, s->nch);
return AVERROR(EINVAL);
}
- s->output_layout = fmt;
+ ret = av_channel_layout_copy(&s->ch_layout, &fmt);
+ if (ret < 0)
+ return ret;
}
- if (!s->output_layout) {
+ if (!av_channel_layout_check(&s->ch_layout)) {
av_log(ctx, AV_LOG_ERROR, "Output channel layout is not set and "
"cannot be guessed from the maps.\n");
return AVERROR(EINVAL);
@@ -270,8 +283,8 @@ static av_cold int channelmap_init(AVFilterContext *ctx)

if (mode == MAP_PAIR_INT_STR || mode == MAP_PAIR_STR_STR) {
for (i = 0; i < s->nch; i++) {
- s->map[i].out_channel_idx = av_get_channel_layout_channel_index(
- s->output_layout, s->map[i].out_channel);
+ s->map[i].out_channel_idx =
+ av_channel_layout_channel_index(&s->ch_layout, s->map[i].out_channel);
}
}

@@ -283,7 +296,7 @@ static int channelmap_query_formats(AVFilterContext *ctx)
ChannelMapContext *s = ctx->priv;
AVFilterChannelLayouts *channel_layouts = NULL;

- ff_add_channel_layout(&channel_layouts, s->output_layout);
+ ff_add_channel_layout(&channel_layouts, s->ch_layout.u.mask);

ff_set_common_formats(ctx, ff_planar_sample_fmts());
ff_set_common_samplerates(ctx, ff_all_samplerates());
@@ -298,9 +311,9 @@ static int channelmap_filter_frame(AVFilterLink *inlink, AVFrame *buf)
AVFilterContext *ctx = inlink->dst;
AVFilterLink *outlink = ctx->outputs[0];
const ChannelMapContext *s = ctx->priv;
- const int nch_in = av_get_channel_layout_nb_channels(inlink->channel_layout);
+ const int nch_in = inlink->ch_layout.nb_channels;
const int nch_out = s->nch;
- int ch;
+ int ret, ch;
uint8_t *source_planes[MAX_CH];

memcpy(source_planes, buf->extended_data,
@@ -335,7 +348,9 @@ static int channelmap_filter_frame(AVFilterLink *inlink, AVFrame *buf)
memcpy(buf->data, buf->extended_data,
FFMIN(FF_ARRAY_ELEMS(buf->data), nch_out) * sizeof(buf->data[0]));

- buf->channel_layout = outlink->channel_layout;
+ ret = av_channel_layout_copy(&buf->ch_layout, &outlink->ch_layout);
+ if (ret < 0)
+ return ret;

return ff_filter_frame(outlink, buf);
}
@@ -344,33 +359,30 @@ static int channelmap_config_input(AVFilterLink *inlink)
{
AVFilterContext *ctx = inlink->dst;
ChannelMapContext *s = ctx->priv;
- int nb_channels = av_get_channel_layout_nb_channels(inlink->channel_layout);
+ int nb_channels = inlink->ch_layout.nb_channels;
int i, err = 0;
- const char *channel_name;
- char layout_name[256];

for (i = 0; i < s->nch; i++) {
struct ChannelMap *m = &s->map[i];

if (s->mode == MAP_PAIR_STR_INT || s->mode == MAP_PAIR_STR_STR) {
- m->in_channel_idx = av_get_channel_layout_channel_index(
- inlink->channel_layout, m->in_channel);
+ m->in_channel_idx = av_channel_layout_channel_index(&inlink->ch_layout,
+ m->in_channel);
}

if (m->in_channel_idx < 0 || m->in_channel_idx >= nb_channels) {
- av_get_channel_layout_string(layout_name, sizeof(layout_name),
- 0, inlink->channel_layout);
+ char *chlstr = av_channel_layout_describe(&inlink->ch_layout);
if (m->in_channel) {
- channel_name = av_get_channel_name(m->in_channel);
av_log(ctx, AV_LOG_ERROR,
"input channel '%s' not available from input layout '%s'\n",
- channel_name, layout_name);
+ av_channel_name(m->in_channel), chlstr);
} else {
av_log(ctx, AV_LOG_ERROR,
"input channel #%d not available from input layout '%s'\n",
- m->in_channel_idx, layout_name);
+ m->in_channel_idx, chlstr);
}
err = AVERROR(EINVAL);
+ av_free(chlstr);
}
}

diff --git a/libavfilter/af_channelsplit.c b/libavfilter/af_channelsplit.c
index 5b410fd87c..41b3051c8c 100644
--- a/libavfilter/af_channelsplit.c
+++ b/libavfilter/af_channelsplit.c
@@ -36,14 +36,14 @@
typedef struct ChannelSplitContext {
const AVClass *class;

- uint64_t channel_layout;
- char *channel_layout_str;
+ AVChannelLayout ch_layout;
} ChannelSplitContext;

#define OFFSET(x) offsetof(ChannelSplitContext, x)
#define A AV_OPT_FLAG_AUDIO_PARAM
static const AVOption options[] = {
- { "channel_layout", "Input channel layout.", OFFSET(channel_layout_str), AV_OPT_TYPE_STRING, { .str = "stereo" }, .flags = A },
+ { "channel_layout", "Input channel layout.", OFFSET(ch_layout),
+ AV_OPT_TYPE_CHANNEL_LAYOUT, { .str = "stereo" }, .flags = A },
{ NULL },
};

@@ -57,23 +57,17 @@ static const AVClass channelsplit_class = {
static av_cold int init(AVFilterContext *ctx)
{
ChannelSplitContext *s = ctx->priv;
- int nb_channels;
+ int nb_channels = s->ch_layout.nb_channels;
int ret = 0, i;

- if (!(s->channel_layout = av_get_channel_layout(s->channel_layout_str))) {
- av_log(ctx, AV_LOG_ERROR, "Error parsing channel layout '%s'.\n",
- s->channel_layout_str);
- ret = AVERROR(EINVAL);
- goto fail;
- }
-
- nb_channels = av_get_channel_layout_nb_channels(s->channel_layout);
for (i = 0; i < nb_channels; i++) {
- uint64_t channel = av_channel_layout_extract_channel(s->channel_layout, i);
AVFilterPad pad = { 0 };
+ ret = av_channel_layout_get_channel(&s->ch_layout, i);
+ if (ret < 0)
+ goto fail;

pad.type = AVMEDIA_TYPE_AUDIO;
- pad.name = av_get_channel_name(channel);
+ pad.name = av_channel_name(ret);

ff_insert_outpad(ctx, i, &pad);
}
@@ -91,14 +85,16 @@ static int query_formats(AVFilterContext *ctx)
ff_set_common_formats (ctx, ff_planar_sample_fmts());
ff_set_common_samplerates(ctx, ff_all_samplerates());

- ff_add_channel_layout(&in_layouts, s->channel_layout);
+ ff_add_channel_layout(&in_layouts, s->ch_layout.u.mask);
ff_channel_layouts_ref(in_layouts, &ctx->inputs[0]->out_channel_layouts);

for (i = 0; i < ctx->nb_outputs; i++) {
AVFilterChannelLayouts *out_layouts = NULL;
- uint64_t channel = av_channel_layout_extract_channel(s->channel_layout, i);
+ int ret = av_channel_layout_get_channel(&s->ch_layout, i);
+ if (ret < 0)
+ return ret;

- ff_add_channel_layout(&out_layouts, channel);
+ ff_add_channel_layout(&out_layouts, 1ULL << ret);
ff_channel_layouts_ref(out_layouts, &ctx->outputs[i]->in_channel_layouts);
}

@@ -112,15 +108,17 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf)

for (i = 0; i < ctx->nb_outputs; i++) {
AVFrame *buf_out = av_frame_clone(buf);
+ enum AVChannel channel;

if (!buf_out) {
ret = AVERROR(ENOMEM);
break;
}
-
buf_out->data[0] = buf_out->extended_data[0] = buf_out->extended_data[i];
- buf_out->channel_layout =
- av_channel_layout_extract_channel(buf->channel_layout, i);
+ channel = av_channel_layout_get_channel(&buf->ch_layout, i);
+
+ av_channel_layout_uninit(&buf_out->ch_layout);
+ av_channel_layout_from_mask(&buf_out->ch_layout, 1 << channel);

ret = ff_filter_frame(ctx->outputs[i], buf_out);
if (ret < 0)
diff --git a/libavfilter/af_compand.c b/libavfilter/af_compand.c
index f21c861e06..cc743e3e6d 100644
--- a/libavfilter/af_compand.c
+++ b/libavfilter/af_compand.c
@@ -342,8 +342,7 @@ static int config_output(AVFilterLink *outlink)
const int sample_rate = outlink->sample_rate;
double radius = s->curve_dB * M_LN10 / 20.0;
const char *p;
- const int channels =
- av_get_channel_layout_nb_channels(outlink->channel_layout);
+ const int channels = outlink->ch_layout.nb_channels;
int nb_attacks, nb_decays, nb_points;
int new_nb_items, num;
int i;
@@ -547,7 +546,10 @@ static int config_output(AVFilterLink *outlink)

s->delay_frame->format = outlink->format;
s->delay_frame->nb_samples = s->delay_samples;
- s->delay_frame->channel_layout = outlink->channel_layout;
+ err = av_channel_layout_copy(&s->delay_frame->ch_layout,
+ &outlink->ch_layout);
+ if (err < 0)
+ return err;

err = av_frame_get_buffer(s->delay_frame, 32);
if (err)
diff --git a/libavfilter/af_hdcd.c b/libavfilter/af_hdcd.c
index b9dadecca4..78cc1e74c8 100644
--- a/libavfilter/af_hdcd.c
+++ b/libavfilter/af_hdcd.c
@@ -76,7 +76,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
const int16_t *in_data;
int32_t *out_data;
int n, result;
- int channel_count = av_get_channel_layout_nb_channels(in->channel_layout);
+ int channel_count = in->ch_layout.nb_channels;

out = ff_get_audio_buffer(outlink, in->nb_samples);
if (!out) {
diff --git a/libavfilter/af_join.c b/libavfilter/af_join.c
index b61033f7a2..6c000b9257 100644
--- a/libavfilter/af_join.c
+++ b/libavfilter/af_join.c
@@ -37,8 +37,8 @@
typedef struct ChannelMap {
int input; ///< input stream index
int in_channel_idx; ///< index of in_channel in the input stream data
- uint64_t in_channel; ///< layout describing the input channel
- uint64_t out_channel; ///< layout describing the output channel
+ enum AVChannel in_channel; ///< input channel
+ enum AVChannel out_channel; ///< output channel
} ChannelMap;

typedef struct JoinContext {
@@ -46,8 +46,7 @@ typedef struct JoinContext {

int inputs;
char *map;
- char *channel_layout_str;
- uint64_t channel_layout;
+ AVChannelLayout ch_layout;

int nb_channels;
ChannelMap *channels;
@@ -68,7 +67,7 @@ typedef struct JoinContext {
static const AVOption join_options[] = {
{ "inputs", "Number of input streams.", OFFSET(inputs), AV_OPT_TYPE_INT, { .i64 = 2 }, 1, INT_MAX, A },
{ "channel_layout", "Channel layout of the "
- "output stream.", OFFSET(channel_layout_str), AV_OPT_TYPE_STRING, {.str = "stereo"}, 0, 0, A },
+ "output stream.", OFFSET(ch_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.str = "stereo"}, 0, 0, A },
{ "map", "A comma-separated list of channels maps in the format "
"'input_stream.input_channel-output_channel.",
OFFSET(map), AV_OPT_TYPE_STRING, .flags = A },
@@ -106,7 +105,7 @@ static int parse_maps(AVFilterContext *ctx)

while (cur && *cur) {
char *sep, *next, *p;
- uint64_t in_channel = 0, out_channel = 0;
+ enum AVChannel in_channel = -1, out_channel;
int input_idx, out_ch_idx, in_ch_idx;

next = strchr(cur, separator);
@@ -122,26 +121,22 @@ static int parse_maps(AVFilterContext *ctx)
*sep++ = 0;

#define PARSE_CHANNEL(str, var, inout) \
- if (!(var = av_get_channel_layout(str))) { \
+ var = av_channel_from_string(str); \
+ if ((int) var < 0) { \
av_log(ctx, AV_LOG_ERROR, "Invalid " inout " channel: %s.\n", str);\
return AVERROR(EINVAL); \
} \
- if (av_get_channel_layout_nb_channels(var) != 1) { \
- av_log(ctx, AV_LOG_ERROR, "Channel map describes more than one " \
- inout " channel.\n"); \
- return AVERROR(EINVAL); \
- }

/* parse output channel */
PARSE_CHANNEL(sep, out_channel, "output");
- if (!(out_channel & s->channel_layout)) {
+
+ out_ch_idx = av_channel_layout_channel_index(&s->ch_layout,
+ out_channel);
+ if (out_ch_idx < 0) {
av_log(ctx, AV_LOG_ERROR, "Output channel '%s' is not present in "
"requested channel layout.\n", sep);
return AVERROR(EINVAL);
}
-
- out_ch_idx = av_get_channel_layout_channel_index(s->channel_layout,
- out_channel);
if (s->channels[out_ch_idx].input >= 0) {
av_log(ctx, AV_LOG_ERROR, "Multiple maps for output channel "
"'%s'.\n", sep);
@@ -167,7 +162,7 @@ static int parse_maps(AVFilterContext *ctx)
}

s->channels[out_ch_idx].input = input_idx;
- if (in_channel)
+ if ((int) in_channel >= 0)
s->channels[out_ch_idx].in_channel = in_channel;
else
s->channels[out_ch_idx].in_channel_idx = in_ch_idx;
@@ -182,14 +177,7 @@ static av_cold int join_init(AVFilterContext *ctx)
JoinContext *s = ctx->priv;
int ret, i;

- if (!(s->channel_layout = av_get_channel_layout(s->channel_layout_str))) {
- av_log(ctx, AV_LOG_ERROR, "Error parsing channel layout '%s'.\n",
- s->channel_layout_str);
- ret = AVERROR(EINVAL);
- goto fail;
- }
-
- s->nb_channels = av_get_channel_layout_nb_channels(s->channel_layout);
+ s->nb_channels = s->ch_layout.nb_channels;
s->channels = av_mallocz(sizeof(*s->channels) * s->nb_channels);
s->buffers = av_mallocz(sizeof(*s->buffers) * s->nb_channels);
s->input_frames = av_mallocz(sizeof(*s->input_frames) * s->inputs);
@@ -199,7 +187,7 @@ static av_cold int join_init(AVFilterContext *ctx)
}

for (i = 0; i < s->nb_channels; i++) {
- s->channels[i].out_channel = av_channel_layout_extract_channel(s->channel_layout, i);
+ s->channels[i].out_channel = av_channel_layout_get_channel(&s->ch_layout, i);
s->channels[i].input = -1;
}

@@ -246,7 +234,7 @@ static int join_query_formats(AVFilterContext *ctx)
AVFilterChannelLayouts *layouts = NULL;
int i;

- ff_add_channel_layout(&layouts, s->channel_layout);
+ ff_add_channel_layout(&layouts, s->ch_layout.u.mask);
ff_channel_layouts_ref(layouts, &ctx->outputs[0]->in_channel_layouts);

for (i = 0; i < ctx->nb_inputs; i++)
@@ -267,11 +255,11 @@ static void guess_map_matching(AVFilterContext *ctx, ChannelMap *ch,
for (i = 0; i < ctx->nb_inputs; i++) {
AVFilterLink *link = ctx->inputs[i];

- if (ch->out_channel & link->channel_layout &&
- !(ch->out_channel & inputs[i])) {
+ if (av_channel_layout_channel_index(&link->ch_layout, ch->out_channel) >= 0 &&
+ !((1ULL << ch->out_channel) & inputs[i])) {
ch->input = i;
ch->in_channel = ch->out_channel;
- inputs[i] |= ch->out_channel;
+ inputs[i] |= 1ULL << ch->out_channel;
return;
}
}
@@ -285,12 +273,14 @@ static void guess_map_any(AVFilterContext *ctx, ChannelMap *ch,
for (i = 0; i < ctx->nb_inputs; i++) {
AVFilterLink *link = ctx->inputs[i];

- if ((inputs[i] & link->channel_layout) != link->channel_layout) {
- uint64_t unused = link->channel_layout & ~inputs[i];
+ if ((inputs[i] & link->ch_layout.u.mask) != link->ch_layout.u.mask) {
+ uint64_t unused = link->ch_layout.u.mask & ~inputs[i];
+ AVChannelLayout layout = {0};
+ av_channel_layout_from_mask(&layout, unused);

ch->input = i;
- ch->in_channel = av_channel_layout_extract_channel(unused, 0);
- inputs[i] |= ch->in_channel;
+ ch->in_channel = av_channel_layout_get_channel(&layout, 0);
+ inputs[i] |= 1ULL << ch->in_channel;
return;
}
}
@@ -315,19 +305,19 @@ static int join_config_output(AVFilterLink *outlink)

inlink = ctx->inputs[ch->input];

- if (!ch->in_channel)
- ch->in_channel = av_channel_layout_extract_channel(inlink->channel_layout,
- ch->in_channel_idx);
+ if ((int) ch->in_channel < 0)
+ ch->in_channel = av_channel_layout_get_channel(&inlink->ch_layout,
+ ch->in_channel_idx);

- if (!(ch->in_channel & inlink->channel_layout)) {
+ if ((int) ch->in_channel < 0) {
av_log(ctx, AV_LOG_ERROR, "Requested channel %s is not present in "
- "input stream #%d.\n", av_get_channel_name(ch->in_channel),
+ "input stream #%d.\n", av_channel_name(ch->in_channel),
ch->input);
ret = AVERROR(EINVAL);
goto fail;
}

- inputs[ch->input] |= ch->in_channel;
+ inputs[ch->input] |= 1ULL << ch->in_channel;
}

/* guess channel maps when not explicitly defined */
@@ -349,12 +339,12 @@ static int join_config_output(AVFilterLink *outlink)
if (ch->input < 0) {
av_log(ctx, AV_LOG_ERROR, "Could not find input channel for "
"output channel '%s'.\n",
- av_get_channel_name(ch->out_channel));
+ av_channel_name(ch->out_channel));
goto fail;
}

- ch->in_channel_idx = av_get_channel_layout_channel_index(ctx->inputs[ch->input]->channel_layout,
- ch->in_channel);
+ ch->in_channel_idx = av_channel_layout_channel_index(&ctx->inputs[ch->input]->ch_layout,
+ ch->in_channel);
}

/* print mappings */
@@ -362,8 +352,8 @@ static int join_config_output(AVFilterLink *outlink)
for (i = 0; i < s->nb_channels; i++) {
ChannelMap *ch = &s->channels[i];
av_log(ctx, AV_LOG_VERBOSE, "%d.%s => %s ", ch->input,
- av_get_channel_name(ch->in_channel),
- av_get_channel_name(ch->out_channel));
+ av_channel_name(ch->in_channel),
+ av_channel_name(ch->out_channel));
}
av_log(ctx, AV_LOG_VERBOSE, "\n");

@@ -469,7 +459,9 @@ static int join_request_frame(AVFilterLink *outlink)
}

frame->nb_samples = nb_samples;
- frame->channel_layout = outlink->channel_layout;
+ ret = av_channel_layout_copy(&frame->ch_layout, &outlink->ch_layout);
+ if (ret < 0)
+ goto fail;
frame->sample_rate = outlink->sample_rate;
frame->format = outlink->format;
frame->pts = s->input_frames[0]->pts;
diff --git a/libavfilter/af_resample.c b/libavfilter/af_resample.c
index 413b6634cc..09984b8a7e 100644
--- a/libavfilter/af_resample.c
+++ b/libavfilter/af_resample.c
@@ -65,8 +65,8 @@ static av_cold int init(AVFilterContext *ctx, AVDictionary **opts)
av_dict_set(opts, e->key, NULL, 0);

/* do not allow the user to override basic format options */
- av_dict_set(&s->options, "in_channel_layout", NULL, 0);
- av_dict_set(&s->options, "out_channel_layout", NULL, 0);
+ av_dict_set(&s->options, "in_ch_layout", NULL, 0);
+ av_dict_set(&s->options, "out_ch_layout", NULL, 0);
av_dict_set(&s->options, "in_sample_fmt", NULL, 0);
av_dict_set(&s->options, "out_sample_fmt", NULL, 0);
av_dict_set(&s->options, "in_sample_rate", NULL, 0);
@@ -115,7 +115,7 @@ static int config_output(AVFilterLink *outlink)
AVFilterContext *ctx = outlink->src;
AVFilterLink *inlink = ctx->inputs[0];
ResampleContext *s = ctx->priv;
- char buf1[64], buf2[64];
+ char *inchlstr, *outchlstr;
int ret;

int64_t resampling_forced;
@@ -125,11 +125,11 @@ static int config_output(AVFilterLink *outlink)
avresample_free(&s->avr);
}

- if (inlink->channel_layout == outlink->channel_layout &&
+ if (!av_channel_layout_compare(&inlink->ch_layout, &outlink->ch_layout) &&
inlink->sample_rate == outlink->sample_rate &&
(inlink->format == outlink->format ||
- (av_get_channel_layout_nb_channels(inlink->channel_layout) == 1 &&
- av_get_channel_layout_nb_channels(outlink->channel_layout) == 1 &&
+ (inlink->ch_layout.nb_channels == 1 &&
+ outlink->ch_layout.nb_channels == 1 &&
av_get_planar_sample_fmt(inlink->format) ==
av_get_planar_sample_fmt(outlink->format))))
return 0;
@@ -148,8 +148,8 @@ static int config_output(AVFilterLink *outlink)
return ret;
}

- av_opt_set_int(s->avr, "in_channel_layout", inlink ->channel_layout, 0);
- av_opt_set_int(s->avr, "out_channel_layout", outlink->channel_layout, 0);
+ av_opt_set_channel_layout(s->avr, "in_ch_layout", &inlink->ch_layout, 0);
+ av_opt_set_channel_layout(s->avr, "out_ch_layout", &outlink->ch_layout, 0);
av_opt_set_int(s->avr, "in_sample_fmt", inlink ->format, 0);
av_opt_set_int(s->avr, "out_sample_fmt", outlink->format, 0);
av_opt_set_int(s->avr, "in_sample_rate", inlink ->sample_rate, 0);
@@ -168,14 +168,19 @@ static int config_output(AVFilterLink *outlink)
} else
outlink->time_base = inlink->time_base;

- av_get_channel_layout_string(buf1, sizeof(buf1),
- -1, inlink ->channel_layout);
- av_get_channel_layout_string(buf2, sizeof(buf2),
- -1, outlink->channel_layout);
+ inchlstr = av_channel_layout_describe(&inlink->ch_layout);
+ outchlstr = av_channel_layout_describe(&outlink->ch_layout);
+ if (!inchlstr || !outchlstr) {
+ av_free(inchlstr);
+ av_free(outchlstr);
+ return AVERROR(ENOMEM);
+ }
av_log(ctx, AV_LOG_VERBOSE,
"fmt:%s srate:%d cl:%s -> fmt:%s srate:%d cl:%s\n",
- av_get_sample_fmt_name(inlink ->format), inlink ->sample_rate, buf1,
- av_get_sample_fmt_name(outlink->format), outlink->sample_rate, buf2);
+ av_get_sample_fmt_name(inlink ->format), inlink ->sample_rate, inchlstr,
+ av_get_sample_fmt_name(outlink->format), outlink->sample_rate, outchlstr);
+ av_free(inchlstr);
+ av_free(outchlstr);

return 0;
}
diff --git a/libavfilter/af_volume.c b/libavfilter/af_volume.c
index 0ec42b031e..bbadd87d47 100644
--- a/libavfilter/af_volume.c
+++ b/libavfilter/af_volume.c
@@ -228,7 +228,7 @@ static int config_output(AVFilterLink *outlink)
AVFilterLink *inlink = ctx->inputs[0];

vol->sample_fmt = inlink->format;
- vol->channels = av_get_channel_layout_nb_channels(inlink->channel_layout);
+ vol->channels = inlink->ch_layout.nb_channels;
vol->planes = av_sample_fmt_is_planar(inlink->format) ? vol->channels : 1;

volume_init(vol);
diff --git a/libavfilter/trim.c b/libavfilter/trim.c
index 2b57540460..df054aa606 100644
--- a/libavfilter/trim.c
+++ b/libavfilter/trim.c
@@ -336,8 +336,7 @@ static int atrim_filter_frame(AVFilterLink *inlink, AVFrame *frame)

av_frame_copy_props(out, frame);
av_samples_copy(out->extended_data, frame->extended_data, 0, start_sample,
- out->nb_samples, av_get_channel_layout_nb_channels(frame->channel_layout),
- frame->format);
+ out->nb_samples, frame->ch_layout.nb_channels, frame->format);
if (out->pts != AV_NOPTS_VALUE)
out->pts += av_rescale_q(start_sample, (AVRational){ 1, out->sample_rate },
inlink->time_base);
--
2.13.1
Diego Biurrun
2017-06-29 07:59:50 UTC
Permalink
Post by Vittorio Giovara
--- a/libavfilter/af_aformat.c
+++ b/libavfilter/af_aformat.c
@@ -94,6 +94,13 @@ static int get_sample_rate(const char *samplerate)
+static int get_channel_layout(const char *channel_layout)
+{
+ AVChannelLayout ch_layout = {0};
--- a/libavfilter/af_channelmap.c
+++ b/libavfilter/af_channelmap.c
@@ -219,50 +223,59 @@ static av_cold int channelmap_init(AVFilterContext *ctx)
if (s->channel_layout_str) {
- uint64_t fmt;
- if ((fmt = av_get_channel_layout(s->channel_layout_str)) == 0) {
+ int ret;
+ AVChannelLayout fmt = {0};
--- a/libavfilter/af_join.c
+++ b/libavfilter/af_join.c
@@ -285,12 +273,14 @@ static void guess_map_any(AVFilterContext *ctx, ChannelMap *ch,
- if ((inputs[i] & link->channel_layout) != link->channel_layout) {
- uint64_t unused = link->channel_layout & ~inputs[i];
+ if ((inputs[i] & link->ch_layout.u.mask) != link->ch_layout.u.mask) {
+ uint64_t unused = link->ch_layout.u.mask & ~inputs[i];
+ AVChannelLayout layout = {0};
spaces inside {}

Diego
Vittorio Giovara
2017-06-29 17:02:51 UTC
Permalink
Post by Diego Biurrun
Post by Vittorio Giovara
--- a/libavfilter/af_aformat.c
+++ b/libavfilter/af_aformat.c
@@ -94,6 +94,13 @@ static int get_sample_rate(const char *samplerate)
+static int get_channel_layout(const char *channel_layout)
+{
+ AVChannelLayout ch_layout = {0};
--- a/libavfilter/af_channelmap.c
+++ b/libavfilter/af_channelmap.c
@@ -219,50 +223,59 @@ static av_cold int channelmap_init(AVFilterContext *ctx)
if (s->channel_layout_str) {
- uint64_t fmt;
- if ((fmt = av_get_channel_layout(s->channel_layout_str)) == 0) {
+ int ret;
+ AVChannelLayout fmt = {0};
--- a/libavfilter/af_join.c
+++ b/libavfilter/af_join.c
@@ -285,12 +273,14 @@ static void guess_map_any(AVFilterContext *ctx, ChannelMap *ch,
- if ((inputs[i] & link->channel_layout) != link->channel_layout) {
- uint64_t unused = link->channel_layout & ~inputs[i];
+ if ((inputs[i] & link->ch_layout.u.mask) != link->ch_layout.u.mask) {
+ uint64_t unused = link->ch_layout.u.mask & ~inputs[i];
+ AVChannelLayout layout = {0};
spaces inside {}
applied locally
--
Vittorio
Anton Khirnov
2017-07-22 10:07:26 UTC
Permalink
Quoting Vittorio Giovara (2017-06-29 00:10:52)
Post by Vittorio Giovara
avtools: Use the new channel layout API in libavfilter
Again, this does not belong here.
The libraries should be converted separately from their users, and FATE
should pass both before and after. That helps ensuring that the compat
layers are correct.
--
Anton Khirnov
Vittorio Giovara
2017-06-28 22:10:54 UTC
Permalink
Signed-off-by: Vittorio Giovara <***@gmail.com>
---
libavcodec/avcodec.h | 11 +++++++++++
libavcodec/utils.c | 31 +++++++++++++++++++++++++++----
libavformat/audiointerleave.c | 2 +-
libavformat/mux.c | 2 +-
4 files changed, 40 insertions(+), 6 deletions(-)

diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 4089c08a24..bc7097c7bd 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -3202,16 +3202,22 @@ typedef struct AVCodecParameters {
enum AVColorSpace color_space;
enum AVChromaLocation chroma_location;

+#if FF_API_OLD_CHANNEL_LAYOUT
/**
* Audio only. The channel layout bitmask. May be 0 if the channel layout is
* unknown or unspecified, otherwise the number of bits set must be equal to
* the channels field.
+ * @deprecated use ch_layout
*/
+ attribute_deprecated
uint64_t channel_layout;
/**
* Audio only. The number of audio channels.
+ * @deprecated use ch_layout.nb_channels
*/
+ attribute_deprecated
int channels;
+#endif
/**
* Audio only. The number of audio samples per second.
*/
@@ -3238,6 +3244,11 @@ typedef struct AVCodecParameters {
* audio without any trailing padding.
*/
int trailing_padding;
+
+ /**
+ * Audio only. The channel layout and number of channels.
+ */
+ AVChannelLayout ch_layout;
} AVCodecParameters;

/**
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index bc421f67f8..f8ae415d52 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -1300,8 +1300,15 @@ int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes)

int av_get_audio_frame_duration2(AVCodecParameters *par, int frame_bytes)
{
+ int channels = par->ch_layout.nb_channels;
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+ if (!channels)
+ channels = par->channels;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
return get_audio_frame_duration(par->codec_id, par->sample_rate,
- par->channels, par->block_align,
+ channels, par->block_align,
par->codec_tag, par->bits_per_coded_sample,
frame_bytes);
}
@@ -1588,7 +1595,7 @@ int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src
dst->extradata_size = src->extradata_size;
}

- return 0;
+ return av_channel_layout_copy(&dst->ch_layout, &src->ch_layout);
}

int avcodec_parameters_from_context(AVCodecParameters *par,
@@ -1620,8 +1627,16 @@ int avcodec_parameters_from_context(AVCodecParameters *par,
break;
case AVMEDIA_TYPE_AUDIO:
par->format = codec->sample_fmt;
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
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;
@@ -1666,8 +1681,16 @@ int avcodec_parameters_to_context(AVCodecContext *codec,
break;
case AVMEDIA_TYPE_AUDIO:
codec->sample_fmt = par->format;
- codec->channel_layout = par->channel_layout;
- codec->channels = par->channels;
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+ codec->channel_layout = par->channel_layout;
+ codec->channels = par->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/audiointerleave.c b/libavformat/audiointerleave.c
index aa379f675e..4923c55b35 100644
--- a/libavformat/audiointerleave.c
+++ b/libavformat/audiointerleave.c
@@ -52,7 +52,7 @@ int ff_audio_interleave_init(AVFormatContext *s,
AudioInterleaveContext *aic = st->priv_data;

if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
- aic->sample_size = (st->codecpar->channels *
+ aic->sample_size = (st->codecpar->ch_layout.nb_channels *
av_get_bits_per_sample(st->codecpar->codec_id)) / 8;
if (!aic->sample_size) {
av_log(s, AV_LOG_ERROR, "could not compute sample size\n");
diff --git a/libavformat/mux.c b/libavformat/mux.c
index cc92f2a960..0084107dd5 100644
--- a/libavformat/mux.c
+++ b/libavformat/mux.c
@@ -140,7 +140,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
goto fail;
}
if (!par->block_align)
- par->block_align = par->channels *
+ par->block_align = par->ch_layout.nb_channels *
av_get_bits_per_sample(par->codec_id) >> 3;
break;
case AVMEDIA_TYPE_VIDEO:
--
2.13.1
Vittorio Giovara
2017-06-28 22:10:57 UTC
Permalink
Signed-off-by: Vittorio Giovara <***@gmail.com>
---
libavcodec/aac.h | 7 +++--
libavcodec/aac_ac3_parser.c | 9 ++++--
libavcodec/aaccoder.c | 2 +-
libavcodec/aacdec.c | 76 ++++++++++++++++++++++++++++++++++++++-------
libavcodec/aacdectab.h | 16 ++++++++++
libavcodec/aacenc.c | 2 +-
libavcodec/aacpsy.c | 10 +++---
7 files changed, 99 insertions(+), 23 deletions(-)

diff --git a/libavcodec/aac.h b/libavcodec/aac.h
index fed6bf4214..b72af09ca0 100644
--- a/libavcodec/aac.h
+++ b/libavcodec/aac.h
@@ -30,6 +30,7 @@
#ifndef AVCODEC_AAC_H
#define AVCODEC_AAC_H

+#include "libavutil/channel_layout.h"
#include "libavutil/float_dsp.h"
#include "avcodec.h"
#include "imdct15.h"
@@ -116,8 +117,7 @@ typedef struct OutputConfiguration {
MPEG4AudioConfig m4ac;
uint8_t layout_map[MAX_ELEM_ID*4][3];
int layout_map_tags;
- int channels;
- uint64_t channel_layout;
+ AVChannelLayout ch_layout;
enum OCStatus status;
} OutputConfiguration;

@@ -260,6 +260,7 @@ typedef struct ChannelElement {
* main AAC context
*/
typedef struct AACContext {
+ const AVClass *class;
AVCodecContext *avctx;
AVFrame *frame;

@@ -306,6 +307,8 @@ typedef struct AACContext {
DECLARE_ALIGNED(32, float, temp)[128];

OutputConfiguration oc[2];
+
+ AVChannelLayout downmix_layout;
} AACContext;

#endif /* AVCODEC_AAC_H */
diff --git a/libavcodec/aac_ac3_parser.c b/libavcodec/aac_ac3_parser.c
index a754f4a957..17e88435f8 100644
--- a/libavcodec/aac_ac3_parser.c
+++ b/libavcodec/aac_ac3_parser.c
@@ -82,8 +82,13 @@ get_next:
seconds is still correct (as is the number of bits in the frame). */
if (avctx->codec_id != AV_CODEC_ID_AAC) {
avctx->sample_rate = s->sample_rate;
- avctx->channels = s->channels;
- avctx->channel_layout = s->channel_layout;
+
+ av_channel_layout_uninit(&avctx->ch_layout);
+ if (s->channel_layout)
+ av_channel_layout_from_mask(&avctx->ch_layout, s->channel_layout);
+ else
+ av_channel_layout_default(&avctx->ch_layout, s->channels);
+
s1->duration = s->samples;
avctx->audio_service_type = s->service_type;
}
diff --git a/libavcodec/aaccoder.c b/libavcodec/aaccoder.c
index a654844cd0..ec936d89ad 100644
--- a/libavcodec/aaccoder.c
+++ b/libavcodec/aaccoder.c
@@ -710,7 +710,7 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx,
const float lambda)
{
int start = 0, i, w, w2, g;
- int destbits = avctx->bit_rate * 1024.0 / avctx->sample_rate / avctx->channels * (lambda / 120.f);
+ int destbits = avctx->bit_rate * 1024.0 / avctx->sample_rate / avctx->ch_layout.nb_channels * (lambda / 120.f);
float dists[128] = { 0 }, uplims[128];
float maxvals[128];
int fflag, minscaler;
diff --git a/libavcodec/aacdec.c b/libavcodec/aacdec.c
index e436b4f2f7..ab184b8634 100644
--- a/libavcodec/aacdec.c
+++ b/libavcodec/aacdec.c
@@ -81,6 +81,7 @@
*/

#include "libavutil/float_dsp.h"
+#include "libavutil/opt.h"
#include "avcodec.h"
#include "internal.h"
#include "get_bits.h"
@@ -193,7 +194,7 @@ static int frame_configure_elements(AVCodecContext *avctx)
}

/* map output channel pointers to AVFrame data */
- for (ch = 0; ch < avctx->channels; ch++) {
+ for (ch = 0; ch < avctx->ch_layout.nb_channels; ch++) {
if (ac->output_element[ch])
ac->output_element[ch]->ret = (float *)ac->frame->extended_data[ch];
}
@@ -432,8 +433,7 @@ static void push_output_configuration(AACContext *ac) {
static void pop_output_configuration(AACContext *ac) {
if (ac->oc[1].status != OC_LOCKED && ac->oc[0].status != OC_NONE) {
ac->oc[1] = ac->oc[0];
- ac->avctx->channels = ac->oc[1].channels;
- ac->avctx->channel_layout = ac->oc[1].channel_layout;
+ av_channel_layout_copy(&ac->avctx->ch_layout, &ac->oc[1].ch_layout);
}
}

@@ -464,7 +464,15 @@ static int output_configure(AACContext *ac,
}
// Try to sniff a reasonable channel order, otherwise output the
// channels in the order the PCE declared them.
- if (avctx->request_channel_layout != AV_CH_LAYOUT_NATIVE)
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+ if (avctx->request_channel_layout) {
+ av_channel_layout_uninit(&ac->downmix_layout);
+ av_channel_layout_from_mask(&ac->downmix_layout, avctx->request_channel_layout);
+ }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+ if (ac->downmix_layout.order == AV_CHANNEL_ORDER_NATIVE)
layout = sniff_channel_order(layout_map, tags);
for (i = 0; i < tags; i++) {
int type = layout_map[i][0];
@@ -486,8 +494,18 @@ static int output_configure(AACContext *ac,
}
}

- avctx->channel_layout = ac->oc[1].channel_layout = layout;
- avctx->channels = ac->oc[1].channels = channels;
+ av_channel_layout_uninit(&ac->oc[1].ch_layout);
+ av_channel_layout_from_mask(&ac->oc[1].ch_layout, layout);
+ ret = av_channel_layout_copy(&avctx->ch_layout, &ac->oc[1].ch_layout);
+ if (ret < 0)
+ return ret;
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+ avctx->channels = avctx->ch_layout.nb_channels;
+ avctx->channel_layout = layout;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+
ac->oc[1].status = oc_type;

if (get_new_frame) {
@@ -1073,12 +1091,12 @@ static av_cold int aac_decode_init(AVCodecContext *avctx)

sr = sample_rate_idx(avctx->sample_rate);
ac->oc[1].m4ac.sampling_index = sr;
- ac->oc[1].m4ac.channels = avctx->channels;
+ ac->oc[1].m4ac.channels = avctx->ch_layout.nb_channels;
ac->oc[1].m4ac.sbr = -1;
ac->oc[1].m4ac.ps = -1;

for (i = 0; i < FF_ARRAY_ELEMS(ff_mpeg4audio_channels); i++)
- if (ff_mpeg4audio_channels[i] == avctx->channels)
+ if (ff_mpeg4audio_channels[i] == avctx->ch_layout.nb_channels)
break;
if (i == FF_ARRAY_ELEMS(ff_mpeg4audio_channels)) {
i = 0;
@@ -2226,7 +2244,8 @@ static int decode_extension_payload(AACContext *ac, GetBitContext *gb, int cnt,
av_log(ac->avctx, AV_LOG_ERROR, "Implicit SBR was found with a first occurrence after the first frame.\n");
skip_bits_long(gb, 8 * cnt - 4);
return res;
- } else if (ac->oc[1].m4ac.ps == -1 && ac->oc[1].status < OC_LOCKED && ac->avctx->channels == 1) {
+ } else if (ac->oc[1].m4ac.ps == -1 && ac->oc[1].status < OC_LOCKED &&
+ ac->avctx->ch_layout.nb_channels == 1) {
ac->oc[1].m4ac.sbr = 1;
ac->oc[1].m4ac.ps = 1;
ac->avctx->profile = FF_PROFILE_AAC_HE_V2;
@@ -2832,7 +2851,7 @@ static int aac_decode_frame_int(AVCodecContext *avctx, void *data,
}
}

- if (avctx->channels)
+ if (avctx->ch_layout.nb_channels)
if ((err = frame_configure_elements(avctx)) < 0)
goto fail;

@@ -2845,7 +2864,7 @@ static int aac_decode_frame_int(AVCodecContext *avctx, void *data,
while ((elem_type = get_bits(gb, 3)) != TYPE_END) {
elem_id = get_bits(gb, 4);

- if (!avctx->channels && elem_type != TYPE_PCE) {
+ if (!avctx->ch_layout.nb_channels && elem_type != TYPE_PCE) {
err = AVERROR_INVALIDDATA;
goto fail;
}
@@ -2936,7 +2955,7 @@ static int aac_decode_frame_int(AVCodecContext *avctx, void *data,
}
}

- if (!avctx->channels) {
+ if (!avctx->ch_layout.nb_channels) {
*got_frame_ptr = 0;
return 0;
}
@@ -3318,6 +3337,20 @@ static av_cold int latm_decode_init(AVCodecContext *avctx)
return ret;
}

+#define OFFSET(x) offsetof(AACContext, x)
+#define A AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM
+static const AVOption options[] = {
+ { "downmix", "Request a specific channel layout from the decoder",
+ OFFSET(downmix_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.str = NULL}, .flags = A },
+ { NULL },
+};
+
+static const AVClass aacdec_class = {
+ .class_name = "AAC decoder",
+ .item_name = av_default_item_name,
+ .option = options,
+ .version = LIBAVUTIL_VERSION_INT,
+};

AVCodec ff_aac_decoder = {
.name = "aac",
@@ -3325,6 +3358,7 @@ AVCodec ff_aac_decoder = {
.type = AVMEDIA_TYPE_AUDIO,
.id = AV_CODEC_ID_AAC,
.priv_data_size = sizeof(AACContext),
+ .priv_class = &aacdec_class,
.init = aac_decode_init,
.close = aac_decode_close,
.decode = aac_decode_frame,
@@ -3333,7 +3367,19 @@ AVCodec ff_aac_decoder = {
},
.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1,
.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
.channel_layouts = aac_channel_layout,
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+ .ch_layouts = aac_ch_layouts,
+};
+
+static const AVClass aaclatmdec_class = {
+ .class_name = "AAC-LATM decoder",
+ .item_name = av_default_item_name,
+ .option = options,
+ .version = LIBAVUTIL_VERSION_INT,
};

/*
@@ -3347,6 +3393,7 @@ AVCodec ff_aac_latm_decoder = {
.type = AVMEDIA_TYPE_AUDIO,
.id = AV_CODEC_ID_AAC_LATM,
.priv_data_size = sizeof(struct LATMContext),
+ .priv_class = &aaclatmdec_class,
.init = latm_decode_init,
.close = aac_decode_close,
.decode = latm_decode_frame,
@@ -3355,5 +3402,10 @@ AVCodec ff_aac_latm_decoder = {
},
.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1,
.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
.channel_layouts = aac_channel_layout,
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+ .ch_layouts = aac_ch_layouts,
};
diff --git a/libavcodec/aacdectab.h b/libavcodec/aacdectab.h
index b7c5f7e719..35773f36d4 100644
--- a/libavcodec/aacdectab.h
+++ b/libavcodec/aacdectab.h
@@ -114,4 +114,20 @@ static const uint64_t aac_channel_layout[16] = {
/* AV_CH_LAYOUT_7POINT1_TOP, */
};

+static const AVChannelLayout aac_ch_layouts[16] = {
+ AV_CHANNEL_LAYOUT_MONO,
+ AV_CHANNEL_LAYOUT_STEREO,
+ AV_CHANNEL_LAYOUT_SURROUND,
+ AV_CHANNEL_LAYOUT_4POINT0,
+ AV_CHANNEL_LAYOUT_5POINT0_BACK,
+ AV_CHANNEL_LAYOUT_5POINT1_BACK,
+ AV_CHANNEL_LAYOUT_7POINT1_WIDE_BACK,
+ { 0 },
+ { 0 },
+ { 0 },
+ AV_CHANNEL_LAYOUT_6POINT1,
+ AV_CHANNEL_LAYOUT_7POINT1,
+ { 0 },
+};
+
#endif /* AVCODEC_AACDECTAB_H */
diff --git a/libavcodec/aacenc.c b/libavcodec/aacenc.c
index b7f60fb872..ad14007011 100644
--- a/libavcodec/aacenc.c
+++ b/libavcodec/aacenc.c
@@ -739,7 +739,7 @@ static av_cold int aac_encode_init(AVCodecContext *avctx)
if (avctx->sample_rate == avpriv_mpeg4audio_sample_rates[i])
break;

- s->channels = avctx->channels;
+ s->channels = avctx->ch_layout.nb_channels;

ERROR_IF(i == 16,
"Unsupported sample rate %d\n", avctx->sample_rate);
diff --git a/libavcodec/aacpsy.c b/libavcodec/aacpsy.c
index 272be9f137..886728cf30 100644
--- a/libavcodec/aacpsy.c
+++ b/libavcodec/aacpsy.c
@@ -253,13 +253,13 @@ static av_cold void lame_window_init(AacPsyContext *ctx, AVCodecContext *avctx)
{
int i, j;

- for (i = 0; i < avctx->channels; i++) {
+ for (i = 0; i < avctx->ch_layout.nb_channels; i++) {
AacPsyChannel *pch = &ctx->ch[i];

if (avctx->flags & AV_CODEC_FLAG_QSCALE)
pch->attack_threshold = psy_vbr_map[avctx->global_quality / FF_QP2LAMBDA].st_lrm;
else
- pch->attack_threshold = lame_calc_attack_threshold(avctx->bit_rate / avctx->channels / 1000);
+ pch->attack_threshold = lame_calc_attack_threshold(avctx->bit_rate / avctx->ch_layout.nb_channels / 1000);

for (j = 0; j < AAC_NUM_BLOCKS_SHORT * PSY_LAME_NUM_SUBBLOCKS; j++)
pch->prev_energy_subshort[j] = 10.0f;
@@ -293,7 +293,7 @@ static av_cold int psy_3gpp_init(FFPsyContext *ctx) {
float bark;
int i, j, g, start;
float prev, minscale, minath, minsnr, pe_min;
- const int chan_bitrate = ctx->avctx->bit_rate / ctx->avctx->channels;
+ const int chan_bitrate = ctx->avctx->bit_rate / ctx->avctx->ch_layout.nb_channels;
const int bandwidth = ctx->avctx->cutoff ? ctx->avctx->cutoff : ctx->avctx->sample_rate / 2;
const float num_bark = calc_bark((float)bandwidth);

@@ -350,7 +350,7 @@ static av_cold int psy_3gpp_init(FFPsyContext *ctx) {
}
}

- pctx->ch = av_mallocz(sizeof(AacPsyChannel) * ctx->avctx->channels);
+ pctx->ch = av_mallocz(sizeof(AacPsyChannel) * ctx->avctx->ch_layout.nb_channels);
if (!pctx->ch) {
av_freep(&pctx);
return AVERROR(ENOMEM);
@@ -391,7 +391,7 @@ static av_unused FFPsyWindowInfo psy_3gpp_window(FFPsyContext *ctx,
int channel, int prev_type)
{
int i, j;
- int br = ctx->avctx->bit_rate / ctx->avctx->channels;
+ int br = ctx->avctx->bit_rate / ctx->avctx->ch_layout.nb_channels;
int attack_ratio = br <= 16000 ? 18 : 10;
AacPsyContext *pctx = (AacPsyContext*) ctx->model_priv_data;
AacPsyChannel *pch = &pctx->ch[channel];
--
2.13.1
Vittorio Giovara
2017-06-28 22:10:56 UTC
Permalink
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
wm4
2017-06-29 09:18:41 UTC
Permalink
On Wed, 28 Jun 2017 18:10:56 -0400
Post by Vittorio Giovara
Since the request_channel_layout is used only by a handful of codecs,
move the option to codec private contexts.
Not sure if that is justified...
Vittorio Giovara
2017-06-29 18:44:52 UTC
Permalink
Post by wm4
On Wed, 28 Jun 2017 18:10:56 -0400
Post by Vittorio Giovara
Since the request_channel_layout is used only by a handful of codecs,
move the option to codec private contexts.
Not sure if that is justified...
I believe it is always good to move options out of the global state,
and this seems to be a perfect opportunity: beside adding the new API,
we are modifying the concept that a channel layout is not represented
(simply) by a bitmask, but by a series of features, such as map,
channel order, and count. The request_channel_layout is the last
holdout of that concept, so I think it makes sense to change and allow
for future expansion, for example an in-codec downmix from ambisonic
to normal stereo.
--
Vittorio
wm4
2017-06-30 07:59:40 UTC
Permalink
On Thu, 29 Jun 2017 14:44:52 -0400
Post by Vittorio Giovara
Post by wm4
On Wed, 28 Jun 2017 18:10:56 -0400
Post by Vittorio Giovara
Since the request_channel_layout is used only by a handful of codecs,
move the option to codec private contexts.
Not sure if that is justified...
I believe it is always good to move options out of the global state,
and this seems to be a perfect opportunity: beside adding the new API,
we are modifying the concept that a channel layout is not represented
(simply) by a bitmask, but by a series of features, such as map,
channel order, and count. The request_channel_layout is the last
holdout of that concept, so I think it makes sense to change and allow
for future expansion, for example an in-codec downmix from ambisonic
to normal stereo.
+1 for less global state, -1 to more AVOption API
Vittorio Giovara
2017-06-28 22:10:58 UTC
Permalink
Signed-off-by: Vittorio Giovara <***@gmail.com>
---
libavcodec/ac3dec.c | 49 +++++++++++++++++++++-------
libavcodec/ac3dec.h | 2 ++
libavcodec/ac3enc.c | 83 ++++++++++++++++++++++++++++++++++++-----------
libavcodec/ac3enc.h | 4 ++-
libavcodec/ac3enc_fixed.c | 5 +++
libavcodec/ac3enc_float.c | 5 +++
libavcodec/eac3enc.c | 5 +++
tests/fate/ac3.mak | 12 +++----
8 files changed, 128 insertions(+), 37 deletions(-)

diff --git a/libavcodec/ac3dec.c b/libavcodec/ac3dec.c
index 4be0f1f411..3d3414f7d7 100644
--- a/libavcodec/ac3dec.c
+++ b/libavcodec/ac3dec.c
@@ -172,6 +172,8 @@ static av_cold void ac3_tables_init(void)
static av_cold int ac3_decode_init(AVCodecContext *avctx)
{
AC3DecodeContext *s = avctx->priv_data;
+ static AVChannelLayout mono = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
+ static AVChannelLayout stereo = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
int i;

s->avctx = avctx;
@@ -190,12 +192,23 @@ static av_cold int ac3_decode_init(AVCodecContext *avctx)
avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;

/* allow downmixing to stereo or mono */
- if (avctx->channels > 1 &&
- avctx->request_channel_layout == AV_CH_LAYOUT_MONO)
- avctx->channels = 1;
- else if (avctx->channels > 2 &&
- avctx->request_channel_layout == AV_CH_LAYOUT_STEREO)
- avctx->channels = 2;
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+ if (avctx->request_channel_layout) {
+ av_channel_layout_uninit(&s->downmix_layout);
+ av_channel_layout_from_mask(&s->downmix_layout, avctx->request_channel_layout);
+ }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+ if (avctx->ch_layout.nb_channels > 1 &&
+ !av_channel_layout_compare(&s->downmix_layout, &mono)) {
+ av_channel_layout_uninit(&avctx->ch_layout);
+ avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
+ } else if (avctx->ch_layout.nb_channels > 2 &&
+ !av_channel_layout_compare(&s->downmix_layout, &stereo)) {
+ av_channel_layout_uninit(&avctx->ch_layout);
+ avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
+ }
s->downmixed = 1;

for (i = 0; i < AC3_MAX_CHANNELS; i++) {
@@ -1364,6 +1377,7 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data,
const float *output[AC3_MAX_CHANNELS];
enum AVMatrixEncoding matrix_encoding;
AVDownmixInfo *downmix_info;
+ uint64_t mask;

/* copy input buffer to decoder context to avoid reading past the end
of the buffer, which can be caused by a damaged input stream. */
@@ -1440,16 +1454,19 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data,

/* channel config */
if (!err || (s->channels && s->out_channels != s->channels)) {
+ static AVChannelLayout mono = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
+ static AVChannelLayout stereo = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
+
s->out_channels = s->channels;
s->output_mode = s->channel_mode;
if (s->lfe_on)
s->output_mode |= AC3_OUTPUT_LFEON;
if (s->channels > 1 &&
- avctx->request_channel_layout == AV_CH_LAYOUT_MONO) {
+ !av_channel_layout_compare(&s->downmix_layout, &mono)) {
s->out_channels = 1;
s->output_mode = AC3_CHMODE_MONO;
} else if (s->channels > 2 &&
- avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) {
+ !av_channel_layout_compare(&s->downmix_layout, &stereo)) {
s->out_channels = 2;
s->output_mode = AC3_CHMODE_STEREO;
}
@@ -1466,10 +1483,19 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data,
av_log(avctx, AV_LOG_ERROR, "unable to determine channel mode\n");
return AVERROR_INVALIDDATA;
}
- avctx->channels = s->out_channels;
- avctx->channel_layout = avpriv_ac3_channel_layout_tab[s->output_mode & ~AC3_OUTPUT_LFEON];
+
+ mask = avpriv_ac3_channel_layout_tab[s->output_mode & ~AC3_OUTPUT_LFEON];
if (s->output_mode & AC3_OUTPUT_LFEON)
- avctx->channel_layout |= AV_CH_LOW_FREQUENCY;
+ mask |= AV_CH_LOW_FREQUENCY;
+
+ av_channel_layout_uninit(&avctx->ch_layout);
+ av_channel_layout_from_mask(&avctx->ch_layout, mask);
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+ avctx->channels = avctx->ch_layout.nb_channels;
+ avctx->channel_layout = avctx->ch_layout.u.mask;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif

/* set audio service type based on bitstream mode for AC-3 */
avctx->audio_service_type = s->bitstream_mode;
@@ -1588,6 +1614,7 @@ static av_cold int ac3_decode_end(AVCodecContext *avctx)
#define PAR (AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM)
static const AVOption options[] = {
{ "drc_scale", "percentage of dynamic range compression to apply", OFFSET(drc_scale), AV_OPT_TYPE_FLOAT, {.dbl = 1.0}, 0.0, 6.0, PAR },
+ { "downmix", "Request a specific channel layout from the decoder", OFFSET(downmix_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.str = NULL}, .flags = PAR },
{ NULL},
};

diff --git a/libavcodec/ac3dec.h b/libavcodec/ac3dec.h
index 4a7e281932..a5461c8a07 100644
--- a/libavcodec/ac3dec.h
+++ b/libavcodec/ac3dec.h
@@ -221,6 +221,8 @@ typedef struct AC3DecodeContext {
DECLARE_ALIGNED(32, float, output)[AC3_MAX_CHANNELS][AC3_BLOCK_SIZE]; ///< output after imdct transform and windowing
DECLARE_ALIGNED(32, uint8_t, input_buffer)[AC3_FRAME_BUFFER_SIZE + AV_INPUT_BUFFER_PADDING_SIZE]; ///< temp buffer to prevent overread
///@}
+
+ AVChannelLayout downmix_layout;
} AC3DecodeContext;

/**
diff --git a/libavcodec/ac3enc.c b/libavcodec/ac3enc.c
index 48bc2e79de..a81f95dc8a 100644
--- a/libavcodec/ac3enc.c
+++ b/libavcodec/ac3enc.c
@@ -78,6 +78,7 @@ static uint8_t exponent_group_tab[2][3][256];
/**
* List of supported channel layouts.
*/
+#if FF_API_OLD_CHANNEL_LAYOUT
const uint64_t ff_ac3_channel_layouts[19] = {
AV_CH_LAYOUT_MONO,
AV_CH_LAYOUT_STEREO,
@@ -99,7 +100,47 @@ const uint64_t ff_ac3_channel_layouts[19] = {
AV_CH_LAYOUT_5POINT1_BACK,
0
};
+#endif

+const AVChannelLayout ff_ac3_ch_layouts[19] = {
+ AV_CHANNEL_LAYOUT_MONO,
+ AV_CHANNEL_LAYOUT_STEREO,
+ AV_CHANNEL_LAYOUT_2_1,
+ AV_CHANNEL_LAYOUT_SURROUND,
+ AV_CHANNEL_LAYOUT_2_2,
+ AV_CHANNEL_LAYOUT_QUAD,
+ AV_CHANNEL_LAYOUT_4POINT0,
+ AV_CHANNEL_LAYOUT_5POINT0,
+ AV_CHANNEL_LAYOUT_5POINT0_BACK,
+ {
+ .nb_channels = 2,
+ .order = AV_CHANNEL_ORDER_NATIVE,
+ .u.mask = AV_CH_LAYOUT_MONO | AV_CH_LOW_FREQUENCY,
+ },
+ {
+ .nb_channels = 3,
+ .order = AV_CHANNEL_ORDER_NATIVE,
+ .u.mask = AV_CH_LAYOUT_STEREO | AV_CH_LOW_FREQUENCY,
+ },
+ {
+ .nb_channels = 4,
+ .order = AV_CHANNEL_ORDER_NATIVE,
+ .u.mask = AV_CH_LAYOUT_2_1 | AV_CH_LOW_FREQUENCY,
+ },
+ {
+ .nb_channels = 4,
+ .order = AV_CHANNEL_ORDER_NATIVE,
+ .u.mask = AV_CH_LAYOUT_SURROUND | AV_CH_LOW_FREQUENCY,
+ },
+ {
+ .nb_channels = 5,
+ .order = AV_CHANNEL_ORDER_NATIVE,
+ .u.mask = AV_CH_LAYOUT_4POINT0 | AV_CH_LOW_FREQUENCY,
+ },
+ AV_CHANNEL_LAYOUT_5POINT1,
+ AV_CHANNEL_LAYOUT_5POINT1_BACK,
+ { 0 },
+};

/**
* LUT to select the bandwidth code based on the bit rate, sample rate, and
@@ -1681,7 +1722,7 @@ static void dprint_options(AC3EncodeContext *s)
{
AVCodecContext *avctx = s->avctx;
AC3EncOptions *opt = &s->options;
- char strbuf[32];
+ char *chlstr;

switch (s->bitstream_id) {
case 6: av_strlcpy(strbuf, "AC-3 (alt syntax)", 32); break;
@@ -1693,8 +1734,10 @@ static void dprint_options(AC3EncodeContext *s)
}
ff_dlog(avctx, "bitstream_id: %s (%d)\n", strbuf, s->bitstream_id);
ff_dlog(avctx, "sample_fmt: %s\n", av_get_sample_fmt_name(avctx->sample_fmt));
- av_get_channel_layout_string(strbuf, 32, s->channels, avctx->channel_layout);
- ff_dlog(avctx, "channel_layout: %s\n", strbuf);
+ chlstr = av_channel_layout_describe(&avctx->ch_layout);
+ if (chlstr)
+ ff_dlog(avctx, "channel_layout: %s\n", chlstr);
+ av_free(chlstr);
ff_dlog(avctx, "sample_rate: %d\n", s->sample_rate);
ff_dlog(avctx, "bit_rate: %d\n", s->bit_rate);
ff_dlog(avctx, "blocks/frame: %d (code=%d)\n", s->num_blocks, s->num_blks_code);
@@ -1939,11 +1982,11 @@ int ff_ac3_validate_metadata(AC3EncodeContext *s)

/* validate audio service type / channels combination */
if ((avctx->audio_service_type == AV_AUDIO_SERVICE_TYPE_KARAOKE &&
- avctx->channels == 1) ||
+ avctx->ch_layout.nb_channels == 1) ||
((avctx->audio_service_type == AV_AUDIO_SERVICE_TYPE_COMMENTARY ||
avctx->audio_service_type == AV_AUDIO_SERVICE_TYPE_EMERGENCY ||
avctx->audio_service_type == AV_AUDIO_SERVICE_TYPE_VOICE_OVER)
- && avctx->channels > 1)) {
+ && avctx->ch_layout.nb_channels > 1)) {
av_log(avctx, AV_LOG_ERROR, "invalid audio service type for the "
"specified number of channels\n");
return AVERROR(EINVAL);
@@ -2063,27 +2106,29 @@ av_cold int ff_ac3_encode_close(AVCodecContext *avctx)
/*
* Set channel information during initialization.
*/
-static av_cold int set_channel_info(AC3EncodeContext *s, int channels,
- uint64_t *channel_layout)
+static av_cold int set_channel_info(AVCodecContext *avctx)
{
- int ch_layout;
+ AC3EncodeContext *s = avctx->priv_data;
+ int channels = avctx->ch_layout.nb_channels;
+ uint64_t mask = avctx->ch_layout.u.mask;

if (channels < 1 || channels > AC3_MAX_CHANNELS)
return AVERROR(EINVAL);
- if (*channel_layout > 0x7FF)
+ if (mask > 0x7FF)
return AVERROR(EINVAL);
- ch_layout = *channel_layout;
- if (!ch_layout)
- ch_layout = av_get_default_channel_layout(channels);

- s->lfe_on = !!(ch_layout & AV_CH_LOW_FREQUENCY);
+ if (!mask)
+ av_channel_layout_default(&avctx->ch_layout, channels);
+ mask = avctx->ch_layout.u.mask;
+
+ s->lfe_on = !!(mask & AV_CH_LOW_FREQUENCY);
s->channels = channels;
s->fbw_channels = channels - s->lfe_on;
s->lfe_channel = s->lfe_on ? s->fbw_channels + 1 : -1;
if (s->lfe_on)
- ch_layout -= AV_CH_LOW_FREQUENCY;
+ mask -= AV_CH_LOW_FREQUENCY;

- switch (ch_layout) {
+ switch (mask) {
case AV_CH_LAYOUT_MONO: s->channel_mode = AC3_CHMODE_MONO; break;
case AV_CH_LAYOUT_STEREO: s->channel_mode = AC3_CHMODE_STEREO; break;
case AV_CH_LAYOUT_SURROUND: s->channel_mode = AC3_CHMODE_3F; break;
@@ -2100,9 +2145,9 @@ static av_cold int set_channel_info(AC3EncodeContext *s, int channels,
s->has_surround = s->channel_mode & 0x04;

s->channel_map = ff_ac3_enc_channel_map[s->channel_mode][s->lfe_on];
- *channel_layout = ch_layout;
if (s->lfe_on)
- *channel_layout |= AV_CH_LOW_FREQUENCY;
+ mask |= AV_CH_LOW_FREQUENCY;
+ av_channel_layout_from_mask(&avctx->ch_layout, mask);

return 0;
}
@@ -2114,12 +2159,12 @@ static av_cold int validate_options(AC3EncodeContext *s)
int i, ret, max_sr;

/* validate channel layout */
- if (!avctx->channel_layout) {
+ if (!avctx->ch_layout.nb_channels) {
av_log(avctx, AV_LOG_WARNING, "No channel layout specified. The "
"encoder will guess the layout, but it "
"might be incorrect.\n");
}
- ret = set_channel_info(s, avctx->channels, &avctx->channel_layout);
+ ret = set_channel_info(avctx);
if (ret) {
av_log(avctx, AV_LOG_ERROR, "invalid channel layout\n");
return ret;
diff --git a/libavcodec/ac3enc.h b/libavcodec/ac3enc.h
index 76b6d7f6e5..c588b73fd7 100644
--- a/libavcodec/ac3enc.h
+++ b/libavcodec/ac3enc.h
@@ -266,8 +266,10 @@ typedef struct AC3EncodeContext {
void (*output_frame_header)(struct AC3EncodeContext *s);
} AC3EncodeContext;

-
+#if FF_API_OLD_CHANNEL_LAYOUT
extern const uint64_t ff_ac3_channel_layouts[19];
+#endif
+extern const AVChannelLayout ff_ac3_ch_layouts[19];

int ff_ac3_encode_init(AVCodecContext *avctx);
int ff_ac3_float_encode_init(AVCodecContext *avctx);
diff --git a/libavcodec/ac3enc_fixed.c b/libavcodec/ac3enc_fixed.c
index a4ab5dfde2..cbd735c69a 100644
--- a/libavcodec/ac3enc_fixed.c
+++ b/libavcodec/ac3enc_fixed.c
@@ -149,6 +149,11 @@ AVCodec ff_ac3_fixed_encoder = {
.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16P,
AV_SAMPLE_FMT_NONE },
.priv_class = &ac3enc_class,
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
.channel_layouts = ff_ac3_channel_layouts,
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+ .ch_layouts = ff_ac3_ch_layouts,
.defaults = ac3_defaults,
};
diff --git a/libavcodec/ac3enc_float.c b/libavcodec/ac3enc_float.c
index 95acea7770..8394d5049c 100644
--- a/libavcodec/ac3enc_float.c
+++ b/libavcodec/ac3enc_float.c
@@ -142,6 +142,11 @@ AVCodec ff_ac3_encoder = {
.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP,
AV_SAMPLE_FMT_NONE },
.priv_class = &ac3enc_class,
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
.channel_layouts = ff_ac3_channel_layouts,
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+ .ch_layouts = ff_ac3_ch_layouts,
.defaults = ac3_defaults,
};
diff --git a/libavcodec/eac3enc.c b/libavcodec/eac3enc.c
index 17757bebef..737e12a323 100644
--- a/libavcodec/eac3enc.c
+++ b/libavcodec/eac3enc.c
@@ -264,6 +264,11 @@ AVCodec ff_eac3_encoder = {
.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP,
AV_SAMPLE_FMT_NONE },
.priv_class = &eac3enc_class,
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
.channel_layouts = ff_ac3_channel_layouts,
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+ .ch_layouts = ff_ac3_ch_layouts,
.defaults = ac3_defaults,
};
diff --git a/tests/fate/ac3.mak b/tests/fate/ac3.mak
index fee4567288..1ec4b74bac 100644
--- a/tests/fate/ac3.mak
+++ b/tests/fate/ac3.mak
@@ -6,14 +6,14 @@ FATE_AC3 += fate-ac3-4.0
fate-ac3-4.0: CMD = pcm -i $(TARGET_SAMPLES)/ac3/millers_crossing_4.0.ac3
fate-ac3-4.0: REF = $(SAMPLES)/ac3/millers_crossing_4.0_v2.pcm

-#request_channel_layout 4 -> front channel
+#downmix 4.0 -> front channel
FATE_AC3 += fate-ac3-4.0-downmix-mono
-fate-ac3-4.0-downmix-mono: CMD = pcm -request_channel_layout 4 -i $(TARGET_SAMPLES)/ac3/millers_crossing_4.0.ac3
+fate-ac3-4.0-downmix-mono: CMD = pcm -downmix 0x4 -i $(TARGET_SAMPLES)/ac3/millers_crossing_4.0.ac3
fate-ac3-4.0-downmix-mono: REF = $(SAMPLES)/ac3/millers_crossing_4.0_mono_v2.pcm

-#request_channel_layout 3 -> left channel + right channel
+#downmix 3.0 -> left channel + right channel
FATE_AC3 += fate-ac3-4.0-downmix-stereo
-fate-ac3-4.0-downmix-stereo: CMD = pcm -request_channel_layout 3 -i $(TARGET_SAMPLES)/ac3/millers_crossing_4.0.ac3
+fate-ac3-4.0-downmix-stereo: CMD = pcm -downmix 0x3 -i $(TARGET_SAMPLES)/ac3/millers_crossing_4.0.ac3
fate-ac3-4.0-downmix-stereo: REF = $(SAMPLES)/ac3/millers_crossing_4.0_stereo_v2.pcm

FATE_AC3 += fate-ac3-5.1
@@ -21,11 +21,11 @@ fate-ac3-5.1: CMD = pcm -i $(TARGET_SAMPLES)/ac3/monsters_inc_5.1_448_small.ac3
fate-ac3-5.1: REF = $(SAMPLES)/ac3/monsters_inc_5.1_448_small_v2.pcm

FATE_AC3 += fate-ac3-5.1-downmix-mono
-fate-ac3-5.1-downmix-mono: CMD = pcm -request_channel_layout 4 -i $(TARGET_SAMPLES)/ac3/monsters_inc_5.1_448_small.ac3
+fate-ac3-5.1-downmix-mono: CMD = pcm -downmix 0x4 -i $(TARGET_SAMPLES)/ac3/monsters_inc_5.1_448_small.ac3
fate-ac3-5.1-downmix-mono: REF = $(SAMPLES)/ac3/monsters_inc_5.1_448_small_mono_v2.pcm

FATE_AC3 += fate-ac3-5.1-downmix-stereo
-fate-ac3-5.1-downmix-stereo: CMD = pcm -request_channel_layout 3 -i $(TARGET_SAMPLES)/ac3/monsters_inc_5.1_448_small.ac3
+fate-ac3-5.1-downmix-stereo: CMD = pcm -downmix 0x3 -i $(TARGET_SAMPLES)/ac3/monsters_inc_5.1_448_small.ac3
fate-ac3-5.1-downmix-stereo: REF = $(SAMPLES)/ac3/monsters_inc_5.1_448_small_stereo_v2.pcm

FATE_EAC3 += fate-eac3-1
--
2.13.1
Vittorio Giovara
2017-06-28 22:11:00 UTC
Permalink
This patch contains the following commits:

avplay: Support the new channel layout API

avconv: Support the new channel layout API

tools: Update to the new channel layout API

examples: Update to the new channel layout API
---
avtools/avconv.c | 30 +++++++-------------------
avtools/avconv.h | 8 +++----
avtools/avconv_filter.c | 44 ++++++++++++++++++++++++++++++--------
avtools/avconv_opt.c | 48 ++++++++++++++++++++++++------------------
avtools/avplay.c | 50 +++++++++++++++++++++++---------------------
avtools/cmdutils.c | 15 +++++++++++--
avtools/cmdutils.h | 8 -------
doc/examples/decode_audio.c | 2 +-
doc/examples/encode_audio.c | 36 ++++++++++++++++++-------------
doc/examples/filter_audio.c | 11 +++++-----
doc/examples/output.c | 30 ++++++++++++++++++--------
doc/examples/transcode_aac.c | 29 +++++++++++++++----------
tools/graph2dot.c | 7 +++----
tools/ismindex.c | 2 +-
tools/sidxindex.c | 2 +-
15 files changed, 185 insertions(+), 137 deletions(-)

diff --git a/avtools/avconv.c b/avtools/avconv.c
index a1427e0cb4..904ea82de8 100644
--- a/avtools/avconv.c
+++ b/avtools/avconv.c
@@ -163,7 +163,7 @@ static void avconv_cleanup(int ret)
for (j = 0; j < fg->nb_outputs; j++) {
av_freep(&fg->outputs[j]->name);
av_freep(&fg->outputs[j]->formats);
- av_freep(&fg->outputs[j]->channel_layouts);
+ av_freep(&fg->outputs[j]->ch_layouts);
av_freep(&fg->outputs[j]->sample_rates);
av_freep(&fg->outputs[j]);
}
@@ -1209,7 +1209,8 @@ static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame)
switch (ifilter->ist->st->codecpar->codec_type) {
case AVMEDIA_TYPE_AUDIO:
need_reinit |= ifilter->sample_rate != frame->sample_rate ||
- ifilter->channel_layout != frame->ch_layout.u.mask;
+ av_channel_layout_compare(&ifilter->ch_layout,
+ &frame->ch_layout);
break;
case AVMEDIA_TYPE_VIDEO:
need_reinit |= ifilter->width != frame->width ||
@@ -1322,24 +1323,6 @@ static int decode(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacke
return 0;
}

-int guess_input_channel_layout(InputStream *ist)
-{
- AVCodecContext *dec = ist->dec_ctx;
-
- if (!dec->channel_layout) {
- char layout_name[256];
-
- dec->channel_layout = av_get_default_channel_layout(dec->channels);
- if (!dec->channel_layout)
- return 0;
- av_get_channel_layout_string(layout_name, sizeof(layout_name),
- dec->channels, dec->channel_layout);
- av_log(NULL, AV_LOG_WARNING, "Guessed Channel Layout for Input Stream "
- "#%d.%d : %s\n", ist->file_index, ist->st->index, layout_name);
- }
- return 1;
-}
-
static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output,
int *decode_failed)
{
@@ -1982,6 +1965,7 @@ static int init_output_stream_encode(OutputStream *ost)
InputStream *ist = get_input_stream(ost);
AVCodecContext *enc_ctx = ost->enc_ctx;
AVCodecContext *dec_ctx = NULL;
+ int ret;

set_encoder_id(output_files[ost->file_index], ost);

@@ -1998,8 +1982,10 @@ static int init_output_stream_encode(OutputStream *ost)
case AVMEDIA_TYPE_AUDIO:
enc_ctx->sample_fmt = ost->filter->filter->inputs[0]->format;
enc_ctx->sample_rate = ost->filter->filter->inputs[0]->sample_rate;
- enc_ctx->channel_layout = ost->filter->filter->inputs[0]->ch_layout.u.mask;
- enc_ctx->channels = av_get_channel_layout_nb_channels(enc_ctx->channel_layout);
+ ret = av_channel_layout_copy(&enc_ctx->ch_layout,
+ &ost->filter->filter->inputs[0]->ch_layout);
+ if (ret < 0)
+ return ret;
enc_ctx->time_base = (AVRational){ 1, enc_ctx->sample_rate };
break;
case AVMEDIA_TYPE_VIDEO:
diff --git a/avtools/avconv.h b/avtools/avconv.h
index 4c699333a5..2d3a77ba65 100644
--- a/avtools/avconv.h
+++ b/avtools/avconv.h
@@ -220,7 +220,7 @@ typedef struct InputFilter {
AVRational sample_aspect_ratio;

int sample_rate;
- uint64_t channel_layout;
+ AVChannelLayout ch_layout;

AVBufferRef *hw_frames_ctx;

@@ -242,11 +242,11 @@ typedef struct OutputFilter {
AVRational frame_rate;
int format;
int sample_rate;
- uint64_t channel_layout;
+ AVChannelLayout ch_layout;

// those are only set if no format is specified and the encoder gives us multiple options
int *formats;
- uint64_t *channel_layouts;
+ AVChannelLayout *ch_layouts;
int *sample_rates;
} OutputFilter;

@@ -499,8 +499,6 @@ void opt_output_file(void *optctx, const char *filename);

void assert_avoptions(AVDictionary *m);

-int guess_input_channel_layout(InputStream *ist);
-
int configure_filtergraph(FilterGraph *fg);
int configure_output_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out);
int ist_in_filtergraph(FilterGraph *fg, InputStream *ist);
diff --git a/avtools/avconv_filter.c b/avtools/avconv_filter.c
index 7df64c647a..30e95a23a5 100644
--- a/avtools/avconv_filter.c
+++ b/avtools/avconv_filter.c
@@ -73,8 +73,30 @@ DEF_CHOOSE_FORMAT(sample_fmts, enum AVSampleFormat, format, formats,
DEF_CHOOSE_FORMAT(sample_rates, int, sample_rate, sample_rates, 0,
GET_SAMPLE_RATE_NAME)

-DEF_CHOOSE_FORMAT(channel_layouts, uint64_t, channel_layout, channel_layouts, 0,
- GET_CH_LAYOUT_NAME)
+static char *choose_channel_layouts(OutputFilter *ofilter)
+{
+ if (av_channel_layout_check(&ofilter->ch_layout)) {
+ return av_channel_layout_describe(&ofilter->ch_layout);
+ } else if (ofilter->ch_layouts) {
+ const AVChannelLayout *p;
+ AVIOContext *s = NULL;
+ uint8_t *ret;
+ int len;
+
+ if (avio_open_dyn_buf(&s) < 0)
+ exit(1);
+
+ for (p = ofilter->ch_layouts; av_channel_layout_check(p); p++) {
+ char *chlstr = av_channel_layout_describe(p);
+ avio_printf(s, "%s|", chlstr);
+ av_free(chlstr);
+ }
+ len = avio_close_dyn_buf(s, &ret);
+ ret[len - 1] = 0;
+ return ret;
+ } else
+ return NULL;
+}

int init_simple_filtergraph(InputStream *ist, OutputStream *ost)
{
@@ -391,7 +413,6 @@ static int configure_output_audio_filter(FilterGraph *fg, OutputFilter *ofilter,
{
OutputStream *ost = ofilter->ost;
OutputFile *of = output_files[ost->file_index];
- AVCodecContext *codec = ost->enc_ctx;
AVFilterContext *last_filter = out->filter_ctx;
int pad_idx = out->pad_idx;
char *sample_fmts, *sample_rates, *channel_layouts;
@@ -406,9 +427,6 @@ static int configure_output_audio_filter(FilterGraph *fg, OutputFilter *ofilter,
if (ret < 0)
return ret;

- if (codec->channels && !codec->channel_layout)
- codec->channel_layout = av_get_default_channel_layout(codec->channels);
-
sample_fmts = choose_sample_fmts(ofilter);
sample_rates = choose_sample_rates(ofilter);
channel_layouts = choose_channel_layouts(ofilter);
@@ -591,7 +609,9 @@ static int configure_input_audio_filter(FilterGraph *fg, InputFilter *ifilter,
par->time_base = (AVRational){ 1, ifilter->sample_rate };
par->sample_rate = ifilter->sample_rate;
par->format = ifilter->format;
- av_channel_layout_from_mask(&par->ch_layout, ifilter->channel_layout);
+ ret = av_channel_layout_copy(&par->ch_layout, &ifilter->ch_layout);
+ if (ret < 0)
+ return ret;

ret = av_buffersrc_parameters_set(ifilter->filter, par);
av_freep(&par);
@@ -758,7 +778,9 @@ int configure_filtergraph(FilterGraph *fg)
ofilter->height = link->h;

ofilter->sample_rate = link->sample_rate;
- ofilter->channel_layout = link->ch_layout.u.mask;
+ ret = av_channel_layout_copy(&ofilter->ch_layout, &link->ch_layout);
+ if (ret < 0)
+ return ret;
}

for (i = 0; i < fg->nb_inputs; i++) {
@@ -789,6 +811,8 @@ fail:

int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame)
{
+ int ret;
+
av_buffer_unref(&ifilter->hw_frames_ctx);

ifilter->format = frame->format;
@@ -798,7 +822,9 @@ int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame)
ifilter->sample_aspect_ratio = frame->sample_aspect_ratio;

ifilter->sample_rate = frame->sample_rate;
- ifilter->channel_layout = frame->ch_layout.u.mask;
+ ret = av_channel_layout_copy(&ifilter->ch_layout, &frame->ch_layout);
+ if (ret < 0)
+ return ret;

if (frame->hw_frames_ctx) {
ifilter->hw_frames_ctx = av_buffer_ref(frame->hw_frames_ctx);
diff --git a/avtools/avconv_opt.c b/avtools/avconv_opt.c
index 9076b74e38..27373fe1f8 100644
--- a/avtools/avconv_opt.c
+++ b/avtools/avconv_opt.c
@@ -662,8 +662,6 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic)

break;
case AVMEDIA_TYPE_AUDIO:
- guess_input_channel_layout(ist);
- break;
case AVMEDIA_TYPE_DATA:
case AVMEDIA_TYPE_SUBTITLE:
case AVMEDIA_TYPE_ATTACHMENT:
@@ -1414,7 +1412,17 @@ static OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext *oc)
if (!ost->stream_copy) {
char *sample_fmt = NULL;

- MATCH_PER_STREAM_OPT(audio_channels, i, audio_enc->channels, oc, st);
+ {
+ int i, ret;
+ for (i = 0; i < o->nb_audio_channels; i++) {
+ char *spec = o->audio_channels[i].specifier;
+ if ((ret = check_stream_specifier(oc, st, spec)) > 0)
+ av_channel_layout_default(&audio_enc->ch_layout,
+ o->audio_channels[i].u.i);
+ else if (ret < 0)
+ exit_program(1);
+ }
+ }

MATCH_PER_STREAM_OPT(sample_fmts, str, sample_fmt, oc, st);
if (sample_fmt &&
@@ -1930,17 +1938,18 @@ loop_end:
memcpy(f->sample_rates, ost->enc->supported_samplerates,
(count + 1) * sizeof(*f->sample_rates));
}
- if (ost->enc_ctx->channels) {
- f->channel_layout = av_get_default_channel_layout(ost->enc_ctx->channels);
- } else if (ost->enc->channel_layouts) {
+ if (av_channel_layout_check(&ost->enc_ctx->ch_layout)) {
+ av_channel_layout_copy(&f->ch_layout, &ost->enc_ctx->ch_layout);
+ } else if (ost->enc->ch_layouts) {
count = 0;
- while (ost->enc->channel_layouts[count])
+ while (av_channel_layout_check(&ost->enc->ch_layouts[count]))
count++;
- f->channel_layouts = av_mallocz_array(count + 1, sizeof(*f->channel_layouts));
- if (!f->channel_layouts)
+ f->ch_layouts = av_mallocz_array(count + 1, sizeof(*f->ch_layouts));
+ if (!f->ch_layouts)
exit_program(1);
- memcpy(f->channel_layouts, ost->enc->channel_layouts,
- (count + 1) * sizeof(*f->channel_layouts));
+ // TODO use av_channel_layout_copy?
+ memcpy(f->ch_layouts, ost->enc->ch_layouts,
+ (count + 1) * sizeof(*f->ch_layouts));
}
break;
}
@@ -2300,22 +2309,21 @@ static int opt_channel_layout(void *optctx, const char *opt, const char *arg)
char layout_str[32];
char *stream_str;
char *ac_str;
- int ret, channels, ac_str_size;
- uint64_t layout;
+ int ret, ac_str_size;
+ AVChannelLayout ch_layout = {0};

- layout = av_get_channel_layout(arg);
- if (!layout) {
+ ret = av_channel_layout_from_string(&ch_layout, arg);
+ if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Unknown channel layout: %s\n", arg);
- return AVERROR(EINVAL);
+ return ret;
}
- snprintf(layout_str, sizeof(layout_str), "%"PRIu64, layout);
- ret = opt_default(NULL, opt, layout_str);
+ snprintf(layout_str, sizeof(layout_str), "%s", arg);
+ ret = opt_default(NULL, "ch_layout", layout_str);
if (ret < 0)
return ret;

/* set 'ac' option based on channel layout */
- channels = av_get_channel_layout_nb_channels(layout);
- snprintf(layout_str, sizeof(layout_str), "%d", channels);
+ snprintf(layout_str, sizeof(layout_str), "%d", ch_layout.nb_channels);
stream_str = strchr(opt, ':');
ac_str_size = 3 + (stream_str ? strlen(stream_str) : 0);
ac_str = av_mallocz(ac_str_size);
diff --git a/avtools/avplay.c b/avtools/avplay.c
index 544c5dd4a1..183890d798 100644
--- a/avtools/avplay.c
+++ b/avtools/avplay.c
@@ -160,11 +160,10 @@ typedef struct PlayerState {
AVPacket audio_pkt_temp;
AVPacket audio_pkt;
enum AVSampleFormat sdl_sample_fmt;
- uint64_t sdl_channel_layout;
- int sdl_channels;
+ AVChannelLayout sdl_ch_layout;
int sdl_sample_rate;
enum AVSampleFormat resample_sample_fmt;
- uint64_t resample_channel_layout;
+ AVChannelLayout resample_ch_layout;
int resample_sample_rate;
AVAudioResampleContext *avr;
AVFrame *frame;
@@ -721,7 +720,7 @@ static void video_audio_display(PlayerState *s)
nb_freq = 1 << (rdft_bits - 1);

/* compute display index : center on currently output samples */
- channels = s->sdl_channels;
+ channels = s->sdl_ch_layout.nb_channels;
nb_display_channels = channels;
if (!s->paused) {
int data_used = s->show_audio == 1 ? s->width : (2 * nb_freq);
@@ -930,7 +929,7 @@ static double get_audio_clock(PlayerState *is)
hw_buf_size = audio_write_get_buf_size(is);
bytes_per_sec = 0;
if (is->audio_st) {
- bytes_per_sec = is->sdl_sample_rate * is->sdl_channels *
+ bytes_per_sec = is->sdl_sample_rate * is->sdl_ch_layout.nb_channels *
av_get_bytes_per_sample(is->sdl_sample_fmt);
}
if (bytes_per_sec)
@@ -1725,7 +1724,7 @@ static int synchronize_audio(PlayerState *is, short *samples,
int n, samples_size;
double ref_clock;

- n = is->sdl_channels * av_get_bytes_per_sample(is->sdl_sample_fmt);
+ n = is->sdl_ch_layout.nb_channels * av_get_bytes_per_sample(is->sdl_sample_fmt);
samples_size = samples_size1;

/* if not master, then we try to remove or add samples to correct the clock */
@@ -1832,16 +1831,18 @@ static int audio_decode_frame(PlayerState *is, double *pts_ptr)
flush_complete = 1;
continue;
}
- data_size = av_samples_get_buffer_size(NULL, dec->channels,
+ data_size = av_samples_get_buffer_size(NULL, dec->ch_layout.nb_channels,
is->frame->nb_samples,
is->frame->format, 1);

audio_resample = is->frame->format != is->sdl_sample_fmt ||
- is->frame->ch_layout.u.mask != is->sdl_channel_layout ||
+ av_channel_layout_compare(&is->frame->ch_layout,
+ &is->sdl_ch_layout) ||
is->frame->sample_rate != is->sdl_sample_rate;

resample_changed = is->frame->format != is->resample_sample_fmt ||
- is->frame->ch_layout.u.mask != is->resample_channel_layout ||
+ av_channel_layout_compare(&is->frame->ch_layout,
+ &is->resample_ch_layout) ||
is->frame->sample_rate != is->resample_sample_rate;

if ((!is->avr && audio_resample) || resample_changed) {
@@ -1856,10 +1857,10 @@ static int audio_decode_frame(PlayerState *is, double *pts_ptr)
}
}
if (audio_resample) {
- av_opt_set_int(is->avr, "in_channel_layout", is->frame->channel_layout, 0);
+ av_opt_set_channel_layout(is->avr, "in_ch_layout", &is->frame->ch_layout, 0);
av_opt_set_int(is->avr, "in_sample_fmt", is->frame->format, 0);
av_opt_set_int(is->avr, "in_sample_rate", is->frame->sample_rate, 0);
- av_opt_set_int(is->avr, "out_channel_layout", is->sdl_channel_layout, 0);
+ av_opt_set_channel_layout(is->avr, "out_ch_layout", &is->sdl_ch_layout, 0);
av_opt_set_int(is->avr, "out_sample_fmt", is->sdl_sample_fmt, 0);
av_opt_set_int(is->avr, "out_sample_rate", is->sdl_sample_rate, 0);

@@ -1869,7 +1870,9 @@ static int audio_decode_frame(PlayerState *is, double *pts_ptr)
}
}
is->resample_sample_fmt = is->frame->format;
- is->resample_channel_layout = is->frame->channel_layout;
+ ret = av_channel_layout_copy(&is->resample_ch_layout, &is->frame->ch_layout);
+ if (ret < 0)
+ break;
is->resample_sample_rate = is->frame->sample_rate;
}

@@ -1880,7 +1883,7 @@ static int audio_decode_frame(PlayerState *is, double *pts_ptr)
int nb_samples = is->frame->nb_samples;

out_size = av_samples_get_buffer_size(&out_linesize,
- is->sdl_channels,
+ is->sdl_ch_layout.nb_channels,
nb_samples,
is->sdl_sample_fmt, 0);
tmp_out = av_realloc(is->audio_buf1, out_size);
@@ -1899,7 +1902,7 @@ static int audio_decode_frame(PlayerState *is, double *pts_ptr)
break;
}
is->audio_buf = is->audio_buf1;
- data_size = out_samples * osize * is->sdl_channels;
+ data_size = out_samples * osize * is->sdl_ch_layout.nb_channels;
} else {
is->audio_buf = is->frame->data[0];
}
@@ -1907,7 +1910,7 @@ static int audio_decode_frame(PlayerState *is, double *pts_ptr)
/* if no pts, then compute it */
pts = is->audio_clock;
*pts_ptr = pts;
- n = is->sdl_channels * av_get_bytes_per_sample(is->sdl_sample_fmt);
+ n = is->sdl_ch_layout.nb_channels * av_get_bytes_per_sample(is->sdl_sample_fmt);
is->audio_clock += (double)data_size /
(double)(n * is->sdl_sample_rate);
#ifdef DEBUG
@@ -2085,22 +2088,19 @@ static int stream_component_open(PlayerState *is, int stream_index)
if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) {
is->sdl_sample_rate = avctx->sample_rate;

- if (!avctx->channel_layout)
- avctx->channel_layout = av_get_default_channel_layout(avctx->channels);
- if (!avctx->channel_layout) {
+ if (!av_channel_layout_check(&avctx->ch_layout)) {
fprintf(stderr, "unable to guess channel layout\n");
ret = AVERROR_INVALIDDATA;
goto fail;
}
- if (avctx->channels == 1)
- is->sdl_channel_layout = AV_CH_LAYOUT_MONO;
+ if (avctx->ch_layout.nb_channels == 1)
+ is->sdl_ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
else
- is->sdl_channel_layout = AV_CH_LAYOUT_STEREO;
- is->sdl_channels = av_get_channel_layout_nb_channels(is->sdl_channel_layout);
+ is->sdl_ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;

wanted_spec.format = AUDIO_S16SYS;
wanted_spec.freq = is->sdl_sample_rate;
- wanted_spec.channels = is->sdl_channels;
+ wanted_spec.channels = is->sdl_ch_layout.nb_channels;
wanted_spec.silence = 0;
wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
wanted_spec.callback = sdl_audio_callback;
@@ -2113,7 +2113,9 @@ static int stream_component_open(PlayerState *is, int stream_index)
is->audio_hw_buf_size = spec.size;
is->sdl_sample_fmt = AV_SAMPLE_FMT_S16;
is->resample_sample_fmt = is->sdl_sample_fmt;
- is->resample_channel_layout = avctx->channel_layout;
+ ret = av_channel_layout_copy(&is->resample_ch_layout, &avctx->ch_layout);
+ if (ret < 0)
+ goto fail;
is->resample_sample_rate = avctx->sample_rate;
}

diff --git a/avtools/cmdutils.c b/avtools/cmdutils.c
index 9d6a2b9f2b..238045f6b7 100644
--- a/avtools/cmdutils.c
+++ b/avtools/cmdutils.c
@@ -1038,8 +1038,19 @@ static void print_codec(const AVCodec *c)
GET_SAMPLE_RATE_NAME);
PRINT_CODEC_SUPPORTED(c, sample_fmts, enum AVSampleFormat, "sample formats",
AV_SAMPLE_FMT_NONE, GET_SAMPLE_FMT_NAME);
- PRINT_CODEC_SUPPORTED(c, channel_layouts, uint64_t, "channel layouts",
- 0, GET_CH_LAYOUT_DESC);
+
+ if (c->ch_layouts) {
+ const AVChannelLayout *p = c->ch_layouts;
+
+ printf(" Supported channel layouts:");
+ while (!av_channel_layout_check(p)) {
+ char *chlstr = av_channel_layout_describe(p);
+ printf(" %s", chlstr);
+ av_free(chlstr);
+ p++;
+ }
+ printf("\n");
+ }

if (c->priv_class) {
show_help_children(c->priv_class,
diff --git a/avtools/cmdutils.h b/avtools/cmdutils.h
index cc78ac5911..2389435a79 100644
--- a/avtools/cmdutils.h
+++ b/avtools/cmdutils.h
@@ -555,12 +555,4 @@ const char *media_type_string(enum AVMediaType media_type);
char name[16];\
snprintf(name, sizeof(name), "%d", rate);

-#define GET_CH_LAYOUT_NAME(ch_layout)\
- char name[16];\
- snprintf(name, sizeof(name), "0x%"PRIx64, ch_layout);
-
-#define GET_CH_LAYOUT_DESC(ch_layout)\
- char name[128];\
- av_get_channel_layout_string(name, sizeof(name), 0, ch_layout);
-
#endif /* LIBAV_CMDUTILS_H */
diff --git a/doc/examples/decode_audio.c b/doc/examples/decode_audio.c
index d952b4923b..ec933ea11c 100644
--- a/doc/examples/decode_audio.c
+++ b/doc/examples/decode_audio.c
@@ -63,7 +63,7 @@ static void decode(AVCodecContext *dec_ctx, AVPacket *pkt, AVFrame *frame,

/* the stream parameters may change at any time, check that they are
* what we expect */
- if (av_get_channel_layout_nb_channels(frame->channel_layout) != 2 ||
+ if (frame->ch_layout.nb_channels != 2 ||
frame->format != AV_SAMPLE_FMT_S16P) {
fprintf(stderr, "Unsupported frame parameters\n");
exit(1);
diff --git a/doc/examples/encode_audio.c b/doc/examples/encode_audio.c
index a32fcc9004..b941fb5352 100644
--- a/doc/examples/encode_audio.c
+++ b/doc/examples/encode_audio.c
@@ -67,26 +67,27 @@ static int select_sample_rate(const AVCodec *codec)
}

/* select layout with the highest channel count */
-static int select_channel_layout(const AVCodec *codec)
+static int select_channel_layout(AVCodecContext *ctx, const AVCodec *codec)
{
- const uint64_t *p;
- uint64_t best_ch_layout = 0;
- int best_nb_channels = 0;
+ const AVChannelLayout *p;
+ int ret, best_nb_channels = 0;

- if (!codec->channel_layouts)
+ if (!codec->ch_layouts)
return AV_CH_LAYOUT_STEREO;

- p = codec->channel_layouts;
- while (*p) {
- int nb_channels = av_get_channel_layout_nb_channels(*p);
+ p = codec->ch_layouts;
+ while (av_channel_layout_check(p)) {
+ int nb_channels = (*p).nb_channels;

if (nb_channels > best_nb_channels) {
- best_ch_layout = *p;
best_nb_channels = nb_channels;
+ ret = av_channel_layout_copy(&ctx->ch_layout, p);
+ if (ret < 0)
+ return ret;
}
p++;
}
- return best_ch_layout;
+ return 0;
}

static void encode(AVCodecContext *ctx, AVFrame *frame, AVPacket *pkt,
@@ -160,8 +161,11 @@ int main(int argc, char **argv)

/* select other audio parameters supported by the encoder */
c->sample_rate = select_sample_rate(codec);
- c->channel_layout = select_channel_layout(codec);
- c->channels = av_get_channel_layout_nb_channels(c->channel_layout);
+ ret = select_channel_layout(c, codec);
+ if (ret < 0) {
+ fprintf(stderr, "failed to select best channel layout\n");
+ exit(1);
+ }

/* open it */
if (avcodec_open2(c, codec, NULL) < 0) {
@@ -191,7 +195,11 @@ int main(int argc, char **argv)

frame->nb_samples = c->frame_size;
frame->format = c->sample_fmt;
- frame->channel_layout = c->channel_layout;
+ ret = av_channel_layout_copy(&frame->ch_layout, &c->ch_layout);
+ if (ret < 0) {
+ fprintf(stderr, "could not copy channel layout in audio frame\n");
+ exit(1);
+ }

/* allocate the data buffers */
ret = av_frame_get_buffer(frame, 0);
@@ -214,7 +222,7 @@ int main(int argc, char **argv)
for (j = 0; j < c->frame_size; j++) {
samples[2*j] = (int)(sin(t) * 10000);

- for (k = 1; k < c->channels; k++)
+ for (k = 1; k < c->ch_layout.nb_channels; k++)
samples[2*j + k] = samples[2*j];
t += tincr;
}
diff --git a/doc/examples/filter_audio.c b/doc/examples/filter_audio.c
index 458004355f..cfd6470984 100644
--- a/doc/examples/filter_audio.c
+++ b/doc/examples/filter_audio.c
@@ -55,7 +55,7 @@

#define INPUT_SAMPLERATE 48000
#define INPUT_FORMAT AV_SAMPLE_FMT_FLTP
-#define INPUT_CHANNEL_LAYOUT AV_CH_LAYOUT_5POINT0
+#define INPUT_CHANNEL_LAYOUT (AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT0

#define VOLUME_VAL 0.90

@@ -74,7 +74,7 @@ static int init_filter_graph(AVFilterGraph **graph, AVFilterContext **src,

AVDictionary *options_dict = NULL;
uint8_t options_str[1024];
- uint8_t ch_layout[64];
+ AVChannelLayout ch_layout = INPUT_CHANNEL_LAYOUT;

int err;

@@ -100,8 +100,7 @@ static int init_filter_graph(AVFilterGraph **graph, AVFilterContext **src,
}

/* Set the filter options through the AVOptions API. */
- av_get_channel_layout_string(ch_layout, sizeof(ch_layout), 0, INPUT_CHANNEL_LAYOUT);
- av_opt_set (abuffer_ctx, "channel_layout", ch_layout, AV_OPT_SEARCH_CHILDREN);
+ av_opt_set_channel_layout(abuffer_ctx, "ch_layout", &ch_layout, AV_OPT_SEARCH_CHILDREN);
av_opt_set (abuffer_ctx, "sample_fmt", av_get_sample_fmt_name(INPUT_FORMAT), AV_OPT_SEARCH_CHILDREN);
av_opt_set_q (abuffer_ctx, "time_base", (AVRational){ 1, INPUT_SAMPLERATE }, AV_OPT_SEARCH_CHILDREN);
av_opt_set_int(abuffer_ctx, "sample_rate", INPUT_SAMPLERATE, AV_OPT_SEARCH_CHILDREN);
@@ -215,7 +214,7 @@ static int init_filter_graph(AVFilterGraph **graph, AVFilterContext **src,
static int process_output(struct AVMD5 *md5, AVFrame *frame)
{
int planar = av_sample_fmt_is_planar(frame->format);
- int channels = av_get_channel_layout_nb_channels(frame->channel_layout);
+ int channels = frame->ch_layout.nb_channels;
int planes = planar ? channels : 1;
int bps = av_get_bytes_per_sample(frame->format);
int plane_size = bps * frame->nb_samples * (planar ? 1 : channels);
@@ -248,7 +247,7 @@ static int get_input(AVFrame *frame, int frame_num)
/* Set up the frame properties and allocate the buffer for the data. */
frame->sample_rate = INPUT_SAMPLERATE;
frame->format = INPUT_FORMAT;
- frame->channel_layout = INPUT_CHANNEL_LAYOUT;
+ frame->ch_layout = INPUT_CHANNEL_LAYOUT;
frame->nb_samples = FRAME_SIZE;
frame->pts = frame_num * FRAME_SIZE;

diff --git a/doc/examples/output.c b/doc/examples/output.c
index 59e7b95d17..85ac37170b 100644
--- a/doc/examples/output.c
+++ b/doc/examples/output.c
@@ -77,6 +77,8 @@ static void add_audio_stream(OutputStream *ost, AVFormatContext *oc,
{
AVCodecContext *c;
AVCodec *codec;
+ AVChannelLayout ch_layout;
+ static AVChannelLayout stereo = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
int ret;

/* find the audio encoder */
@@ -99,12 +101,17 @@ static void add_audio_stream(OutputStream *ost, AVFormatContext *oc,
}
ost->enc = c;

+ ch_layout = codec->ch_layouts ? codec->ch_layouts[0] : stereo;
+
/* put sample parameters */
c->sample_fmt = codec->sample_fmts ? codec->sample_fmts[0] : AV_SAMPLE_FMT_S16;
c->sample_rate = codec->supported_samplerates ? codec->supported_samplerates[0] : 44100;
- c->channel_layout = codec->channel_layouts ? codec->channel_layouts[0] : AV_CH_LAYOUT_STEREO;
- c->channels = av_get_channel_layout_nb_channels(c->channel_layout);
c->bit_rate = 64000;
+ ret = av_channel_layout_copy(&c->ch_layout, &ch_layout);
+ if (ret < 0) {
+ fprintf(stderr, "Could not copy channel layout\n");
+ exit(1);
+ }

ost->st->time_base = (AVRational){ 1, c->sample_rate };

@@ -125,10 +132,10 @@ static void add_audio_stream(OutputStream *ost, AVFormatContext *oc,

av_opt_set_int(ost->avr, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
av_opt_set_int(ost->avr, "in_sample_rate", 44100, 0);
- av_opt_set_int(ost->avr, "in_channel_layout", AV_CH_LAYOUT_STEREO, 0);
+ av_opt_set_channel_layout(ost->avr, "in_ch_layout", &stereo, 0);
av_opt_set_int(ost->avr, "out_sample_fmt", c->sample_fmt, 0);
av_opt_set_int(ost->avr, "out_sample_rate", c->sample_rate, 0);
- av_opt_set_int(ost->avr, "out_channel_layout", c->channel_layout, 0);
+ av_opt_set_channel_layout(ost->avr, "out_ch_layout", &c->ch_layout, 0);

ret = avresample_open(ost->avr);
if (ret < 0) {
@@ -138,7 +145,7 @@ static void add_audio_stream(OutputStream *ost, AVFormatContext *oc,
}

static AVFrame *alloc_audio_frame(enum AVSampleFormat sample_fmt,
- uint64_t channel_layout,
+ AVChannelLayout *ch_layout,
int sample_rate, int nb_samples)
{
AVFrame *frame = av_frame_alloc();
@@ -150,9 +157,13 @@ static AVFrame *alloc_audio_frame(enum AVSampleFormat sample_fmt,
}

frame->format = sample_fmt;
- frame->channel_layout = channel_layout;
frame->sample_rate = sample_rate;
frame->nb_samples = nb_samples;
+ ret = av_channel_layout_copy(&frame->ch_layout, ch_layout);
+ if (ret < 0) {
+ fprintf(stderr, "Error copying a channel layout in an audio frame\n");
+ exit(1);
+ }

if (nb_samples) {
ret = av_frame_get_buffer(frame, 0);
@@ -169,6 +180,7 @@ static void open_audio(AVFormatContext *oc, OutputStream *ost)
{
AVCodecContext *c;
int nb_samples, ret;
+ static AVChannelLayout stereo = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;

c = ost->enc;

@@ -189,9 +201,9 @@ static void open_audio(AVFormatContext *oc, OutputStream *ost)
else
nb_samples = c->frame_size;

- ost->frame = alloc_audio_frame(c->sample_fmt, c->channel_layout,
+ ost->frame = alloc_audio_frame(c->sample_fmt, &c->ch_layout,
c->sample_rate, nb_samples);
- ost->tmp_frame = alloc_audio_frame(AV_SAMPLE_FMT_S16, AV_CH_LAYOUT_STEREO,
+ ost->tmp_frame = alloc_audio_frame(AV_SAMPLE_FMT_S16, &stereo,
44100, nb_samples);

/* copy the stream parameters to the muxer */
@@ -218,7 +230,7 @@ static AVFrame *get_audio_frame(OutputStream *ost)

for (j = 0; j < frame->nb_samples; j++) {
v = (int)(sin(ost->t) * 10000);
- for (i = 0; i < ost->enc->channels; i++)
+ for (i = 0; i < ost->enc->ch_layout.nb_channels; i++)
*q++ = v;
ost->t += ost->tincr;
ost->tincr += ost->tincr2;
diff --git a/doc/examples/transcode_aac.c b/doc/examples/transcode_aac.c
index 44d5af6b04..5ee4056c8e 100644
--- a/doc/examples/transcode_aac.c
+++ b/doc/examples/transcode_aac.c
@@ -207,8 +207,7 @@ static int open_output_file(const char *filename,

/* Set the basic encoder parameters.
* The input file's sample rate is used to avoid a sample rate conversion. */
- avctx->channels = OUTPUT_CHANNELS;
- avctx->channel_layout = av_get_default_channel_layout(OUTPUT_CHANNELS);
+ av_channel_layout_default(&avctx->ch_layout, OUTPUT_CHANNELS);
avctx->sample_rate = input_codec_context->sample_rate;
avctx->sample_fmt = output_codec->sample_fmts[0];
avctx->bit_rate = OUTPUT_BIT_RATE;
@@ -293,7 +292,8 @@ static int init_resampler(AVCodecContext *input_codec_context,
/* Only initialize the resampler if it is necessary, i.e.,
* if and only if the sample formats differ. */
if (input_codec_context->sample_fmt != output_codec_context->sample_fmt ||
- input_codec_context->channels != output_codec_context->channels) {
+ av_channel_layout_compare(&input_codec_context->ch_layout,
+ &output_codec_context->ch_layout)) {
int error;

/* Create a resampler context for the conversion. */
@@ -307,10 +307,10 @@ static int init_resampler(AVCodecContext *input_codec_context,
* are assumed for simplicity (they are sometimes not detected
* properly by the demuxer and/or decoder).
*/
- av_opt_set_int(*resample_context, "in_channel_layout",
- av_get_default_channel_layout(input_codec_context->channels), 0);
- av_opt_set_int(*resample_context, "out_channel_layout",
- av_get_default_channel_layout(output_codec_context->channels), 0);
+ av_opt_set_channel_layout(*resample_context, "in_ch_layout",
+ &input_codec_context->ch_layout, 0);
+ av_opt_set_channel_layout(*resample_context, "out_ch_layout",
+ &output_codec_context->ch_layout, 0);
av_opt_set_int(*resample_context, "in_sample_rate",
input_codec_context->sample_rate, 0);
av_opt_set_int(*resample_context, "out_sample_rate",
@@ -340,7 +340,7 @@ static int init_fifo(AVAudioFifo **fifo, AVCodecContext *output_codec_context)
{
/* Create the FIFO buffer based on the specified output sample format. */
if (!(*fifo = av_audio_fifo_alloc(output_codec_context->sample_fmt,
- output_codec_context->channels, 1))) {
+ output_codec_context->ch_layout.nb_channels, 1))) {
fprintf(stderr, "Could not allocate FIFO\n");
return AVERROR(ENOMEM);
}
@@ -440,7 +440,7 @@ static int init_converted_samples(uint8_t ***converted_input_samples,
* Each pointer will later point to the audio samples of the corresponding
* channels (although it may be NULL for interleaved formats).
*/
- if (!(*converted_input_samples = calloc(output_codec_context->channels,
+ if (!(*converted_input_samples = calloc(output_codec_context->ch_layout.nb_channels,
sizeof(**converted_input_samples)))) {
fprintf(stderr, "Could not allocate converted input sample pointers\n");
return AVERROR(ENOMEM);
@@ -449,7 +449,7 @@ static int init_converted_samples(uint8_t ***converted_input_samples,
/* Allocate memory for the samples of all channels in one consecutive
* block for convenience. */
if ((error = av_samples_alloc(*converted_input_samples, NULL,
- output_codec_context->channels,
+ output_codec_context->ch_layout.nb_channels,
frame_size,
output_codec_context->sample_fmt, 0)) < 0) {
fprintf(stderr,
@@ -630,9 +630,16 @@ static int init_output_frame(AVFrame **frame,
* Default channel layouts based on the number of channels
* are assumed for simplicity. */
(*frame)->nb_samples = frame_size;
- (*frame)->channel_layout = output_codec_context->channel_layout;
(*frame)->format = output_codec_context->sample_fmt;
(*frame)->sample_rate = output_codec_context->sample_rate;
+ error = av_channel_layout_copy(&(*frame)->ch_layout,
+ &output_codec_context->ch_layout);
+ if (error < 0) {
+ fprintf(stderr, "Could not copy channel layout (error '%s')\n",
+ get_error_text(error));
+ av_frame_free(frame);
+ return error;
+ }

/* Allocate the samples of the created frame. This call will make
* sure that the audio frame can hold as many samples as specified. */
diff --git a/tools/graph2dot.c b/tools/graph2dot.c
index fbf8902146..9a48208a6c 100644
--- a/tools/graph2dot.c
+++ b/tools/graph2dot.c
@@ -86,13 +86,12 @@ static void print_digraph(FILE *outfile, AVFilterGraph *graph)
desc->name, link->w, link->h, link->time_base.num,
link->time_base.den);
} else if (link->type == AVMEDIA_TYPE_AUDIO) {
- char buf[255];
- av_get_channel_layout_string(buf, sizeof(buf), -1,
- link->channel_layout);
+ char *chlstr = av_channel_layout_describe(&link->ch_layout);
fprintf(outfile,
" [ label= \"fmt:%s sr:%d cl:%s\" ]",
av_get_sample_fmt_name(link->format),
- link->sample_rate, buf);
+ link->sample_rate, chlstr);
+ av_free(chlstr);
}
fprintf(outfile, ";\n");
}
diff --git a/tools/ismindex.c b/tools/ismindex.c
index 3d7e082b6d..5127e3a3cd 100644
--- a/tools/ismindex.c
+++ b/tools/ismindex.c
@@ -571,7 +571,7 @@ static int handle_file(struct Tracks *tracks, const char *file, int split,
if (tracks->audio_track < 0)
tracks->audio_track = tracks->nb_tracks;
tracks->nb_audio_tracks++;
- track->channels = st->codecpar->channels;
+ track->channels = st->codecpar->ch_layout.nb_channels;
track->sample_rate = st->codecpar->sample_rate;
if (st->codecpar->codec_id == AV_CODEC_ID_AAC) {
track->fourcc = "AACL";
diff --git a/tools/sidxindex.c b/tools/sidxindex.c
index e740a94b98..4724321e30 100644
--- a/tools/sidxindex.c
+++ b/tools/sidxindex.c
@@ -191,7 +191,7 @@ static int handle_file(struct Tracks *tracks, const char *file)
track->timescale, AV_ROUND_UP));

if (track->is_audio) {
- track->channels = st->codecpar->channels;
+ track->channels = st->codecpar->ch_layout.nb_channels;
track->sample_rate = st->codecpar->sample_rate;
}
if (track->is_video) {
--
2.13.1
Vittorio Giovara
2017-06-28 22:11:01 UTC
Permalink
Signed-off-by: Vittorio Giovara <***@gmail.com>
---
libavutil/channel_layout.c | 86 ++++++++++++++++++++++++++++++++++++++++++++--
libavutil/channel_layout.h | 33 ++++++++++++++++++
2 files changed, 116 insertions(+), 3 deletions(-)

diff --git a/libavutil/channel_layout.c b/libavutil/channel_layout.c
index 285997446d..d4791a9b61 100644
--- a/libavutil/channel_layout.c
+++ b/libavutil/channel_layout.c
@@ -260,7 +260,7 @@ void av_channel_layout_from_mask(AVChannelLayout *channel_layout,
int av_channel_layout_from_string(AVChannelLayout *channel_layout,
const char *str)
{
- int i, channels;
+ int i, channels, order;
const char *dup = str;
uint64_t mask = 0;

@@ -309,6 +309,44 @@ int av_channel_layout_from_string(AVChannelLayout *channel_layout,
return 0;
}

+ /* ambisonic */
+ if (sscanf(str, "ambisonic channels %d order %d", &channels, &order) == 2) {
+ AVChannelLayout extra = {0};
+ int harmonics = 0;
+
+ // handle nondiegetic channels or half-sphere harmonics
+ dup = str;
+ while (*dup) {
+ char *chname = av_get_token(&dup, "|");
+ if (!chname)
+ return AVERROR(ENOMEM);
+ if (*dup)
+ dup++; // skip separator
+
+ // no extra channel found
+ if (!strcmp(chname, str))
+ break;
+
+ if (av_channel_from_string(chname) == AV_CHAN_AMBISONIC)
+ harmonics++;
+ else {
+ char *nondiegetic = strstr(str, chname);
+ int ret = av_channel_layout_from_string(&extra, nondiegetic);
+ // no other channels allowed after nondiegetic
+ av_free(chname);
+ if (ret < 0)
+ return ret;
+ break;
+ }
+ av_free(chname);
+ }
+
+ channel_layout->nb_channels = channels + harmonics + extra.nb_channels;
+ channel_layout->u.mask = extra.u.mask;
+
+ return 0;
+ }
+
return AVERROR_INVALIDDATA;
}

@@ -361,6 +399,35 @@ char *av_channel_layout_describe(const AVChannelLayout *channel_layout)
}
return ret;
}
+ case AV_CHANNEL_ORDER_AMBISONIC: {
+ char buf[64];
+ int order = floor(sqrt(channel_layout->nb_channels)) - 1;
+ int channels = (order + 1) * (order + 1);
+
+ snprintf(buf, sizeof(buf), "ambisonic channels %d order %d",
+ channels, order);
+
+ // handle nondiegetic channels or half-sphere harmonics
+ for (i = channels; i < channel_layout->nb_channels; i++) {
+ enum AVChannel chan = av_channel_layout_get_channel(channel_layout, i);
+ if (chan == AV_CHAN_AMBISONIC) {
+ av_strlcat(buf, "|", sizeof(buf));
+ av_strlcat(buf, av_channel_name(chan), sizeof(buf));
+ }
+ }
+ if (channel_layout->u.mask) {
+ AVChannelLayout extra = {0};
+ char *chlstr;
+
+ av_channel_layout_from_mask(&extra, channel_layout->u.mask);
+ chlstr = av_channel_layout_describe(&extra);
+ av_strlcat(buf, "|", sizeof(buf));
+ av_strlcat(buf, chlstr, sizeof(buf));
+ av_free(chlstr);
+ }
+
+ return av_strdup(buf);
+ }
case AV_CHANNEL_ORDER_UNSPEC: {
char buf[64];
snprintf(buf, sizeof(buf), "%d channels", channel_layout->nb_channels);
@@ -381,6 +448,11 @@ int av_channel_layout_get_channel(const AVChannelLayout *channel_layout, int idx
switch (channel_layout->order) {
case AV_CHANNEL_ORDER_CUSTOM:
return channel_layout->u.map[idx];
+ case AV_CHANNEL_ORDER_AMBISONIC:
+ idx -= channel_layout->nb_channels - av_popcount64(channel_layout->u.mask);
+ if (idx < 0)
+ return AV_CHAN_AMBISONIC;
+ // fall-through
case AV_CHANNEL_ORDER_NATIVE:
for (i = 0; i < 64; i++) {
if ((1ULL << i) & channel_layout->u.mask && !idx--)
@@ -394,7 +466,7 @@ int av_channel_layout_get_channel(const AVChannelLayout *channel_layout, int idx
int av_channel_layout_channel_index(const AVChannelLayout *channel_layout,
enum AVChannel channel)
{
- int i;
+ int i, off = 0;

switch (channel_layout->order) {
case AV_CHANNEL_ORDER_CUSTOM:
@@ -402,12 +474,17 @@ int av_channel_layout_channel_index(const AVChannelLayout *channel_layout,
if (channel_layout->u.map[i] == channel)
return i;
return AVERROR(EINVAL);
+ case AV_CHANNEL_ORDER_AMBISONIC:
+ if (channel == AV_CHAN_AMBISONIC)
+ return 0;
+ off = channel_layout->nb_channels - av_popcount64(channel_layout->u.mask);
+ // fall-through
case AV_CHANNEL_ORDER_NATIVE: {
uint64_t mask = channel_layout->u.mask;
if (!(mask & (1ULL << channel)))
return AVERROR(EINVAL);
mask &= (1ULL << channel) - 1;
- return av_popcount64(mask);
+ return av_popcount64(mask) + off;
}
default:
return AVERROR(EINVAL);
@@ -422,6 +499,9 @@ int av_channel_layout_check(const AVChannelLayout *channel_layout)
switch (channel_layout->order) {
case AV_CHANNEL_ORDER_NATIVE:
return av_popcount64(channel_layout->u.mask) == channel_layout->nb_channels;
+ case AV_CHANNEL_ORDER_AMBISONIC:
+ return channel_layout->nb_channels != 2 &&
+ channel_layout->nb_channels >= av_popcount64(channel_layout->u.mask);
case AV_CHANNEL_ORDER_CUSTOM:
return !!channel_layout->u.map;
case AV_CHANNEL_ORDER_UNSPEC:
diff --git a/libavutil/channel_layout.h b/libavutil/channel_layout.h
index 2604ad1537..bd78cc9ff9 100644
--- a/libavutil/channel_layout.h
+++ b/libavutil/channel_layout.h
@@ -68,6 +68,8 @@ enum AVChannel {

/** Channel is empty can be safely skipped. */
AV_CHAN_SILENCE = 64,
+ /** Channel represents an ambisonic component. */
+ AV_CHAN_AMBISONIC,
};

enum AVChannelOrder {
@@ -88,6 +90,26 @@ enum AVChannelOrder {
* about the channel order.
*/
AV_CHANNEL_ORDER_UNSPEC,
+ /**
+ * Each channel represents a different speaker position, also known as
+ * ambisonic components. Channels are ordered according to ACN (Ambisonic
+ * Channel Number), and they follow these mathematical properties:
+ *
+ * @code{.unparsed}
+ * ACN = n * (n + 1) + m
+ * n = floor(sqrt(k)) - 1,
+ * m = k - n * (n + 1) - 1.
+ * @endcode
+ *
+ * for order n and degree m; the ACN component corresponds to channel
+ * index as k = ACN + 1. In case non-diegetic channels are present,
+ * they are always the last ones, and mask is initialized with a correct
+ * layout.
+ *
+ * Normalization is assumed to be SN3D (Schmidt Semi-Normalization)
+ * as defined in AmbiX format § 2.1.
+ */
+ AV_CHANNEL_ORDER_AMBISONIC,
};


@@ -224,6 +246,10 @@ typedef struct AVChannelLayout {
* modified manually (i.e. not using any of the av_channel_layout_*
* functions), the code doing it must ensure that the number of set bits
* is equal to nb_channels.
+ *
+ * This member maybe be optionially used for AV_CHANNEL_ORDER_AMBISONIC.
+ * It is a bitmask that indicates the channel layout of the last
+ * non-diegetic channels present in the stream.
*/
uint64_t mask;
/**
@@ -295,6 +321,8 @@ typedef struct AVChannelLayout {
{ .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 16, .u = { .mask = AV_CH_LAYOUT_HEXAGONAL }}
#define AV_CHANNEL_LAYOUT_STEREO_DOWNMIX \
{ .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 2, .u = { .mask = AV_CH_LAYOUT_STEREO_DOWNMIX }}
+#define AV_CHANNEL_LAYOUT_AMBISONIC_FIRST_ORDER \
+ { .order = AV_CHANNEL_ORDER_AMBISONIC, .nb_channels = 4, .u = { .mask = 0 }}

#if FF_API_OLD_CHANNEL_LAYOUT
/**
@@ -403,6 +431,8 @@ void av_channel_layout_from_mask(AVChannelLayout *channel_layout, uint64_t mask)
* - a hexadecimal value of a channel layout (eg. "0x4")
* - the number of channels with default layout (eg. "5")
* - the number of unordered channels (eg. "4 channels")
+ * - the ambisonic channel count and order followed by optional non-diegetic
+ * channels (eg. "ambisonic channels 9 order 2|stereo")
*
* @param channel_layout input channel layout
* @param str string describing the channel layout
@@ -452,6 +482,9 @@ int av_channel_layout_get_channel(const AVChannelLayout *channel_layout, int idx
/**
* Get the index of a given channel in a channel layout.
*
+ * @note AV_CHAN_AMBISONIC will always be at index 0: callers need to use the
+ * ACN mathematical properties to determine the order.
+ *
* @return index of channel in channel_layout on success or a negative number if
* channel is not present in channel_layout.
*/
--
2.13.1
wm4
2017-06-29 09:22:36 UTC
Permalink
On Wed, 28 Jun 2017 18:11:01 -0400
Post by Vittorio Giovara
---
libavutil/channel_layout.c | 86 ++++++++++++++++++++++++++++++++++++++++++++--
libavutil/channel_layout.h | 33 ++++++++++++++++++
2 files changed, 116 insertions(+), 3 deletions(-)
* is equal to nb_channels.
+ *
+ * This member maybe be optionially used for AV_CHANNEL_ORDER_AMBISONIC.
+ * It is a bitmask that indicates the channel layout of the last
+ * non-diegetic channels present in the stream.
*/
uint64_t mask;
(Should say it's 0 for AV_CHANNEL_ORDER_AMBISONIC if unused.)
Luca Barbato
2017-07-04 10:53:00 UTC
Permalink
Post by Vittorio Giovara
---
libavutil/channel_layout.c | 86 ++++++++++++++++++++++++++++++++++++++++++++--
libavutil/channel_layout.h | 33 ++++++++++++++++++
2 files changed, 116 insertions(+), 3 deletions(-)
Looks fine.
Vittorio Giovara
2017-06-28 22:10:55 UTC
Permalink
This patch contains the following commits:

avtools: Use the new channel layout API in AVCodecParameters

4xm: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

adxdec: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

aea: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

aiff: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

alsa: convert to new channel layout API

amr: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

apc: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

ape: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

au: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

bethsoftvid: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

bfi: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

bink: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

bmv: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

cafdec: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

cdxl: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

dash: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

dsicin: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

dss: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

dv: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

eac: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

electronicarts: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

flac: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

flic: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

flv: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

g722: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

g723_1: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

g729: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

gsm: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

gxf: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

idcin: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

idroq: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

iff: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

ilbc: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

ipmovie: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

iss: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

jvdec: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

lxfdec: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

matroska: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

mm: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

mmf: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

mov: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

movenc-test: convert to new channel layout API

mp3: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

mpc: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

mpc8: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

mpegenc: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

mvdec: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

mvi: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

mxf: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

mxg: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

nsvdec: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

nutdec: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

nuv: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

ogg: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

oma: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

paf: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

pcm: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

pmp: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

psxstr: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

qcp: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

r3d: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

riff: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

rl2: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

rm: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

rpl: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

rso: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

rtp: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

sdp: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

segafilm: convert to new channel layout API

sierravmd: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

siff: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

smacker: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

smjpegenc: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

smoothstreaming: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

smush: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

sol: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

sox: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

swf: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

tak: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

thp: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

tiertexseq: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

tmv: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

tta: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

voc: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

vqf: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

wav: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

wc3movie: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

westwood: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

wtv: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

wv: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

xa: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

xmv: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

xwma: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

yop: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>
---
avtools/avconv_opt.c | 4 +--
avtools/avplay.c | 2 +-
avtools/avprobe.c | 2 +-
avtools/cmdutils.c | 2 +-
libavdevice/alsa.c | 10 ++++---
libavformat/4xm.c | 7 +++--
libavformat/adxdec.c | 11 +++++---
libavformat/aea.c | 11 ++++----
libavformat/aiffdec.c | 13 +++++----
libavformat/aiffenc.c | 4 +--
libavformat/amr.c | 3 +-
libavformat/apc.c | 12 +++-----
libavformat/ape.c | 3 +-
libavformat/au.c | 5 ++--
libavformat/bethsoftvid.c | 3 +-
libavformat/bfi.c | 3 +-
libavformat/bink.c | 12 +++-----
libavformat/bmv.c | 3 +-
libavformat/cafdec.c | 3 +-
libavformat/cdxl.c | 9 ++----
libavformat/dashenc.c | 2 +-
libavformat/dauddec.c | 3 +-
libavformat/daudenc.c | 2 +-
libavformat/dsicin.c | 7 +++--
libavformat/dss.c | 3 +-
libavformat/dv.c | 3 +-
libavformat/dvenc.c | 2 +-
libavformat/eacdata.c | 3 +-
libavformat/electronicarts.c | 7 +++--
libavformat/flacdec.c | 2 +-
libavformat/flacenc.c | 13 +++++----
libavformat/flic.c | 3 +-
libavformat/flvdec.c | 21 +++++++-------
libavformat/flvenc.c | 6 ++--
libavformat/g722.c | 2 +-
libavformat/g723_1.c | 3 +-
libavformat/g729dec.c | 2 +-
libavformat/gsmdec.c | 3 +-
libavformat/gxf.c | 9 ++----
libavformat/gxfenc.c | 2 +-
libavformat/idcin.c | 4 +--
libavformat/idroqdec.c | 12 ++++----
libavformat/iff.c | 16 +++++------
libavformat/ilbc.c | 2 +-
libavformat/ipmovie.c | 8 ++----
libavformat/isom.c | 5 ++--
libavformat/iss.c | 17 ++++++------
libavformat/jvdec.c | 3 +-
libavformat/lxfdec.c | 3 +-
libavformat/matroskadec.c | 4 +--
libavformat/matroskaenc.c | 15 +++++-----
libavformat/mm.c | 3 +-
libavformat/mmf.c | 3 +-
libavformat/mov.c | 60 +++++++++++++++++++++++++++-------------
libavformat/mov_chan.c | 26 ++++++++++-------
libavformat/mov_chan.h | 4 ++-
libavformat/movenc.c | 8 +++---
libavformat/mp3enc.c | 2 +-
libavformat/mpc.c | 3 +-
libavformat/mpc8.c | 5 +++-
libavformat/mpegenc.c | 6 ++--
libavformat/mvdec.c | 10 +++----
libavformat/mvi.c | 3 +-
libavformat/mxfdec.c | 13 +++++----
libavformat/mxfenc.c | 6 ++--
libavformat/mxg.c | 3 +-
libavformat/nsvdec.c | 2 +-
libavformat/nutdec.c | 2 +-
libavformat/nutenc.c | 2 +-
libavformat/nuv.c | 7 ++---
libavformat/oggparsecelt.c | 3 +-
libavformat/oggparseogm.c | 6 ++--
libavformat/oggparseopus.c | 3 +-
libavformat/oggparsespeex.c | 8 +++---
libavformat/oggparsevorbis.c | 3 +-
libavformat/oma.c | 19 ++++++-------
libavformat/oma.h | 5 ++--
libavformat/omadec.c | 10 +++----
libavformat/omaenc.c | 4 +--
libavformat/paf.c | 3 +-
libavformat/pcm.c | 2 +-
libavformat/pcmdec.c | 7 +++--
libavformat/pmpdec.c | 3 +-
libavformat/psxstr.c | 10 ++-----
libavformat/qcp.c | 3 +-
libavformat/r3d.c | 3 +-
libavformat/riffdec.c | 13 ++++++---
libavformat/riffenc.c | 11 ++++----
libavformat/rl2.c | 7 +++--
libavformat/rmdec.c | 6 ++--
libavformat/rmenc.c | 2 +-
libavformat/rpl.c | 8 ++++--
libavformat/rsodec.c | 3 +-
libavformat/rsoenc.c | 2 +-
libavformat/rtp.c | 10 ++++---
libavformat/rtpdec_amr.c | 3 +-
libavformat/rtpenc.c | 12 ++++----
libavformat/rtsp.c | 6 ++--
libavformat/rtsp.h | 1 -
libavformat/sdp.c | 34 +++++++++++++----------
libavformat/segafilm.c | 9 +++---
libavformat/sierravmd.c | 12 ++------
libavformat/siff.c | 3 +-
libavformat/smacker.c | 12 +++-----
libavformat/smjpegdec.c | 3 +-
libavformat/smjpegenc.c | 2 +-
libavformat/smoothstreamingenc.c | 2 +-
libavformat/smush.c | 4 +--
libavformat/sol.c | 4 +--
libavformat/soxdec.c | 14 ++++++----
libavformat/soxenc.c | 4 +--
libavformat/swfdec.c | 8 +-----
libavformat/swfenc.c | 2 +-
libavformat/takdec.c | 7 +++--
libavformat/tests/movenc.c | 2 +-
libavformat/thp.c | 3 +-
libavformat/tiertexseq.c | 7 ++---
libavformat/tmv.c | 10 ++-----
libavformat/tta.c | 3 +-
libavformat/voc_packet.c | 7 +++--
libavformat/vocenc.c | 8 +++---
libavformat/vqf.c | 11 ++++----
libavformat/wavdec.c | 4 +--
libavformat/wc3movie.c | 8 ++----
libavformat/westwood_aud.c | 6 ++--
libavformat/westwood_vqa.c | 2 +-
libavformat/wtv.c | 6 ++--
libavformat/wvdec.c | 3 +-
libavformat/xa.c | 7 +++--
libavformat/xmv.c | 3 +-
libavformat/xwma.c | 8 +++---
libavformat/yop.c | 3 +-
132 files changed, 440 insertions(+), 434 deletions(-)

diff --git a/avtools/avconv_opt.c b/avtools/avconv_opt.c
index 575ce120dd..9076b74e38 100644
--- a/avtools/avconv_opt.c
+++ b/avtools/avconv_opt.c
@@ -1679,8 +1679,8 @@ static int open_output_file(OptionsContext *o, const char *filename)
for (i = 0; i < nb_input_streams; i++) {
ist = input_streams[i];
if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
- ist->st->codecpar->channels > channels) {
- channels = ist->st->codecpar->channels;
+ ist->st->codecpar->ch_layout.nb_channels > channels) {
+ channels = ist->st->codecpar->ch_layout.nb_channels;
idx = i;
}
}
diff --git a/avtools/avplay.c b/avtools/avplay.c
index 6cc63258fc..544c5dd4a1 100644
--- a/avtools/avplay.c
+++ b/avtools/avplay.c
@@ -2609,7 +2609,7 @@ static void stream_cycle_channel(PlayerState *is, int codec_type)
switch (codec_type) {
case AVMEDIA_TYPE_AUDIO:
if (st->codecpar->sample_rate != 0 &&
- st->codecpar->channels != 0)
+ st->codecpar->ch_layout.nb_channels != 0)
goto the_end;
break;
case AVMEDIA_TYPE_VIDEO:
diff --git a/avtools/avprobe.c b/avtools/avprobe.c
index a9ca1934ca..7eab2573eb 100644
--- a/avtools/avprobe.c
+++ b/avtools/avprobe.c
@@ -756,7 +756,7 @@ static void show_stream(InputFile *ifile, InputStream *ist)
value_string(val_str, sizeof(val_str),
par->sample_rate,
unit_hertz_str));
- probe_int("channels", par->channels);
+ probe_int("channels", par->ch_layout.nb_channels);
probe_int("bits_per_sample",
av_get_bits_per_sample(par->codec_id));
break;
diff --git a/avtools/cmdutils.c b/avtools/cmdutils.c
index 727e2835eb..9d6a2b9f2b 100644
--- a/avtools/cmdutils.c
+++ b/avtools/cmdutils.c
@@ -1571,7 +1571,7 @@ int check_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec)
int val;
switch (par->codec_type) {
case AVMEDIA_TYPE_AUDIO:
- val = par->sample_rate && par->channels;
+ val = par->sample_rate && par->ch_layout.nb_channels;
if (par->format == AV_SAMPLE_FMT_NONE)
return 0;
break;
diff --git a/libavdevice/alsa.c b/libavdevice/alsa.c
index d394e4377d..cf080d7eef 100644
--- a/libavdevice/alsa.c
+++ b/libavdevice/alsa.c
@@ -194,7 +194,7 @@ av_cold int ff_alsa_open(AVFormatContext *ctx, snd_pcm_stream_t mode,
snd_pcm_t *h;
snd_pcm_hw_params_t *hw_params;
snd_pcm_uframes_t buffer_size, period_size;
- uint64_t layout = ctx->streams[0]->codecpar->channel_layout;
+ uint64_t layout = ctx->streams[0]->codecpar->ch_layout.u.mask;

if (ctx->filename[0] == 0) audio_device = "default";
else audio_device = ctx->filename;
@@ -292,10 +292,12 @@ av_cold int ff_alsa_open(AVFormatContext *ctx, snd_pcm_stream_t mode,

if (channels > 2 && layout) {
if (find_reorder_func(s, *codec_id, layout, mode == SND_PCM_STREAM_PLAYBACK) < 0) {
- char name[128];
- av_get_channel_layout_string(name, sizeof(name), channels, layout);
+ char *chlstr = av_channel_layout(&ctx->streams[0]->codecpar->ch_layout);
+ if (!chlstr)
+ goto fail1;
av_log(ctx, AV_LOG_WARNING, "ALSA channel layout unknown or unimplemented for %s %s.\n",
- name, mode == SND_PCM_STREAM_PLAYBACK ? "playback" : "capture");
+ chlstr, mode == SND_PCM_STREAM_PLAYBACK ? "playback" : "capture");
+ av_free(chlstr);
}
if (s->reorder_func) {
s->reorder_buf_size = buffer_size;
diff --git a/libavformat/4xm.c b/libavformat/4xm.c
index 1597b3b569..adb8ed66bd 100644
--- a/libavformat/4xm.c
+++ b/libavformat/4xm.c
@@ -167,13 +167,14 @@ static int parse_strk(AVFormatContext *s,

st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_tag = 0;
- st->codecpar->channels = fourxm->tracks[track].channels;
+ st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ st->codecpar->ch_layout.nb_channels = fourxm->tracks[track].channels;
st->codecpar->sample_rate = fourxm->tracks[track].sample_rate;
st->codecpar->bits_per_coded_sample = fourxm->tracks[track].bits;
- st->codecpar->bit_rate = st->codecpar->channels *
+ st->codecpar->bit_rate = st->codecpar->ch_layout.nb_channels *
st->codecpar->sample_rate *
st->codecpar->bits_per_coded_sample;
- st->codecpar->block_align = st->codecpar->channels *
+ st->codecpar->block_align = st->codecpar->ch_layout.nb_channels *
st->codecpar->bits_per_coded_sample;

if (fourxm->tracks[track].adpcm){
diff --git a/libavformat/adxdec.c b/libavformat/adxdec.c
index 8162c69a9a..2744db1254 100644
--- a/libavformat/adxdec.c
+++ b/libavformat/adxdec.c
@@ -40,7 +40,7 @@ static int adx_read_packet(AVFormatContext *s, AVPacket *pkt)
AVCodecParameters *par = s->streams[0]->codecpar;
int ret, size;

- size = BLOCK_SIZE * par->channels;
+ size = BLOCK_SIZE * par->ch_layout.nb_channels;

pkt->pos = avio_tell(s->pb);
pkt->stream_index = 0;
@@ -65,6 +65,7 @@ static int adx_read_header(AVFormatContext *s)
{
ADXDemuxerContext *c = s->priv_data;
AVCodecParameters *par;
+ int channels;

AVStream *st = avformat_new_stream(s, NULL);
if (!st)
@@ -89,11 +90,13 @@ static int adx_read_header(AVFormatContext *s)
av_log(s, AV_LOG_ERROR, "Invalid extradata size.\n");
return AVERROR_INVALIDDATA;
}
- par->channels = AV_RB8 (par->extradata + 7);
+ channels = AV_RB8 (par->extradata + 7);
+ par->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ par->ch_layout.nb_channels = channels;
par->sample_rate = AV_RB32(par->extradata + 8);

- if (par->channels <= 0) {
- av_log(s, AV_LOG_ERROR, "invalid number of channels %d\n", par->channels);
+ if (channels <= 0) {
+ av_log(s, AV_LOG_ERROR, "invalid number of channels %d\n", channels);
return AVERROR_INVALIDDATA;
}

diff --git a/libavformat/aea.c b/libavformat/aea.c
index fc914f08fb..3e519832db 100644
--- a/libavformat/aea.c
+++ b/libavformat/aea.c
@@ -57,12 +57,13 @@ static int aea_read_probe(AVProbeData *p)
static int aea_read_header(AVFormatContext *s)
{
AVStream *st = avformat_new_stream(s, NULL);
+ int channels;
if (!st)
return AVERROR(ENOMEM);

/* Parse the amount of channels and skip to pos 2048(0x800) */
avio_skip(s->pb, 264);
- st->codecpar->channels = avio_r8(s->pb);
+ channels = avio_r8(s->pb);
avio_skip(s->pb, 1783);


@@ -71,14 +72,14 @@ static int aea_read_header(AVFormatContext *s)
st->codecpar->sample_rate = 44100;
st->codecpar->bit_rate = 292000;

- if (st->codecpar->channels != 1 && st->codecpar->channels != 2) {
- av_log(s, AV_LOG_ERROR, "Channels %d not supported!\n", st->codecpar->channels);
+ if (channels != 1 && channels != 2) {
+ av_log(s, AV_LOG_ERROR, "Channels %d not supported!\n", channels);
return AVERROR_INVALIDDATA;
}

- st->codecpar->channel_layout = (st->codecpar->channels == 1) ? AV_CH_LAYOUT_MONO : AV_CH_LAYOUT_STEREO;
+ av_channel_layout_default(&st->codecpar->ch_layout, channels);

- st->codecpar->block_align = AT1_SU_SIZE * st->codecpar->channels;
+ st->codecpar->block_align = AT1_SU_SIZE * st->codecpar->ch_layout.nb_channels;
return 0;
}

diff --git a/libavformat/aiffdec.c b/libavformat/aiffdec.c
index 481a92d351..490a767968 100644
--- a/libavformat/aiffdec.c
+++ b/libavformat/aiffdec.c
@@ -96,11 +96,14 @@ static unsigned int get_aiff_header(AVFormatContext *s, int size,
uint64_t val;
double sample_rate;
unsigned int num_frames;
+ int channels;

if (size & 1)
size++;
par->codec_type = AVMEDIA_TYPE_AUDIO;
- par->channels = avio_rb16(pb);
+ channels = avio_rb16(pb);
+ par->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ par->ch_layout.nb_channels = channels;
num_frames = avio_rb32(pb);
par->bits_per_coded_sample = avio_rb16(pb);

@@ -131,14 +134,14 @@ static unsigned int get_aiff_header(AVFormatContext *s, int size,
aiff->block_duration = 1;
break;
case AV_CODEC_ID_ADPCM_IMA_QT:
- par->block_align = 34 * par->channels;
+ par->block_align = 34 * channels;
break;
case AV_CODEC_ID_MACE3:
- par->block_align = 2 * par->channels;
+ par->block_align = 2 * channels;
break;
case AV_CODEC_ID_ADPCM_G722:
case AV_CODEC_ID_MACE6:
- par->block_align = 1 * par->channels;
+ par->block_align = 1 * channels;
break;
case AV_CODEC_ID_GSM:
par->block_align = 33;
@@ -157,7 +160,7 @@ static unsigned int get_aiff_header(AVFormatContext *s, int size,
/* Block align needs to be computed in all cases, as the definition
* is specific to applications -> here we use the WAVE format definition */
if (!par->block_align)
- par->block_align = (par->bits_per_coded_sample * par->channels) >> 3;
+ par->block_align = (par->bits_per_coded_sample * channels) >> 3;

if (aiff->block_duration) {
par->bit_rate = par->sample_rate * (par->block_align << 3) /
diff --git a/libavformat/aiffenc.c b/libavformat/aiffenc.c
index 191e746672..5fff9c009e 100644
--- a/libavformat/aiffenc.c
+++ b/libavformat/aiffenc.c
@@ -68,7 +68,7 @@ static int aiff_write_header(AVFormatContext *s)
/* Common chunk */
ffio_wfourcc(pb, "COMM");
avio_wb32(pb, aifc ? 24 : 18); /* size */
- avio_wb16(pb, par->channels); /* Number of channels */
+ avio_wb16(pb, par->ch_layout.nb_channels); /* Number of channels */

aiff->frames = avio_tell(pb);
avio_wb32(pb, 0); /* Number of frames */
@@ -80,7 +80,7 @@ static int aiff_write_header(AVFormatContext *s)
return -1;
}
if (!par->block_align)
- par->block_align = (par->bits_per_coded_sample * par->channels) >> 3;
+ par->block_align = (par->bits_per_coded_sample * par->ch_layout.nb_channels) >> 3;

avio_wb16(pb, par->bits_per_coded_sample); /* Sample size */

diff --git a/libavformat/amr.c b/libavformat/amr.c
index cdba27d430..59029cb469 100644
--- a/libavformat/amr.c
+++ b/libavformat/amr.c
@@ -97,8 +97,7 @@ static int amr_read_header(AVFormatContext *s)
st->codecpar->codec_id = AV_CODEC_ID_AMR_NB;
st->codecpar->sample_rate = 8000;
}
- st->codecpar->channels = 1;
- st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);

diff --git a/libavformat/apc.c b/libavformat/apc.c
index 40ecdf2c5d..8a8a5c3491 100644
--- a/libavformat/apc.c
+++ b/libavformat/apc.c
@@ -36,6 +36,7 @@ static int apc_read_header(AVFormatContext *s)
{
AVIOContext *pb = s->pb;
AVStream *st;
+ int channels;

avio_rl32(pb); /* CRYO */
avio_rl32(pb); /* _APC */
@@ -60,16 +61,11 @@ static int apc_read_header(AVFormatContext *s)
/* initial predictor values for adpcm decoder */
avio_read(pb, st->codecpar->extradata, 2 * 4);

- if (avio_rl32(pb)) {
- st->codecpar->channels = 2;
- st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
- } else {
- st->codecpar->channels = 1;
- st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
- }
+ channels = avio_rl32(pb) + 1;
+ av_channel_layout_default(&st->codecpar->ch_layout, channels);

st->codecpar->bits_per_coded_sample = 4;
- st->codecpar->bit_rate = st->codecpar->bits_per_coded_sample * st->codecpar->channels
+ st->codecpar->bit_rate = st->codecpar->bits_per_coded_sample * channels
* st->codecpar->sample_rate;
st->codecpar->block_align = 1;

diff --git a/libavformat/ape.c b/libavformat/ape.c
index 010b795c59..bee471813a 100644
--- a/libavformat/ape.c
+++ b/libavformat/ape.c
@@ -349,7 +349,8 @@ static int ape_read_header(AVFormatContext * s)
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_APE;
st->codecpar->codec_tag = MKTAG('A', 'P', 'E', ' ');
- st->codecpar->channels = ape->channels;
+ st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ st->codecpar->ch_layout.nb_channels = ape->channels;
st->codecpar->sample_rate = ape->samplerate;
st->codecpar->bits_per_coded_sample = ape->bps;

diff --git a/libavformat/au.c b/libavformat/au.c
index 20c9d41f47..e1df580d4c 100644
--- a/libavformat/au.c
+++ b/libavformat/au.c
@@ -111,7 +111,8 @@ static int au_read_header(AVFormatContext *s)
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_tag = id;
st->codecpar->codec_id = codec;
- st->codecpar->channels = channels;
+ st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ st->codecpar->ch_layout.nb_channels = channels;
st->codecpar->sample_rate = rate;
st->codecpar->bit_rate = channels * rate * bps;
st->codecpar->block_align = channels * bps >> 3;
@@ -167,7 +168,7 @@ static int put_au_header(AVIOContext *pb, AVCodecParameters *par)
avio_wb32(pb, AU_UNKNOWN_SIZE); /* data size */
avio_wb32(pb, par->codec_tag); /* codec ID */
avio_wb32(pb, par->sample_rate);
- avio_wb32(pb, par->channels);
+ avio_wb32(pb, par->ch_layout.nb_channels);

return 0;
}
diff --git a/libavformat/bethsoftvid.c b/libavformat/bethsoftvid.c
index 8ed9d4f290..03ba2785f7 100644
--- a/libavformat/bethsoftvid.c
+++ b/libavformat/bethsoftvid.c
@@ -242,8 +242,7 @@ static int vid_read_packet(AVFormatContext *s,
vid->audio_index = st->index;
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_PCM_U8;
- st->codecpar->channels = 1;
- st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
st->codecpar->bits_per_coded_sample = 8;
st->codecpar->sample_rate = vid->sample_rate;
st->codecpar->bit_rate = 8 * st->codecpar->sample_rate;
diff --git a/libavformat/bfi.c b/libavformat/bfi.c
index 99371bd4c0..7eff148524 100644
--- a/libavformat/bfi.c
+++ b/libavformat/bfi.c
@@ -96,8 +96,7 @@ static int bfi_read_header(AVFormatContext * s)
/* Set up the audio codec now... */
astream->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
astream->codecpar->codec_id = AV_CODEC_ID_PCM_U8;
- astream->codecpar->channels = 1;
- astream->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+ astream->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
astream->codecpar->bits_per_coded_sample = 8;
astream->codecpar->bit_rate =
astream->codecpar->sample_rate * astream->codecpar->bits_per_coded_sample;
diff --git a/libavformat/bink.c b/libavformat/bink.c
index 8f28212ab4..be8e5711c5 100644
--- a/libavformat/bink.c
+++ b/libavformat/bink.c
@@ -139,6 +139,7 @@ static int read_header(AVFormatContext *s)
avio_skip(pb, 4 * bink->num_audio_tracks);

for (i = 0; i < bink->num_audio_tracks; i++) {
+ int channels;
ast = avformat_new_stream(s, NULL);
if (!ast)
return AVERROR(ENOMEM);
@@ -149,13 +150,8 @@ static int read_header(AVFormatContext *s)
flags = avio_rl16(pb);
ast->codecpar->codec_id = flags & BINK_AUD_USEDCT ?
AV_CODEC_ID_BINKAUDIO_DCT : AV_CODEC_ID_BINKAUDIO_RDFT;
- if (flags & BINK_AUD_STEREO) {
- ast->codecpar->channels = 2;
- ast->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
- } else {
- ast->codecpar->channels = 1;
- ast->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
- }
+ channels = !!(flags & BINK_AUD_STEREO) + 1;
+ av_channel_layout_default(&ast->codecpar->ch_layout, channels);
ast->codecpar->extradata = av_mallocz(4 + AV_INPUT_BUFFER_PADDING_SIZE);
if (!ast->codecpar->extradata)
return AVERROR(ENOMEM);
@@ -242,7 +238,7 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt)
(in bytes). We use this value to calculate the audio PTS */
if (pkt->size >= 4)
bink->audio_pts[bink->current_track -1] +=
- AV_RL32(pkt->data) / (2 * s->streams[bink->current_track]->codecpar->channels);
+ AV_RL32(pkt->data) / (2 * s->streams[bink->current_track]->codecpar->ch_layout.nb_channels);
return 0;
} else {
avio_skip(pb, audio_size);
diff --git a/libavformat/bmv.c b/libavformat/bmv.c
index 9bc8dda871..eee29bf43e 100644
--- a/libavformat/bmv.c
+++ b/libavformat/bmv.c
@@ -58,8 +58,7 @@ static int bmv_read_header(AVFormatContext *s)
return AVERROR(ENOMEM);
ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
ast->codecpar->codec_id = AV_CODEC_ID_BMV_AUDIO;
- ast->codecpar->channels = 2;
- ast->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
+ ast->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
ast->codecpar->sample_rate = 22050;
avpriv_set_pts_info(ast, 16, 1, 22050);

diff --git a/libavformat/cafdec.c b/libavformat/cafdec.c
index efc8c49c4a..f6d09c1abe 100644
--- a/libavformat/cafdec.c
+++ b/libavformat/cafdec.c
@@ -76,7 +76,8 @@ static int read_desc_chunk(AVFormatContext *s)
caf->bytes_per_packet = avio_rb32(pb);
st->codecpar->block_align = caf->bytes_per_packet;
caf->frames_per_packet = avio_rb32(pb);
- st->codecpar->channels = avio_rb32(pb);
+ st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ st->codecpar->ch_layout.nb_channels = avio_rb32(pb);
st->codecpar->bits_per_coded_sample = avio_rb32(pb);

/* calculate bit rate for constant size packets */
diff --git a/libavformat/cdxl.c b/libavformat/cdxl.c
index 26a5f8161c..6f09ee2d76 100644
--- a/libavformat/cdxl.c
+++ b/libavformat/cdxl.c
@@ -95,6 +95,7 @@ static int cdxl_read_packet(AVFormatContext *s, AVPacket *pkt)

if (cdxl->read_chunk && audio_size) {
if (cdxl->audio_stream_index == -1) {
+ int channels = !!(cdxl->header[1] & 0x10) + 1;
AVStream *st = avformat_new_stream(s, NULL);
if (!st)
return AVERROR(ENOMEM);
@@ -102,13 +103,7 @@ static int cdxl_read_packet(AVFormatContext *s, AVPacket *pkt)
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_tag = 0;
st->codecpar->codec_id = AV_CODEC_ID_PCM_S8;
- if (cdxl->header[1] & 0x10) {
- st->codecpar->channels = 2;
- st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
- } else {
- st->codecpar->channels = 1;
- st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
- }
+ av_channel_layout_default(&st->codecpar->ch_layout, channels);
st->codecpar->sample_rate = cdxl->sample_rate;
st->start_time = 0;
cdxl->audio_stream_index = st->index;
diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 7134af4978..1b92babdc8 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -533,7 +533,7 @@ static int write_adaptation_set(AVFormatContext *s, AVIOContext *out, int as_ind
avio_printf(out, "\t\t\t<Representation id=\"%d\" mimeType=\"audio/%s\" codecs=\"%s\"%s audioSamplingRate=\"%d\">\n",
i, os->format_name, os->codec_str, os->bandwidth_str, s->streams[i]->codecpar->sample_rate);
avio_printf(out, "\t\t\t\t<AudioChannelConfiguration schemeIdUri=\"urn:mpeg:dash:23003:3:audio_channel_configuration:2011\" value=\"%d\" />\n",
- s->streams[i]->codecpar->channels);
+ s->streams[i]->codecpar->ch_layout.nb_channels);
}
output_segment_list(os, out, c);
avio_printf(out, "\t\t\t</Representation>\n");
diff --git a/libavformat/dauddec.c b/libavformat/dauddec.c
index 98f8a5749d..01e5e37e42 100644
--- a/libavformat/dauddec.c
+++ b/libavformat/dauddec.c
@@ -29,8 +29,7 @@ static int daud_header(AVFormatContext *s) {
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_PCM_S24DAUD;
st->codecpar->codec_tag = MKTAG('d', 'a', 'u', 'd');
- st->codecpar->channels = 6;
- st->codecpar->channel_layout = AV_CH_LAYOUT_5POINT1;
+ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1;
st->codecpar->sample_rate = 96000;
st->codecpar->bit_rate = 3 * 6 * 96000 * 8;
st->codecpar->block_align = 3 * 6;
diff --git a/libavformat/daudenc.c b/libavformat/daudenc.c
index 93608e3319..eae35e80e4 100644
--- a/libavformat/daudenc.c
+++ b/libavformat/daudenc.c
@@ -24,7 +24,7 @@
static int daud_write_header(struct AVFormatContext *s)
{
AVCodecParameters *par = s->streams[0]->codecpar;
- if (par->channels!=6 || par->sample_rate!=96000)
+ if (par->ch_layout.nb_channels != 6 || par->sample_rate != 96000)
return -1;
return 0;
}
diff --git a/libavformat/dsicin.c b/libavformat/dsicin.c
index fa5943dfe2..a02253c95b 100644
--- a/libavformat/dsicin.c
+++ b/libavformat/dsicin.c
@@ -131,11 +131,12 @@ static int cin_read_header(AVFormatContext *s)
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_DSICINAUDIO;
st->codecpar->codec_tag = 0; /* no tag */
- st->codecpar->channels = 1;
- st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
st->codecpar->sample_rate = 22050;
st->codecpar->bits_per_coded_sample = 8;
- st->codecpar->bit_rate = st->codecpar->sample_rate * st->codecpar->bits_per_coded_sample * st->codecpar->channels;
+ st->codecpar->bit_rate = st->codecpar->sample_rate *
+ st->codecpar->bits_per_coded_sample *
+ st->codecpar->ch_layout.nb_channels;

return 0;
}
diff --git a/libavformat/dss.c b/libavformat/dss.c
index a9b2ebf2d8..b5b5ed3b98 100644
--- a/libavformat/dss.c
+++ b/libavformat/dss.c
@@ -153,8 +153,7 @@ static int dss_read_header(AVFormatContext *s)
}

st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
- st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
- st->codecpar->channels = 1;
+ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;

avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
st->start_time = 0;
diff --git a/libavformat/dv.c b/libavformat/dv.c
index 748b5e8926..7ba3869c36 100644
--- a/libavformat/dv.c
+++ b/libavformat/dv.c
@@ -255,8 +255,7 @@ static int dv_extract_audio_info(DVDemuxContext *c, uint8_t *frame)
c->audio_pkt[i].flags |= AV_PKT_FLAG_KEY;
}
c->ast[i]->codecpar->sample_rate = dv_audio_frequency[freq];
- c->ast[i]->codecpar->channels = 2;
- c->ast[i]->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
+ c->ast[i]->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
c->ast[i]->codecpar->bit_rate = 2 * dv_audio_frequency[freq] * 16;
c->ast[i]->start_time = 0;
}
diff --git a/libavformat/dvenc.c b/libavformat/dvenc.c
index cf795347ad..000c24fd44 100644
--- a/libavformat/dvenc.c
+++ b/libavformat/dvenc.c
@@ -331,7 +331,7 @@ static DVMuxContext* dv_init_mux(AVFormatContext* s)
for (i=0; i<c->n_ast; i++) {
if (c->ast[i] && (c->ast[i]->codecpar->codec_id != AV_CODEC_ID_PCM_S16LE ||
c->ast[i]->codecpar->sample_rate != 48000 ||
- c->ast[i]->codecpar->channels != 2))
+ c->ast[i]->codecpar->ch_layout.nb_channels != 2))
goto bail_out;
}
c->sys = av_dv_codec_profile(vst->codecpar->width, vst->codecpar->height, vst->codecpar->format);
diff --git a/libavformat/eacdata.c b/libavformat/eacdata.c
index d3f27a44c2..fdcd66ebe1 100644
--- a/libavformat/eacdata.c
+++ b/libavformat/eacdata.c
@@ -71,7 +71,8 @@ static int cdata_read_header(AVFormatContext *s)
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_tag = 0; /* no fourcc */
st->codecpar->codec_id = AV_CODEC_ID_ADPCM_EA_XAS;
- st->codecpar->channels = cdata->channels;
+ st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ st->codecpar->ch_layout.nb_channels = cdata->channels;
st->codecpar->sample_rate = sample_rate;
avpriv_set_pts_info(st, 64, 1, sample_rate);

diff --git a/libavformat/electronicarts.c b/libavformat/electronicarts.c
index 2df27e4a00..2242027257 100644
--- a/libavformat/electronicarts.c
+++ b/libavformat/electronicarts.c
@@ -500,13 +500,14 @@ static int ea_read_header(AVFormatContext *s)
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = ea->audio_codec;
st->codecpar->codec_tag = 0; /* no tag */
- st->codecpar->channels = ea->num_channels;
+ st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ st->codecpar->ch_layout.nb_channels = ea->num_channels;
st->codecpar->sample_rate = ea->sample_rate;
st->codecpar->bits_per_coded_sample = ea->bytes * 8;
- st->codecpar->bit_rate = st->codecpar->channels *
+ st->codecpar->bit_rate = ea->num_channels *
st->codecpar->sample_rate *
st->codecpar->bits_per_coded_sample / 4;
- st->codecpar->block_align = st->codecpar->channels *
+ st->codecpar->block_align = ea->num_channels *
st->codecpar->bits_per_coded_sample;
ea->audio_stream_index = st->index;
st->start_time = 0;
diff --git a/libavformat/flacdec.c b/libavformat/flacdec.c
index 2f4ac56040..6970bec7e8 100644
--- a/libavformat/flacdec.c
+++ b/libavformat/flacdec.c
@@ -159,7 +159,7 @@ static int flac_read_header(AVFormatContext *s)
av_log(s, AV_LOG_WARNING,
"Invalid value of WAVEFORMATEXTENSIBLE_CHANNEL_MASK\n");
} else {
- st->codecpar->channel_layout = mask;
+ av_channel_layout_from_mask(&st->codecpar->ch_layout, mask);
av_dict_set(&s->metadata, "WAVEFORMATEXTENSIBLE_CHANNEL_MASK", NULL, 0);
}
}
diff --git a/libavformat/flacenc.c b/libavformat/flacenc.c
index 06985cf240..99f3fd0f5d 100644
--- a/libavformat/flacenc.c
+++ b/libavformat/flacenc.c
@@ -89,9 +89,8 @@ static int flac_write_header(struct AVFormatContext *s)
return ret;

/* add the channel layout tag */
- if (par->channel_layout &&
- !(par->channel_layout & ~0x3ffffULL) &&
- !ff_flac_is_native_layout(par->channel_layout)) {
+ if (!av_channel_layout_subset(&par->ch_layout, ~0x3ffffULL) &&
+ !ff_flac_is_native_layout(par->ch_layout.u.mask)) {
AVDictionaryEntry *chmask = av_dict_get(s->metadata, "WAVEFORMATEXTENSIBLE_CHANNEL_MASK",
NULL, 0);

@@ -99,9 +98,11 @@ static int flac_write_header(struct AVFormatContext *s)
av_log(s, AV_LOG_WARNING, "A WAVEFORMATEXTENSIBLE_CHANNEL_MASK is "
"already present, this muxer will not overwrite it.\n");
} else {
- uint8_t buf[32];
- snprintf(buf, sizeof(buf), "0x%"PRIx64, par->channel_layout);
- av_dict_set(&s->metadata, "WAVEFORMATEXTENSIBLE_CHANNEL_MASK", buf, 0);
+ char *chlstr = av_channel_layout_describe(&par->ch_layout);
+ if (!chlstr)
+ return AVERROR(ENOMEM);
+ av_dict_set(&s->metadata, "WAVEFORMATEXTENSIBLE_CHANNEL_MASK", chlstr, 0);
+ av_free(chlstr);
}
}

diff --git a/libavformat/flic.c b/libavformat/flic.c
index 85e4790f87..b783dffd93 100644
--- a/libavformat/flic.c
+++ b/libavformat/flic.c
@@ -157,11 +157,10 @@ static int flic_read_header(AVFormatContext *s)
ast->codecpar->codec_id = AV_CODEC_ID_PCM_U8;
ast->codecpar->codec_tag = 0;
ast->codecpar->sample_rate = FLIC_TFTD_SAMPLE_RATE;
- ast->codecpar->channels = 1;
ast->codecpar->format = AV_SAMPLE_FMT_U8;
ast->codecpar->bit_rate = st->codecpar->sample_rate * 8;
ast->codecpar->bits_per_coded_sample = 8;
- ast->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+ ast->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
ast->codecpar->extradata_size = 0;

/* Since the header information is incorrect we have to figure out the
diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c
index 1b29740f41..e6adfb1006 100644
--- a/libavformat/flvdec.c
+++ b/libavformat/flvdec.c
@@ -480,10 +480,7 @@ static int amf_parse_object(AVFormatContext *s, AVStream *astream,
} else if (!strcmp(key, "audiosamplesize") && apar) {
apar->bits_per_coded_sample = num_val;
} else if (!strcmp(key, "stereo") && apar) {
- apar->channels = num_val + 1;
- apar->channel_layout = apar->channels == 2 ?
- AV_CH_LAYOUT_STEREO :
- AV_CH_LAYOUT_MONO;
+ av_channel_layout_default(&apar->ch_layout, num_val + 1);
} else if (!strcmp(key, "width") && vpar) {
vpar->width = num_val;
} else if (!strcmp(key, "height") && vpar) {
@@ -876,12 +873,10 @@ skip:
sample_rate = 44100 << ((flags & FLV_AUDIO_SAMPLERATE_MASK) >>
FLV_AUDIO_SAMPLERATE_OFFSET) >> 3;
bits_per_coded_sample = (flags & FLV_AUDIO_SAMPLESIZE_MASK) ? 16 : 8;
- if (!st->codecpar->channels || !st->codecpar->sample_rate ||
+ if (!av_channel_layout_check(&st->codecpar->ch_layout) ||
+ !st->codecpar->sample_rate ||
!st->codecpar->bits_per_coded_sample) {
- st->codecpar->channels = channels;
- st->codecpar->channel_layout = channels == 1
- ? AV_CH_LAYOUT_MONO
- : AV_CH_LAYOUT_STEREO;
+ av_channel_layout_default(&st->codecpar->ch_layout, channels);
st->codecpar->sample_rate = sample_rate;
st->codecpar->bits_per_coded_sample = bits_per_coded_sample;
}
@@ -891,7 +886,7 @@ skip:
flv->last_sample_rate =
sample_rate = st->codecpar->sample_rate;
flv->last_channels =
- channels = st->codecpar->channels;
+ channels = st->codecpar->ch_layout.nb_channels;
} else {
AVCodecParameters *par = avcodec_parameters_alloc();
if (!par) {
@@ -947,14 +942,18 @@ skip:

avpriv_mpeg4audio_get_config(&cfg, st->codecpar->extradata,
st->codecpar->extradata_size * 8, 1);
+ av_channel_layout_default(&st->codecpar->ch_layout, cfg.channels);
+ // or should it be UNORDERED?
+ /*
st->codecpar->channels = cfg.channels;
st->codecpar->channel_layout = 0;
+ */
if (cfg.ext_sample_rate)
st->codecpar->sample_rate = cfg.ext_sample_rate;
else
st->codecpar->sample_rate = cfg.sample_rate;
av_log(s, AV_LOG_TRACE, "mp4a config channels %d sample rate %d\n",
- st->codecpar->channels, st->codecpar->sample_rate);
+ st->codecpar->ch_layout.nb_channels, st->codecpar->sample_rate);
}

ret = AVERROR(EAGAIN);
diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c
index 00bd65cb58..e2dc1bfaaa 100644
--- a/libavformat/flvenc.c
+++ b/libavformat/flvenc.c
@@ -86,7 +86,7 @@ static int get_audio_flags(AVFormatContext *s, AVCodecParameters *par)
"flv only supports wideband (16kHz) Speex audio\n");
return -1;
}
- if (par->channels != 1) {
+ if (par->ch_layout.nb_channels != 1) {
av_log(s, AV_LOG_ERROR, "flv only supports mono Speex audio\n");
return -1;
}
@@ -117,7 +117,7 @@ static int get_audio_flags(AVFormatContext *s, AVCodecParameters *par)
}
}

- if (par->channels > 1)
+ if (par->ch_layout.nb_channels > 1)
flags |= FLV_STEREO;

switch (par->codec_id) {
@@ -261,7 +261,7 @@ static void write_metadata(AVFormatContext *s, unsigned int ts)
put_amf_double(pb, flv->audio_par->codec_id == AV_CODEC_ID_PCM_U8 ? 8 : 16);

put_amf_string(pb, "stereo");
- put_amf_bool(pb, flv->audio_par->channels == 2);
+ put_amf_bool(pb, flv->audio_par->ch_layout.nb_channels == 2);

put_amf_string(pb, "audiocodecid");
put_amf_double(pb, flv->audio_par->codec_tag);
diff --git a/libavformat/g722.c b/libavformat/g722.c
index 7e60e4e58c..7ebe9e0696 100644
--- a/libavformat/g722.c
+++ b/libavformat/g722.c
@@ -34,7 +34,7 @@ static int g722_read_header(AVFormatContext *s)
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_ADPCM_G722;
st->codecpar->sample_rate = 16000;
- st->codecpar->channels = 1;
+ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;

st->codecpar->bits_per_coded_sample =
av_get_bits_per_sample(st->codecpar->codec_id);
diff --git a/libavformat/g723_1.c b/libavformat/g723_1.c
index 9eca3f9bb8..5dc05a95d7 100644
--- a/libavformat/g723_1.c
+++ b/libavformat/g723_1.c
@@ -41,8 +41,7 @@ static av_cold int g723_1_init(AVFormatContext *s)

st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_G723_1;
- st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
- st->codecpar->channels = 1;
+ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
st->codecpar->sample_rate = 8000;

avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
diff --git a/libavformat/g729dec.c b/libavformat/g729dec.c
index c2beb60eda..70a2fe167a 100644
--- a/libavformat/g729dec.c
+++ b/libavformat/g729dec.c
@@ -43,7 +43,7 @@ static int g729_read_header(AVFormatContext *s)
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_G729;
st->codecpar->sample_rate = 8000;
- st->codecpar->channels = 1;
+ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;

if (s1 && s1->bit_rate)
s->bit_rate = s1->bit_rate;
diff --git a/libavformat/gsmdec.c b/libavformat/gsmdec.c
index d13327d879..c04cf72f97 100644
--- a/libavformat/gsmdec.c
+++ b/libavformat/gsmdec.c
@@ -64,8 +64,7 @@ static int gsm_read_header(AVFormatContext *s)

st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = s->iformat->raw_codec_id;
- st->codecpar->channels = 1;
- st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
st->codecpar->sample_rate = c->sample_rate;
st->codecpar->bit_rate = GSM_BLOCK_SIZE * 8 * c->sample_rate / GSM_BLOCK_SAMPLES;

diff --git a/libavformat/gxf.c b/libavformat/gxf.c
index e6ebb27af9..59eb39893b 100644
--- a/libavformat/gxf.c
+++ b/libavformat/gxf.c
@@ -121,8 +121,7 @@ static int get_sindex(AVFormatContext *s, int id, int format) {
case 9:
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_PCM_S24LE;
- st->codecpar->channels = 1;
- st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
st->codecpar->sample_rate = 48000;
st->codecpar->bit_rate = 3 * 1 * 48000 * 8;
st->codecpar->block_align = 3 * 1;
@@ -131,8 +130,7 @@ static int get_sindex(AVFormatContext *s, int id, int format) {
case 10:
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
- st->codecpar->channels = 1;
- st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
st->codecpar->sample_rate = 48000;
st->codecpar->bit_rate = 2 * 1 * 48000 * 8;
st->codecpar->block_align = 2 * 1;
@@ -141,8 +139,7 @@ static int get_sindex(AVFormatContext *s, int id, int format) {
case 17:
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_AC3;
- st->codecpar->channels = 2;
- st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
+ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
st->codecpar->sample_rate = 48000;
break;
// timecode tracks:
diff --git a/libavformat/gxfenc.c b/libavformat/gxfenc.c
index 32714f63ae..36d7d50938 100644
--- a/libavformat/gxfenc.c
+++ b/libavformat/gxfenc.c
@@ -656,7 +656,7 @@ static int gxf_write_header(AVFormatContext *s)
av_log(s, AV_LOG_ERROR, "only 48000hz sampling rate is allowed\n");
return -1;
}
- if (st->codecpar->channels != 1) {
+ if (st->codecpar->ch_layout.nb_channels != 1) {
av_log(s, AV_LOG_ERROR, "only mono tracks are allowed\n");
return -1;
}
diff --git a/libavformat/idcin.c b/libavformat/idcin.c
index 86e9f41e0b..2165ea5aa5 100644
--- a/libavformat/idcin.c
+++ b/libavformat/idcin.c
@@ -216,9 +216,7 @@ static int idcin_read_header(AVFormatContext *s)
idcin->audio_stream_index = st->index;
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_tag = 1;
- st->codecpar->channels = channels;
- st->codecpar->channel_layout = channels > 1 ? AV_CH_LAYOUT_STEREO :
- AV_CH_LAYOUT_MONO;
+ av_channel_layout_default(&st->codecpar->ch_layout, channels);
st->codecpar->sample_rate = sample_rate;
st->codecpar->bits_per_coded_sample = bytes_per_sample * 8;
st->codecpar->bit_rate = sample_rate * bytes_per_sample * 8 * channels;
diff --git a/libavformat/idroqdec.c b/libavformat/idroqdec.c
index a40894686d..a73bdaaf7d 100644
--- a/libavformat/idroqdec.c
+++ b/libavformat/idroqdec.c
@@ -179,18 +179,16 @@ static int roq_read_packet(AVFormatContext *s,
st->codecpar->codec_id = AV_CODEC_ID_ROQ_DPCM;
st->codecpar->codec_tag = 0; /* no tag */
if (chunk_type == RoQ_SOUND_STEREO) {
- st->codecpar->channels = 2;
- st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
+ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
} else {
- st->codecpar->channels = 1;
- st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
}
- roq->audio_channels = st->codecpar->channels;
+ roq->audio_channels = st->codecpar->ch_layout.nb_channels;
st->codecpar->sample_rate = RoQ_AUDIO_SAMPLE_RATE;
st->codecpar->bits_per_coded_sample = 16;
- st->codecpar->bit_rate = st->codecpar->channels * st->codecpar->sample_rate *
+ st->codecpar->bit_rate = roq->audio_channels * st->codecpar->sample_rate *
st->codecpar->bits_per_coded_sample;
- st->codecpar->block_align = st->codecpar->channels * st->codecpar->bits_per_coded_sample;
+ st->codecpar->block_align = roq->audio_channels * st->codecpar->bits_per_coded_sample;
}
case RoQ_QUAD_VQ:
if (chunk_type == RoQ_QUAD_VQ) {
diff --git a/libavformat/iff.c b/libavformat/iff.c
index 52c7e97280..3ffe08858c 100644
--- a/libavformat/iff.c
+++ b/libavformat/iff.c
@@ -122,8 +122,7 @@ static int iff_read_header(AVFormatContext *s)
if (!st)
return AVERROR(ENOMEM);

- st->codecpar->channels = 1;
- st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
avio_skip(pb, 8);
// codec_tag used by ByteRun1 decoder to distinguish progressive (PBM) and interlaced (ILBM) content
st->codecpar->codec_tag = avio_rl32(pb);
@@ -159,11 +158,9 @@ static int iff_read_header(AVFormatContext *s)
if (data_size < 4)
return AVERROR_INVALIDDATA;
if (avio_rb32(pb) < 6) {
- st->codecpar->channels = 1;
- st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
} else {
- st->codecpar->channels = 2;
- st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
+ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
}
break;

@@ -249,8 +246,11 @@ static int iff_read_header(AVFormatContext *s)
}

st->codecpar->bits_per_coded_sample = 8;
- st->codecpar->bit_rate = st->codecpar->channels * st->codecpar->sample_rate * st->codecpar->bits_per_coded_sample;
- st->codecpar->block_align = st->codecpar->channels * st->codecpar->bits_per_coded_sample;
+ st->codecpar->bit_rate = st->codecpar->ch_layout.nb_channels *
+ st->codecpar->sample_rate *
+ st->codecpar->bits_per_coded_sample;
+ st->codecpar->block_align = st->codecpar->ch_layout.nb_channels *
+ st->codecpar->bits_per_coded_sample;
break;

case AVMEDIA_TYPE_VIDEO:
diff --git a/libavformat/ilbc.c b/libavformat/ilbc.c
index b8549f3332..17ea808fd3 100644
--- a/libavformat/ilbc.c
+++ b/libavformat/ilbc.c
@@ -81,7 +81,7 @@ static int ilbc_read_header(AVFormatContext *s)
return AVERROR(ENOMEM);
st->codecpar->codec_id = AV_CODEC_ID_ILBC;
st->codecpar->sample_rate = 8000;
- st->codecpar->channels = 1;
+ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->start_time = 0;
avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
diff --git a/libavformat/ipmovie.c b/libavformat/ipmovie.c
index 5d789ffd54..0647d5f117 100644
--- a/libavformat/ipmovie.c
+++ b/libavformat/ipmovie.c
@@ -597,16 +597,14 @@ static int ipmovie_read_header(AVFormatContext *s)
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = ipmovie->audio_type;
st->codecpar->codec_tag = 0; /* no tag */
- st->codecpar->channels = ipmovie->audio_channels;
- st->codecpar->channel_layout = st->codecpar->channels == 1 ? AV_CH_LAYOUT_MONO :
- AV_CH_LAYOUT_STEREO;
+ av_channel_layout_default(&st->codecpar->ch_layout, ipmovie->audio_channels);
st->codecpar->sample_rate = ipmovie->audio_sample_rate;
st->codecpar->bits_per_coded_sample = ipmovie->audio_bits;
- st->codecpar->bit_rate = st->codecpar->channels * st->codecpar->sample_rate *
+ st->codecpar->bit_rate = ipmovie->audio_channels * st->codecpar->sample_rate *
st->codecpar->bits_per_coded_sample;
if (st->codecpar->codec_id == AV_CODEC_ID_INTERPLAY_DPCM)
st->codecpar->bit_rate /= 2;
- st->codecpar->block_align = st->codecpar->channels * st->codecpar->bits_per_coded_sample;
+ st->codecpar->block_align = ipmovie->audio_channels * st->codecpar->bits_per_coded_sample;
}

return 0;
diff --git a/libavformat/isom.c b/libavformat/isom.c
index 931c438d87..c49e631497 100644
--- a/libavformat/isom.c
+++ b/libavformat/isom.c
@@ -476,7 +476,8 @@ int ff_mp4_read_dec_config_descr(AVFormatContext *fc, AVStream *st, AVIOContext
MPEG4AudioConfig cfg;
avpriv_mpeg4audio_get_config(&cfg, st->codecpar->extradata,
st->codecpar->extradata_size * 8, 1);
- st->codecpar->channels = cfg.channels;
+ st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ st->codecpar->ch_layout.nb_channels = cfg.channels;
if (cfg.object_type == 29 && cfg.sampling_index < 3) // old mp3on4
st->codecpar->sample_rate = avpriv_mpa_freq_tab[cfg.sampling_index];
else if (cfg.ext_sample_rate)
@@ -484,7 +485,7 @@ int ff_mp4_read_dec_config_descr(AVFormatContext *fc, AVStream *st, AVIOContext
else
st->codecpar->sample_rate = cfg.sample_rate;
av_log(fc, AV_LOG_TRACE, "mp4a config channels %d obj %d ext obj %d "
- "sample rate %d ext sample rate %d\n", st->codecpar->channels,
+ "sample rate %d ext sample rate %d\n", cfg.channels,
cfg.object_type, cfg.ext_object_type,
cfg.sample_rate, cfg.ext_sample_rate);
if (!(st->codecpar->codec_id = ff_codec_get_id(mp4_audio_types,
diff --git a/libavformat/iss.c b/libavformat/iss.c
index 1653b27408..1a26d7e888 100644
--- a/libavformat/iss.c
+++ b/libavformat/iss.c
@@ -95,19 +95,20 @@ static av_cold int iss_read_header(AVFormatContext *s)
return AVERROR(ENOMEM);
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_ADPCM_IMA_ISS;
+
if (stereo) {
- st->codecpar->channels = 2;
- st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
+ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
} else {
- st->codecpar->channels = 1;
- st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
}
+
st->codecpar->sample_rate = 44100;
if(rate_divisor > 0)
st->codecpar->sample_rate /= rate_divisor;
st->codecpar->bits_per_coded_sample = 4;
- st->codecpar->bit_rate = st->codecpar->channels * st->codecpar->sample_rate
- * st->codecpar->bits_per_coded_sample;
+ st->codecpar->bit_rate = st->codecpar->ch_layout.nb_channels *
+ st->codecpar->sample_rate *
+ st->codecpar->bits_per_coded_sample;
st->codecpar->block_align = iss->packet_size;
avpriv_set_pts_info(st, 32, 1, st->codecpar->sample_rate);

@@ -124,8 +125,8 @@ static int iss_read_packet(AVFormatContext *s, AVPacket *pkt)

pkt->stream_index = 0;
pkt->pts = avio_tell(s->pb) - iss->sample_start_pos;
- if(s->streams[0]->codecpar->channels > 0)
- pkt->pts /= s->streams[0]->codecpar->channels*2;
+ if (s->streams[0]->codecpar->ch_layout.nb_channels > 0)
+ pkt->pts /= s->streams[0]->codecpar->ch_layout.nb_channels * 2;
return 0;
}

diff --git a/libavformat/jvdec.c b/libavformat/jvdec.c
index 7fc3131847..5a5532d3d0 100644
--- a/libavformat/jvdec.c
+++ b/libavformat/jvdec.c
@@ -101,8 +101,7 @@ static int read_header(AVFormatContext *s)
ast->codecpar->codec_id = AV_CODEC_ID_PCM_U8;
ast->codecpar->codec_tag = 0; /* no fourcc */
ast->codecpar->sample_rate = avio_rl16(pb);
- ast->codecpar->channels = 1;
- ast->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+ ast->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;;
avpriv_set_pts_info(ast, 64, 1, ast->codecpar->sample_rate);

avio_skip(pb, 10);
diff --git a/libavformat/lxfdec.c b/libavformat/lxfdec.c
index 285539c22a..876a646710 100644
--- a/libavformat/lxfdec.c
+++ b/libavformat/lxfdec.c
@@ -277,7 +277,8 @@ static int lxf_read_header(AVFormatContext *s)

st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->sample_rate = LXF_SAMPLERATE;
- st->codecpar->channels = lxf->channels;
+ st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ st->codecpar->ch_layout.nb_channels = lxf->channels;

avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
}
diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
index c6e1a190a8..410e8ac6f6 100644
--- a/libavformat/matroskadec.c
+++ b/libavformat/matroskadec.c
@@ -1539,7 +1539,7 @@ static int matroska_parse_flac(AVFormatContext *s,
av_log(s, AV_LOG_WARNING,
"Invalid value of WAVEFORMATEXTENSIBLE_CHANNEL_MASK\n");
} else
- st->codecpar->channel_layout = mask;
+ av_channel_layout_from_mask(&st->codecpar->ch_layout, mask);
}
av_dict_free(&dict);
}
@@ -2031,7 +2031,7 @@ static int matroska_parse_tracks(AVFormatContext *s)
} else if (track->type == MATROSKA_TRACK_TYPE_AUDIO) {
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->sample_rate = track->audio.out_samplerate;
- st->codecpar->channels = track->audio.channels;
+ av_channel_layout_default(&st->codecpar->ch_layout, track->audio.channels);
if (st->codecpar->codec_id != AV_CODEC_ID_AAC)
st->need_parsing = AVSTREAM_PARSE_HEADERS;
if (st->codecpar->codec_id == AV_CODEC_ID_MP3)
diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c
index ab83acfffb..23a56eee03 100644
--- a/libavformat/matroskaenc.c
+++ b/libavformat/matroskaenc.c
@@ -485,9 +485,8 @@ static int put_wv_codecpriv(AVIOContext *pb, AVCodecParameters *par)
static int put_flac_codecpriv(AVFormatContext *s,
AVIOContext *pb, AVCodecParameters *par)
{
- int write_comment = (par->channel_layout &&
- !(par->channel_layout & ~0x3ffffULL) &&
- !ff_flac_is_native_layout(par->channel_layout));
+ int write_comment = (!av_channel_layout_subset(&par->ch_layout, ~0x3ffffULL) &&
+ !ff_flac_is_native_layout(par->ch_layout.u.mask));
int ret = ff_flac_write_header(pb, par->extradata, par->extradata_size,
!write_comment);

@@ -498,11 +497,13 @@ static int put_flac_codecpriv(AVFormatContext *s,
const char *vendor = (s->flags & AVFMT_FLAG_BITEXACT) ?
"Libav" : LIBAVFORMAT_IDENT;
AVDictionary *dict = NULL;
- uint8_t buf[32], *data, *p;
+ uint8_t *data, *p;
+ char *chlstr;
int len;

- snprintf(buf, sizeof(buf), "0x%"PRIx64, par->channel_layout);
- av_dict_set(&dict, "WAVEFORMATEXTENSIBLE_CHANNEL_MASK", buf, 0);
+ chlstr = av_channel_layout_describe(&par->ch_layout);
+ av_dict_set(&dict, "WAVEFORMATEXTENSIBLE_CHANNEL_MASK", chlstr, 0);
+ av_free(chlstr);

len = ff_vorbiscomment_length(dict, vendor);
data = av_malloc(len + 4);
@@ -991,7 +992,7 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv,
put_ebml_string(pb, MATROSKA_ID_CODECID, "A_MS/ACM");

subinfo = start_ebml_master(pb, MATROSKA_ID_TRACKAUDIO, 0);
- put_ebml_uint (pb, MATROSKA_ID_AUDIOCHANNELS , par->channels);
+ put_ebml_uint(pb, MATROSKA_ID_AUDIOCHANNELS, par->ch_layout.nb_channels);

mkv->tracks[i].sample_rate_offset = avio_tell(pb);
put_ebml_float (pb, MATROSKA_ID_AUDIOSAMPLINGFREQ, sample_rate);
diff --git a/libavformat/mm.c b/libavformat/mm.c
index a94d2611a2..0ad0c8b3e5 100644
--- a/libavformat/mm.c
+++ b/libavformat/mm.c
@@ -124,8 +124,7 @@ static int read_header(AVFormatContext *s)
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_tag = 0; /* no fourcc */
st->codecpar->codec_id = AV_CODEC_ID_PCM_U8;
- st->codecpar->channels = 1;
- st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
st->codecpar->sample_rate = 8000;
avpriv_set_pts_info(st, 64, 1, 8000); /* 8000 hz */
}
diff --git a/libavformat/mmf.c b/libavformat/mmf.c
index 454e609e67..110597bb66 100644
--- a/libavformat/mmf.c
+++ b/libavformat/mmf.c
@@ -258,8 +258,7 @@ static int mmf_read_header(AVFormatContext *s)
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_ADPCM_YAMAHA;
st->codecpar->sample_rate = rate;
- st->codecpar->channels = 1;
- st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
st->codecpar->bits_per_coded_sample = 4;
st->codecpar->bit_rate = st->codecpar->sample_rate *
st->codecpar->bits_per_coded_sample;
diff --git a/libavformat/mov.c b/libavformat/mov.c
index bf68fbd46a..c90b5fa108 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -684,6 +684,7 @@ static int mov_read_dac3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
AVStream *st;
enum AVAudioServiceType *ast;
int ac3info, acmod, lfeon, bsmod;
+ uint64_t mask;

if (c->fc->nb_streams < 1)
return 0;
@@ -698,12 +699,15 @@ static int mov_read_dac3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
bsmod = (ac3info >> 14) & 0x7;
acmod = (ac3info >> 11) & 0x7;
lfeon = (ac3info >> 10) & 0x1;
- st->codecpar->channels = ((int[]){2,1,2,3,3,4,4,5})[acmod] + lfeon;
- st->codecpar->channel_layout = avpriv_ac3_channel_layout_tab[acmod];
+
+ mask = avpriv_ac3_channel_layout_tab[acmod];
if (lfeon)
- st->codecpar->channel_layout |= AV_CH_LOW_FREQUENCY;
+ mask |= 1ULL << AV_CH_LOW_FREQUENCY;
+ av_channel_layout_uninit(&st->codecpar->ch_layout);
+ av_channel_layout_from_mask(&st->codecpar->ch_layout, mask);
+
*ast = bsmod;
- if (st->codecpar->channels > 1 && bsmod == 0x7)
+ if (st->codecpar->ch_layout.nb_channels > 1 && bsmod == 0x7)
*ast = AV_AUDIO_SERVICE_TYPE_KARAOKE;

#if FF_API_LAVF_AVCTX
@@ -720,6 +724,7 @@ static int mov_read_dec3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
AVStream *st;
enum AVAudioServiceType *ast;
int eac3info, acmod, lfeon, bsmod;
+ uint64_t mask;

if (c->fc->nb_streams < 1)
return 0;
@@ -738,12 +743,15 @@ static int mov_read_dec3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
bsmod = (eac3info >> 12) & 0x1f;
acmod = (eac3info >> 9) & 0x7;
lfeon = (eac3info >> 8) & 0x1;
- st->codecpar->channel_layout = avpriv_ac3_channel_layout_tab[acmod];
+
+ mask = avpriv_ac3_channel_layout_tab[acmod];
if (lfeon)
- st->codecpar->channel_layout |= AV_CH_LOW_FREQUENCY;
- st->codecpar->channels = av_get_channel_layout_nb_channels(st->codecpar->channel_layout);
+ mask |= 1ULL << AV_CH_LOW_FREQUENCY;
+ av_channel_layout_uninit(&st->codecpar->ch_layout);
+ av_channel_layout_from_mask(&st->codecpar->ch_layout, mask);
+
*ast = bsmod;
- if (st->codecpar->channels > 1 && bsmod == 0x7)
+ if (st->codecpar->ch_layout.nb_channels > 1 && bsmod == 0x7)
*ast = AV_AUDIO_SERVICE_TYPE_KARAOKE;

#if FF_API_LAVF_AVCTX
@@ -1502,13 +1510,17 @@ static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb,
{
int bits_per_sample, flags;
uint16_t version = avio_rb16(pb);
+ int channel_count;

avio_rb16(pb); /* revision level */
avio_rb32(pb); /* vendor */

- st->codecpar->channels = avio_rb16(pb); /* channel count */
+ channel_count = avio_rb16(pb);
+
+ st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ st->codecpar->ch_layout.nb_channels = channel_count;
st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* sample size */
- av_log(c->fc, AV_LOG_TRACE, "audio channels %d\n", st->codecpar->channels);
+ av_log(c->fc, AV_LOG_TRACE, "audio channels %d\n", channel_count);

sc->audio_cid = avio_rb16(pb);
avio_rb16(pb); /* packet size = 0 */
@@ -1526,7 +1538,9 @@ static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb,
} else if (version == 2) {
avio_rb32(pb); /* sizeof struct only */
st->codecpar->sample_rate = av_int2double(avio_rb64(pb));
- st->codecpar->channels = avio_rb32(pb);
+ channel_count = avio_rb32(pb);
+ st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ st->codecpar->ch_layout.nb_channels = channel_count;
avio_rb32(pb); /* always 0x7F000000 */
st->codecpar->bits_per_coded_sample = avio_rb32(pb);

@@ -1567,15 +1581,15 @@ static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb,
/* set values for old format before stsd version 1 appeared */
case AV_CODEC_ID_MACE3:
sc->samples_per_frame = 6;
- sc->bytes_per_frame = 2 * st->codecpar->channels;
+ sc->bytes_per_frame = 2 * st->codecpar->ch_layout.nb_channels;
break;
case AV_CODEC_ID_MACE6:
sc->samples_per_frame = 6;
- sc->bytes_per_frame = 1 * st->codecpar->channels;
+ sc->bytes_per_frame = 1 * st->codecpar->ch_layout.nb_channels;
break;
case AV_CODEC_ID_ADPCM_IMA_QT:
sc->samples_per_frame = 64;
- sc->bytes_per_frame = 34 * st->codecpar->channels;
+ sc->bytes_per_frame = 34 * st->codecpar->ch_layout.nb_channels;
break;
case AV_CODEC_ID_GSM:
sc->samples_per_frame = 160;
@@ -1588,7 +1602,7 @@ static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb,
bits_per_sample = av_get_bits_per_sample(st->codecpar->codec_id);
if (bits_per_sample) {
st->codecpar->bits_per_coded_sample = bits_per_sample;
- sc->sample_size = (bits_per_sample >> 3) * st->codecpar->channels;
+ sc->sample_size = (bits_per_sample >> 3) * st->codecpar->ch_layout.nb_channels;
}
}

@@ -1705,18 +1719,21 @@ static int mov_finalize_stsd_codec(MOVContext *c, AVIOContext *pb,
#endif
/* no ifdef since parameters are always those */
case AV_CODEC_ID_QCELP:
- st->codecpar->channels = 1;
+ av_channel_layout_uninit(&st->codecpar->ch_layout);
+ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
// force sample rate for qcelp when not stored in mov
if (st->codecpar->codec_tag != MKTAG('Q','c','l','p'))
st->codecpar->sample_rate = 8000;
break;
case AV_CODEC_ID_AMR_NB:
- st->codecpar->channels = 1;
+ av_channel_layout_uninit(&st->codecpar->ch_layout);
+ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
/* force sample rate for amr, stsd in 3gp does not store sample rate */
st->codecpar->sample_rate = 8000;
break;
case AV_CODEC_ID_AMR_WB:
- st->codecpar->channels = 1;
+ av_channel_layout_uninit(&st->codecpar->ch_layout);
+ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
st->codecpar->sample_rate = 16000;
break;
case AV_CODEC_ID_MP2:
@@ -1732,7 +1749,12 @@ static int mov_finalize_stsd_codec(MOVContext *c, AVIOContext *pb,
break;
case AV_CODEC_ID_ALAC:
if (st->codecpar->extradata_size == 36) {
- st->codecpar->channels = AV_RB8 (st->codecpar->extradata + 21);
+ int channel_count = AV_RB8(st->codecpar->extradata + 21);
+ if (st->codecpar->ch_layout.nb_channels != channel_count) {
+ av_channel_layout_uninit(&st->codecpar->ch_layout);
+ st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ st->codecpar->ch_layout.nb_channels = channel_count;
+ }
st->codecpar->sample_rate = AV_RB32(st->codecpar->extradata + 32);
}
break;
diff --git a/libavformat/mov_chan.c b/libavformat/mov_chan.c
index 42decb1e81..91bd5275cd 100644
--- a/libavformat/mov_chan.c
+++ b/libavformat/mov_chan.c
@@ -491,7 +491,7 @@ static uint32_t mov_get_channel_label(uint32_t label)
}

uint32_t ff_mov_get_channel_layout_tag(enum AVCodecID codec_id,
- uint64_t channel_layout,
+ AVChannelLayout *ch_layout,
uint32_t *bitmap)
{
int i, j;
@@ -511,7 +511,7 @@ uint32_t ff_mov_get_channel_layout_tag(enum AVCodecID codec_id,
const struct MovChannelLayoutMap *layout_map;

/* get the layout map based on the channel count */
- channels = av_get_channel_layout_nb_channels(channel_layout);
+ channels = ch_layout->nb_channels;
if (channels > 9)
channels = 0;
layout_map = mov_ch_layout_map[channels];
@@ -522,7 +522,8 @@ uint32_t ff_mov_get_channel_layout_tag(enum AVCodecID codec_id,
continue;
for (j = 0; layout_map[j].tag != 0; j++) {
if (layout_map[j].tag == layouts[i] &&
- layout_map[j].layout == channel_layout)
+ (ch_layout->order == AV_CHANNEL_ORDER_NATIVE &&
+ layout_map[j].layout == ch_layout->u.mask))
break;
}
if (layout_map[j].tag)
@@ -532,9 +533,9 @@ uint32_t ff_mov_get_channel_layout_tag(enum AVCodecID codec_id,
}

/* if no tag was found, use channel bitmap as a backup if possible */
- if (tag == 0 && channel_layout > 0 && channel_layout < 0x40000) {
+ if (tag == 0 && av_channel_layout_check(ch_layout) && ch_layout->u.mask < 0x40000) {
tag = MOV_CH_LAYOUT_USE_BITMAP;
- *bitmap = (uint32_t)channel_layout;
+ *bitmap = (uint32_t)ch_layout->u.mask;
} else
*bitmap = 0;

@@ -547,6 +548,7 @@ int ff_mov_read_chan(AVFormatContext *s, AVIOContext *pb, AVStream *st,
int64_t size)
{
uint32_t layout_tag, bitmap, num_descr, label_mask;
+ uint64_t mask;
int i;

if (size < 12)
@@ -585,11 +587,15 @@ int ff_mov_read_chan(AVFormatContext *s, AVIOContext *pb, AVStream *st,
label_mask |= mask_incr;
}
}
- if (layout_tag == 0) {
- if (label_mask)
- st->codecpar->channel_layout = label_mask;
- } else
- st->codecpar->channel_layout = ff_mov_get_channel_layout(layout_tag, bitmap);
+ if (layout_tag == 0)
+ mask = label_mask;
+ else
+ mask = ff_mov_get_channel_layout(layout_tag, bitmap);
+
+ if (mask) {
+ av_channel_layout_uninit(&st->codecpar->ch_layout);
+ av_channel_layout_from_mask(&st->codecpar->ch_layout, mask);
+ }

return 0;
}
diff --git a/libavformat/mov_chan.h b/libavformat/mov_chan.h
index 3fae93961e..cf4aab6376 100644
--- a/libavformat/mov_chan.h
+++ b/libavformat/mov_chan.h
@@ -28,6 +28,8 @@

#include <stdint.h>

+#include "libavutil/channel_layout.h"
+
#include "libavcodec/avcodec.h"
#include "avformat.h"

@@ -50,7 +52,7 @@ uint64_t ff_mov_get_channel_layout(uint32_t tag, uint32_t bitmap);
* @return channel layout tag
*/
uint32_t ff_mov_get_channel_layout_tag(enum AVCodecID codec_id,
- uint64_t channel_layout,
+ AVChannelLayout *ch_layout,
uint32_t *bitmap);

/**
diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index a546fdfead..49d6793cee 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -387,7 +387,7 @@ static int mov_write_chan_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *tra
int64_t pos = avio_tell(pb);

layout_tag = ff_mov_get_channel_layout_tag(track->par->codec_id,
- track->par->channel_layout,
+ &track->par->ch_layout,
&bitmap);
if (!layout_tag) {
av_log(s, AV_LOG_WARNING, "not writing 'chan' tag due to "
@@ -641,7 +641,7 @@ static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *tr
avio_wb32(pb, 0x00010000);
avio_wb32(pb, 72);
avio_wb64(pb, av_double2int(track->par->sample_rate));
- avio_wb32(pb, track->par->channels);
+ avio_wb32(pb, track->par->ch_layout.nb_channels);
avio_wb32(pb, 0x7F000000);
avio_wb32(pb, av_get_bits_per_sample(track->par->codec_id));
avio_wb32(pb, mov_get_lpcm_flags(track->par->codec_id));
@@ -2423,7 +2423,7 @@ static int mov_write_isml_manifest(AVIOContext *pb, MOVMuxContext *mov)
track->par->extradata_size);
param_write_int(pb, "AudioTag", ff_codec_get_tag(ff_codec_wav_tags,
track->par->codec_id));
- param_write_int(pb, "Channels", track->par->channels);
+ param_write_int(pb, "Channels", track->par->ch_layout.nb_channels);
param_write_int(pb, "SamplingRate", track->par->sample_rate);
param_write_int(pb, "BitsPerSample", 16);
param_write_int(pb, "PacketSize", track->par->block_align ?
@@ -3070,7 +3070,7 @@ static void mov_write_uuidprof_tag(AVIOContext *pb, AVFormatContext *s)
avio_wb32(pb, audio_kbitrate);
avio_wb32(pb, audio_kbitrate);
avio_wb32(pb, audio_rate);
- avio_wb32(pb, audio_par->channels);
+ avio_wb32(pb, audio_par->ch_layout.nb_channels);

avio_wb32(pb, 0x34); /* size */
ffio_wfourcc(pb, "VPRF"); /* video */
diff --git a/libavformat/mp3enc.c b/libavformat/mp3enc.c
index d87d7be3f4..21051c298f 100644
--- a/libavformat/mp3enc.c
+++ b/libavformat/mp3enc.c
@@ -161,7 +161,7 @@ static void mp3_write_xing(AVFormatContext *s)
return;
}

- switch (par->channels) {
+ switch (par->ch_layout.nb_channels) {
case 1: channels = MPA_MONO; break;
case 2: channels = MPA_STEREO; break;
default: av_log(s, AV_LOG_WARNING, "Unsupported number of channels, "
diff --git a/libavformat/mpc.c b/libavformat/mpc.c
index 5be50a7c24..a5d30d5564 100644
--- a/libavformat/mpc.c
+++ b/libavformat/mpc.c
@@ -91,8 +91,7 @@ static int mpc_read_header(AVFormatContext *s)
return AVERROR(ENOMEM);
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_MUSEPACK7;
- st->codecpar->channels = 2;
- st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
+ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
st->codecpar->bits_per_coded_sample = 16;

st->codecpar->extradata_size = 16;
diff --git a/libavformat/mpc8.c b/libavformat/mpc8.c
index c4027e5d88..3506ae8d2b 100644
--- a/libavformat/mpc8.c
+++ b/libavformat/mpc8.c
@@ -206,6 +206,7 @@ static int mpc8_read_header(AVFormatContext *s)
AVIOContext *pb = s->pb;
AVStream *st;
int tag = 0;
+ int channels;
int64_t size, pos;

c->header_pos = avio_tell(pb);
@@ -246,7 +247,9 @@ static int mpc8_read_header(AVFormatContext *s)
st->codecpar->extradata = av_mallocz(st->codecpar->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
avio_read(pb, st->codecpar->extradata, st->codecpar->extradata_size);

- st->codecpar->channels = (st->codecpar->extradata[1] >> 4) + 1;
+ channels = (st->codecpar->extradata[1] >> 4) + 1;
+ st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ st->codecpar->ch_layout.nb_channels = channels;
st->codecpar->sample_rate = mpc8_rate[st->codecpar->extradata[0] >> 5];
avpriv_set_pts_info(st, 32, 1152 << (st->codecpar->extradata[1]&3)*2, st->codecpar->sample_rate);
st->start_time = 0;
diff --git a/libavformat/mpegenc.c b/libavformat/mpegenc.c
index 1507e0ee30..bf36ebf01e 100644
--- a/libavformat/mpegenc.c
+++ b/libavformat/mpegenc.c
@@ -365,12 +365,12 @@ static av_cold int mpeg_mux_init(AVFormatContext *ctx)
}
if (j == 4)
goto fail;
- if (st->codecpar->channels > 8)
+ if (st->codecpar->ch_layout.nb_channels > 8)
return -1;
stream->lpcm_header[0] = 0x0c;
- stream->lpcm_header[1] = (st->codecpar->channels - 1) | (j << 4);
+ stream->lpcm_header[1] = (st->codecpar->ch_layout.nb_channels - 1) | (j << 4);
stream->lpcm_header[2] = 0x80;
- stream->lpcm_align = st->codecpar->channels * 2;
+ stream->lpcm_align = st->codecpar->ch_layout.nb_channels * 2;
} else {
stream->id = mpa_id++;
}
diff --git a/libavformat/mvdec.c b/libavformat/mvdec.c
index 52c5355e6a..fa667dcbef 100644
--- a/libavformat/mvdec.c
+++ b/libavformat/mvdec.c
@@ -101,9 +101,7 @@ static int set_channels(AVFormatContext *avctx, AVStream *st, int channels)
av_log(avctx, AV_LOG_ERROR, "Channel count %d invalid.\n", channels);
return AVERROR_INVALIDDATA;
}
- st->codecpar->channels = channels;
- st->codecpar->channel_layout = (st->codecpar->channels == 1) ? AV_CH_LAYOUT_MONO
- : AV_CH_LAYOUT_STEREO;
+ av_channel_layout_default(&st->codecpar->ch_layout, channels);
return 0;
}

@@ -250,7 +248,7 @@ static void read_index(AVIOContext *pb, AVStream *st)
avio_skip(pb, 8);
av_add_index_entry(st, pos, timestamp, size, 0, AVINDEX_KEYFRAME);
if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
- timestamp += size / (st->codecpar->channels * 2);
+ timestamp += size / (st->codecpar->ch_layout.nb_channels * 2);
} else {
timestamp++;
}
@@ -330,7 +328,7 @@ static int mv_read_header(AVFormatContext *avctx)
avio_skip(pb, 8);
av_add_index_entry(ast, pos, timestamp, asize, 0, AVINDEX_KEYFRAME);
av_add_index_entry(vst, pos + asize, i, vsize, 0, AVINDEX_KEYFRAME);
- timestamp += asize / (ast->codecpar->channels * 2);
+ timestamp += asize / (ast->codecpar->ch_layout.nb_channels * 2);
}
} else if (!version && avio_rb16(pb) == 3) {
avio_skip(pb, 4);
@@ -357,7 +355,7 @@ static int mv_read_header(AVFormatContext *avctx)
ast->codecpar->bits_per_coded_sample);
ast->codecpar->codec_id = AV_CODEC_ID_NONE;
}
- if (ast->codecpar->channels <= 0) {
+ if (ast->codecpar->ch_layout.nb_channels <= 0) {
av_log(avctx, AV_LOG_ERROR, "No valid channel count found.\n");
return AVERROR_INVALIDDATA;
}
diff --git a/libavformat/mvi.c b/libavformat/mvi.c
index 187407492f..1b8a9ce79b 100644
--- a/libavformat/mvi.c
+++ b/libavformat/mvi.c
@@ -83,8 +83,7 @@ static int read_header(AVFormatContext *s)
avpriv_set_pts_info(ast, 64, 1, ast->codecpar->sample_rate);
ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
ast->codecpar->codec_id = AV_CODEC_ID_PCM_U8;
- ast->codecpar->channels = 1;
- ast->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+ ast->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
ast->codecpar->bits_per_coded_sample = 8;
ast->codecpar->bit_rate = ast->codecpar->sample_rate * 8;

diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c
index cf4931e731..b9bbacf129 100644
--- a/libavformat/mxfdec.c
+++ b/libavformat/mxfdec.c
@@ -320,15 +320,16 @@ static int mxf_get_d10_aes3_packet(AVIOContext *pb, AVStream *st, AVPacket *pkt,
data_ptr = pkt->data;
end_ptr = pkt->data + length;
buf_ptr = pkt->data + 4; /* skip SMPTE 331M header */
- for (; end_ptr - buf_ptr >= st->codecpar->channels * 4; ) {
- for (i = 0; i < st->codecpar->channels; i++) {
+ for (; end_ptr - buf_ptr >= st->codecpar->ch_layout.nb_channels * 4; ) {
+ for (i = 0; i < st->codecpar->ch_layout.nb_channels; i++) {
uint32_t sample = bytestream_get_le32(&buf_ptr);
if (st->codecpar->bits_per_coded_sample == 24)
bytestream_put_le24(&data_ptr, (sample >> 4) & 0xffffff);
else
bytestream_put_le16(&data_ptr, (sample >> 12) & 0xffff);
}
- buf_ptr += 32 - st->codecpar->channels*4; // always 8 channels stored SMPTE 331M
+ // always 8 channels stored SMPTE 331M
+ buf_ptr += 32 - st->codecpar->ch_layout.nb_channels * 4;
}
av_shrink_packet(pkt, data_ptr - pkt->data);
return 0;
@@ -1609,7 +1610,7 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
container_ul = mxf_get_codec_ul(mxf_sound_essence_container_uls, essence_container_ul);
if (st->codecpar->codec_id == AV_CODEC_ID_NONE)
st->codecpar->codec_id = container_ul->id;
- st->codecpar->channels = descriptor->channels;
+ av_channel_layout_default(&st->codecpar->ch_layout, descriptor->channels);
st->codecpar->bits_per_coded_sample = descriptor->bits_per_sample;

if (descriptor->sample_rate.den > 0) {
@@ -2326,10 +2327,10 @@ static int mxf_set_audio_pts(MXFContext *mxf, AVCodecParameters *par,

pkt->pts = track->sample_count;

- if (par->channels <= 0 || par->channels * bits_per_sample < 8)
+ if (par->ch_layout.nb_channels <= 0 || par->ch_layout.nb_channels * bits_per_sample < 8)
return AVERROR_INVALIDDATA;

- track->sample_count += pkt->size / (par->channels * bits_per_sample / 8);
+ track->sample_count += pkt->size / (par->ch_layout.nb_channels * bits_per_sample / 8);
return 0;
}

diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c
index eb53dbff21..a9376e2ec3 100644
--- a/libavformat/mxfenc.c
+++ b/libavformat/mxfenc.c
@@ -889,7 +889,7 @@ static void mxf_write_generic_sound_common(AVFormatContext *s, AVStream *st, con
avio_wb32(pb, 1);

mxf_write_local_tag(pb, 4, 0x3D07);
- avio_wb32(pb, st->codecpar->channels);
+ avio_wb32(pb, st->codecpar->ch_layout.nb_channels);

mxf_write_local_tag(pb, 4, 0x3D01);
avio_wb32(pb, av_get_bits_per_sample(st->codecpar->codec_id));
@@ -1654,10 +1654,10 @@ static void mxf_write_d10_audio_packet(AVFormatContext *s, AVStream *st, AVPacke

avio_w8(pb, (frame_size == 1920 ? 0 : (mxf->edit_units_count-1) % 5 + 1));
avio_wl16(pb, frame_size);
- avio_w8(pb, (1<<st->codecpar->channels)-1);
+ avio_w8(pb, (1 << st->codecpar->ch_layout.nb_channels)-1);

while (samples < end) {
- for (i = 0; i < st->codecpar->channels; i++) {
+ for (i = 0; i < st->codecpar->ch_layout.nb_channels; i++) {
uint32_t sample;
if (st->codecpar->codec_id == AV_CODEC_ID_PCM_S24LE) {
sample = AV_RL24(samples)<< 4;
diff --git a/libavformat/mxg.c b/libavformat/mxg.c
index 245afb40ef..3d28932cc8 100644
--- a/libavformat/mxg.c
+++ b/libavformat/mxg.c
@@ -57,8 +57,7 @@ static int mxg_read_header(AVFormatContext *s)
return AVERROR(ENOMEM);
audio_st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
audio_st->codecpar->codec_id = AV_CODEC_ID_PCM_ALAW;
- audio_st->codecpar->channels = 1;
- audio_st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+ audio_st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
audio_st->codecpar->sample_rate = 8000;
audio_st->codecpar->bits_per_coded_sample = 8;
audio_st->codecpar->block_align = 1;
diff --git a/libavformat/nsvdec.c b/libavformat/nsvdec.c
index 924c8694b1..2fc901a847 100644
--- a/libavformat/nsvdec.c
+++ b/libavformat/nsvdec.c
@@ -611,7 +611,7 @@ null_chunk_retry:
st[NSV_ST_AUDIO]->codecpar->codec_id = AV_CODEC_ID_PCM_U8;
samplerate /= 4;/* UGH ??? XXX */
channels = 1;
- st[NSV_ST_AUDIO]->codecpar->channels = channels;
+ st[NSV_ST_AUDIO]->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
st[NSV_ST_AUDIO]->codecpar->sample_rate = samplerate;
av_log(s, AV_LOG_TRACE, "NSV RAWAUDIO: bps %"PRIu8", nchan %"PRIu8", srate %"PRIu16"\n",
bps, channels, samplerate);
diff --git a/libavformat/nutdec.c b/libavformat/nutdec.c
index 55c21714ce..005194b114 100644
--- a/libavformat/nutdec.c
+++ b/libavformat/nutdec.c
@@ -407,7 +407,7 @@ static int decode_stream_header(NUTContext *nut)
} else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
GET_V(st->codecpar->sample_rate, tmp > 0);
ffio_read_varlen(bc); // samplerate_den
- GET_V(st->codecpar->channels, tmp > 0);
+ GET_V(st->codecpar->ch_layout.nb_channels, tmp > 0);
}
if (skip_reserved(bc, end) || ffio_get_checksum(bc)) {
av_log(s, AV_LOG_ERROR,
diff --git a/libavformat/nutenc.c b/libavformat/nutenc.c
index 57179bb885..08ff161087 100644
--- a/libavformat/nutenc.c
+++ b/libavformat/nutenc.c
@@ -449,7 +449,7 @@ static int write_streamheader(AVFormatContext *avctx, AVIOContext *bc,
case AVMEDIA_TYPE_AUDIO:
ff_put_v(bc, par->sample_rate);
ff_put_v(bc, 1);
- ff_put_v(bc, par->channels);
+ ff_put_v(bc, par->ch_layout.nb_channels);
break;
case AVMEDIA_TYPE_VIDEO:
ff_put_v(bc, par->width);
diff --git a/libavformat/nuv.c b/libavformat/nuv.c
index 492f68f493..efbd60973c 100644
--- a/libavformat/nuv.c
+++ b/libavformat/nuv.c
@@ -118,8 +118,8 @@ static int get_codec_data(AVIOContext *pb, AVStream *vst,
ast->codecpar->codec_tag = avio_rl32(pb);
ast->codecpar->sample_rate = avio_rl32(pb);
ast->codecpar->bits_per_coded_sample = avio_rl32(pb);
- ast->codecpar->channels = avio_rl32(pb);
- ast->codecpar->channel_layout = 0;
+ ast->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ ast->codecpar->ch_layout.nb_channels = avio_rl32(pb);

id = ff_wav_codec_get_id(ast->codecpar->codec_tag,
ast->codecpar->bits_per_coded_sample);
@@ -222,8 +222,7 @@ static int nuv_header(AVFormatContext *s)

ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
ast->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
- ast->codecpar->channels = 2;
- ast->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
+ ast->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
ast->codecpar->sample_rate = 44100;
ast->codecpar->bit_rate = 2 * 2 * 44100 * 8;
ast->codecpar->block_align = 2 * 2;
diff --git a/libavformat/oggparsecelt.c b/libavformat/oggparsecelt.c
index 291a6b5aab..6226192696 100644
--- a/libavformat/oggparsecelt.c
+++ b/libavformat/oggparsecelt.c
@@ -66,7 +66,8 @@ static int celt_header(AVFormatContext *s, int idx)
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_CELT;
st->codecpar->sample_rate = sample_rate;
- st->codecpar->channels = nb_channels;
+ st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ st->codecpar->ch_layout.nb_channels = nb_channels;
st->codecpar->extradata = extradata;
st->codecpar->extradata_size = 2 * sizeof(uint32_t);
if (sample_rate)
diff --git a/libavformat/oggparseogm.c b/libavformat/oggparseogm.c
index 62784650b6..8c07540382 100644
--- a/libavformat/oggparseogm.c
+++ b/libavformat/oggparseogm.c
@@ -90,7 +90,8 @@ ogm_header(AVFormatContext *s, int idx)
st->codecpar->height = bytestream2_get_le32(&p);
avpriv_set_pts_info(st, 64, time_unit, spu * 10000000);
} else {
- st->codecpar->channels = bytestream2_get_le16(&p);
+ st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ st->codecpar->ch_layout.nb_channels = bytestream2_get_le16(&p);
bytestream2_skip(&p, 2); /* block_align */
st->codecpar->bit_rate = bytestream2_get_le32(&p) * 8;
st->codecpar->sample_rate = spu * 10000000 / time_unit;
@@ -130,7 +131,8 @@ ogm_dshow_header(AVFormatContext *s, int idx)
} else if(t == 0x05589f81){
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = ff_codec_get_id(ff_codec_wav_tags, AV_RL16(p + 124));
- st->codecpar->channels = AV_RL16(p + 126);
+ st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ st->codecpar->ch_layout.nb_channels = AV_RL16(p + 126);
st->codecpar->sample_rate = AV_RL32(p + 128);
st->codecpar->bit_rate = AV_RL32(p + 132) * 8;
}
diff --git a/libavformat/oggparseopus.c b/libavformat/oggparseopus.c
index f523143cab..147d35286d 100644
--- a/libavformat/oggparseopus.c
+++ b/libavformat/oggparseopus.c
@@ -54,7 +54,8 @@ static int opus_header(AVFormatContext *avf, int idx)

st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_OPUS;
- st->codecpar->channels = AV_RL8(packet + 9);
+ st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ st->codecpar->ch_layout.nb_channels = AV_RL8(packet + 9);
priv->pre_skip = AV_RL16(packet + 10);

st->codecpar->initial_padding = priv->pre_skip;
diff --git a/libavformat/oggparsespeex.c b/libavformat/oggparsespeex.c
index 2430cd742b..6e998a77c4 100644
--- a/libavformat/oggparsespeex.c
+++ b/libavformat/oggparsespeex.c
@@ -59,17 +59,17 @@ static int speex_header(AVFormatContext *s, int idx) {

if (spxp->seq == 0) {
int frames_per_packet;
+ int channels;
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_SPEEX;

st->codecpar->sample_rate = AV_RL32(p + 36);
- st->codecpar->channels = AV_RL32(p + 48);
- if (st->codecpar->channels < 1 || st->codecpar->channels > 2) {
+ channels = AV_RL32(p + 48);
+ if (channels < 1 || channels > 2) {
av_log(s, AV_LOG_ERROR, "invalid channel count. Speex must be mono or stereo.\n");
return AVERROR_INVALIDDATA;
}
- st->codecpar->channel_layout = st->codecpar->channels == 1 ? AV_CH_LAYOUT_MONO :
- AV_CH_LAYOUT_STEREO;
+ av_channel_layout_default(&st->codecpar->ch_layout, channels);

spxp->packet_size = AV_RL32(p + 56);
frames_per_packet = AV_RL32(p + 64);
diff --git a/libavformat/oggparsevorbis.c b/libavformat/oggparsevorbis.c
index 95fe082949..09d201480c 100644
--- a/libavformat/oggparsevorbis.c
+++ b/libavformat/oggparsevorbis.c
@@ -296,7 +296,8 @@ static int vorbis_header(AVFormatContext *s, int idx)
if (bytestream_get_le32(&p) != 0) /* vorbis_version */
return AVERROR_INVALIDDATA;

- st->codecpar->channels = bytestream_get_byte(&p);
+ st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ st->codecpar->ch_layout.nb_channels = bytestream_get_byte(&p);
srate = bytestream_get_le32(&p);
p += 4; // skip maximum bitrate
st->codecpar->bit_rate = bytestream_get_le32(&p); // nominal bitrate
diff --git a/libavformat/oma.c b/libavformat/oma.c
index 27b598857c..ec1544c530 100644
--- a/libavformat/oma.c
+++ b/libavformat/oma.c
@@ -34,15 +34,12 @@ const AVCodecTag ff_oma_codec_tags[] = {
};

/** map ATRAC-X channel id to internal channel layout */
-const uint64_t ff_oma_chid_to_native_layout[7] = {
- AV_CH_LAYOUT_MONO,
- AV_CH_LAYOUT_STEREO,
- AV_CH_LAYOUT_SURROUND,
- AV_CH_LAYOUT_4POINT0,
- AV_CH_LAYOUT_5POINT1_BACK,
- AV_CH_LAYOUT_6POINT1_BACK,
- AV_CH_LAYOUT_7POINT1
+const AVChannelLayout ff_oma_chid_to_native_layout[7] = {
+ AV_CHANNEL_LAYOUT_MONO,
+ AV_CHANNEL_LAYOUT_STEREO,
+ AV_CHANNEL_LAYOUT_SURROUND,
+ AV_CHANNEL_LAYOUT_4POINT0,
+ AV_CHANNEL_LAYOUT_5POINT1_BACK,
+ AV_CHANNEL_LAYOUT_6POINT1_BACK,
+ AV_CHANNEL_LAYOUT_7POINT1
};
-
-/** map ATRAC-X channel id to total number of channels */
-const int ff_oma_chid_to_num_channels[7] = {1, 2, 3, 4, 6, 7, 8};
diff --git a/libavformat/oma.h b/libavformat/oma.h
index 9a35da2623..4f1cd7a7d7 100644
--- a/libavformat/oma.h
+++ b/libavformat/oma.h
@@ -23,6 +23,8 @@

#include <stdint.h>

+#include "libavutil/channel_layout.h"
+
#include "internal.h"

#define EA3_HEADER_SIZE 96
@@ -41,7 +43,6 @@ extern const uint16_t ff_oma_srate_tab[8];

extern const AVCodecTag ff_oma_codec_tags[];

-extern const uint64_t ff_oma_chid_to_native_layout[7];
-extern const int ff_oma_chid_to_num_channels[7];
+extern const AVChannelLayout ff_oma_chid_to_native_layout[7];

#endif /* AVFORMAT_OMA_H */
diff --git a/libavformat/omadec.c b/libavformat/omadec.c
index e29b93eeb9..92e3fc92a1 100644
--- a/libavformat/omadec.c
+++ b/libavformat/omadec.c
@@ -366,8 +366,7 @@ static int oma_read_header(AVFormatContext *s)
/* get stereo coding mode, 1 for joint-stereo */
jsflag = (codec_params >> 17) & 1;

- st->codecpar->channels = 2;
- st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
+ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
st->codecpar->sample_rate = samplerate;
st->codecpar->bit_rate = st->codecpar->sample_rate * framesize * 8 / 1024;

@@ -395,8 +394,8 @@ static int oma_read_header(AVFormatContext *s)
"Invalid ATRAC-X channel id: %"PRIu32"\n", channel_id);
return AVERROR_INVALIDDATA;
}
- st->codecpar->channel_layout = ff_oma_chid_to_native_layout[channel_id - 1];
- st->codecpar->channels = ff_oma_chid_to_num_channels[channel_id - 1];
+ av_channel_layout_copy(&st->codecpar->ch_layout,
+ &ff_oma_chid_to_native_layout[channel_id - 1]);
framesize = ((codec_params & 0x3FF) * 8) + 8;
samplerate = ff_oma_srate_tab[(codec_params >> 13) & 7] * 100;
if (!samplerate) {
@@ -413,8 +412,7 @@ static int oma_read_header(AVFormatContext *s)
break;
case OMA_CODECID_LPCM:
/* PCM 44.1 kHz 16 bit stereo big-endian */
- st->codecpar->channels = 2;
- st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
+ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
st->codecpar->sample_rate = 44100;
framesize = 1024;
/* bit rate = sample rate x PCM block align (= 4) x 8 */
diff --git a/libavformat/omaenc.c b/libavformat/omaenc.c
index 793d0fd345..a6fd93c472 100644
--- a/libavformat/omaenc.c
+++ b/libavformat/omaenc.c
@@ -60,7 +60,7 @@ static av_cold int oma_write_header(AVFormatContext *s)

switch (par->codec_tag) {
case OMA_CODECID_ATRAC3:
- if (par->channels != 2) {
+ if (par->ch_layout.nb_channels != 2) {
av_log(s, AV_LOG_ERROR, "ATRAC3 in OMA is only supported with 2 channels");
return AVERROR(EINVAL);
}
@@ -80,7 +80,7 @@ static av_cold int oma_write_header(AVFormatContext *s)
case OMA_CODECID_ATRAC3P:
avio_wb32(s->pb, (OMA_CODECID_ATRAC3P << 24) |
(srate_index << 13) |
- (par->channels << 10) |
+ (par->ch_layout.nb_channels << 10) |
(par->block_align/8 - 1));
break;
default:
diff --git a/libavformat/paf.c b/libavformat/paf.c
index 81a45cecee..24720b02fb 100644
--- a/libavformat/paf.c
+++ b/libavformat/paf.c
@@ -123,8 +123,7 @@ static int read_header(AVFormatContext *s)
ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
ast->codecpar->codec_tag = 0;
ast->codecpar->codec_id = AV_CODEC_ID_PAF_AUDIO;
- ast->codecpar->channels = 2;
- ast->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
+ ast->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
ast->codecpar->sample_rate = 22050;
avpriv_set_pts_info(ast, 64, 1, 22050);

diff --git a/libavformat/pcm.c b/libavformat/pcm.c
index c506edd777..ba2e046537 100644
--- a/libavformat/pcm.c
+++ b/libavformat/pcm.c
@@ -34,7 +34,7 @@ int ff_pcm_read_seek(AVFormatContext *s,
st = s->streams[0];

block_align = st->codecpar->block_align ? st->codecpar->block_align :
- (av_get_bits_per_sample(st->codecpar->codec_id) * st->codecpar->channels) >> 3;
+ (av_get_bits_per_sample(st->codecpar->codec_id) * st->codecpar->ch_layout.nb_channels) >> 3;
byte_rate = st->codecpar->bit_rate ? st->codecpar->bit_rate >> 3 :
block_align * st->codecpar->sample_rate;

diff --git a/libavformat/pcmdec.c b/libavformat/pcmdec.c
index 69789b62e8..1a11031311 100644
--- a/libavformat/pcmdec.c
+++ b/libavformat/pcmdec.c
@@ -46,7 +46,8 @@ static int pcm_read_header(AVFormatContext *s)
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = s->iformat->raw_codec_id;
st->codecpar->sample_rate = s1->sample_rate;
- st->codecpar->channels = s1->channels;
+ st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ st->codecpar->ch_layout.nb_channels = s1->channels;

st->codecpar->bits_per_coded_sample =
av_get_bits_per_sample(st->codecpar->codec_id);
@@ -54,7 +55,7 @@ static int pcm_read_header(AVFormatContext *s)
assert(st->codecpar->bits_per_coded_sample > 0);

st->codecpar->block_align =
- st->codecpar->bits_per_coded_sample * st->codecpar->channels / 8;
+ st->codecpar->bits_per_coded_sample * s1->channels / 8;

avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
return 0;
@@ -80,7 +81,7 @@ static int pcm_read_packet(AVFormatContext *s, AVPacket *pkt)
}

pkt->dts=
- pkt->pts= pkt->pos*8 / (bps * s->streams[0]->codecpar->channels);
+ pkt->pts= pkt->pos*8 / (bps * s->streams[0]->codecpar->ch_layout.nb_channels);

return ret;
}
diff --git a/libavformat/pmpdec.c b/libavformat/pmpdec.c
index e2709bbbe3..f876861120 100644
--- a/libavformat/pmpdec.c
+++ b/libavformat/pmpdec.c
@@ -97,7 +97,8 @@ static int pmp_header(AVFormatContext *s)
return AVERROR(ENOMEM);
ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
ast->codecpar->codec_id = audio_codec_id;
- ast->codecpar->channels = channels;
+ ast->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ ast->codecpar->ch_layout.nb_channels = channels;
ast->codecpar->sample_rate = srate;
avpriv_set_pts_info(ast, 32, 1, srate);
}
diff --git a/libavformat/psxstr.c b/libavformat/psxstr.c
index 6897f26790..182910a1c1 100644
--- a/libavformat/psxstr.c
+++ b/libavformat/psxstr.c
@@ -222,18 +222,12 @@ static int str_read_packet(AVFormatContext *s,
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_ADPCM_XA;
st->codecpar->codec_tag = 0; /* no fourcc */
- if (fmt & 1) {
- st->codecpar->channels = 2;
- st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
- } else {
- st->codecpar->channels = 1;
- st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
- }
+ av_channel_layout_default(&st->codecpar->ch_layout, (fmt & 1) + 1);
st->codecpar->sample_rate = (fmt&4)?18900:37800;
// st->codecpar->bit_rate = 0; //FIXME;
st->codecpar->block_align = 128;

- avpriv_set_pts_info(st, 64, 18 * 224 / st->codecpar->channels,
+ avpriv_set_pts_info(st, 64, 18 * 224 / st->codecpar->ch_layout.nb_channels,
st->codecpar->sample_rate);
st->start_time = 0;
}
diff --git a/libavformat/qcp.c b/libavformat/qcp.c
index b262d609df..6b384b14a8 100644
--- a/libavformat/qcp.c
+++ b/libavformat/qcp.c
@@ -96,8 +96,7 @@ static int qcp_read_header(AVFormatContext *s)
avio_skip(pb, 4 + 8 + 4 + 1 + 1); // filesize + "QLCMfmt " + chunk-size + major-version + minor-version

st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
- st->codecpar->channels = 1;
- st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
avio_read(pb, buf, 16);
if (is_qcelp_13k_guid(buf)) {
st->codecpar->codec_id = AV_CODEC_ID_QCELP;
diff --git a/libavformat/r3d.c b/libavformat/r3d.c
index 9369cdd7df..d03dc2a27c 100644
--- a/libavformat/r3d.c
+++ b/libavformat/r3d.c
@@ -284,7 +284,8 @@ static int r3d_read_reda(AVFormatContext *s, AVPacket *pkt, Atom *atom)
return AVERROR(ENOMEM);
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_PCM_S32BE;
- st->codecpar->channels = r3d->audio_channels;
+ st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ st->codecpar->ch_layout.nb_channels = r3d->audio_channels;
avpriv_set_pts_info(st, 32, 1, s->streams[0]->time_base.den);
} else {
st = s->streams[1];
diff --git a/libavformat/riffdec.c b/libavformat/riffdec.c
index db83b3205a..00acc9237f 100644
--- a/libavformat/riffdec.c
+++ b/libavformat/riffdec.c
@@ -58,11 +58,14 @@ static void parse_waveformatex(AVIOContext *pb, AVCodecParameters *par)
{
ff_asf_guid subformat;
int bps;
+ uint64_t mask;

bps = avio_rl16(pb);
if (bps)
par->bits_per_coded_sample = bps;
- par->channel_layout = avio_rl32(pb); /* dwChannelMask */
+
+ mask = avio_rl32(pb); /* dwChannelMask */
+ av_channel_layout_from_mask(&par->ch_layout, mask);

ff_get_guid(pb, &subformat);
if (!memcmp(subformat + 4,
@@ -82,7 +85,7 @@ static void parse_waveformatex(AVIOContext *pb, AVCodecParameters *par)
int ff_get_wav_header(AVFormatContext *s, AVIOContext *pb,
AVCodecParameters *par, int size)
{
- int id;
+ int id, channels;
uint64_t bitrate;

if (size < 14)
@@ -90,7 +93,7 @@ int ff_get_wav_header(AVFormatContext *s, AVIOContext *pb,

id = avio_rl16(pb);
par->codec_type = AVMEDIA_TYPE_AUDIO;
- par->channels = avio_rl16(pb);
+ channels = avio_rl16(pb);
par->sample_rate = avio_rl32(pb);
bitrate = avio_rl32(pb) * 8;
par->block_align = avio_rl16(pb);
@@ -153,13 +156,15 @@ int ff_get_wav_header(AVFormatContext *s, AVIOContext *pb,
if (par->codec_id == AV_CODEC_ID_AAC_LATM) {
/* Channels and sample_rate values are those prior to applying SBR
* and/or PS. */
- par->channels = 0;
+ channels = 0;
par->sample_rate = 0;
}
/* override bits_per_coded_sample for G.726 */
if (par->codec_id == AV_CODEC_ID_ADPCM_G726)
par->bits_per_coded_sample = par->bit_rate / par->sample_rate;

+ av_channel_layout_default(&par->ch_layout, channels);
+
return 0;
}

diff --git a/libavformat/riffenc.c b/libavformat/riffenc.c
index e6b8411529..b1bf2b8d9b 100644
--- a/libavformat/riffenc.c
+++ b/libavformat/riffenc.c
@@ -65,7 +65,8 @@ int ff_put_wav_header(AVFormatContext *s, AVIOContext *pb,
* for indicating packet duration. */
frame_size = av_get_audio_frame_duration2(par, par->block_align);

- waveformatextensible = (par->channels > 2 && par->channel_layout) ||
+ waveformatextensible = (av_channel_layout_check(&par->ch_layout) &&
+ par->ch_layout.nb_channels > 2) ||
par->sample_rate > 48000 ||
av_get_bits_per_sample(par->codec_id) > 16;

@@ -74,7 +75,7 @@ int ff_put_wav_header(AVFormatContext *s, AVIOContext *pb,
else
avio_wl16(pb, par->codec_tag);

- avio_wl16(pb, par->channels);
+ avio_wl16(pb, par->ch_layout.nb_channels);
avio_wl32(pb, par->sample_rate);
if (par->codec_id == AV_CODEC_ID_MP2 ||
par->codec_id == AV_CODEC_ID_MP3 ||
@@ -104,7 +105,7 @@ int ff_put_wav_header(AVFormatContext *s, AVIOContext *pb,
} else if (par->block_align != 0) { /* specified by the codec */
blkalign = par->block_align;
} else
- blkalign = bps * par->channels / av_gcd(8, bps);
+ blkalign = bps * par->ch_layout.nb_channels / av_gcd(8, bps);
if (par->codec_id == AV_CODEC_ID_PCM_U8 ||
par->codec_id == AV_CODEC_ID_PCM_S24LE ||
par->codec_id == AV_CODEC_ID_PCM_S32LE ||
@@ -132,7 +133,7 @@ int ff_put_wav_header(AVFormatContext *s, AVIOContext *pb,
/* dwHeadBitrate */
bytestream_put_le32(&riff_extradata, par->bit_rate);
/* fwHeadMode */
- bytestream_put_le16(&riff_extradata, par->channels == 2 ? 1 : 8);
+ bytestream_put_le16(&riff_extradata, par->ch_layout.nb_channels == 2 ? 1 : 8);
/* fwHeadModeExt */
bytestream_put_le16(&riff_extradata, 0);
/* wHeadEmphasis */
@@ -161,7 +162,7 @@ int ff_put_wav_header(AVFormatContext *s, AVIOContext *pb,
/* ValidBitsPerSample || SamplesPerBlock || Reserved */
avio_wl16(pb, bps);
/* dwChannelMask */
- avio_wl32(pb, par->channel_layout);
+ avio_wl32(pb, par->ch_layout.u.mask);
/* GUID + next 3 */
avio_wl32(pb, par->codec_tag);
avio_wl32(pb, 0x00100000);
diff --git a/libavformat/rl2.c b/libavformat/rl2.c
index 0e8d346a37..287e9c7c9e 100644
--- a/libavformat/rl2.c
+++ b/libavformat/rl2.c
@@ -151,12 +151,13 @@ static av_cold int rl2_read_header(AVFormatContext *s)
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_PCM_U8;
st->codecpar->codec_tag = 1;
- st->codecpar->channels = channels;
+ st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ st->codecpar->ch_layout.nb_channels = channels;
st->codecpar->bits_per_coded_sample = 8;
st->codecpar->sample_rate = rate;
- st->codecpar->bit_rate = st->codecpar->channels * st->codecpar->sample_rate *
+ st->codecpar->bit_rate = channels * st->codecpar->sample_rate *
st->codecpar->bits_per_coded_sample;
- st->codecpar->block_align = st->codecpar->channels *
+ st->codecpar->block_align = channels *
st->codecpar->bits_per_coded_sample / 8;
avpriv_set_pts_info(st,32,1,rate);
}
diff --git a/libavformat/rmdec.c b/libavformat/rmdec.c
index 2e93f1d4e8..546194c96b 100644
--- a/libavformat/rmdec.c
+++ b/libavformat/rmdec.c
@@ -143,8 +143,7 @@ static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb,
if ((startpos + header_size) > avio_tell(pb))
avio_skip(pb, header_size + startpos - avio_tell(pb));
st->codecpar->sample_rate = 8000;
- st->codecpar->channels = 1;
- st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_RA_144;
ast->deint_id = DEINT_ID_INT0;
@@ -171,7 +170,8 @@ static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb,
}
st->codecpar->sample_rate = avio_rb16(pb);
avio_rb32(pb);
- st->codecpar->channels = avio_rb16(pb);
+ st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ st->codecpar->ch_layout.nb_channels = avio_rb16(pb);
if (version == 5) {
ast->deint_id = avio_rl32(pb);
avio_read(pb, buf, 4);
diff --git a/libavformat/rmenc.c b/libavformat/rmenc.c
index 6cbe700219..dc8bb11edd 100644
--- a/libavformat/rmenc.c
+++ b/libavformat/rmenc.c
@@ -230,7 +230,7 @@ static int rv10_write_header(AVFormatContext *ctx,
avio_wb32(s, 0); /* unknown */
avio_wb16(s, stream->par->sample_rate); /* sample rate */
avio_wb32(s, 0x10); /* unknown */
- avio_wb16(s, stream->par->channels);
+ avio_wb16(s, stream->par->ch_layout.nb_channels);
put_str8(s, "Int0"); /* codec name */
if (stream->par->codec_tag) {
avio_w8(s, 4); /* tag length */
diff --git a/libavformat/rpl.c b/libavformat/rpl.c
index 6f6119c685..f9eba14915 100644
--- a/libavformat/rpl.c
+++ b/libavformat/rpl.c
@@ -182,14 +182,18 @@ static int rpl_read_header(AVFormatContext *s)
// samples, though. This code will ignore additional tracks.
audio_format = read_line_and_int(pb, &error); // audio format ID
if (audio_format) {
+ int channels;
ast = avformat_new_stream(s, NULL);
if (!ast)
return AVERROR(ENOMEM);
ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
ast->codecpar->codec_tag = audio_format;
ast->codecpar->sample_rate = read_line_and_int(pb, &error); // audio bitrate
- ast->codecpar->channels = read_line_and_int(pb, &error); // number of audio channels
+ channels = read_line_and_int(pb, &error); // number of audio channels
ast->codecpar->bits_per_coded_sample = read_line_and_int(pb, &error); // audio bits per sample
+ ast->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ ast->codecpar->ch_layout.nb_channels = channels;
+
// At least one sample uses 0 for ADPCM, which is really 4 bits
// per sample.
if (ast->codecpar->bits_per_coded_sample == 0)
@@ -197,7 +201,7 @@ static int rpl_read_header(AVFormatContext *s)

ast->codecpar->bit_rate = ast->codecpar->sample_rate *
ast->codecpar->bits_per_coded_sample *
- ast->codecpar->channels;
+ channels;

ast->codecpar->codec_id = AV_CODEC_ID_NONE;
switch (audio_format) {
diff --git a/libavformat/rsodec.c b/libavformat/rsodec.c
index 6f352af96c..9f6d1c180a 100644
--- a/libavformat/rsodec.c
+++ b/libavformat/rsodec.c
@@ -62,8 +62,7 @@ static int rso_read_header(AVFormatContext *s)
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_tag = id;
st->codecpar->codec_id = codec;
- st->codecpar->channels = 1;
- st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
st->codecpar->sample_rate = rate;

avpriv_set_pts_info(st, 64, 1, rate);
diff --git a/libavformat/rsoenc.c b/libavformat/rsoenc.c
index f9dd419c4c..08e205fe67 100644
--- a/libavformat/rsoenc.c
+++ b/libavformat/rsoenc.c
@@ -33,7 +33,7 @@ static int rso_write_header(AVFormatContext *s)
if (!par->codec_tag)
return AVERROR_INVALIDDATA;

- if (par->channels != 1) {
+ if (par->ch_layout.nb_channels != 1) {
av_log(s, AV_LOG_ERROR, "RSO only supports mono\n");
return AVERROR_INVALIDDATA;
}
diff --git a/libavformat/rtp.c b/libavformat/rtp.c
index 5eb92e4df0..e914a6d5e3 100644
--- a/libavformat/rtp.c
+++ b/libavformat/rtp.c
@@ -76,8 +76,10 @@ int ff_rtp_get_codec_info(AVCodecParameters *par, int payload_type)
if (rtp_payload_types[i].codec_id != AV_CODEC_ID_NONE) {
par->codec_type = rtp_payload_types[i].codec_type;
par->codec_id = rtp_payload_types[i].codec_id;
- if (rtp_payload_types[i].audio_channels > 0)
- par->channels = rtp_payload_types[i].audio_channels;
+ if (rtp_payload_types[i].audio_channels > 0) {
+ par->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ par->ch_layout.nb_channels = rtp_payload_types[i].audio_channels;
+ }
if (rtp_payload_types[i].clock_rate > 0)
par->sample_rate = rtp_payload_types[i].clock_rate;
return 0;
@@ -110,13 +112,13 @@ int ff_rtp_get_payload_type(AVFormatContext *fmt,
/* G722 has 8000 as nominal rate even if the sample rate is 16000,
* see section 4.5.2 in RFC 3551. */
if (par->codec_id == AV_CODEC_ID_ADPCM_G722 &&
- par->sample_rate == 16000 && par->channels == 1)
+ par->sample_rate == 16000 && par->ch_layout.nb_channels == 1)
return rtp_payload_types[i].pt;
if (par->codec_type == AVMEDIA_TYPE_AUDIO &&
((rtp_payload_types[i].clock_rate > 0 &&
par->sample_rate != rtp_payload_types[i].clock_rate) ||
(rtp_payload_types[i].audio_channels > 0 &&
- par->channels != rtp_payload_types[i].audio_channels)))
+ par->ch_layout.nb_channels != rtp_payload_types[i].audio_channels)))
continue;
return rtp_payload_types[i].pt;
}
diff --git a/libavformat/rtpdec_amr.c b/libavformat/rtpdec_amr.c
index baf4de9918..54f2a0dc79 100644
--- a/libavformat/rtpdec_amr.c
+++ b/libavformat/rtpdec_amr.c
@@ -64,11 +64,10 @@ static int amr_handle_packet(AVFormatContext *ctx, PayloadContext *data,
return AVERROR_INVALIDDATA;
}

- if (st->codecpar->channels != 1) {
+ if (st->codecpar->ch_layout.nb_channels != 1) {
av_log(ctx, AV_LOG_ERROR, "Only mono AMR is supported\n");
return AVERROR_INVALIDDATA;
}
- st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;

/* The AMR RTP packet consists of one header byte, followed
* by one TOC byte for each AMR frame in the packet, followed
diff --git a/libavformat/rtpenc.c b/libavformat/rtpenc.c
index 28c309ea18..1968c7ef32 100644
--- a/libavformat/rtpenc.c
+++ b/libavformat/rtpenc.c
@@ -206,7 +206,7 @@ static int rtp_write_header(AVFormatContext *s1)
avpriv_set_pts_info(st, 32, 1, 8000);
break;
case AV_CODEC_ID_OPUS:
- if (st->codecpar->channels > 2) {
+ if (st->codecpar->ch_layout.nb_channels > 2) {
av_log(s1, AV_LOG_ERROR, "Multistream opus not supported in RTP\n");
goto fail;
}
@@ -234,7 +234,7 @@ static int rtp_write_header(AVFormatContext *s1)
av_log(s1, AV_LOG_ERROR, "RTP max payload size too small for AMR\n");
goto fail;
}
- if (st->codecpar->channels != 1) {
+ if (st->codecpar->ch_layout.nb_channels != 1) {
av_log(s1, AV_LOG_ERROR, "Only mono is supported\n");
goto fail;
}
@@ -511,21 +511,21 @@ static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt)
case AV_CODEC_ID_PCM_ALAW:
case AV_CODEC_ID_PCM_U8:
case AV_CODEC_ID_PCM_S8:
- return rtp_send_samples(s1, pkt->data, size, 8 * st->codecpar->channels);
+ return rtp_send_samples(s1, pkt->data, size, 8 * st->codecpar->ch_layout.nb_channels);
case AV_CODEC_ID_PCM_U16BE:
case AV_CODEC_ID_PCM_U16LE:
case AV_CODEC_ID_PCM_S16BE:
case AV_CODEC_ID_PCM_S16LE:
- return rtp_send_samples(s1, pkt->data, size, 16 * st->codecpar->channels);
+ return rtp_send_samples(s1, pkt->data, size, 16 * st->codecpar->ch_layout.nb_channels);
case AV_CODEC_ID_ADPCM_G722:
/* The actual sample size is half a byte per sample, but since the
* stream clock rate is 8000 Hz while the sample rate is 16000 Hz,
* the correct parameter for send_samples_bits is 8 bits per stream
* clock. */
- return rtp_send_samples(s1, pkt->data, size, 8 * st->codecpar->channels);
+ return rtp_send_samples(s1, pkt->data, size, 8 * st->codecpar->ch_layout.nb_channels);
case AV_CODEC_ID_ADPCM_G726:
return rtp_send_samples(s1, pkt->data, size,
- st->codecpar->bits_per_coded_sample * st->codecpar->channels);
+ st->codecpar->bits_per_coded_sample * st->codecpar->ch_layout.nb_channels);
case AV_CODEC_ID_MP2:
case AV_CODEC_ID_MP3:
rtp_send_mpegaudio(s1, pkt->data, size);
diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c
index fb6203d585..aa16e04ad2 100644
--- a/libavformat/rtsp.c
+++ b/libavformat/rtsp.c
@@ -280,19 +280,19 @@ static int sdp_parse_rtpmap(AVFormatContext *s,
case AVMEDIA_TYPE_AUDIO:
av_log(s, AV_LOG_DEBUG, "audio codec set to: %s\n", c_name);
par->sample_rate = RTSP_DEFAULT_AUDIO_SAMPLERATE;
- par->channels = RTSP_DEFAULT_NB_AUDIO_CHANNELS;
+ par->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
if (i > 0) {
par->sample_rate = i;
avpriv_set_pts_info(st, 32, 1, par->sample_rate);
get_word_sep(buf, sizeof(buf), "/", &p);
i = atoi(buf);
if (i > 0)
- par->channels = i;
+ av_channel_layout_default(&par->ch_layout, i);
}
av_log(s, AV_LOG_DEBUG, "audio samplerate set to: %i\n",
par->sample_rate);
av_log(s, AV_LOG_DEBUG, "audio channels set to: %i\n",
- par->channels);
+ par->ch_layout.nb_channels);
break;
case AVMEDIA_TYPE_VIDEO:
av_log(s, AV_LOG_DEBUG, "video codec set to: %s\n", c_name);
diff --git a/libavformat/rtsp.h b/libavformat/rtsp.h
index 9dfbc5367f..ded267dfb5 100644
--- a/libavformat/rtsp.h
+++ b/libavformat/rtsp.h
@@ -73,7 +73,6 @@ enum RTSPControlTransport {
#define RTSPS_DEFAULT_PORT 322
#define RTSP_MAX_TRANSPORTS 8
#define RTSP_TCP_MAX_PACKET_SIZE 1472
-#define RTSP_DEFAULT_NB_AUDIO_CHANNELS 1
#define RTSP_DEFAULT_AUDIO_SAMPLERATE 44100
#define RTSP_RTP_PORT_MIN 5000
#define RTSP_RTP_PORT_MAX 10000
diff --git a/libavformat/sdp.c b/libavformat/sdp.c
index be6c95dc23..94b4c558ca 100644
--- a/libavformat/sdp.c
+++ b/libavformat/sdp.c
@@ -426,16 +426,16 @@ static int latm_context2profilelevel(AVCodecParameters *par)
* Different Object Types should implement different Profile Levels */

if (par->sample_rate <= 24000) {
- if (par->channels <= 2)
+ if (par->ch_layout.nb_channels <= 2)
profile_level = 0x28; // AAC Profile, Level 1
} else if (par->sample_rate <= 48000) {
- if (par->channels <= 2) {
+ if (par->ch_layout.nb_channels <= 2) {
profile_level = 0x29; // AAC Profile, Level 2
- } else if (par->channels <= 5) {
+ } else if (par->ch_layout.nb_channels <= 5) {
profile_level = 0x2A; // AAC Profile, Level 4
}
} else if (par->sample_rate <= 96000) {
- if (par->channels <= 5) {
+ if (par->ch_layout.nb_channels <= 5) {
profile_level = 0x2B; // AAC Profile, Level 5
}
}
@@ -464,7 +464,7 @@ static char *latm_context2config(AVFormatContext *s, AVCodecParameters *par)
config_byte[0] = 0x40;
config_byte[1] = 0;
config_byte[2] = 0x20 | rate_index;
- config_byte[3] = par->channels << 4;
+ config_byte[3] = par->ch_layout.nb_channels << 4;
config_byte[4] = 0x3f;
config_byte[5] = 0xc0;

@@ -551,7 +551,7 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecParameters
return NULL;
av_strlcatf(buff, size, "a=rtpmap:%d MP4A-LATM/%d/%d\r\n"
"a=fmtp:%d profile-level-id=%d;cpresent=0;config=%s\r\n",
- payload_type, p->sample_rate, p->channels,
+ payload_type, p->sample_rate, p->ch_layout.nb_channels,
payload_type, latm_context2profilelevel(p), config);
} else {
if (p->extradata_size) {
@@ -570,7 +570,8 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecParameters
"a=fmtp:%d profile-level-id=1;"
"mode=AAC-hbr;sizelength=13;indexlength=3;"
"indexdeltalength=3%s\r\n",
- payload_type, p->sample_rate, p->channels,
+ payload_type, p->sample_rate,
+ p->ch_layout.nb_channels,
payload_type, config);
}
break;
@@ -578,30 +579,32 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecParameters
if (payload_type >= RTP_PT_PRIVATE)
av_strlcatf(buff, size, "a=rtpmap:%d L16/%d/%d\r\n",
payload_type,
- p->sample_rate, p->channels);
+ p->sample_rate, p->ch_layout.nb_channels);
break;
case AV_CODEC_ID_PCM_MULAW:
if (payload_type >= RTP_PT_PRIVATE)
av_strlcatf(buff, size, "a=rtpmap:%d PCMU/%d/%d\r\n",
payload_type,
- p->sample_rate, p->channels);
+ p->sample_rate, p->ch_layout.nb_channels);
break;
case AV_CODEC_ID_PCM_ALAW:
if (payload_type >= RTP_PT_PRIVATE)
av_strlcatf(buff, size, "a=rtpmap:%d PCMA/%d/%d\r\n",
payload_type,
- p->sample_rate, p->channels);
+ p->sample_rate, p->ch_layout.nb_channels);
break;
case AV_CODEC_ID_AMR_NB:
av_strlcatf(buff, size, "a=rtpmap:%d AMR/%d/%d\r\n"
"a=fmtp:%d octet-align=1\r\n",
- payload_type, p->sample_rate, p->channels,
+ payload_type, p->sample_rate,
+ p->ch_layout.nb_channels,
payload_type);
break;
case AV_CODEC_ID_AMR_WB:
av_strlcatf(buff, size, "a=rtpmap:%d AMR-WB/%d/%d\r\n"
"a=fmtp:%d octet-align=1\r\n",
- payload_type, p->sample_rate, p->channels,
+ payload_type, p->sample_rate,
+ p->ch_layout.nb_channels,
payload_type);
break;
case AV_CODEC_ID_VORBIS:
@@ -614,7 +617,8 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecParameters

av_strlcatf(buff, size, "a=rtpmap:%d vorbis/%d/%d\r\n"
"a=fmtp:%d configuration=%s\r\n",
- payload_type, p->sample_rate, p->channels,
+ payload_type, p->sample_rate,
+ p->ch_layout.nb_channels,
payload_type, config);
break;
case AV_CODEC_ID_THEORA: {
@@ -662,7 +666,7 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecParameters
if (payload_type >= RTP_PT_PRIVATE)
av_strlcatf(buff, size, "a=rtpmap:%d G722/%d/%d\r\n",
payload_type,
- 8000, p->channels);
+ 8000, p->ch_layout.nb_channels);
break;
case AV_CODEC_ID_ADPCM_G726: {
if (payload_type >= RTP_PT_PRIVATE)
@@ -691,7 +695,7 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecParameters
receivers MUST be able to receive and process stereo packets. */
av_strlcatf(buff, size, "a=rtpmap:%d opus/48000/2\r\n",
payload_type);
- if (p->channels == 2) {
+ if (p->ch_layout.nb_channels == 2) {
av_strlcatf(buff, size, "a=fmtp:%d sprop-stereo=1\r\n",
payload_type);
}
diff --git a/libavformat/segafilm.c b/libavformat/segafilm.c
index 16500b4349..331c6e8172 100644
--- a/libavformat/segafilm.c
+++ b/libavformat/segafilm.c
@@ -175,20 +175,21 @@ static int film_read_header(AVFormatContext *s)
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = film->audio_type;
st->codecpar->codec_tag = 1;
- st->codecpar->channels = film->audio_channels;
+ st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ st->codecpar->ch_layout.nb_channels = film->audio_channels;
st->codecpar->sample_rate = film->audio_samplerate;

if (film->audio_type == AV_CODEC_ID_ADPCM_ADX) {
st->codecpar->bits_per_coded_sample = 18 * 8 / 32;
- st->codecpar->block_align = st->codecpar->channels * 18;
+ st->codecpar->block_align = film->audio_channels * 18;
st->need_parsing = AVSTREAM_PARSE_FULL;
} else {
st->codecpar->bits_per_coded_sample = film->audio_bits;
- st->codecpar->block_align = st->codecpar->channels *
+ st->codecpar->block_align = film->audio_channels *
st->codecpar->bits_per_coded_sample / 8;
}

- st->codecpar->bit_rate = st->codecpar->channels * st->codecpar->sample_rate *
+ st->codecpar->bit_rate = film->audio_channels * st->codecpar->sample_rate *
st->codecpar->bits_per_coded_sample;
}

diff --git a/libavformat/sierravmd.c b/libavformat/sierravmd.c
index 604ab6b5a4..33adde0251 100644
--- a/libavformat/sierravmd.c
+++ b/libavformat/sierravmd.c
@@ -133,13 +133,7 @@ static int vmd_read_header(AVFormatContext *s)
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_VMDAUDIO;
st->codecpar->codec_tag = 0; /* no fourcc */
- if (vmd->vmd_header[811] & 0x80) {
- st->codecpar->channels = 2;
- st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
- } else {
- st->codecpar->channels = 1;
- st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
- }
+ av_channel_layout_default(&st->codecpar->ch_layout, (vmd->vmd_header[811] & 0x80) + 1);
st->codecpar->sample_rate = vmd->sample_rate;
st->codecpar->block_align = AV_RL16(&vmd->vmd_header[806]);
if (st->codecpar->block_align & 0x8000) {
@@ -149,11 +143,11 @@ static int vmd_read_header(AVFormatContext *s)
st->codecpar->bits_per_coded_sample = 8;
}
st->codecpar->bit_rate = st->codecpar->sample_rate *
- st->codecpar->bits_per_coded_sample * st->codecpar->channels;
+ st->codecpar->bits_per_coded_sample * st->codecpar->ch_layout.nb_channels;

/* calculate pts */
num = st->codecpar->block_align;
- den = st->codecpar->sample_rate * st->codecpar->channels;
+ den = st->codecpar->sample_rate * st->codecpar->ch_layout.nb_channels;
av_reduce(&den, &num, den, num, (1UL<<31)-1);
avpriv_set_pts_info(vst, 33, num, den);
avpriv_set_pts_info(st, 33, num, den);
diff --git a/libavformat/siff.c b/libavformat/siff.c
index e11d5bd489..0f603c5700 100644
--- a/libavformat/siff.c
+++ b/libavformat/siff.c
@@ -79,8 +79,7 @@ static int create_audio_stream(AVFormatContext *s, SIFFContext *c)
return AVERROR(ENOMEM);
ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
ast->codecpar->codec_id = AV_CODEC_ID_PCM_U8;
- ast->codecpar->channels = 1;
- ast->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+ ast->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
ast->codecpar->bits_per_coded_sample = 8;
ast->codecpar->sample_rate = c->rate;
avpriv_set_pts_info(ast, 16, 1, c->rate);
diff --git a/libavformat/smacker.c b/libavformat/smacker.c
index eb4b63fdad..18805582de 100644
--- a/libavformat/smacker.c
+++ b/libavformat/smacker.c
@@ -194,19 +194,15 @@ static int smacker_read_header(AVFormatContext *s)
} else {
ast[i]->codecpar->codec_id = AV_CODEC_ID_PCM_U8;
}
- if (smk->aflags[i] & SMK_AUD_STEREO) {
- ast[i]->codecpar->channels = 2;
- ast[i]->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
- } else {
- ast[i]->codecpar->channels = 1;
- ast[i]->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
- }
+ av_channel_layout_default(&ast[i]->codecpar->ch_layout,
+ !!(smk->aflags[i] & SMK_AUD_STEREO) + 1);
ast[i]->codecpar->sample_rate = smk->rates[i];
ast[i]->codecpar->bits_per_coded_sample = (smk->aflags[i] & SMK_AUD_16BITS) ? 16 : 8;
if(ast[i]->codecpar->bits_per_coded_sample == 16 && ast[i]->codecpar->codec_id == AV_CODEC_ID_PCM_U8)
ast[i]->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
avpriv_set_pts_info(ast[i], 64, 1, ast[i]->codecpar->sample_rate
- * ast[i]->codecpar->channels * ast[i]->codecpar->bits_per_coded_sample / 8);
+ * ast[i]->codecpar->ch_layout.nb_channels
+ * ast[i]->codecpar->bits_per_coded_sample / 8);
}
}

diff --git a/libavformat/smjpegdec.c b/libavformat/smjpegdec.c
index bc69c89e2b..e983171279 100644
--- a/libavformat/smjpegdec.c
+++ b/libavformat/smjpegdec.c
@@ -91,7 +91,8 @@ static int smjpeg_read_header(AVFormatContext *s)
ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
ast->codecpar->sample_rate = avio_rb16(pb);
ast->codecpar->bits_per_coded_sample = avio_r8(pb);
- ast->codecpar->channels = avio_r8(pb);
+ ast->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ ast->codecpar->ch_layout.nb_channels = avio_r8(pb);
ast->codecpar->codec_tag = avio_rl32(pb);
ast->codecpar->codec_id = ff_codec_get_id(ff_codec_smjpeg_audio_tags,
ast->codecpar->codec_tag);
diff --git a/libavformat/smjpegenc.c b/libavformat/smjpegenc.c
index 91b0939cbc..2f27eb6005 100644
--- a/libavformat/smjpegenc.c
+++ b/libavformat/smjpegenc.c
@@ -67,7 +67,7 @@ static int smjpeg_write_header(AVFormatContext *s)
avio_wb32(pb, 8);
avio_wb16(pb, par->sample_rate);
avio_w8(pb, av_get_bits_per_sample(par->codec_id));
- avio_w8(pb, par->channels);
+ avio_w8(pb, par->ch_layout.nb_channels);
avio_wl32(pb, tag);
avpriv_set_pts_info(st, 32, 1, 1000);
} else if (par->codec_type == AVMEDIA_TYPE_VIDEO) {
diff --git a/libavformat/smoothstreamingenc.c b/libavformat/smoothstreamingenc.c
index 997b9e636c..f0743ee25d 100644
--- a/libavformat/smoothstreamingenc.c
+++ b/libavformat/smoothstreamingenc.c
@@ -283,7 +283,7 @@ static int write_manifest(AVFormatContext *s, int final)
if (s->streams[i]->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
continue;
last = i;
- avio_printf(out, "<QualityLevel Index=\"%d\" Bitrate=\"%d\" FourCC=\"%s\" SamplingRate=\"%d\" Channels=\"%d\" BitsPerSample=\"16\" PacketSize=\"%d\" AudioTag=\"%d\" CodecPrivateData=\"%s\" />\n", index, s->streams[i]->codecpar->bit_rate, os->fourcc, s->streams[i]->codecpar->sample_rate, s->streams[i]->codecpar->channels, os->packet_size, os->audio_tag, os->private_str);
+ avio_printf(out, "<QualityLevel Index=\"%d\" Bitrate=\"%d\" FourCC=\"%s\" SamplingRate=\"%d\" Channels=\"%d\" BitsPerSample=\"16\" PacketSize=\"%d\" AudioTag=\"%d\" CodecPrivateData=\"%s\" />\n", index, s->streams[i]->codecpar->bit_rate, os->fourcc, s->streams[i]->codecpar->sample_rate, s->streams[i]->codecpar->ch_layout.nb_channels, os->packet_size, os->audio_tag, os->private_str);
index++;
}
output_chunk_list(&c->streams[last], out, final, c->lookahead_count, c->window_size);
diff --git a/libavformat/smush.c b/libavformat/smush.c
index 817e736bf7..f3e7c1efab 100644
--- a/libavformat/smush.c
+++ b/libavformat/smush.c
@@ -181,8 +181,8 @@ static int smush_read_header(AVFormatContext *ctx)
ast->codecpar->codec_id = AV_CODEC_ID_ADPCM_VIMA;
ast->codecpar->codec_tag = 0;
ast->codecpar->sample_rate = sample_rate;
- ast->codecpar->channels = channels;
-
+ ast->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ ast->codecpar->ch_layout.nb_channels = channels;
avpriv_set_pts_info(ast, 64, 1, ast->codecpar->sample_rate);
}

diff --git a/libavformat/sol.c b/libavformat/sol.c
index 5c7f43da03..53047b3d59 100644
--- a/libavformat/sol.c
+++ b/libavformat/sol.c
@@ -113,9 +113,7 @@ static int sol_read_header(AVFormatContext *s)
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_tag = id;
st->codecpar->codec_id = codec;
- st->codecpar->channels = channels;
- st->codecpar->channel_layout = channels == 1 ? AV_CH_LAYOUT_MONO :
- AV_CH_LAYOUT_STEREO;
+ av_channel_layout_default(&st->codecpar->ch_layout,channels);
st->codecpar->sample_rate = rate;
avpriv_set_pts_info(st, 64, 1, rate);
return 0;
diff --git a/libavformat/soxdec.c b/libavformat/soxdec.c
index ee3d1dc560..2ef7bc98f4 100644
--- a/libavformat/soxdec.c
+++ b/libavformat/soxdec.c
@@ -49,6 +49,7 @@ static int sox_read_header(AVFormatContext *s)
AVIOContext *pb = s->pb;
unsigned header_size, comment_size;
double sample_rate, sample_rate_frac;
+ int channels;
AVStream *st;

st = avformat_new_stream(s, NULL);
@@ -62,17 +63,20 @@ static int sox_read_header(AVFormatContext *s)
header_size = avio_rl32(pb);
avio_skip(pb, 8); /* sample count */
sample_rate = av_int2double(avio_rl64(pb));
- st->codecpar->channels = avio_rl32(pb);
+ channels = avio_rl32(pb);
comment_size = avio_rl32(pb);
} else {
st->codecpar->codec_id = AV_CODEC_ID_PCM_S32BE;
header_size = avio_rb32(pb);
avio_skip(pb, 8); /* sample count */
sample_rate = av_int2double(avio_rb64(pb));
- st->codecpar->channels = avio_rb32(pb);
+ channels = avio_rb32(pb);
comment_size = avio_rb32(pb);
}

+ st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ st->codecpar->ch_layout.nb_channels = channels;
+
if (comment_size > 0xFFFFFFFFU - SOX_FIXED_HDR - 4U) {
av_log(s, AV_LOG_ERROR, "invalid comment size (%u)\n", comment_size);
return -1;
@@ -90,7 +94,7 @@ static int sox_read_header(AVFormatContext *s)
sample_rate_frac);

if ((header_size + 4) & 7 || header_size < SOX_FIXED_HDR + comment_size
- || st->codecpar->channels > 65535) /* Reserve top 16 bits */ {
+ || channels > 65535) /* Reserve top 16 bits */ {
av_log(s, AV_LOG_ERROR, "invalid header\n");
return -1;
}
@@ -113,9 +117,9 @@ static int sox_read_header(AVFormatContext *s)
st->codecpar->bits_per_coded_sample = 32;
st->codecpar->bit_rate = st->codecpar->sample_rate *
st->codecpar->bits_per_coded_sample *
- st->codecpar->channels;
+ channels;
st->codecpar->block_align = st->codecpar->bits_per_coded_sample *
- st->codecpar->channels / 8;
+ channels / 8;

avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);

diff --git a/libavformat/soxenc.c b/libavformat/soxenc.c
index d0f7d410d2..5fcfc01736 100644
--- a/libavformat/soxenc.c
+++ b/libavformat/soxenc.c
@@ -60,14 +60,14 @@ static int sox_write_header(AVFormatContext *s)
avio_wl32(pb, sox->header_size);
avio_wl64(pb, 0); /* number of samples */
avio_wl64(pb, av_double2int(par->sample_rate));
- avio_wl32(pb, par->channels);
+ avio_wl32(pb, par->ch_layout.nb_channels);
avio_wl32(pb, comment_size);
} else if (par->codec_id == AV_CODEC_ID_PCM_S32BE) {
ffio_wfourcc(pb, "XoS.");
avio_wb32(pb, sox->header_size);
avio_wb64(pb, 0); /* number of samples */
avio_wb64(pb, av_double2int(par->sample_rate));
- avio_wb32(pb, par->channels);
+ avio_wb32(pb, par->ch_layout.nb_channels);
avio_wb32(pb, comment_size);
} else {
av_log(s, AV_LOG_ERROR, "invalid codec; use pcm_s32le or pcm_s32be\n");
diff --git a/libavformat/swfdec.c b/libavformat/swfdec.c
index 984fedffcf..4f93f99348 100644
--- a/libavformat/swfdec.c
+++ b/libavformat/swfdec.c
@@ -207,13 +207,7 @@ static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
if (!ast)
return -1;
ast->id = -1; /* -1 to avoid clash with video stream ch_id */
- if (v & 1) {
- ast->codecpar->channels = 2;
- ast->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
- } else {
- ast->codecpar->channels = 1;
- ast->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
- }
+ av_channel_layout_default(&ast->codecpar->ch_layout, !!(v & 1) + 1);
ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
ast->codecpar->codec_id = ff_codec_get_id(swf_audio_codec_tags, (v>>4) & 15);
ast->need_parsing = AVSTREAM_PARSE_FULL;
diff --git a/libavformat/swfenc.c b/libavformat/swfenc.c
index 345688c654..32a93a29c3 100644
--- a/libavformat/swfenc.c
+++ b/libavformat/swfenc.c
@@ -321,7 +321,7 @@ static int swf_write_header(AVFormatContext *s)
return -1;
}
v |= 0x02; /* 16 bit playback */
- if (swf->audio_par->channels == 2)
+ if (swf->audio_par->ch_layout.nb_channels == 2)
v |= 0x01; /* stereo playback */
avio_w8(s->pb, v);
v |= 0x20; /* mp3 compressed */
diff --git a/libavformat/takdec.c b/libavformat/takdec.c
index b3739e446e..d01f6dbe40 100644
--- a/libavformat/takdec.c
+++ b/libavformat/takdec.c
@@ -124,9 +124,12 @@ static int tak_read_header(AVFormatContext *s)
st->duration = ti.samples;
st->codecpar->bits_per_coded_sample = ti.bps;
if (ti.ch_layout)
- st->codecpar->channel_layout = ti.ch_layout;
+ av_channel_layout_from_mask(&st->codecpar->ch_layout, ti.ch_layout);
+ else {
+ st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ st->codecpar->ch_layout.nb_channels = ti.channels;
+ }
st->codecpar->sample_rate = ti.sample_rate;
- st->codecpar->channels = ti.channels;
st->start_time = 0;
avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
st->codecpar->extradata = buffer;
diff --git a/libavformat/tests/movenc.c b/libavformat/tests/movenc.c
index f2aa662b3c..0f9ce16511 100644
--- a/libavformat/tests/movenc.c
+++ b/libavformat/tests/movenc.c
@@ -212,7 +212,7 @@ static void init_fps(int bf, int audio_preroll, int fps)
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_AAC;
st->codecpar->sample_rate = 44100;
- st->codecpar->channels = 2;
+ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
st->time_base.num = 1;
st->time_base.den = 44100;
st->codecpar->extradata_size = sizeof(aac_extradata);
diff --git a/libavformat/thp.c b/libavformat/thp.c
index c9ec5c131d..a44abbcae6 100644
--- a/libavformat/thp.c
+++ b/libavformat/thp.c
@@ -124,7 +124,8 @@ static int thp_read_header(AVFormatContext *s)
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_ADPCM_THP;
st->codecpar->codec_tag = 0; /* no fourcc */
- st->codecpar->channels = avio_rb32(pb); /* numChannels. */
+ st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ st->codecpar->ch_layout.nb_channels = avio_rb32(pb);
st->codecpar->sample_rate = avio_rb32(pb); /* Frequency. */
st->duration = avio_rb32(pb);

diff --git a/libavformat/tiertexseq.c b/libavformat/tiertexseq.c
index 8427f92145..351c616b1c 100644
--- a/libavformat/tiertexseq.c
+++ b/libavformat/tiertexseq.c
@@ -231,12 +231,11 @@ static int seq_read_header(AVFormatContext *s)
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
st->codecpar->codec_tag = 0; /* no tag */
- st->codecpar->channels = 1;
- st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
st->codecpar->sample_rate = SEQ_SAMPLE_RATE;
st->codecpar->bits_per_coded_sample = 16;
- st->codecpar->bit_rate = st->codecpar->sample_rate * st->codecpar->bits_per_coded_sample * st->codecpar->channels;
- st->codecpar->block_align = st->codecpar->channels * st->codecpar->bits_per_coded_sample / 8;
+ st->codecpar->bit_rate = st->codecpar->sample_rate * st->codecpar->bits_per_coded_sample * st->codecpar->ch_layout.nb_channels;
+ st->codecpar->block_align = st->codecpar->ch_layout.nb_channels * st->codecpar->bits_per_coded_sample / 8;

return 0;
}
diff --git a/libavformat/tmv.c b/libavformat/tmv.c
index 0283ddaad9..28ae087e5e 100644
--- a/libavformat/tmv.c
+++ b/libavformat/tmv.c
@@ -113,19 +113,13 @@ static int tmv_read_header(AVFormatContext *s)

ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
ast->codecpar->codec_id = AV_CODEC_ID_PCM_U8;
- if (features & TMV_STEREO) {
- ast->codecpar->channels = 2;
- ast->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
- } else {
- ast->codecpar->channels = 1;
- ast->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
- }
+ av_channel_layout_default(&ast->codecpar->ch_layout, !!(features & TMV_STEREO) + 1);
ast->codecpar->bits_per_coded_sample = 8;
ast->codecpar->bit_rate = ast->codecpar->sample_rate *
ast->codecpar->bits_per_coded_sample;
avpriv_set_pts_info(ast, 32, 1, ast->codecpar->sample_rate);

- fps.num = ast->codecpar->sample_rate * ast->codecpar->channels;
+ fps.num = ast->codecpar->sample_rate * ast->codecpar->ch_layout.nb_channels;
fps.den = tmv->audio_chunk_size;
av_reduce(&fps.num, &fps.den, fps.num, fps.den, 0xFFFFFFFFLL);

diff --git a/libavformat/tta.c b/libavformat/tta.c
index 091b502567..c09f4ecebb 100644
--- a/libavformat/tta.c
+++ b/libavformat/tta.c
@@ -109,7 +109,8 @@ static int tta_read_header(AVFormatContext *s)

st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_TTA;
- st->codecpar->channels = channels;
+ st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ st->codecpar->ch_layout.nb_channels = channels;
st->codecpar->sample_rate = samplerate;
st->codecpar->bits_per_coded_sample = bps;

diff --git a/libavformat/voc_packet.c b/libavformat/voc_packet.c
index 38650756f7..09f1ebfe37 100644
--- a/libavformat/voc_packet.c
+++ b/libavformat/voc_packet.c
@@ -50,7 +50,8 @@ ff_voc_get_packet(AVFormatContext *s, AVPacket *pkt, AVStream *st, int max_size)
if (sample_rate)
par->sample_rate = sample_rate;
avpriv_set_pts_info(st, 64, 1, par->sample_rate);
- par->channels = channels;
+ par->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ par->ch_layout.nb_channels = channels;
par->bits_per_coded_sample = av_get_bits_per_sample(par->codec_id);
} else
avio_skip(pb, 1);
@@ -77,7 +78,9 @@ ff_voc_get_packet(AVFormatContext *s, AVPacket *pkt, AVStream *st, int max_size)
par->sample_rate = avio_rl32(pb);
avpriv_set_pts_info(st, 64, 1, par->sample_rate);
par->bits_per_coded_sample = avio_r8(pb);
- par->channels = avio_r8(pb);
+ channels = avio_r8(pb);
+ par->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ par->ch_layout.nb_channels = channels;
} else
avio_skip(pb, 6);
tmp_codec = avio_rl16(pb);
diff --git a/libavformat/vocenc.c b/libavformat/vocenc.c
index 033fc5633b..2a5068fc57 100644
--- a/libavformat/vocenc.c
+++ b/libavformat/vocenc.c
@@ -57,16 +57,16 @@ static int voc_write_packet(AVFormatContext *s, AVPacket *pkt)
avio_wl24(pb, pkt->size + 12);
avio_wl32(pb, par->sample_rate);
avio_w8(pb, par->bits_per_coded_sample);
- avio_w8(pb, par->channels);
+ avio_w8(pb, par->ch_layout.nb_channels);
avio_wl16(pb, par->codec_tag);
avio_wl32(pb, 0);
} else {
- if (s->streams[0]->codecpar->channels > 1) {
+ if (s->streams[0]->codecpar->ch_layout.nb_channels > 1) {
avio_w8(pb, VOC_TYPE_EXTENDED);
avio_wl24(pb, 4);
- avio_wl16(pb, 65536-256000000/(par->sample_rate*par->channels));
+ avio_wl16(pb, 65536 - 256000000 / (par->sample_rate * par->ch_layout.nb_channels));
avio_w8(pb, par->codec_tag);
- avio_w8(pb, par->channels - 1);
+ avio_w8(pb, par->ch_layout.nb_channels - 1);
}
avio_w8(pb, VOC_TYPE_VOICE_DATA);
avio_wl24(pb, pkt->size + 2);
diff --git a/libavformat/vqf.c b/libavformat/vqf.c
index c3a6a97720..f332b1141c 100644
--- a/libavformat/vqf.c
+++ b/libavformat/vqf.c
@@ -127,7 +127,8 @@ static int vqf_read_header(AVFormatContext *s)
switch(chunk_tag){
case MKTAG('C','O','M','M'):
avio_read(s->pb, comm_chunk, 12);
- st->codecpar->channels = AV_RB32(comm_chunk ) + 1;
+ st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ st->codecpar->ch_layout.nb_channels = AV_RB32(comm_chunk) + 1;
read_bitrate = AV_RB32(comm_chunk + 4);
rate_flag = AV_RB32(comm_chunk + 8);
avio_skip(s->pb, len-12);
@@ -182,15 +183,15 @@ static int vqf_read_header(AVFormatContext *s)
break;
}

- if (read_bitrate / st->codecpar->channels < 8 ||
- read_bitrate / st->codecpar->channels > 48) {
+ if (read_bitrate / st->codecpar->ch_layout.nb_channels < 8 ||
+ read_bitrate / st->codecpar->ch_layout.nb_channels > 48) {
av_log(s, AV_LOG_ERROR, "Invalid bitrate per channel %d\n",
- read_bitrate / st->codecpar->channels);
+ read_bitrate / st->codecpar->ch_layout.nb_channels);
return AVERROR_INVALIDDATA;
}

switch (((st->codecpar->sample_rate/1000) << 8) +
- read_bitrate/st->codecpar->channels) {
+ read_bitrate/st->codecpar->ch_layout.nb_channels) {
case (11<<8) + 8 :
case (8 <<8) + 8 :
case (11<<8) + 10:
diff --git a/libavformat/wavdec.c b/libavformat/wavdec.c
index 8c78666f84..456fb1340e 100644
--- a/libavformat/wavdec.c
+++ b/libavformat/wavdec.c
@@ -328,10 +328,10 @@ break_loop:

avio_seek(pb, data_ofs, SEEK_SET);

- if (!sample_count && st->codecpar->channels &&
+ if (!sample_count && st->codecpar->ch_layout.nb_channels &&
av_get_bits_per_sample(st->codecpar->codec_id))
sample_count = (data_size << 3) /
- (st->codecpar->channels *
+ (st->codecpar->ch_layout.nb_channels *
(uint64_t)av_get_bits_per_sample(st->codecpar->codec_id));
if (sample_count)
st->duration = sample_count;
diff --git a/libavformat/wc3movie.c b/libavformat/wc3movie.c
index f46b8c2f09..742b280510 100644
--- a/libavformat/wc3movie.c
+++ b/libavformat/wc3movie.c
@@ -53,7 +53,6 @@

/* always use the same PCM audio parameters */
#define WC3_SAMPLE_RATE 22050
-#define WC3_AUDIO_CHANNELS 1
#define WC3_AUDIO_BITS 16

/* nice, constant framerate */
@@ -183,13 +182,12 @@ static int wc3_read_header(AVFormatContext *s)
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
st->codecpar->codec_tag = 1;
- st->codecpar->channels = WC3_AUDIO_CHANNELS;
- st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
st->codecpar->bits_per_coded_sample = WC3_AUDIO_BITS;
st->codecpar->sample_rate = WC3_SAMPLE_RATE;
- st->codecpar->bit_rate = st->codecpar->channels * st->codecpar->sample_rate *
+ st->codecpar->bit_rate = st->codecpar->ch_layout.nb_channels * st->codecpar->sample_rate *
st->codecpar->bits_per_coded_sample;
- st->codecpar->block_align = WC3_AUDIO_BITS * WC3_AUDIO_CHANNELS;
+ st->codecpar->block_align = WC3_AUDIO_BITS * st->codecpar->ch_layout.nb_channels;

return 0;
}
diff --git a/libavformat/westwood_aud.c b/libavformat/westwood_aud.c
index 1bfc010f56..f028d4680d 100644
--- a/libavformat/westwood_aud.c
+++ b/libavformat/westwood_aud.c
@@ -120,9 +120,7 @@ static int wsaud_read_header(AVFormatContext *s)
}
avpriv_set_pts_info(st, 64, 1, sample_rate);
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
- st->codecpar->channels = channels;
- st->codecpar->channel_layout = channels == 1 ? AV_CH_LAYOUT_MONO :
- AV_CH_LAYOUT_STEREO;
+ av_channel_layout_default(&st->codecpar->ch_layout, channels);
st->codecpar->sample_rate = sample_rate;

return 0;
@@ -167,7 +165,7 @@ static int wsaud_read_packet(AVFormatContext *s,
return AVERROR(EIO);

/* 2 samples/byte, 1 or 2 samples per frame depending on stereo */
- pkt->duration = (chunk_size * 2) / st->codecpar->channels;
+ pkt->duration = (chunk_size * 2) / st->codecpar->ch_layout.nb_channels;
}
pkt->stream_index = st->index;

diff --git a/libavformat/westwood_vqa.c b/libavformat/westwood_vqa.c
index 8bd647e122..a5b032061c 100644
--- a/libavformat/westwood_vqa.c
+++ b/libavformat/westwood_vqa.c
@@ -206,7 +206,7 @@ static int wsvqa_read_packet(AVFormatContext *s,
wsvqa->bps = 8;
st->codecpar->sample_rate = wsvqa->sample_rate;
st->codecpar->bits_per_coded_sample = wsvqa->bps;
- st->codecpar->channels = wsvqa->channels;
+ av_channel_layout_default(&st->codecpar->ch_layout, wsvqa->channels);
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;

avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
diff --git a/libavformat/wtv.c b/libavformat/wtv.c
index d750cef647..8212818e5f 100644
--- a/libavformat/wtv.c
+++ b/libavformat/wtv.c
@@ -609,11 +609,9 @@ static void parse_mpeg1waveformatex(AVStream *st)
switch (AV_RL16(st->codecpar->extradata + 6)) {
case 1 :
case 2 :
- case 4 : st->codecpar->channels = 2;
- st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
+ case 4 : st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
break;
- case 8 : st->codecpar->channels = 1;
- st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+ case 8 : st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
break;
}
}
diff --git a/libavformat/wvdec.c b/libavformat/wvdec.c
index 51aae084ea..27e31342c8 100644
--- a/libavformat/wvdec.c
+++ b/libavformat/wvdec.c
@@ -230,8 +230,7 @@ static int wv_read_header(AVFormatContext *s)
return AVERROR(ENOMEM);
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_WAVPACK;
- st->codecpar->channels = wc->chan;
- st->codecpar->channel_layout = wc->chmask;
+ av_channel_layout_from_mask(&st->codecpar->ch_layout, wc->chmask);
st->codecpar->sample_rate = wc->rate;
st->codecpar->bits_per_coded_sample = wc->bpp;
avpriv_set_pts_info(st, 64, 1, wc->rate);
diff --git a/libavformat/xa.c b/libavformat/xa.c
index 06b9c3f9bb..25b6405a88 100644
--- a/libavformat/xa.c
+++ b/libavformat/xa.c
@@ -78,13 +78,14 @@ static int xa_read_header(AVFormatContext *s)
avio_skip(pb, 4); /* Skip the XA ID */
xa->out_size = avio_rl32(pb);
avio_skip(pb, 2); /* Skip the tag */
- st->codecpar->channels = avio_rl16(pb);
+ st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ st->codecpar->ch_layout.nb_channels = avio_rl16(pb);
st->codecpar->sample_rate = avio_rl32(pb);
avio_skip(pb, 4); /* Skip average byte rate */
avio_skip(pb, 2); /* Skip block align */
avio_skip(pb, 2); /* Skip bits-per-sample */

- st->codecpar->bit_rate = av_clip(15LL * st->codecpar->channels * 8 *
+ st->codecpar->bit_rate = av_clip(15LL * st->codecpar->ch_layout.nb_channels * 8 *
st->codecpar->sample_rate / 28, 0, INT_MAX);

avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
@@ -105,7 +106,7 @@ static int xa_read_packet(AVFormatContext *s,
if (xa->sent_bytes >= xa->out_size)
return AVERROR_EOF;
/* 1 byte header and 14 bytes worth of samples * number channels per block */
- packet_size = 15*st->codecpar->channels;
+ packet_size = 15*st->codecpar->ch_layout.nb_channels;

ret = av_get_packet(pb, pkt, packet_size);
if(ret < 0)
diff --git a/libavformat/xmv.c b/libavformat/xmv.c
index b2112b0e95..18dfad3969 100644
--- a/libavformat/xmv.c
+++ b/libavformat/xmv.c
@@ -243,7 +243,8 @@ static int xmv_read_header(AVFormatContext *s)
ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
ast->codecpar->codec_id = track->codec_id;
ast->codecpar->codec_tag = track->compression;
- ast->codecpar->channels = track->channels;
+ ast->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ ast->codecpar->ch_layout.nb_channels = track->channels;
ast->codecpar->sample_rate = track->sample_rate;
ast->codecpar->bits_per_coded_sample = track->bits_per_sample;
ast->codecpar->bit_rate = track->bit_rate;
diff --git a/libavformat/xwma.c b/libavformat/xwma.c
index 006f60d33e..6411e73151 100644
--- a/libavformat/xwma.c
+++ b/libavformat/xwma.c
@@ -114,9 +114,9 @@ static int xwma_read_header(AVFormatContext *s)
}
}

- if (!st->codecpar->channels) {
+ if (!av_channel_layout_check(&st->codecpar->ch_layout)) {
av_log(s, AV_LOG_WARNING, "Invalid channel count: %d\n",
- st->codecpar->channels);
+ st->codecpar->ch_layout.nb_channels);
return AVERROR_INVALIDDATA;
}
if (!st->codecpar->bits_per_coded_sample) {
@@ -200,7 +200,7 @@ static int xwma_read_header(AVFormatContext *s)
if (dpds_table && dpds_table_size) {
int64_t cur_pos;
const uint32_t bytes_per_sample
- = (st->codecpar->channels * st->codecpar->bits_per_coded_sample) >> 3;
+ = (st->codecpar->ch_layout.nb_channels * st->codecpar->bits_per_coded_sample) >> 3;

/* Estimate the duration from the total number of output bytes. */
const uint64_t total_decoded_bytes = dpds_table[dpds_table_size - 1];
@@ -208,7 +208,7 @@ static int xwma_read_header(AVFormatContext *s)
if (!bytes_per_sample) {
av_log(s, AV_LOG_ERROR,
"Invalid bits_per_coded_sample %d for %d channels\n",
- st->codecpar->bits_per_coded_sample, st->codecpar->channels);
+ st->codecpar->bits_per_coded_sample, st->codecpar->ch_layout.nb_channels);
ret = AVERROR_INVALIDDATA;
goto fail;
}
diff --git a/libavformat/yop.c b/libavformat/yop.c
index c782ecd77d..b9b76e2de4 100644
--- a/libavformat/yop.c
+++ b/libavformat/yop.c
@@ -73,8 +73,7 @@ static int yop_read_header(AVFormatContext *s)
audio_par = audio_stream->codecpar;
audio_par->codec_type = AVMEDIA_TYPE_AUDIO;
audio_par->codec_id = AV_CODEC_ID_ADPCM_IMA_APC;
- audio_par->channels = 1;
- audio_par->channel_layout = AV_CH_LAYOUT_MONO;
+ audio_par->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
audio_par->sample_rate = 22050;

// Video
--
2.13.1
Vittorio Giovara
2017-06-28 22:11:02 UTC
Permalink
Resampling or conversion to/from ambisonic audio are currently
unsupported features.

Signed-off-by: Vittorio Giovara <***@gmail.com>
---
libavresample/utils.c | 8 ++++++++
1 file changed, 8 insertions(+)

diff --git a/libavresample/utils.c b/libavresample/utils.c
index 15c827efbe..af2b9dbf2d 100644
--- a/libavresample/utils.c
+++ b/libavresample/utils.c
@@ -70,6 +70,14 @@ int avresample_open(AVAudioResampleContext *avr)
av_channel_layout_default(&avr->out_ch_layout, avr->out_ch_layout.nb_channels);
}

+ if (( avr->in_ch_layout.order == AV_CHANNEL_ORDER_AMBISONIC ||
+ avr->out_ch_layout.order == AV_CHANNEL_ORDER_AMBISONIC) &&
+ av_channel_layout_compare(&avr->in_ch_layout, &avr->out_ch_layout)) {
+ av_log(avr, AV_LOG_ERROR,
+ "Resampling to/from ambisonic channel layouts is not supported.\n");
+ return AVERROR(ENOSYS);
+ }
+
/* set channel mixing parameters */
#if FF_API_OLD_CHANNEL_LAYOUT
if (avr->in_channel_layout) {
--
2.13.1
Diego Biurrun
2017-06-29 07:22:02 UTC
Permalink
Post by Vittorio Giovara
Resampling or conversion to/from ambisonic audio are currently
unsupported features.
Maybe you mean something like

lavr: Only allow pass-through of ambisonic channel layouts

? Your current commit title does not parse...

Diego
Vittorio Giovara
2017-06-29 19:02:13 UTC
Permalink
Post by Diego Biurrun
Post by Vittorio Giovara
Resampling or conversion to/from ambisonic audio are currently
unsupported features.
Maybe you mean something like
lavr: Only allow pass-through of ambisonic channel layouts
? Your current commit title does not parse...
Yeah that is good. I tried to convey the fact that as long as you
don't change channel order, you're fine with using an ambisonic
channel layout for input and output.
--
Vittorio
wm4
2017-06-29 09:23:31 UTC
Permalink
On Wed, 28 Jun 2017 18:11:02 -0400
Post by Vittorio Giovara
Resampling or conversion to/from ambisonic audio are currently
unsupported features.
---
libavresample/utils.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/libavresample/utils.c b/libavresample/utils.c
index 15c827efbe..af2b9dbf2d 100644
--- a/libavresample/utils.c
+++ b/libavresample/utils.c
@@ -70,6 +70,14 @@ int avresample_open(AVAudioResampleContext *avr)
av_channel_layout_default(&avr->out_ch_layout, avr->out_ch_layout.nb_channels);
}
+ if (( avr->in_ch_layout.order == AV_CHANNEL_ORDER_AMBISONIC ||
+ avr->out_ch_layout.order == AV_CHANNEL_ORDER_AMBISONIC) &&
+ av_channel_layout_compare(&avr->in_ch_layout, &avr->out_ch_layout)) {
+ av_log(avr, AV_LOG_ERROR,
+ "Resampling to/from ambisonic channel layouts is not supported.\n");
+ return AVERROR(ENOSYS);
+ }
+
/* set channel mixing parameters */
#if FF_API_OLD_CHANNEL_LAYOUT
if (avr->in_channel_layout) {
Did it error out in all cases before this patch? It shouldn't use a
blacklist for unknown channel orders, but a whitelist for supported
ones.
Vittorio Giovara
2017-06-29 19:06:48 UTC
Permalink
Post by wm4
On Wed, 28 Jun 2017 18:11:02 -0400
Post by Vittorio Giovara
Resampling or conversion to/from ambisonic audio are currently
unsupported features.
---
libavresample/utils.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/libavresample/utils.c b/libavresample/utils.c
index 15c827efbe..af2b9dbf2d 100644
--- a/libavresample/utils.c
+++ b/libavresample/utils.c
@@ -70,6 +70,14 @@ int avresample_open(AVAudioResampleContext *avr)
av_channel_layout_default(&avr->out_ch_layout, avr->out_ch_layout.nb_channels);
}
+ if (( avr->in_ch_layout.order == AV_CHANNEL_ORDER_AMBISONIC ||
+ avr->out_ch_layout.order == AV_CHANNEL_ORDER_AMBISONIC) &&
+ av_channel_layout_compare(&avr->in_ch_layout, &avr->out_ch_layout)) {
+ av_log(avr, AV_LOG_ERROR,
+ "Resampling to/from ambisonic channel layouts is not supported.\n");
+ return AVERROR(ENOSYS);
+ }
+
/* set channel mixing parameters */
#if FF_API_OLD_CHANNEL_LAYOUT
if (avr->in_channel_layout) {
Did it error out in all cases before this patch? It shouldn't use a
blacklist for unknown channel orders, but a whitelist for supported
ones.
In the past it used to support up any layout up to 62 channels, but it
never errored out.
I will change it to use a whitelist for only NATIVE and UNSPEC orders,
in the first lavr patch, and modify this one to only allow
passthrough.
--
Vittorio
Vittorio Giovara
2017-06-29 20:17:52 UTC
Permalink
Signed-off-by: Vittorio Giovara <***@gmail.com>
---
libavresample/utils.c | 10 ++++++++++
1 file changed, 10 insertions(+)

diff --git a/libavresample/utils.c b/libavresample/utils.c
index 5e4a9f3ac3..cadfd5474f 100644
--- a/libavresample/utils.c
+++ b/libavresample/utils.c
@@ -46,8 +46,10 @@ int avresample_open(AVAudioResampleContext *avr)

/* whitelist allowed channel orders */
if ( (avr->in_ch_layout.order != AV_CHANNEL_ORDER_NATIVE &&
+ avr->in_ch_layout.order != AV_CHANNEL_ORDER_AMBISONIC &&
avr->in_ch_layout.order != AV_CHANNEL_ORDER_UNSPEC) ||
(avr->out_ch_layout.order != AV_CHANNEL_ORDER_NATIVE &&
+ avr->out_ch_layout.order != AV_CHANNEL_ORDER_AMBISONIC &&
avr->out_ch_layout.order != AV_CHANNEL_ORDER_UNSPEC)) {
av_log(avr, AV_LOG_ERROR,
"Input or ouput channel order is not supported.\n");
@@ -73,6 +75,14 @@ int avresample_open(AVAudioResampleContext *avr)
av_channel_layout_default(&avr->out_ch_layout, avr->out_ch_layout.nb_channels);
}

+ if (( avr->in_ch_layout.order == AV_CHANNEL_ORDER_AMBISONIC ||
+ avr->out_ch_layout.order == AV_CHANNEL_ORDER_AMBISONIC) &&
+ av_channel_layout_compare(&avr->in_ch_layout, &avr->out_ch_layout)) {
+ av_log(avr, AV_LOG_ERROR,
+ "Resampling to/from ambisonic channel layouts is not supported.\n");
+ return AVERROR(ENOSYS);
+ }
+
/* set channel mixing parameters */
#if FF_API_OLD_CHANNEL_LAYOUT
if (avr->in_channel_layout) {
--
2.13.1
Vittorio Giovara
2017-06-28 22:11:03 UTC
Permalink
Signed-off-by: Vittorio Giovara <***@gmail.com>
---
libavcodec/opus.c | 36 ++++++++++++++++++++++++++++--------
1 file changed, 28 insertions(+), 8 deletions(-)

diff --git a/libavcodec/opus.c b/libavcodec/opus.c
index 308d104212..6aebb40155 100644
--- a/libavcodec/opus.c
+++ b/libavcodec/opus.c
@@ -347,7 +347,7 @@ av_cold int ff_opus_parse_extradata(AVCodecContext *avctx,
streams = 1;
stereo_streams = channels - 1;
channel_map = default_channel_map;
- } else if (map_type == 1 || map_type == 255) {
+ } else if (map_type == 1 || map_type == 2 || map_type == 255) {
if (extradata_size < 21 + channels) {
av_log(avctx, AV_LOG_ERROR, "Invalid extradata size: %d\n",
extradata_size);
@@ -363,6 +363,7 @@ av_cold int ff_opus_parse_extradata(AVCodecContext *avctx,
return AVERROR_INVALIDDATA;
}

+ layout = 0;
if (map_type == 1) {
if (channels > 8) {
av_log(avctx, AV_LOG_ERROR,
@@ -371,8 +372,24 @@ av_cold int ff_opus_parse_extradata(AVCodecContext *avctx,
}
layout = ff_vorbis_ch_layouts[channels - 1].u.mask;
channel_reorder = channel_reorder_vorbis;
- } else
- layout = 0;
+ } else if (map_type == 2) {
+ int ambisonic_order = ff_sqrt(channels) - 1;
+ int idx = (ambisonic_order + 1) * (ambisonic_order + 1);
+ if (channels <= 227 && (channels == idx || channels == idx + 2)) {
+ av_channel_layout_uninit(&avctx->ch_layout);
+ avctx->ch_layout.order = AV_CHANNEL_ORDER_AMBISONIC;
+ avctx->ch_layout.nb_channels = channels;
+
+ /* ACN order, followed by two optional channels of non-diegetic stereo */
+ if (idx != channels)
+ avctx->ch_layout.u.mask = AV_CH_LAYOUT_STEREO;
+ } else {
+ av_log(avctx, AV_LOG_ERROR, "Channel map 2 is only valid for "
+ "channel counts equal to (n + 1)^2 + 2j for {n,j} >= 0 "
+ "(max 227 channels).\n");
+ return AVERROR_INVALIDDATA;
+ }
+ }

channel_map = extradata + 21;
} else {
@@ -415,11 +432,14 @@ av_cold int ff_opus_parse_extradata(AVCodecContext *avctx,
}
}

- av_channel_layout_uninit(&avctx->ch_layout);
- if (layout)
- av_channel_layout_from_mask(&avctx->ch_layout, layout);
- else
- av_channel_layout_default(&avctx->ch_layout, channels);
+ if (avctx->ch_layout.order == AV_CHANNEL_ORDER_NATIVE) {
+ av_channel_layout_uninit(&avctx->ch_layout);
+ if (layout)
+ av_channel_layout_from_mask(&avctx->ch_layout, layout);
+ else
+ av_channel_layout_default(&avctx->ch_layout, channels);
+ }
+
s->nb_streams = streams;
s->nb_stereo_streams = stereo_streams;
--
2.13.1
Luca Barbato
2017-07-01 10:39:25 UTC
Permalink
Post by Vittorio Giovara
---
libavcodec/opus.c | 36 ++++++++++++++++++++++++++++--------
1 file changed, 28 insertions(+), 8 deletions(-)
diff --git a/libavcodec/opus.c b/libavcodec/opus.c
index 308d104212..6aebb40155 100644
--- a/libavcodec/opus.c
+++ b/libavcodec/opus.c
@@ -347,7 +347,7 @@ av_cold int ff_opus_parse_extradata(AVCodecContext *avctx,
streams = 1;
stereo_streams = channels - 1;
channel_map = default_channel_map;
- } else if (map_type == 1 || map_type == 255) {
+ } else if (map_type == 1 || map_type == 2 || map_type == 255) {
if (extradata_size < 21 + channels) {
av_log(avctx, AV_LOG_ERROR, "Invalid extradata size: %d\n",
extradata_size);
@@ -363,6 +363,7 @@ av_cold int ff_opus_parse_extradata(AVCodecContext *avctx,
return AVERROR_INVALIDDATA;
}
+ layout = 0;
if (map_type == 1) {
if (channels > 8) {
av_log(avctx, AV_LOG_ERROR,
@@ -371,8 +372,24 @@ av_cold int ff_opus_parse_extradata(AVCodecContext *avctx,
}
layout = ff_vorbis_ch_layouts[channels - 1].u.mask;
channel_reorder = channel_reorder_vorbis;
- } else
- layout = 0;
+ } else if (map_type == 2) {
+ int ambisonic_order = ff_sqrt(channels) - 1;
+ int idx = (ambisonic_order + 1) * (ambisonic_order + 1);
+ if (channels <= 227 && (channels == idx || channels == idx + 2)) {
+ av_channel_layout_uninit(&avctx->ch_layout);
+ avctx->ch_layout.order = AV_CHANNEL_ORDER_AMBISONIC;
+ avctx->ch_layout.nb_channels = channels;
+
+ /* ACN order, followed by two optional channels of non-diegetic stereo */
+ if (idx != channels)
+ avctx->ch_layout.u.mask = AV_CH_LAYOUT_STEREO;
+ } else {
+ av_log(avctx, AV_LOG_ERROR, "Channel map 2 is only valid for "
+ "channel counts equal to (n + 1)^2 + 2j for {n,j} >= 0 "
+ "(max 227 channels).\n");
+ return AVERROR_INVALIDDATA;
+ }
+ }
Seems fine.
Vittorio Giovara
2017-06-28 22:11:04 UTC
Permalink
Signed-off-by: Vittorio Giovara <***@gmail.com>
---
libavformat/avformat.h | 6 ++++++
libavformat/dump.c | 2 ++
2 files changed, 8 insertions(+)

diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index 1bf66b15d1..47f7a445dd 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -673,6 +673,12 @@ typedef struct AVIndexEntry {
* It can also be accessed at any time in AVStream.attached_pic.
*/
#define AV_DISPOSITION_ATTACHED_PIC 0x0400
+/**
+ * The stream is intended to be mixed with a spatial audio track. For example,
+ * it could be used for narration or stereo music, and may remain unchanged by
+ * listener head rotation.
+ */
+#define AV_DISPOSITION_NON_DIEGETIC 0x1000

typedef struct AVStreamInternal AVStreamInternal;

diff --git a/libavformat/dump.c b/libavformat/dump.c
index e1f6848547..b29f0ad834 100644
--- a/libavformat/dump.c
+++ b/libavformat/dump.c
@@ -482,6 +482,8 @@ static void dump_stream_format(AVFormatContext *ic, int i,
av_log(NULL, AV_LOG_INFO, " (visual impaired)");
if (st->disposition & AV_DISPOSITION_CLEAN_EFFECTS)
av_log(NULL, AV_LOG_INFO, " (clean effects)");
+ if (st->disposition & AV_DISPOSITION_NON_DIEGETIC)
+ av_log(NULL, AV_LOG_INFO, " (non diegetic)");
av_log(NULL, AV_LOG_INFO, "\n");

dump_metadata(NULL, st->metadata, " ");
--
2.13.1
Diego Biurrun
2017-06-29 08:02:35 UTC
Permalink
Post by Vittorio Giovara
---
libavformat/avformat.h | 6 ++++++
libavformat/dump.c | 2 ++
2 files changed, 8 insertions(+)
non-diegetic
Post by Vittorio Giovara
--- a/libavformat/dump.c
+++ b/libavformat/dump.c
@@ -482,6 +482,8 @@ static void dump_stream_format(AVFormatContext *ic, int i,
if (st->disposition & AV_DISPOSITION_CLEAN_EFFECTS)
av_log(NULL, AV_LOG_INFO, " (clean effects)");
+ if (st->disposition & AV_DISPOSITION_NON_DIEGETIC)
+ av_log(NULL, AV_LOG_INFO, " (non diegetic)");
same

Diego
Vittorio Giovara
2017-06-29 16:59:20 UTC
Permalink
Post by Vittorio Giovara
Post by Vittorio Giovara
---
libavformat/avformat.h | 6 ++++++
libavformat/dump.c | 2 ++
2 files changed, 8 insertions(+)
non-diegetic
Post by Vittorio Giovara
--- a/libavformat/dump.c
+++ b/libavformat/dump.c
@@ -482,6 +482,8 @@ static void dump_stream_format(AVFormatContext *ic, int i,
if (st->disposition & AV_DISPOSITION_CLEAN_EFFECTS)
av_log(NULL, AV_LOG_INFO, " (clean effects)");
+ if (st->disposition & AV_DISPOSITION_NON_DIEGETIC)
+ av_log(NULL, AV_LOG_INFO, " (non diegetic)");
same
applied locally
--
Vittorio
Vittorio Giovara
2017-06-28 22:11:05 UTC
Permalink
As defined by Google's Spatial Audio RFC.

Signed-off-by: Vittorio Giovara <***@gmail.com>
---
libavformat/mov.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 98 insertions(+)

diff --git a/libavformat/mov.c b/libavformat/mov.c
index c90b5fa108..48fd865411 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -3459,6 +3459,102 @@ static int mov_read_uuid(MOVContext *c, AVIOContext *pb, MOVAtom atom)
return 0;
}

+static int mov_read_SA3D(MOVContext *c, AVIOContext *pb, MOVAtom atom)
+{
+ AVStream *st;
+ MOVStreamContext *sc;
+ int i, version, type;
+ int ambisonic_order, channel_order, normalization, channel_count;
+
+ if (c->fc->nb_streams < 1)
+ return 0;
+
+ st = c->fc->streams[c->fc->nb_streams - 1];
+ sc = st->priv_data;
+
+ if (atom.size < 16) {
+ av_log(c->fc, AV_LOG_ERROR, "SA3D audio box too small\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ version = avio_r8(pb);
+ if (version) {
+ av_log(c->fc, AV_LOG_WARNING, "Unsupported SA3D box version %d\n", version);
+ return 0;
+ }
+
+ type = avio_r8(pb);
+ if (type) {
+ av_log(c->fc, AV_LOG_WARNING,
+ "Unsupported ambisonic type %d\n", type);
+ return 0;
+ }
+
+ ambisonic_order = avio_rb32(pb);
+
+ channel_order = avio_r8(pb);
+ if (channel_order) {
+ av_log(c->fc, AV_LOG_WARNING,
+ "Unsupported channel_order %d\n", channel_order);
+ return 0;
+ }
+
+ normalization = avio_r8(pb);
+ if (normalization) {
+ av_log(c->fc, AV_LOG_WARNING,
+ "Unsupported normalization %d\n", normalization);
+ return 0;
+ }
+
+ channel_count = avio_rb32(pb);
+ if (ambisonic_order != sqrt(channel_count) - 1) {
+ av_log(c->fc, AV_LOG_ERROR,
+ "Invalid number of channels (%d / %d)\n",
+ channel_count, ambisonic_order);
+ return 0;
+ }
+
+ for (i = 0; i < channel_count; i++) {
+ if (i != avio_rb32(pb)) {
+ av_log(c->fc, AV_LOG_WARNING,
+ "Ambisonic channel reordering is not supported\n");
+ return 0;
+ }
+ }
+
+ av_channel_layout_uninit(&st->codecpar->ch_layout);
+ st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_AMBISONIC;
+ st->codecpar->ch_layout.nb_channels = channel_count;
+
+ return 0;
+}
+
+static int mov_read_SAND(MOVContext *c, AVIOContext *pb, MOVAtom atom)
+{
+ AVStream *st;
+ int version;
+
+ if (c->fc->nb_streams < 1)
+ return 0;
+
+ st = c->fc->streams[c->fc->nb_streams - 1];
+
+ if (atom.size < 5) {
+ av_log(c->fc, AV_LOG_ERROR, "Empty SAND audio box\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ version = avio_r8(pb);
+ if (version) {
+ av_log(c->fc, AV_LOG_WARNING, "Unsupported SAND box version %d\n", version);
+ return 0;
+ }
+
+ st->disposition |= AV_DISPOSITION_NON_DIEGETIC;
+
+ return 0;
+}
+
static const MOVParseTableEntry mov_default_parse_table[] = {
{ MKTAG('a','v','s','s'), mov_read_extradata },
{ MKTAG('c','h','p','l'), mov_read_chpl },
@@ -3523,6 +3619,8 @@ static const MOVParseTableEntry mov_default_parse_table[] = {
{ MKTAG('s','t','3','d'), mov_read_st3d }, /* stereoscopic 3D video box */
{ MKTAG('s','v','3','d'), mov_read_sv3d }, /* spherical video box */
{ MKTAG('u','u','i','d'), mov_read_uuid }, /* universal unique identifier */
+{ MKTAG('S','A','3','D'), mov_read_SA3D }, /* ambisonic audio box */
+{ MKTAG('S','A','N','D'), mov_read_SAND }, /* non diegetic audio box */
{ MKTAG('-','-','-','-'), mov_read_custom },
{ 0, NULL }
};
--
2.13.1
Vittorio Giovara
2017-06-28 22:11:06 UTC
Permalink
The defacto mov standard mandates support for PCM and AAC: only the
latter decoder overrides the channel layout passed by the container,
so let this happen only when the layout order is native (or unspecified).

On the encoding side, until full ambisonic channel layout conversion
is implemented, add a temporary layout to allow pass-through transcoding
of files tagged with this specification.

Signed-off-by: Vittorio Giovara <***@gmail.com>
---
libavcodec/aacdec.c | 13 ++++++++-----
libavcodec/libfdk-aacdec.c | 6 ++++--
libavcodec/libfdk-aacenc.c | 3 ++-
3 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/libavcodec/aacdec.c b/libavcodec/aacdec.c
index ab184b8634..33b6e3a40a 100644
--- a/libavcodec/aacdec.c
+++ b/libavcodec/aacdec.c
@@ -494,11 +494,14 @@ FF_ENABLE_DEPRECATION_WARNINGS
}
}

- av_channel_layout_uninit(&ac->oc[1].ch_layout);
- av_channel_layout_from_mask(&ac->oc[1].ch_layout, layout);
- ret = av_channel_layout_copy(&avctx->ch_layout, &ac->oc[1].ch_layout);
- if (ret < 0)
- return ret;
+ if (avctx->ch_layout.order == AV_CHANNEL_ORDER_NATIVE ||
+ avctx->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) {
+ av_channel_layout_uninit(&ac->oc[1].ch_layout);
+ av_channel_layout_from_mask(&ac->oc[1].ch_layout, layout);
+ ret = av_channel_layout_copy(&avctx->ch_layout, &ac->oc[1].ch_layout);
+ if (ret < 0)
+ return ret;
+ }
#if FF_API_OLD_CHANNEL_LAYOUT
FF_DISABLE_DEPRECATION_WARNINGS
avctx->channels = avctx->ch_layout.nb_channels;
diff --git a/libavcodec/libfdk-aacdec.c b/libavcodec/libfdk-aacdec.c
index 6a77e90392..a8eeb6a1c9 100644
--- a/libavcodec/libfdk-aacdec.c
+++ b/libavcodec/libfdk-aacdec.c
@@ -184,8 +184,10 @@ static int get_stream_info(AVCodecContext *avctx)
}
}

- av_channel_layout_uninit(&avctx->ch_layout);
- av_channel_layout_from_mask(&avctx->ch_layout, ch_layout);
+ if (avctx->ch_layout.order == AV_CHANNEL_ORDER_NATIVE) {
+ av_channel_layout_uninit(&avctx->ch_layout);
+ av_channel_layout_from_mask(&avctx->ch_layout, ch_layout);
+ }
if (!ch_error && avctx->ch_layout.nb_channels != info->numChannels) {
av_log(avctx, AV_LOG_WARNING, "unsupported channel configuration\n");
ch_error = 1;
diff --git a/libavcodec/libfdk-aacenc.c b/libavcodec/libfdk-aacenc.c
index f92c14d65f..ec29e1c6ad 100644
--- a/libavcodec/libfdk-aacenc.c
+++ b/libavcodec/libfdk-aacenc.c
@@ -410,7 +410,7 @@ static const uint64_t aac_channel_layout[] = {
};
#endif /* FF_API_OLD_CHANNEL_LAYOUT */

-static const AVChannelLayout aac_ch_layouts[16] = {
+static const AVChannelLayout aac_ch_layouts[17] = {
AV_CHANNEL_LAYOUT_MONO,
AV_CHANNEL_LAYOUT_STEREO,
AV_CHANNEL_LAYOUT_SURROUND,
@@ -421,6 +421,7 @@ static const AVChannelLayout aac_ch_layouts[16] = {
AV_CHANNEL_LAYOUT_7POINT1_WIDE_BACK,
AV_CHANNEL_LAYOUT_7POINT1,
#endif
+ AV_CHANNEL_LAYOUT_AMBISONIC_FIRST_ORDER,
{ 0 },
};
--
2.13.1
Diego Biurrun
2017-06-29 08:03:42 UTC
Permalink
Post by Vittorio Giovara
The defacto mov standard mandates support for PCM and AAC: only the
de facto MOV

Diego
Vittorio Giovara
2017-06-28 22:10:59 UTC
Permalink
This patch contains the following commits:

libfdk-aac: convert to new channel layout API

8svx: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

adpcm: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

adx: convert to new channel layout API

alac: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

als: convert to new channel layout API

amrnbdec: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

amrwbdec: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

atrac1: convert to new channel layout API

atrac3: convert to new channel layout API

atrac3plus: convert to new channel layout API

apedec: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

binkaudio: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

bmvaudio: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

cng: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

cook: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

dcadec: convert to new channel layout API

dpcm: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

dsicinav: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

dss_sp: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

flacdec: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

g722: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

g723_1: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

g726: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

gsmdec: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

imc: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

libdcadec: convert to new channel layout API

libilbcdec: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

libgsm: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

libopencore-amr: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

libopus: convert to new channel layout API

Drop the multiple validation steps for the decoding part.

Signed-off-by: Vittorio Giovara <***@gmail.com>

libspeexdec: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

mace: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

metasound: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

mlpdec: convert to new channel layout API

mpc7: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

mpc8: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

mpegaudiodec: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

nellymoser: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

on2avc: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

opus: convert to new channel layout API

pafaudio: convert to new channel layout API

pcm: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

psymodel: convert to new channel layout API

qcelpdec: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

qdm2: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

ra144: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

ra288: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

ralf: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

roqaudioenc: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

s302m: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

shorten: convert to new channel layout API

sipr: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

smacker: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

takdec: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

truespeech: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

tta: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

twinvq: convert to new channel layout API

vima: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

vmdaudio: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

vorbis: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

wavpack: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

wma: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

wmaprodec: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

wmalosslessdec: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>

ws-snd1: convert to new channel layout API

Signed-off-by: Vittorio Giovara <***@gmail.com>
---
libavcodec/8svx.c | 15 +++---
libavcodec/adpcm.c | 57 +++++++++++-----------
libavcodec/adpcmenc.c | 92 +++++++++++++++++++-----------------
libavcodec/adx.c | 16 +++++--
libavcodec/adxdec.c | 6 +--
libavcodec/adxenc.c | 11 +++--
libavcodec/alac.c | 18 +++----
libavcodec/alac_data.c | 12 +++++
libavcodec/alac_data.h | 6 +++
libavcodec/alacenc.c | 20 +++++---
libavcodec/alsdec.c | 65 +++++++++++++++-----------
libavcodec/amrnbdec.c | 6 +--
libavcodec/amrwbdec.c | 6 +--
libavcodec/apedec.c | 9 ++--
libavcodec/atrac1.c | 10 ++--
libavcodec/atrac3.c | 26 ++++++-----
libavcodec/atrac3plusdec.c | 25 +++++-----
libavcodec/binkaudio.c | 17 +++----
libavcodec/bmvaudio.c | 4 +-
libavcodec/cngdec.c | 3 +-
libavcodec/cngenc.c | 6 +--
libavcodec/cook.c | 22 +++++----
libavcodec/cook_parser.c | 4 +-
libavcodec/dca.h | 2 +
libavcodec/dca_xll.c | 6 +--
libavcodec/dcadec.c | 54 +++++++++++++--------
libavcodec/dpcm.c | 14 +++---
libavcodec/dsicinaudio.c | 4 +-
libavcodec/dss_sp.c | 4 +-
libavcodec/flac.c | 37 ++++++++-------
libavcodec/flac.h | 2 +-
libavcodec/flac_parser.c | 7 +--
libavcodec/flacdec.c | 10 ++--
libavcodec/flacenc.c | 2 +-
libavcodec/g722dec.c | 4 +-
libavcodec/g722enc.c | 8 ++--
libavcodec/g723_1dec.c | 4 +-
libavcodec/g723_1enc.c | 8 ++--
libavcodec/g726.c | 6 +--
libavcodec/gsmdec.c | 4 +-
libavcodec/imc.c | 22 ++++-----
libavcodec/libdcadec.c | 6 +--
libavcodec/libfdk-aacdec.c | 32 ++++++++-----
libavcodec/libfdk-aacenc.c | 35 +++++++++++---
libavcodec/libgsmdec.c | 4 +-
libavcodec/libgsmenc.c | 4 +-
libavcodec/libilbc.c | 4 +-
libavcodec/libopencore-amr.c | 8 ++--
libavcodec/libopusdec.c | 42 +++++++----------
libavcodec/libopusenc.c | 32 +++++++------
libavcodec/libspeexdec.c | 18 +++----
libavcodec/mace.c | 11 +++--
libavcodec/metasound.c | 31 ++++++------
libavcodec/mlp_parser.c | 34 ++------------
libavcodec/mlp_parser.h | 4 +-
libavcodec/mlpdec.c | 96 ++++++++++++++++++++++----------------
libavcodec/mpc7.c | 7 +--
libavcodec/mpc8.c | 5 +-
libavcodec/mpegaudio_parser.c | 2 +-
libavcodec/mpegaudiodec_template.c | 37 ++++++++-------
libavcodec/mpegaudioenc.c | 11 ++++-
libavcodec/nellymoserdec.c | 4 +-
libavcodec/nellymoserenc.c | 6 +--
libavcodec/on2avc.c | 19 ++++----
libavcodec/opus.c | 16 ++++---
libavcodec/opusdec.c | 13 +++---
libavcodec/pafaudio.c | 5 +-
libavcodec/pcm-bluray.c | 36 +++++++-------
libavcodec/pcm-dvd.c | 24 ++++++----
libavcodec/pcm.c | 23 ++++-----
libavcodec/psymodel.c | 8 ++--
libavcodec/qcelpdec.c | 4 +-
libavcodec/qdm2.c | 6 +--
libavcodec/ra144dec.c | 4 +-
libavcodec/ra144enc.c | 6 +--
libavcodec/ra288.c | 4 +-
libavcodec/ralf.c | 16 +++----
libavcodec/roqaudioenc.c | 20 ++++----
libavcodec/s302m.c | 15 ++++--
libavcodec/shorten.c | 6 ++-
libavcodec/sipr.c | 4 +-
libavcodec/smacker.c | 11 +++--
libavcodec/takdec.c | 40 +++++++++-------
libavcodec/truespeech.c | 7 +--
libavcodec/tta.c | 15 ++++--
libavcodec/twinvq.c | 20 ++++----
libavcodec/twinvqdec.c | 18 +++----
libavcodec/vima.c | 5 +-
libavcodec/vmdaudio.c | 22 ++++-----
libavcodec/vorbis.h | 5 ++
libavcodec/vorbis_data.c | 18 +++++++
libavcodec/vorbisdec.c | 18 ++++---
libavcodec/vorbisenc.c | 4 +-
libavcodec/wavpack.c | 19 ++++----
libavcodec/wma.c | 13 +++---
libavcodec/wmadec.c | 25 +++++-----
libavcodec/wmaenc.c | 27 +++++------
libavcodec/wmalosslessdec.c | 36 ++++++--------
libavcodec/wmaprodec.c | 66 ++++++++++++--------------
libavcodec/wmavoice.c | 4 +-
libavcodec/ws-snd1.c | 4 +-
tests/fate/lossless-audio.mak | 2 +-
102 files changed, 915 insertions(+), 780 deletions(-)

diff --git a/libavcodec/8svx.c b/libavcodec/8svx.c
index fe90b168e3..540e461d5a 100644
--- a/libavcodec/8svx.c
+++ b/libavcodec/8svx.c
@@ -85,6 +85,7 @@ static int eightsvx_decode_frame(AVCodecContext *avctx, void *data,
{
EightSvxContext *esc = avctx->priv_data;
AVFrame *frame = data;
+ int channels = avctx->ch_layout.nb_channels;
int buf_size;
int ch, ret;
int is_compr = (avctx->codec_id != AV_CODEC_ID_PCM_S8_PLANAR);
@@ -92,9 +93,9 @@ static int eightsvx_decode_frame(AVCodecContext *avctx, void *data,
/* for the first packet, copy data to buffer */
if (avpkt->data) {
int hdr_size = is_compr ? 2 : 0;
- int chan_size = (avpkt->size - hdr_size * avctx->channels) / avctx->channels;
+ int chan_size = (avpkt->size - hdr_size * channels) / channels;

- if (avpkt->size < hdr_size * avctx->channels) {
+ if (avpkt->size < hdr_size * channels) {
av_log(avctx, AV_LOG_ERROR, "packet size is too small\n");
return AVERROR_INVALIDDATA;
}
@@ -105,7 +106,7 @@ static int eightsvx_decode_frame(AVCodecContext *avctx, void *data,

if (is_compr) {
esc->fib_acc[0] = avpkt->data[1] + 128;
- if (avctx->channels == 2)
+ if (channels == 2)
esc->fib_acc[1] = avpkt->data[2+chan_size+1] + 128;
}

@@ -113,14 +114,14 @@ static int eightsvx_decode_frame(AVCodecContext *avctx, void *data,
esc->data_size = chan_size;
if (!(esc->data[0] = av_malloc(chan_size)))
return AVERROR(ENOMEM);
- if (avctx->channels == 2) {
+ if (channels == 2) {
if (!(esc->data[1] = av_malloc(chan_size))) {
av_freep(&esc->data[0]);
return AVERROR(ENOMEM);
}
}
memcpy(esc->data[0], &avpkt->data[hdr_size], chan_size);
- if (avctx->channels == 2)
+ if (channels == 2)
memcpy(esc->data[1], &avpkt->data[2*hdr_size+chan_size], chan_size);
}
if (!esc->data[0]) {
@@ -142,7 +143,7 @@ static int eightsvx_decode_frame(AVCodecContext *avctx, void *data,
return ret;
}

- for (ch = 0; ch < avctx->channels; ch++) {
+ for (ch = 0; ch < channels; ch++) {
if (is_compr) {
delta_decode(frame->data[ch], &esc->data[ch][esc->data_idx],
buf_size, &esc->fib_acc[ch], esc->table);
@@ -164,7 +165,7 @@ static av_cold int eightsvx_decode_init(AVCodecContext *avctx)
{
EightSvxContext *esc = avctx->priv_data;

- if (avctx->channels < 1 || avctx->channels > 2) {
+ if (avctx->ch_layout.nb_channels < 1 || avctx->ch_layout.nb_channels > 2) {
av_log(avctx, AV_LOG_ERROR, "8SVX does not support more than 2 channels\n");
return AVERROR_INVALIDDATA;
}
diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c
index fe51c0d008..dd66de246c 100644
--- a/libavcodec/adpcm.c
+++ b/libavcodec/adpcm.c
@@ -107,7 +107,8 @@ static av_cold int adpcm_decode_init(AVCodecContext * avctx)
max_channels = 6;
break;
}
- if (avctx->channels < min_channels || avctx->channels > max_channels) {
+ if (avctx->ch_layout.nb_channels < min_channels ||
+ avctx->ch_layout.nb_channels > max_channels) {
av_log(avctx, AV_LOG_ERROR, "Invalid number of channels\n");
return AVERROR(EINVAL);
}
@@ -369,6 +370,7 @@ static void adpcm_swf_decode(AVCodecContext *avctx, const uint8_t *buf, int buf_
ADPCMDecodeContext *c = avctx->priv_data;
BitstreamContext bc;
const int *table;
+ int channels = avctx->ch_layout.nb_channels;
int k0, signmask, nb_bits, count;
int size = buf_size*8;
int i;
@@ -381,17 +383,17 @@ static void adpcm_swf_decode(AVCodecContext *avctx, const uint8_t *buf, int buf_
k0 = 1 << (nb_bits-2);
signmask = 1 << (nb_bits-1);

- while (bitstream_tell(&bc) <= size - 22 * avctx->channels) {
- for (i = 0; i < avctx->channels; i++) {
+ while (bitstream_tell(&bc) <= size - 22 * channels) {
+ for (i = 0; i < channels; i++) {
*samples++ =
c->status[i].predictor = bitstream_read_signed(&bc, 16);
c->status[i].step_index = bitstream_read(&bc, 6);
}

- for (count = 0; bitstream_tell(&bc) <= size - nb_bits * avctx->channels && count < 4095; count++) {
+ for (count = 0; bitstream_tell(&bc) <= size - nb_bits * channels && count < 4095; count++) {
int i;

- for (i = 0; i < avctx->channels; i++) {
+ for (i = 0; i < channels; i++) {
// similar to IMA adpcm
int delta = bitstream_read(&bc, nb_bits);
int step = ff_adpcm_step_table[c->status[i].step_index];
@@ -436,7 +438,7 @@ static int get_nb_samples(AVCodecContext *avctx, GetByteContext *gb,
{
ADPCMDecodeContext *s = avctx->priv_data;
int nb_samples = 0;
- int ch = avctx->channels;
+ int ch = avctx->ch_layout.nb_channels;
int has_coded_samples = 0;
int header_size;

@@ -594,6 +596,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
int buf_size = avpkt->size;
ADPCMDecodeContext *c = avctx->priv_data;
ADPCMChannelStatus *cs;
+ int channels = avctx->ch_layout.nb_channels;
int n, m, channel, i;
short *samples;
int16_t **samples_p;
@@ -626,13 +629,13 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
frame->nb_samples = nb_samples = coded_samples;
}

- st = avctx->channels == 2 ? 1 : 0;
+ st = channels == 2 ? 1 : 0;

switch(avctx->codec->id) {
case AV_CODEC_ID_ADPCM_IMA_QT:
/* In QuickTime, IMA is encoded by chunks of 34 bytes (=64 samples).
Channel data is interleaved per-chunk. */
- for (channel = 0; channel < avctx->channels; channel++) {
+ for (channel = 0; channel < channels; channel++) {
int predictor;
int step_index;
cs = &(c->status[channel]);
@@ -671,7 +674,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
}
break;
case AV_CODEC_ID_ADPCM_IMA_WAV:
- for(i=0; i<avctx->channels; i++){
+ for (i = 0; i < channels; i++) {
cs = &(c->status[i]);
cs->predictor = samples_p[i][0] = sign_extend(bytestream2_get_le16u(&gb), 16);

@@ -684,7 +687,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
}

for (n = 0; n < (nb_samples - 1) / 8; n++) {
- for (i = 0; i < avctx->channels; i++) {
+ for (i = 0; i < channels; i++) {
cs = &c->status[i];
samples = &samples_p[i][1 + n * 8];
for (m = 0; m < 8; m += 2) {
@@ -696,10 +699,10 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
}
break;
case AV_CODEC_ID_ADPCM_4XM:
- for (i = 0; i < avctx->channels; i++)
+ for (i = 0; i < channels; i++)
c->status[i].predictor = sign_extend(bytestream2_get_le16u(&gb), 16);

- for (i = 0; i < avctx->channels; i++) {
+ for (i = 0; i < channels; i++) {
c->status[i].step_index = sign_extend(bytestream2_get_le16u(&gb), 16);
if (c->status[i].step_index > 88u) {
av_log(avctx, AV_LOG_ERROR, "ERROR: step_index[%d] = %i\n",
@@ -708,7 +711,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
}
}

- for (i = 0; i < avctx->channels; i++) {
+ for (i = 0; i < channels; i++) {
samples = (int16_t *)frame->data[i];
cs = &c->status[i];
for (n = nb_samples >> 1; n > 0; n--) {
@@ -762,7 +765,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
break;
}
case AV_CODEC_ID_ADPCM_IMA_DK4:
- for (channel = 0; channel < avctx->channels; channel++) {
+ for (channel = 0; channel < channels; channel++) {
cs = &c->status[channel];
cs->predictor = *samples++ = sign_extend(bytestream2_get_le16u(&gb), 16);
cs->step_index = sign_extend(bytestream2_get_le16u(&gb), 16);
@@ -784,7 +787,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
int nibble;
int decode_top_nibble_next = 0;
int diff_channel;
- const int16_t *samples_end = samples + avctx->channels * nb_samples;
+ const int16_t *samples_end = samples + channels * nb_samples;

bytestream2_skipu(&gb, 10);
c->status[0].predictor = sign_extend(bytestream2_get_le16u(&gb), 16);
@@ -840,7 +843,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
break;
}
case AV_CODEC_ID_ADPCM_IMA_ISS:
- for (channel = 0; channel < avctx->channels; channel++) {
+ for (channel = 0; channel < channels; channel++) {
cs = &c->status[channel];
cs->predictor = sign_extend(bytestream2_get_le16u(&gb), 16);
cs->step_index = sign_extend(bytestream2_get_le16u(&gb), 16);
@@ -875,7 +878,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
break;
case AV_CODEC_ID_ADPCM_IMA_WS:
if (c->vqa_version == 3) {
- for (channel = 0; channel < avctx->channels; channel++) {
+ for (channel = 0; channel < channels; channel++) {
int16_t *smp = samples_p[channel];

for (n = nb_samples / 2; n > 0; n--) {
@@ -886,12 +889,12 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
}
} else {
for (n = nb_samples / 2; n > 0; n--) {
- for (channel = 0; channel < avctx->channels; channel++) {
+ for (channel = 0; channel < channels; channel++) {
int v = bytestream2_get_byteu(&gb);
*samples++ = adpcm_ima_expand_nibble(&c->status[channel], v >> 4 , 3);
samples[st] = adpcm_ima_expand_nibble(&c->status[channel], v & 0x0F, 3);
}
- samples += avctx->channels;
+ samples += channels;
}
}
bytestream2_seek(&gb, 0, SEEK_END);
@@ -900,12 +903,12 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
{
int16_t *out0 = samples_p[0];
int16_t *out1 = samples_p[1];
- int samples_per_block = 28 * (3 - avctx->channels) * 4;
+ int samples_per_block = 28 * (3 - channels) * 4;
int sample_offset = 0;
while (bytestream2_get_bytes_left(&gb) >= 128) {
if ((ret = xa_decode(avctx, out0, out1, buf + bytestream2_tell(&gb),
&c->status[0], &c->status[1],
- avctx->channels, sample_offset)) < 0)
+ channels, sample_offset)) < 0)
return ret;
bytestream2_skipu(&gb, 128);
sample_offset += samples_per_block;
@@ -993,7 +996,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
{
int coeff[2][2], shift[2];

- for(channel = 0; channel < avctx->channels; channel++) {
+ for(channel = 0; channel < channels; channel++) {
int byte = bytestream2_get_byteu(&gb);
for (i=0; i<2; i++)
coeff[channel][i] = ea_adpcm_table[(byte >> 4) + 4*i];
@@ -1005,7 +1008,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
byte[0] = bytestream2_get_byteu(&gb);
if (st) byte[1] = bytestream2_get_byteu(&gb);
for(i = 4; i >= 0; i-=4) { /* Pairwise samples LL RR (st) or LL LL (mono) */
- for(channel = 0; channel < avctx->channels; channel++) {
+ for(channel = 0; channel < channels; channel++) {
int sample = sign_extend(byte[channel] >> i, 4) << shift[channel];
sample = (sample +
c->status[channel].sample1 * coeff[channel][0] +
@@ -1035,12 +1038,12 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
int count = 0;
int offsets[6];

- for (channel=0; channel<avctx->channels; channel++)
+ for (channel = 0; channel < channels; channel++)
offsets[channel] = (big_endian ? bytestream2_get_be32(&gb) :
bytestream2_get_le32(&gb)) +
- (avctx->channels + 1) * 4;
+ (channels + 1) * 4;

- for (channel=0; channel<avctx->channels; channel++) {
+ for (channel = 0; channel < channels; channel++) {
bytestream2_seek(&gb, offsets[channel], SEEK_SET);
samplesC = samples_p[channel];

@@ -1101,7 +1104,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
break;
}
case AV_CODEC_ID_ADPCM_EA_XAS:
- for (channel=0; channel<avctx->channels; channel++) {
+ for (channel = 0; channel < channels; channel++) {
int coeff[2][4], shift[4];
int16_t *s = samples_p[channel];
for (n = 0; n < 4; n++, s += 32) {
diff --git a/libavcodec/adpcmenc.c b/libavcodec/adpcmenc.c
index 0757624aef..3acc35bbaa 100644
--- a/libavcodec/adpcmenc.c
+++ b/libavcodec/adpcmenc.c
@@ -64,11 +64,7 @@ static av_cold int adpcm_encode_init(AVCodecContext *avctx)
uint8_t *extradata;
int i;
int ret = AVERROR(ENOMEM);
-
- if (avctx->channels > 2) {
- av_log(avctx, AV_LOG_ERROR, "only stereo or mono is supported\n");
- return AVERROR(EINVAL);
- }
+ int channels = avctx->ch_layout.nb_channels;

if (avctx->trellis && (unsigned)avctx->trellis > 16U) {
av_log(avctx, AV_LOG_ERROR, "invalid trellis size\n");
@@ -94,21 +90,21 @@ static av_cold int adpcm_encode_init(AVCodecContext *avctx)
case AV_CODEC_ID_ADPCM_IMA_WAV:
/* each 16 bits sample gives one nibble
and we have 4 bytes per channel overhead */
- avctx->frame_size = (BLKSIZE - 4 * avctx->channels) * 8 /
- (4 * avctx->channels) + 1;
+ avctx->frame_size = (BLKSIZE - 4 * channels) * 8 /
+ (4 * channels) + 1;
/* seems frame_size isn't taken into account...
have to buffer the samples :-( */
avctx->block_align = BLKSIZE;
break;
case AV_CODEC_ID_ADPCM_IMA_QT:
avctx->frame_size = 64;
- avctx->block_align = 34 * avctx->channels;
+ avctx->block_align = 34 * channels;
break;
case AV_CODEC_ID_ADPCM_MS:
/* each 16 bits sample gives one nibble
and we have 7 bytes per channel overhead */
- avctx->frame_size = (BLKSIZE - 7 * avctx->channels) * 2 /
- avctx->channels + 2;
+ avctx->frame_size = (BLKSIZE - 7 * channels) * 2 /
+ channels + 2;
avctx->block_align = BLKSIZE;
if (!(avctx->extradata = av_malloc(32 + AV_INPUT_BUFFER_PADDING_SIZE)))
goto error;
@@ -122,7 +118,7 @@ static av_cold int adpcm_encode_init(AVCodecContext *avctx)
}
break;
case AV_CODEC_ID_ADPCM_YAMAHA:
- avctx->frame_size = BLKSIZE * 2 / avctx->channels;
+ avctx->frame_size = BLKSIZE * 2 / channels;
avctx->block_align = BLKSIZE;
break;
case AV_CODEC_ID_ADPCM_SWF:
@@ -474,13 +470,14 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
uint8_t *dst;
ADPCMEncodeContext *c = avctx->priv_data;
uint8_t *buf;
+ int channels = avctx->ch_layout.nb_channels;

samples = (const int16_t *)frame->data[0];
samples_p = (int16_t **)frame->extended_data;
- st = avctx->channels == 2;
+ st = channels == 2;

if (avctx->codec_id == AV_CODEC_ID_ADPCM_SWF)
- pkt_size = (2 + avctx->channels * (22 + 4 * (frame->nb_samples - 1)) + 7) / 8;
+ pkt_size = (2 + channels * (22 + 4 * (frame->nb_samples - 1)) + 7) / 8;
else
pkt_size = avctx->block_align;
if ((ret = ff_alloc_packet(avpkt, pkt_size))) {
@@ -496,7 +493,7 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,

blocks = (frame->nb_samples - 1) / 8;

- for (ch = 0; ch < avctx->channels; ch++) {
+ for (ch = 0; ch < channels; ch++) {
ADPCMChannelStatus *status = &c->status[ch];
status->prev_sample = samples_p[ch][0];
/* status->step_index = 0;
@@ -508,14 +505,14 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,

/* stereo: 4 bytes (8 samples) for left, 4 bytes for right */
if (avctx->trellis > 0) {
- FF_ALLOC_OR_GOTO(avctx, buf, avctx->channels * blocks * 8, error);
- for (ch = 0; ch < avctx->channels; ch++) {
+ FF_ALLOC_OR_GOTO(avctx, buf, channels * blocks * 8, error);
+ for (ch = 0; ch < channels; ch++) {
adpcm_compress_trellis(avctx, &samples_p[ch][1],
buf + ch * blocks * 8, &c->status[ch],
blocks * 8, 1);
}
for (i = 0; i < blocks; i++) {
- for (ch = 0; ch < avctx->channels; ch++) {
+ for (ch = 0; ch < channels; ch++) {
uint8_t *buf1 = buf + ch * blocks * 8 + i * 8;
for (j = 0; j < 8; j += 2)
*dst++ = buf1[j] | (buf1[j + 1] << 4);
@@ -524,7 +521,7 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
av_free(buf);
} else {
for (i = 0; i < blocks; i++) {
- for (ch = 0; ch < avctx->channels; ch++) {
+ for (ch = 0; ch < channels; ch++) {
ADPCMChannelStatus *status = &c->status[ch];
const int16_t *smp = &samples_p[ch][1 + i * 8];
for (j = 0; j < 8; j += 2) {
@@ -542,7 +539,7 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
PutBitContext pb;
init_put_bits(&pb, dst, pkt_size * 8);

- for (ch = 0; ch < avctx->channels; ch++) {
+ for (ch = 0; ch < channels; ch++) {
ADPCMChannelStatus *status = &c->status[ch];
put_bits(&pb, 9, (status->prev_sample & 0xFFFF) >> 7);
put_bits(&pb, 7, status->step_index);
@@ -578,7 +575,7 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
put_bits(&pb, 2, 2); // set 4-bit flash adpcm format

// init the encoder state
- for (i = 0; i < avctx->channels; i++) {
+ for (i = 0; i < channels; i++) {
// clip step so it fits 6 bits
c->status[i].step_index = av_clip(c->status[i].step_index, 0, 63);
put_sbits(&pb, 16, samples[i]);
@@ -588,23 +585,23 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,

if (avctx->trellis > 0) {
FF_ALLOC_OR_GOTO(avctx, buf, 2 * n, error);
- adpcm_compress_trellis(avctx, samples + avctx->channels, buf,
- &c->status[0], n, avctx->channels);
- if (avctx->channels == 2)
- adpcm_compress_trellis(avctx, samples + avctx->channels + 1,
+ adpcm_compress_trellis(avctx, samples + channels, buf,
+ &c->status[0], n, channels);
+ if (channels == 2)
+ adpcm_compress_trellis(avctx, samples + channels + 1,
buf + n, &c->status[1], n,
- avctx->channels);
+ channels);
for (i = 0; i < n; i++) {
put_bits(&pb, 4, buf[i]);
- if (avctx->channels == 2)
+ if (channels == 2)
put_bits(&pb, 4, buf[n + i]);
}
av_free(buf);
} else {
for (i = 1; i < frame->nb_samples; i++) {
put_bits(&pb, 4, adpcm_ima_compress_sample(&c->status[0],
- samples[avctx->channels * i]));
- if (avctx->channels == 2)
+ samples[channels * i]));
+ if (channels == 2)
put_bits(&pb, 4, adpcm_ima_compress_sample(&c->status[1],
samples[2 * i + 1]));
}
@@ -613,45 +610,45 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
break;
}
case AV_CODEC_ID_ADPCM_MS:
- for (i = 0; i < avctx->channels; i++) {
+ for (i = 0; i < channels; i++) {
int predictor = 0;
*dst++ = predictor;
c->status[i].coeff1 = ff_adpcm_AdaptCoeff1[predictor];
c->status[i].coeff2 = ff_adpcm_AdaptCoeff2[predictor];
}
- for (i = 0; i < avctx->channels; i++) {
+ for (i = 0; i < channels; i++) {
if (c->status[i].idelta < 16)
c->status[i].idelta = 16;
bytestream_put_le16(&dst, c->status[i].idelta);
}
- for (i = 0; i < avctx->channels; i++)
+ for (i = 0; i < channels; i++)
c->status[i].sample2= *samples++;
- for (i = 0; i < avctx->channels; i++) {
+ for (i = 0; i < channels; i++) {
c->status[i].sample1 = *samples++;
bytestream_put_le16(&dst, c->status[i].sample1);
}
- for (i = 0; i < avctx->channels; i++)
+ for (i = 0; i < channels; i++)
bytestream_put_le16(&dst, c->status[i].sample2);

if (avctx->trellis > 0) {
- n = avctx->block_align - 7 * avctx->channels;
+ n = avctx->block_align - 7 * channels;
FF_ALLOC_OR_GOTO(avctx, buf, 2 * n, error);
- if (avctx->channels == 1) {
+ if (channels == 1) {
adpcm_compress_trellis(avctx, samples, buf, &c->status[0], n,
- avctx->channels);
+ channels);
for (i = 0; i < n; i += 2)
*dst++ = (buf[i] << 4) | buf[i + 1];
} else {
adpcm_compress_trellis(avctx, samples, buf,
- &c->status[0], n, avctx->channels);
+ &c->status[0], n, channels);
adpcm_compress_trellis(avctx, samples + 1, buf + n,
- &c->status[1], n, avctx->channels);
+ &c->status[1], n, channels);
for (i = 0; i < n; i++)
*dst++ = (buf[i] << 4) | buf[n + i];
}
av_free(buf);
} else {
- for (i = 7 * avctx->channels; i < avctx->block_align; i++) {
+ for (i = 7 * channels; i < avctx->block_align; i++) {
int nibble;
nibble = adpcm_ms_compress_sample(&c->status[ 0], *samples++) << 4;
nibble |= adpcm_ms_compress_sample(&c->status[st], *samples++);
@@ -664,22 +661,22 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
if (avctx->trellis > 0) {
FF_ALLOC_OR_GOTO(avctx, buf, 2 * n * 2, error);
n *= 2;
- if (avctx->channels == 1) {
+ if (channels == 1) {
adpcm_compress_trellis(avctx, samples, buf, &c->status[0], n,
- avctx->channels);
+ channels);
for (i = 0; i < n; i += 2)
*dst++ = buf[i] | (buf[i + 1] << 4);
} else {
adpcm_compress_trellis(avctx, samples, buf,
- &c->status[0], n, avctx->channels);
+ &c->status[0], n, channels);
adpcm_compress_trellis(avctx, samples + 1, buf + n,
- &c->status[1], n, avctx->channels);
+ &c->status[1], n, channels);
for (i = 0; i < n; i++)
*dst++ = buf[i] | (buf[n + i] << 4);
}
av_free(buf);
} else
- for (n *= avctx->channels; n > 0; n--) {
+ for (n *= channels; n > 0; n--) {
int nibble;
nibble = adpcm_yamaha_compress_sample(&c->status[ 0], *samples++);
nibble |= adpcm_yamaha_compress_sample(&c->status[st], *samples++) << 4;
@@ -705,6 +702,12 @@ static const enum AVSampleFormat sample_fmts_p[] = {
AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_NONE
};

+static const AVChannelLayout ch_layouts[] = {
+ AV_CHANNEL_LAYOUT_MONO,
+ AV_CHANNEL_LAYOUT_STEREO,
+ { 0 },
+};
+
#define ADPCM_ENCODER(id_, name_, sample_fmts_, long_name_) \
AVCodec ff_ ## name_ ## _encoder = { \
.name = #name_, \
@@ -716,6 +719,7 @@ AVCodec ff_ ## name_ ## _encoder = { \
.encode2 = adpcm_encode_frame, \
.close = adpcm_encode_close, \
.sample_fmts = sample_fmts_, \
+ .ch_layouts = ch_layouts, \
}

ADPCM_ENCODER(AV_CODEC_ID_ADPCM_IMA_QT, adpcm_ima_qt, sample_fmts_p, "ADPCM IMA QuickTime");
diff --git a/libavcodec/adx.c b/libavcodec/adx.c
index d941d7b89c..4042d10343 100644
--- a/libavcodec/adx.c
+++ b/libavcodec/adx.c
@@ -38,7 +38,7 @@ void ff_adx_calculate_coeffs(int cutoff, int sample_rate, int bits, int *coeff)
int ff_adx_decode_header(AVCodecContext *avctx, const uint8_t *buf,
int bufsize, int *header_size, int *coeff)
{
- int offset, cutoff;
+ int offset, cutoff, channels;

if (bufsize < 24)
return AVERROR_INVALIDDATA;
@@ -58,18 +58,24 @@ int ff_adx_decode_header(AVCodecContext *avctx, const uint8_t *buf,
}

/* channels */
- avctx->channels = buf[7];
- if (avctx->channels <= 0 || avctx->channels > 2)
+ channels = buf[7];
+ if (channels <= 0 || channels > 2)
return AVERROR_INVALIDDATA;

+ if (avctx->ch_layout.nb_channels != channels) {
+ av_channel_layout_uninit(&avctx->ch_layout);
+ avctx->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ avctx->ch_layout.nb_channels = channels;
+ }
+
/* sample rate */
avctx->sample_rate = AV_RB32(buf + 8);
if (avctx->sample_rate < 1 ||
- avctx->sample_rate > INT_MAX / (avctx->channels * BLOCK_SIZE * 8))
+ avctx->sample_rate > INT_MAX / (channels * BLOCK_SIZE * 8))
return AVERROR_INVALIDDATA;

/* bit rate */
- avctx->bit_rate = avctx->sample_rate * avctx->channels * BLOCK_SIZE * 8 / BLOCK_SAMPLES;
+ avctx->bit_rate = avctx->sample_rate * channels * BLOCK_SIZE * 8 / BLOCK_SAMPLES;

/* LPC coefficients */
if (coeff) {
diff --git a/libavcodec/adxdec.c b/libavcodec/adxdec.c
index 86aaade846..9ab1314e17 100644
--- a/libavcodec/adxdec.c
+++ b/libavcodec/adxdec.c
@@ -47,7 +47,7 @@ static av_cold int adx_decode_init(AVCodecContext *avctx)
av_log(avctx, AV_LOG_ERROR, "error parsing ADX header\n");
return AVERROR_INVALIDDATA;
}
- c->channels = avctx->channels;
+ c->channels = avctx->ch_layout.nb_channels;
c->header_parsed = 1;
}

@@ -116,7 +116,7 @@ static int adx_decode_frame(AVCodecContext *avctx, void *data,
av_log(avctx, AV_LOG_ERROR, "error parsing ADX header\n");
return AVERROR_INVALIDDATA;
}
- c->channels = avctx->channels;
+ c->channels = avctx->ch_layout.nb_channels;
c->header_parsed = 1;
if (buf_size < header_size)
return AVERROR_INVALIDDATA;
@@ -131,7 +131,7 @@ static int adx_decode_frame(AVCodecContext *avctx, void *data,

/* if the packet is not an even multiple of BLOCK_SIZE, check for an EOF
packet */
- if (!num_blocks || buf_size % (BLOCK_SIZE * avctx->channels)) {
+ if (!num_blocks || buf_size % (BLOCK_SIZE * c->channels)) {
if (buf_size >= 4 && (AV_RB16(buf) & 0x8000)) {
c->eof = 1;
*got_frame_ptr = 0;
diff --git a/libavcodec/adxenc.c b/libavcodec/adxenc.c
index e730811744..a822b7b6f1 100644
--- a/libavcodec/adxenc.c
+++ b/libavcodec/adxenc.c
@@ -93,7 +93,7 @@ static int adx_encode_header(AVCodecContext *avctx, uint8_t *buf, int bufsize)
bytestream_put_byte(&buf, 3); /* encoding */
bytestream_put_byte(&buf, BLOCK_SIZE); /* block size */
bytestream_put_byte(&buf, 4); /* sample size */
- bytestream_put_byte(&buf, avctx->channels); /* channels */
+ bytestream_put_byte(&buf, avctx->ch_layout.nb_channels); /* channels */
bytestream_put_be32(&buf, avctx->sample_rate); /* sample rate */
bytestream_put_be32(&buf, 0); /* total sample count */
bytestream_put_be16(&buf, c->cutoff); /* cutoff frequency */
@@ -111,7 +111,7 @@ static av_cold int adx_encode_init(AVCodecContext *avctx)
{
ADXContext *c = avctx->priv_data;

- if (avctx->channels > 2) {
+ if (avctx->ch_layout.nb_channels > 2) {
av_log(avctx, AV_LOG_ERROR, "Invalid number of channels\n");
return AVERROR(EINVAL);
}
@@ -130,9 +130,10 @@ static int adx_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
ADXContext *c = avctx->priv_data;
const int16_t *samples = (const int16_t *)frame->data[0];
uint8_t *dst;
+ int channels = avctx->ch_layout.nb_channels;
int ch, out_size, ret;

- out_size = BLOCK_SIZE * avctx->channels + !c->header_parsed * HEADER_SIZE;
+ out_size = BLOCK_SIZE * channels + !c->header_parsed * HEADER_SIZE;
if ((ret = ff_alloc_packet(avpkt, out_size)) < 0) {
av_log(avctx, AV_LOG_ERROR, "Error getting output packet\n");
return ret;
@@ -149,8 +150,8 @@ static int adx_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
c->header_parsed = 1;
}

- for (ch = 0; ch < avctx->channels; ch++) {
- adx_encode(c, dst, samples + ch, &c->prev[ch], avctx->channels);
+ for (ch = 0; ch < channels; ch++) {
+ adx_encode(c, dst, samples + ch, &c->prev[ch], channels);
dst += BLOCK_SIZE;
}

diff --git a/libavcodec/alac.c b/libavcodec/alac.c
index 0f1c59e486..c6466bcf47 100644
--- a/libavcodec/alac.c
+++ b/libavcodec/alac.c
@@ -559,21 +559,17 @@ static av_cold int alac_decode_init(AVCodecContext * avctx)
}
avctx->bits_per_raw_sample = alac->sample_size;

- if (alac->channels < 1) {
+ if (alac->channels < 1 || alac->channels > ALAC_MAX_CHANNELS) {
av_log(avctx, AV_LOG_WARNING, "Invalid channel count\n");
- alac->channels = avctx->channels;
- } else {
- if (alac->channels > ALAC_MAX_CHANNELS)
- alac->channels = avctx->channels;
- else
- avctx->channels = alac->channels;
+ alac->channels = avctx->ch_layout.nb_channels;
}
- if (avctx->channels > ALAC_MAX_CHANNELS) {
- avpriv_report_missing_feature(avctx, "Channel count %d",
- avctx->channels);
+ if (alac->channels > ALAC_MAX_CHANNELS) {
+ av_log(avctx, AV_LOG_ERROR, "Unsupported channel count: %d\n",
+ alac->channels);
return AVERROR_PATCHWELCOME;
}
- avctx->channel_layout = ff_alac_channel_layouts[alac->channels - 1];
+ av_channel_layout_uninit(&avctx->ch_layout);
+ avctx->ch_layout = ff_alac_ch_layouts[alac->channels - 1];

if ((ret = allocate_buffers(alac)) < 0) {
av_log(avctx, AV_LOG_ERROR, "Error allocating buffers\n");
diff --git a/libavcodec/alac_data.c b/libavcodec/alac_data.c
index 9e131199b1..542768b01b 100644
--- a/libavcodec/alac_data.c
+++ b/libavcodec/alac_data.c
@@ -44,6 +44,18 @@ const uint64_t ff_alac_channel_layouts[ALAC_MAX_CHANNELS + 1] = {
0
};

+const AVChannelLayout ff_alac_ch_layouts[ALAC_MAX_CHANNELS + 1] = {
+ AV_CHANNEL_LAYOUT_MONO,
+ AV_CHANNEL_LAYOUT_STEREO,
+ AV_CHANNEL_LAYOUT_SURROUND,
+ AV_CHANNEL_LAYOUT_4POINT0,
+ AV_CHANNEL_LAYOUT_5POINT0_BACK,
+ AV_CHANNEL_LAYOUT_5POINT1_BACK,
+ AV_CHANNEL_LAYOUT_6POINT1_BACK,
+ AV_CHANNEL_LAYOUT_7POINT1_WIDE_BACK,
+ { 0 }
+};
+
const enum AlacRawDataBlockType ff_alac_channel_elements[ALAC_MAX_CHANNELS][5] = {
{ TYPE_SCE, },
{ TYPE_CPE, },
diff --git a/libavcodec/alac_data.h b/libavcodec/alac_data.h
index ebb1f33a93..9e354091c2 100644
--- a/libavcodec/alac_data.h
+++ b/libavcodec/alac_data.h
@@ -23,6 +23,8 @@

#include <stdint.h>

+#include "libavutil/channel_layout.h"
+
enum AlacRawDataBlockType {
/* At the moment, only SCE, CPE, LFE, and END are recognized. */
TYPE_SCE,
@@ -39,7 +41,11 @@ enum AlacRawDataBlockType {

extern const uint8_t ff_alac_channel_layout_offsets[ALAC_MAX_CHANNELS][ALAC_MAX_CHANNELS];

+extern const AVChannelLayout ff_alac_ch_layouts[ALAC_MAX_CHANNELS + 1];
+
+#if FF_API_OLD_CHANNEL_LAYOUT
extern const uint64_t ff_alac_channel_layouts[ALAC_MAX_CHANNELS + 1];
+#endif

extern const enum AlacRawDataBlockType ff_alac_channel_elements[ALAC_MAX_CHANNELS][5];

diff --git a/libavcodec/alacenc.c b/libavcodec/alacenc.c
index d921fa124c..0d0ba66d16 100644
--- a/libavcodec/alacenc.c
+++ b/libavcodec/alacenc.c
@@ -447,14 +447,15 @@ static int write_frame(AlacEncodeContext *s, AVPacket *avpkt,
uint8_t * const *samples)
{
PutBitContext *pb = &s->pbctx;
- const enum AlacRawDataBlockType *ch_elements = ff_alac_channel_elements[s->avctx->channels - 1];
- const uint8_t *ch_map = ff_alac_channel_layout_offsets[s->avctx->channels - 1];
+ int channels = s->avctx->ch_layout.nb_channels;
+ const enum AlacRawDataBlockType *ch_elements = ff_alac_channel_elements[channels - 1];
+ const uint8_t *ch_map = ff_alac_channel_layout_offsets[channels - 1];
int ch, element, sce, cpe;

init_put_bits(pb, avpkt->data, avpkt->size);

ch = element = sce = cpe = 0;
- while (ch < s->avctx->channels) {
+ while (ch < channels) {
if (ch_elements[element] == TYPE_CPE) {
write_element(s, TYPE_CPE, cpe, samples[ch_map[ch]],
samples[ch_map[ch + 1]]);
@@ -519,7 +520,7 @@ static av_cold int alac_encode_init(AVCodecContext *avctx)
s->rc.rice_modifier = 4;

s->max_coded_frame_size = get_max_frame_size(avctx->frame_size,
- avctx->channels,
+ avctx->ch_layout.nb_channels,
avctx->bits_per_raw_sample);

avctx->extradata = av_mallocz(ALAC_EXTRADATA_SIZE + AV_INPUT_BUFFER_PADDING_SIZE);
@@ -534,10 +535,10 @@ static av_cold int alac_encode_init(AVCodecContext *avctx)
AV_WB32(alac_extradata+4, MKBETAG('a','l','a','c'));
AV_WB32(alac_extradata+12, avctx->frame_size);
AV_WB8 (alac_extradata+17, avctx->bits_per_raw_sample);
- AV_WB8 (alac_extradata+21, avctx->channels);
+ AV_WB8 (alac_extradata+21, avctx->ch_layout.nb_channels);
AV_WB32(alac_extradata+24, s->max_coded_frame_size);
AV_WB32(alac_extradata+28,
- avctx->sample_rate * avctx->channels * avctx->bits_per_raw_sample); // average bitrate
+ avctx->sample_rate * avctx->ch_layout.nb_channels * avctx->bits_per_raw_sample); // average bitrate
AV_WB32(alac_extradata+32, avctx->sample_rate);

// Set relevant extradata fields
@@ -606,7 +607,7 @@ static int alac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
s->frame_size = frame->nb_samples;

if (frame->nb_samples < DEFAULT_FRAME_SIZE)
- max_frame_size = get_max_frame_size(s->frame_size, avctx->channels,
+ max_frame_size = get_max_frame_size(s->frame_size, avctx->ch_layout.nb_channels,
avctx->bits_per_raw_sample);
else
max_frame_size = s->max_coded_frame_size;
@@ -666,7 +667,12 @@ AVCodec ff_alac_encoder = {
.encode2 = alac_encode_frame,
.close = alac_encode_close,
.capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME,
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
.channel_layouts = ff_alac_channel_layouts,
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+ .ch_layouts = ff_alac_ch_layouts,
.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S32P,
AV_SAMPLE_FMT_S16P,
AV_SAMPLE_FMT_NONE },
diff --git a/libavcodec/alsdec.c b/libavcodec/alsdec.c
index 5f09a9d4b9..1e8440b8af 100644
--- a/libavcodec/alsdec.c
+++ b/libavcodec/alsdec.c
@@ -307,7 +307,13 @@ static av_cold int read_specific_config(ALSDecContext *ctx)
avctx->sample_rate = m4ac.sample_rate;
bitstream_skip(&bc, 32); // sample rate already known
sconf->samples = bitstream_read(&bc, 32);
- avctx->channels = m4ac.channels;
+
+ if (avctx->ch_layout.nb_channels != m4ac.channels) {
+ av_channel_layout_uninit(&avctx->ch_layout);
+ avctx->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ avctx->ch_layout.nb_channels = m4ac.channels;
+ }
+
bitstream_skip(&bc, 16); // number of channels already known
bitstream_skip(&bc, 3); // skip file_type
sconf->resolution = bitstream_read(&bc, 3);
@@ -342,20 +348,20 @@ static av_cold int read_specific_config(ALSDecContext *ctx)
// read channel config
if (sconf->chan_config)
sconf->chan_config_info = bitstream_read(&bc, 16);
- // TODO: use this to set avctx->channel_layout
+ // TODO: use this to set avctx->ch_layout


// read channel sorting
- if (sconf->chan_sort && avctx->channels > 1) {
- int chan_pos_bits = av_ceil_log2(avctx->channels);
- int bits_needed = avctx->channels * chan_pos_bits + 7;
+ if (sconf->chan_sort && m4ac.channels > 1) {
+ int chan_pos_bits = av_ceil_log2(m4ac.channels);
+ int bits_needed = m4ac.channels * chan_pos_bits + 7;
if (bitstream_bits_left(&bc) < bits_needed)
return AVERROR_INVALIDDATA;

- if (!(sconf->chan_pos = av_malloc(avctx->channels * sizeof(*sconf->chan_pos))))
+ if (!(sconf->chan_pos = av_malloc(m4ac.channels * sizeof(*sconf->chan_pos))))
return AVERROR(ENOMEM);

- for (i = 0; i < avctx->channels; i++)
+ for (i = 0; i < m4ac.channels; i++)
sconf->chan_pos[i] = bitstream_read(&bc, chan_pos_bits);

bitstream_align(&bc);
@@ -1176,7 +1182,7 @@ static int read_channel_data(ALSDecContext *ctx, ALSChannelData *cd, int c)
{
BitstreamContext *bc = &ctx->bc;
ALSChannelData *current = cd;
- unsigned int channels = ctx->avctx->channels;
+ unsigned int channels = ctx->avctx->ch_layout.nb_channels;
int entries = 0;

while (entries < channels && !(current->stop_flag = bitstream_read_bit(bc))) {
@@ -1225,7 +1231,7 @@ static int revert_channel_correlation(ALSDecContext *ctx, ALSBlockData *bd,
{
ALSChannelData *ch = cd[c];
unsigned int dep = 0;
- unsigned int channels = ctx->avctx->channels;
+ unsigned int channels = ctx->avctx->ch_layout.nb_channels;
unsigned int channel_size = ctx->sconf.frame_length + ctx->sconf.max_order;

if (reverted[c])
@@ -1332,6 +1338,7 @@ static int read_frame_data(ALSDecContext *ctx, unsigned int ra_frame)
unsigned int div_blocks[32]; ///< block sizes.
unsigned int c;
unsigned int js_blocks[2];
+ int channels = avctx->ch_layout.nb_channels;
uint32_t bs_info = 0;
int ret;

@@ -1347,7 +1354,7 @@ static int read_frame_data(ALSDecContext *ctx, unsigned int ra_frame)
if (!sconf->mc_coding || ctx->js_switch) {
int independent_bs = !sconf->joint_stereo;

- for (c = 0; c < avctx->channels; c++) {
+ for (c = 0; c < channels; c++) {
js_blocks[0] = 0;
js_blocks[1] = 0;

@@ -1360,7 +1367,7 @@ static int read_frame_data(ALSDecContext *ctx, unsigned int ra_frame)
independent_bs = 2;

// if this is the last channel, it has to be decoded independently
- if (c == avctx->channels - 1)
+ if (c == channels - 1)
independent_bs = 1;

if (independent_bs) {
@@ -1388,13 +1395,13 @@ static int read_frame_data(ALSDecContext *ctx, unsigned int ra_frame)
int *reverted_channels = ctx->reverted_channels;
unsigned int offset = 0;

- for (c = 0; c < avctx->channels; c++)
+ for (c = 0; c < channels; c++)
if (ctx->chan_data[c] < ctx->chan_data_buffer) {
av_log(ctx->avctx, AV_LOG_ERROR, "Invalid channel data!\n");
return AVERROR_INVALIDDATA;
}

- memset(reverted_channels, 0, sizeof(*reverted_channels) * avctx->channels);
+ memset(reverted_channels, 0, sizeof(*reverted_channels) * channels);

bd.ra_block = ra_frame;
bd.prev_raw_samples = ctx->prev_raw_samples;
@@ -1410,7 +1417,7 @@ static int read_frame_data(ALSDecContext *ctx, unsigned int ra_frame)
continue;
}

- for (c = 0; c < avctx->channels; c++) {
+ for (c = 0; c < channels; c++) {
bd.const_block = ctx->const_block + c;
bd.shift_lsbs = ctx->shift_lsbs + c;
bd.opt_order = ctx->opt_order + c;
@@ -1429,13 +1436,13 @@ static int read_frame_data(ALSDecContext *ctx, unsigned int ra_frame)
return ret;
}

- for (c = 0; c < avctx->channels; c++) {
+ for (c = 0; c < channels; c++) {
ret = revert_channel_correlation(ctx, &bd, ctx->chan_data,
reverted_channels, offset, c);
if (ret < 0)
return ret;
}
- for (c = 0; c < avctx->channels; c++) {
+ for (c = 0; c < channels; c++) {
bd.const_block = ctx->const_block + c;
bd.shift_lsbs = ctx->shift_lsbs + c;
bd.opt_order = ctx->opt_order + c;
@@ -1450,13 +1457,13 @@ static int read_frame_data(ALSDecContext *ctx, unsigned int ra_frame)
return ret;
}

- memset(reverted_channels, 0, avctx->channels * sizeof(*reverted_channels));
+ memset(reverted_channels, 0, channels * sizeof(*reverted_channels));
offset += div_blocks[b];
bd.ra_block = 0;
}

// store carryover raw samples
- for (c = 0; c < avctx->channels; c++)
+ for (c = 0; c < channels; c++)
memmove(ctx->raw_samples[c] - sconf->max_order,
ctx->raw_samples[c] - sconf->max_order + sconf->frame_length,
sizeof(*ctx->raw_samples[c]) * sconf->max_order);
@@ -1479,6 +1486,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr,
const uint8_t *buffer = avpkt->data;
int buffer_size = avpkt->size;
int invalid_frame, ret;
+ int channels = avctx->ch_layout.nb_channels;
unsigned int c, sample, ra_frame, bytes_read, shift;

bitstream_init8(&ctx->bc, buffer, buffer_size);
@@ -1516,7 +1524,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr,
int##bps##_t *dest = (int##bps##_t*)frame->data[0]; \
shift = bps - ctx->avctx->bits_per_raw_sample; \
for (sample = 0; sample < ctx->cur_frame_length; sample++) \
- for (c = 0; c < avctx->channels; c++) \
+ for (c = 0; c < channels; c++) \
*dest++ = ctx->raw_samples[c][sample] << shift; \
}

@@ -1534,7 +1542,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr,
int32_t *src = (int32_t *)frame->data[0];

for (sample = 0;
- sample < ctx->cur_frame_length * avctx->channels;
+ sample < ctx->cur_frame_length * channels;
sample++) {
int32_t v;

@@ -1555,13 +1563,13 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr,
int16_t *src = (int16_t*) frame->data[0];
int16_t *dest = (int16_t*) ctx->crc_buffer;
for (sample = 0;
- sample < ctx->cur_frame_length * avctx->channels;
+ sample < ctx->cur_frame_length * channels;
sample++)
*dest++ = av_bswap16(src[sample]);
} else {
ctx->bdsp.bswap_buf((uint32_t *) ctx->crc_buffer,
(uint32_t *) frame->data[0],
- ctx->cur_frame_length * avctx->channels);
+ ctx->cur_frame_length * channels);
}
crc_source = ctx->crc_buffer;
} else {
@@ -1569,7 +1577,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr,
}

ctx->crc = av_crc(ctx->crc_table, ctx->crc, crc_source,
- ctx->cur_frame_length * avctx->channels *
+ ctx->cur_frame_length * channels *
av_get_bytes_per_sample(avctx->sample_fmt));
}

@@ -1634,6 +1642,7 @@ static av_cold int decode_init(AVCodecContext *avctx)
unsigned int c;
unsigned int channel_size;
int num_buffers, ret;
+ int channels = avctx->ch_layout.nb_channels;
ALSDecContext *ctx = avctx->priv_data;
ALSSpecificConfig *sconf = &ctx->sconf;
ctx->avctx = avctx;
@@ -1682,7 +1691,7 @@ static av_cold int decode_init(AVCodecContext *avctx)
(avctx->sample_rate >= 192000);

// allocate quantized parcor coefficient buffer
- num_buffers = sconf->mc_coding ? avctx->channels : 1;
+ num_buffers = sconf->mc_coding ? channels : 1;

ctx->quant_cof = av_malloc(sizeof(*ctx->quant_cof) * num_buffers);
ctx->lpc_cof = av_malloc(sizeof(*ctx->lpc_cof) * num_buffers);
@@ -1756,8 +1765,8 @@ static av_cold int decode_init(AVCodecContext *avctx)
channel_size = sconf->frame_length + sconf->max_order;

ctx->prev_raw_samples = av_malloc (sizeof(*ctx->prev_raw_samples) * sconf->max_order);
- ctx->raw_buffer = av_mallocz(sizeof(*ctx-> raw_buffer) * avctx->channels * channel_size);
- ctx->raw_samples = av_malloc (sizeof(*ctx-> raw_samples) * avctx->channels);
+ ctx->raw_buffer = av_mallocz(sizeof(*ctx-> raw_buffer) * channels * channel_size);
+ ctx->raw_samples = av_malloc (sizeof(*ctx-> raw_samples) * channels);

// allocate previous raw sample buffer
if (!ctx->prev_raw_samples || !ctx->raw_buffer|| !ctx->raw_samples) {
@@ -1768,7 +1777,7 @@ static av_cold int decode_init(AVCodecContext *avctx)

// assign raw samples buffers
ctx->raw_samples[0] = ctx->raw_buffer + sconf->max_order;
- for (c = 1; c < avctx->channels; c++)
+ for (c = 1; c < channels; c++)
ctx->raw_samples[c] = ctx->raw_samples[c - 1] + channel_size;

// allocate crc buffer
@@ -1776,7 +1785,7 @@ static av_cold int decode_init(AVCodecContext *avctx)
(avctx->err_recognition & AV_EF_CRCCHECK)) {
ctx->crc_buffer = av_malloc(sizeof(*ctx->crc_buffer) *
ctx->cur_frame_length *
- avctx->channels *
+ channels *
av_get_bytes_per_sample(avctx->sample_fmt));
if (!ctx->crc_buffer) {
av_log(avctx, AV_LOG_ERROR, "Allocating buffer memory failed.\n");
diff --git a/libavcodec/amrnbdec.c b/libavcodec/amrnbdec.c
index e2b5641c23..cf5ca0073a 100644
--- a/libavcodec/amrnbdec.c
+++ b/libavcodec/amrnbdec.c
@@ -155,13 +155,13 @@ static av_cold int amrnb_decode_init(AVCodecContext *avctx)
AMRContext *p = avctx->priv_data;
int i;

- if (avctx->channels > 1) {
+ if (avctx->ch_layout.nb_channels > 1) {
avpriv_report_missing_feature(avctx, "multi-channel AMR");
return AVERROR_PATCHWELCOME;
}

- avctx->channels = 1;
- avctx->channel_layout = AV_CH_LAYOUT_MONO;
+ av_channel_layout_uninit(&avctx->ch_layout);
+ avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
avctx->sample_rate = 8000;
avctx->sample_fmt = AV_SAMPLE_FMT_FLT;

diff --git a/libavcodec/amrwbdec.c b/libavcodec/amrwbdec.c
index f1fbcc09ea..586be847c6 100644
--- a/libavcodec/amrwbdec.c
+++ b/libavcodec/amrwbdec.c
@@ -91,13 +91,13 @@ static av_cold int amrwb_decode_init(AVCodecContext *avctx)
AMRWBContext *ctx = avctx->priv_data;
int i;

- if (avctx->channels > 1) {
+ if (avctx->ch_layout.nb_channels > 1) {
avpriv_report_missing_feature(avctx, "multi-channel AMR");
return AVERROR_PATCHWELCOME;
}

- avctx->channels = 1;
- avctx->channel_layout = AV_CH_LAYOUT_MONO;
+ av_channel_layout_uninit(&avctx->ch_layout);
+ avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
avctx->sample_rate = 16000;
avctx->sample_fmt = AV_SAMPLE_FMT_FLT;

diff --git a/libavcodec/apedec.c b/libavcodec/apedec.c
index da45e85e51..96f3154c5a 100644
--- a/libavcodec/apedec.c
+++ b/libavcodec/apedec.c
@@ -229,13 +229,14 @@ static int32_t scalarproduct_and_madd_int16_c(int16_t *v1, const int16_t *v2,
static av_cold int ape_decode_init(AVCodecContext *avctx)
{
APEContext *s = avctx->priv_data;
+ int channels = avctx->ch_layout.nb_channels;
int i;

if (avctx->extradata_size != 6) {
av_log(avctx, AV_LOG_ERROR, "Incorrect extradata\n");
return AVERROR(EINVAL);
}
- if (avctx->channels > 2) {
+ if (channels > 2) {
av_log(avctx, AV_LOG_ERROR, "Only mono and stereo is supported\n");
return AVERROR(EINVAL);
}
@@ -256,7 +257,7 @@ static av_cold int ape_decode_init(AVCodecContext *avctx)
return AVERROR_PATCHWELCOME;
}
s->avctx = avctx;
- s->channels = avctx->channels;
+ s->channels = channels;
s->fileversion = AV_RL16(avctx->extradata);
s->compression_level = AV_RL16(avctx->extradata + 2);
s->flags = AV_RL16(avctx->extradata + 4);
@@ -316,7 +317,9 @@ static av_cold int ape_decode_init(AVCodecContext *avctx)
ff_apedsp_init_x86(&s->adsp);

ff_bswapdsp_init(&s->bdsp);
- avctx->channel_layout = (avctx->channels==2) ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO;
+
+ av_channel_layout_uninit(&avctx->ch_layout);
+ av_channel_layout_default(&avctx->ch_layout, channels);

return 0;
filter_alloc_fail:
diff --git a/libavcodec/atrac1.c b/libavcodec/atrac1.c
index 52d43e2c94..fa56b7578e 100644
--- a/libavcodec/atrac1.c
+++ b/libavcodec/atrac1.c
@@ -278,11 +278,12 @@ static int atrac1_decode_frame(AVCodecContext *avctx, void *data,
const uint8_t *buf = avpkt->data;
int buf_size = avpkt->size;
AT1Ctx *q = avctx->priv_data;
+ int channels = avctx->ch_layout.nb_channels;
int ch, ret;
BitstreamContext bc;


- if (buf_size < 212 * avctx->channels) {
+ if (buf_size < 212 * channels) {
av_log(avctx, AV_LOG_ERROR, "Not enough data to decode!\n");
return AVERROR_INVALIDDATA;
}
@@ -294,7 +295,7 @@ static int atrac1_decode_frame(AVCodecContext *avctx, void *data,
return ret;
}

- for (ch = 0; ch < avctx->channels; ch++) {
+ for (ch = 0; ch < channels; ch++) {
AT1SUCtx* su = &q->SUs[ch];

bitstream_init8(&bc, &buf[212 * ch], 212);
@@ -335,13 +336,14 @@ static av_cold int atrac1_decode_end(AVCodecContext * avctx)
static av_cold int atrac1_decode_init(AVCodecContext *avctx)
{
AT1Ctx *q = avctx->priv_data;
+ int channels = avctx->ch_layout.nb_channels;
int ret;

avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;

- if (avctx->channels < 1 || avctx->channels > AT1_MAX_CHANNELS) {
+ if (channels < 1 || channels > AT1_MAX_CHANNELS) {
av_log(avctx, AV_LOG_ERROR, "Unsupported number of channels: %d\n",
- avctx->channels);
+ channels);
return AVERROR(EINVAL);
}

diff --git a/libavcodec/atrac3.c b/libavcodec/atrac3.c
index d0661c83fc..5b15bf833e 100644
--- a/libavcodec/atrac3.c
+++ b/libavcodec/atrac3.c
@@ -642,6 +642,7 @@ static int decode_frame(AVCodecContext *avctx, const uint8_t *databuf,
ATRAC3Context *q = avctx->priv_data;
int ret, i;
uint8_t *ptr1;
+ int channels = avctx->ch_layout.nb_channels;

if (q->coding_mode == JOINT_STEREO) {
/* channel coupling mode */
@@ -704,11 +705,11 @@ static int decode_frame(AVCodecContext *avctx, const uint8_t *databuf,
} else {
/* normal stereo mode or mono */
/* Decode the channel sound units. */
- for (i = 0; i < avctx->channels; i++) {
+ for (i = 0; i < channels; i++) {
/* Set the bitstream reader at the start of a channel sound unit. */
bitstream_init8(&q->bc,
- databuf + i * avctx->block_align / avctx->channels,
- avctx->block_align / avctx->channels);
+ databuf + i * avctx->block_align / channels,
+ avctx->block_align / channels);

ret = decode_channel_sound_unit(q, &q->bc, &q->units[i],
out_samples[i], i, q->coding_mode);
@@ -718,7 +719,7 @@ static int decode_frame(AVCodecContext *avctx, const uint8_t *databuf,
}

/* Apply the iQMF synthesis filter. */
- for (i = 0; i < avctx->channels; i++) {
+ for (i = 0; i < channels; i++) {
float *p1 = out_samples[i];
float *p2 = p1 + 256;
float *p3 = p2 + 256;
@@ -797,8 +798,9 @@ static av_cold int atrac3_decode_init(AVCodecContext *avctx)
int version, delay, samples_per_frame, frame_factor;
const uint8_t *edata_ptr = avctx->extradata;
ATRAC3Context *q = avctx->priv_data;
+ int channels = avctx->ch_layout.nb_channels;

- if (avctx->channels <= 0 || avctx->channels > 2) {
+ if (channels <= 0 || channels > 2) {
av_log(avctx, AV_LOG_ERROR, "Channel configuration error!\n");
return AVERROR(EINVAL);
}
@@ -817,18 +819,18 @@ static av_cold int atrac3_decode_init(AVCodecContext *avctx)
bytestream_get_le16(&edata_ptr)); // Unknown always 0

/* setup */
- samples_per_frame = SAMPLES_PER_FRAME * avctx->channels;
+ samples_per_frame = SAMPLES_PER_FRAME * channels;
version = 4;
delay = 0x88E;
q->coding_mode = q->coding_mode ? JOINT_STEREO : STEREO;
q->scrambled_stream = 0;

- if (avctx->block_align != 96 * avctx->channels * frame_factor &&
- avctx->block_align != 152 * avctx->channels * frame_factor &&
- avctx->block_align != 192 * avctx->channels * frame_factor) {
+ if (avctx->block_align != 96 * channels * frame_factor &&
+ avctx->block_align != 152 * channels * frame_factor &&
+ avctx->block_align != 192 * channels * frame_factor) {
av_log(avctx, AV_LOG_ERROR, "Unknown frame/channel/frame_factor "
"configuration %d/%d/%d\n", avctx->block_align,
- avctx->channels, frame_factor);
+ channels, frame_factor);
return AVERROR_INVALIDDATA;
}
} else if (avctx->extradata_size == 10) {
@@ -868,7 +870,7 @@ static av_cold int atrac3_decode_init(AVCodecContext *avctx)
if (q->coding_mode == STEREO)
av_log(avctx, AV_LOG_DEBUG, "Normal stereo detected.\n");
else if (q->coding_mode == JOINT_STEREO) {
- if (avctx->channels != 2)
+ if (channels != 2)
return AVERROR_INVALIDDATA;
av_log(avctx, AV_LOG_DEBUG, "Joint stereo detected.\n");
} else {
@@ -911,7 +913,7 @@ static av_cold int atrac3_decode_init(AVCodecContext *avctx)
ff_atrac_init_gain_compensation(&q->gainc_ctx, 4, 3);
avpriv_float_dsp_init(&q->fdsp, avctx->flags & AV_CODEC_FLAG_BITEXACT);

- q->units = av_mallocz(sizeof(*q->units) * avctx->channels);
+ q->units = av_mallocz(sizeof(*q->units) * channels);
if (!q->units) {
atrac3_decode_close(avctx);
return AVERROR(ENOMEM);
diff --git a/libavcodec/atrac3plusdec.c b/libavcodec/atrac3plusdec.c
index 17774d5657..9a3941a582 100644
--- a/libavcodec/atrac3plusdec.c
+++ b/libavcodec/atrac3plusdec.c
@@ -63,7 +63,6 @@ typedef struct ATRAC3PContext {

int num_channel_blocks; ///< number of channel blocks
uint8_t channel_blocks[5]; ///< channel configuration descriptor
- uint64_t my_channel_layout; ///< current channel layout
} ATRAC3PContext;

static av_cold int atrac3p_decode_close(AVCodecContext *avctx)
@@ -76,36 +75,36 @@ static av_cold int atrac3p_decode_close(AVCodecContext *avctx)
static av_cold int set_channel_params(ATRAC3PContext *ctx,
AVCodecContext *avctx)
{
+ int channels = avctx->ch_layout.nb_channels;
memset(ctx->channel_blocks, 0, sizeof(ctx->channel_blocks));

- switch (avctx->channels) {
+ av_channel_layout_uninit(&avctx->ch_layout);
+ switch (channels) {
case 1:
- if (avctx->channel_layout != AV_CH_FRONT_LEFT)
- avctx->channel_layout = AV_CH_LAYOUT_MONO;
-
+ avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
ctx->num_channel_blocks = 1;
ctx->channel_blocks[0] = CH_UNIT_MONO;
break;
case 2:
- avctx->channel_layout = AV_CH_LAYOUT_STEREO;
+ avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
ctx->num_channel_blocks = 1;
ctx->channel_blocks[0] = CH_UNIT_STEREO;
break;
case 3:
- avctx->channel_layout = AV_CH_LAYOUT_SURROUND;
+ avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_SURROUND;
ctx->num_channel_blocks = 2;
ctx->channel_blocks[0] = CH_UNIT_STEREO;
ctx->channel_blocks[1] = CH_UNIT_MONO;
break;
case 4:
- avctx->channel_layout = AV_CH_LAYOUT_4POINT0;
+ avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_4POINT0;
ctx->num_channel_blocks = 3;
ctx->channel_blocks[0] = CH_UNIT_STEREO;
ctx->channel_blocks[1] = CH_UNIT_MONO;
ctx->channel_blocks[2] = CH_UNIT_MONO;
break;
case 6:
- avctx->channel_layout = AV_CH_LAYOUT_5POINT1_BACK;
+ avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1_BACK;
ctx->num_channel_blocks = 4;
ctx->channel_blocks[0] = CH_UNIT_STEREO;
ctx->channel_blocks[1] = CH_UNIT_MONO;
@@ -113,7 +112,7 @@ static av_cold int set_channel_params(ATRAC3PContext *ctx,
ctx->channel_blocks[3] = CH_UNIT_MONO;
break;
case 7:
- avctx->channel_layout = AV_CH_LAYOUT_6POINT1_BACK;
+ avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_6POINT1_BACK;
ctx->num_channel_blocks = 5;
ctx->channel_blocks[0] = CH_UNIT_STEREO;
ctx->channel_blocks[1] = CH_UNIT_MONO;
@@ -122,7 +121,7 @@ static av_cold int set_channel_params(ATRAC3PContext *ctx,
ctx->channel_blocks[4] = CH_UNIT_MONO;
break;
case 8:
- avctx->channel_layout = AV_CH_LAYOUT_7POINT1;
+ avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_7POINT1;
ctx->num_channel_blocks = 5;
ctx->channel_blocks[0] = CH_UNIT_STEREO;
ctx->channel_blocks[1] = CH_UNIT_MONO;
@@ -132,7 +131,7 @@ static av_cold int set_channel_params(ATRAC3PContext *ctx,
break;
default:
av_log(avctx, AV_LOG_ERROR,
- "Unsupported channel count: %d!\n", avctx->channels);
+ "Unsupported channel count: %d!\n", channels);
return AVERROR_INVALIDDATA;
}

@@ -163,8 +162,6 @@ static av_cold int atrac3p_decode_init(AVCodecContext *avctx)
if ((ret = set_channel_params(ctx, avctx)) < 0)
return ret;

- ctx->my_channel_layout = avctx->channel_layout;
-
ctx->ch_units = av_mallocz(sizeof(*ctx->ch_units) *
ctx->num_channel_blocks);
if (!ctx->ch_units) {
diff --git a/libavcodec/binkaudio.c b/libavcodec/binkaudio.c
index 51fb6c83ce..5a0448b573 100644
--- a/libavcodec/binkaudio.c
+++ b/libavcodec/binkaudio.c
@@ -73,6 +73,7 @@ static av_cold int decode_init(AVCodecContext *avctx)
int sample_rate_half;
int i;
int frame_len_bits;
+ int channels = avctx->ch_layout.nb_channels;

/* determine frame length */
if (avctx->sample_rate < 22050) {
@@ -83,24 +84,24 @@ static av_cold int decode_init(AVCodecContext *avctx)
frame_len_bits = 11;
}

- if (avctx->channels > MAX_CHANNELS) {
- av_log(avctx, AV_LOG_ERROR, "too many channels: %d\n", avctx->channels);
+ if (channels > MAX_CHANNELS) {
+ av_log(avctx, AV_LOG_ERROR, "too many channels: %d\n", channels);
return -1;
}
- avctx->channel_layout = avctx->channels == 1 ? AV_CH_LAYOUT_MONO :
- AV_CH_LAYOUT_STEREO;
+ av_channel_layout_uninit(&avctx->ch_layout);
+ av_channel_layout_default(&avctx->ch_layout, channels);

s->version_b = avctx->extradata && avctx->extradata[3] == 'b';

if (avctx->codec->id == AV_CODEC_ID_BINKAUDIO_RDFT) {
// audio is already interleaved for the RDFT format variant
avctx->sample_fmt = AV_SAMPLE_FMT_FLT;
- sample_rate *= avctx->channels;
+ sample_rate *= channels;
s->channels = 1;
if (!s->version_b)
- frame_len_bits += av_log2(avctx->channels);
+ frame_len_bits += av_log2(channels);
} else {
- s->channels = avctx->channels;
+ s->channels = channels;
avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
}

@@ -334,7 +335,7 @@ static int binkaudio_receive_frame(AVCodecContext *avctx, AVFrame *frame)
av_packet_unref(s->pkt);
}

- frame->nb_samples = s->block_size / avctx->channels;
+ frame->nb_samples = s->block_size / avctx->ch_layout.nb_channels;

return 0;
fail:
diff --git a/libavcodec/bmvaudio.c b/libavcodec/bmvaudio.c
index 8b4bd784a1..d65064f0e9 100644
--- a/libavcodec/bmvaudio.c
+++ b/libavcodec/bmvaudio.c
@@ -31,8 +31,8 @@ static const int bmv_aud_mults[16] = {

static av_cold int bmv_aud_decode_init(AVCodecContext *avctx)
{
- avctx->channels = 2;
- avctx->channel_layout = AV_CH_LAYOUT_STEREO;
+ av_channel_layout_uninit(&avctx->ch_layout);
+ avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
avctx->sample_fmt = AV_SAMPLE_FMT_S16;

return 0;
diff --git a/libavcodec/cngdec.c b/libavcodec/cngdec.c
index 482ef94a32..2cdb701b07 100644
--- a/libavcodec/cngdec.c
+++ b/libavcodec/cngdec.c
@@ -54,7 +54,8 @@ static av_cold int cng_decode_init(AVCodecContext *avctx)
CNGContext *p = avctx->priv_data;

avctx->sample_fmt = AV_SAMPLE_FMT_S16;
- avctx->channels = 1;
+ av_channel_layout_uninit(&avctx->ch_layout);
+ avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
avctx->sample_rate = 8000;

p->order = 12;
diff --git a/libavcodec/cngenc.c b/libavcodec/cngenc.c
index 98f3c4e91a..95092607ff 100644
--- a/libavcodec/cngenc.c
+++ b/libavcodec/cngenc.c
@@ -47,11 +47,6 @@ static av_cold int cng_encode_init(AVCodecContext *avctx)
CNGContext *p = avctx->priv_data;
int ret;

- if (avctx->channels != 1) {
- av_log(avctx, AV_LOG_ERROR, "Only mono supported\n");
- return AVERROR(EINVAL);
- }
-
avctx->frame_size = 640;
p->order = 10;
if ((ret = ff_lpc_init(&p->lpc, avctx->frame_size, p->order, FF_LPC_TYPE_LEVINSON)) < 0)
@@ -113,4 +108,5 @@ AVCodec ff_comfortnoise_encoder = {
.close = cng_encode_close,
.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
AV_SAMPLE_FMT_NONE },
+ .ch_layouts = (const AVChannelLayout[]){ AV_CHANNEL_LAYOUT_MONO, { 0 } },
};
diff --git a/libavcodec/cook.c b/libavcodec/cook.c
index bd8ad1d1da..66c93fbaab 100644
--- a/libavcodec/cook.c
+++ b/libavcodec/cook.c
@@ -1023,7 +1023,7 @@ static void dump_cook_context(COOKContext *q)
PRINT("js_vlc_bits", q->subpacket[0].js_vlc_bits);
}
ff_dlog(q->avctx, "COOKContext\n");
- PRINT("nb_channels", q->avctx->channels);
+ PRINT("nb_channels", q->avctx->ch_layout.nb_channels);
PRINT("bit_rate", q->avctx->bit_rate);
PRINT("sample_rate", q->avctx->sample_rate);
PRINT("samples_per_channel", q->subpacket[0].samples_per_channel);
@@ -1048,6 +1048,8 @@ static av_cold int cook_decode_init(AVCodecContext *avctx)
unsigned int channel_mask = 0;
int samples_per_frame;
int ret;
+ int channels = avctx->ch_layout.nb_channels;
+
q->avctx = avctx;

/* Take care of the codec specific extradata. */
@@ -1060,7 +1062,7 @@ static av_cold int cook_decode_init(AVCodecContext *avctx)
bytestream2_init(&gb, avctx->extradata, avctx->extradata_size);

/* Take data from the AVCodecContext (RM container). */
- if (!avctx->channels) {
+ if (!channels) {
av_log(avctx, AV_LOG_ERROR, "Invalid number of channels\n");
return AVERROR_INVALIDDATA;
}
@@ -1081,7 +1083,7 @@ static av_cold int cook_decode_init(AVCodecContext *avctx)
q->subpacket[s].js_vlc_bits = bytestream2_get_be16(&gb);

/* Initialize extradata related variables. */
- q->subpacket[s].samples_per_channel = samples_per_frame / avctx->channels;
+ q->subpacket[s].samples_per_channel = samples_per_frame / channels;
q->subpacket[s].bits_per_subpacket = avctx->block_align * 8;

/* Initialize default data states. */
@@ -1096,21 +1098,21 @@ static av_cold int cook_decode_init(AVCodecContext *avctx)
q->subpacket[s].joint_stereo = 0;
switch (q->subpacket[s].cookversion) {
case MONO:
- if (avctx->channels != 1) {
+ if (channels != 1) {
avpriv_request_sample(avctx, "Container channels != 1");
return AVERROR_PATCHWELCOME;
}
av_log(avctx, AV_LOG_DEBUG, "MONO\n");
break;
case STEREO:
- if (avctx->channels != 1) {
+ if (channels != 1) {
q->subpacket[s].bits_per_subpdiv = 1;
q->subpacket[s].num_channels = 2;
}
av_log(avctx, AV_LOG_DEBUG, "STEREO\n");
break;
case JOINT_STEREO:
- if (avctx->channels != 2) {
+ if (channels != 2) {
avpriv_request_sample(avctx, "Container channels != 2");
return AVERROR_PATCHWELCOME;
}
@@ -1131,8 +1133,9 @@ static av_cold int cook_decode_init(AVCodecContext *avctx)
case MC_COOK:
av_log(avctx, AV_LOG_DEBUG, "MULTI_CHANNEL\n");
channel_mask |= q->subpacket[s].channel_mask = bytestream2_get_be32(&gb);
+ av_channel_layout_from_mask(&avctx->ch_layout, q->subpacket[s].channel_mask);

- if (av_get_channel_layout_nb_channels(q->subpacket[s].channel_mask) > 1) {
+ if (avctx->ch_layout.nb_channels > 1) {
q->subpacket[s].total_subbands = q->subpacket[s].subbands +
q->subpacket[s].js_subband_start;
q->subpacket[s].joint_stereo = 1;
@@ -1238,10 +1241,11 @@ static av_cold int cook_decode_init(AVCodecContext *avctx)
}

avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
+ av_channel_layout_uninit(&avctx->ch_layout);
if (channel_mask)
- avctx->channel_layout = channel_mask;
+ av_channel_layout_from_mask(&avctx->ch_layout, channel_mask);
else
- avctx->channel_layout = (avctx->channels == 2) ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO;
+ av_channel_layout_default(&avctx->ch_layout, channels);

#ifdef DEBUG
dump_cook_context(q);
diff --git a/libavcodec/cook_parser.c b/libavcodec/cook_parser.c
index f140e90461..4e7b037dda 100644
--- a/libavcodec/cook_parser.c
+++ b/libavcodec/cook_parser.c
@@ -42,8 +42,8 @@ static int cook_parse(AVCodecParserContext *s1, AVCodecContext *avctx,

if (s->duration)
s1->duration = s->duration;
- else if (avctx->extradata && avctx->extradata_size >= 8 && avctx->channels)
- s->duration = AV_RB16(avctx->extradata + 4) / avctx->channels;
+ else if (avctx->extradata && avctx->extradata_size >= 8 && avctx->ch_layout.nb_channels)
+ s->duration = AV_RB16(avctx->extradata + 4) / avctx->ch_layout.nb_channels;

/* always return the full packet. this parser isn't doing any splitting or
combining, only setting packet duration */
diff --git a/libavcodec/dca.h b/libavcodec/dca.h
index 787a9c74de..873d7152e8 100644
--- a/libavcodec/dca.h
+++ b/libavcodec/dca.h
@@ -286,6 +286,8 @@ typedef struct DCAContext {
DCADSPContext dcadsp;
QMF64_table *qmf64_table;
FmtConvertContext fmt_conv;
+
+ AVChannelLayout downmix_layout;
} DCAContext;

extern av_export const uint32_t avpriv_dca_sample_rates[16];
diff --git a/libavcodec/dca_xll.c b/libavcodec/dca_xll.c
index 5d76793fbb..8fcae31336 100644
--- a/libavcodec/dca_xll.c
+++ b/libavcodec/dca_xll.c
@@ -448,7 +448,7 @@ int ff_dca_xll_decode_audio(DCAContext *s, AVFrame *frame)
* other parameters from the previous segment. */
int use_seg_state_code_param;
XllChSetSubHeader *chset = &s->xll_chsets[chset_i];
- if (in_channel >= s->avctx->channels)
+ if (in_channel >= s->avctx->ch_layout.nb_channels)
/* FIXME: Could go directly to next segment */
goto next_chset;

@@ -673,7 +673,7 @@ int ff_dca_xll_decode_audio(DCAContext *s, AVFrame *frame)
out_channel = out_channel ? out_channel - 1 : 2;

out_channel += in_channel;
- if (out_channel >= s->avctx->channels)
+ if (out_channel >= s->avctx->ch_layout.nb_channels)
continue;

out = (float *) frame->extended_data[out_channel];
@@ -717,7 +717,7 @@ int ff_dca_xll_decode_audio(DCAContext *s, AVFrame *frame)
mix_buf[j] *= coeff;

for (row = 0;
- row < chset->channels && in_channel + row < s->avctx->channels;
+ row < chset->channels && in_channel + row < s->avctx->ch_layout.nb_channels;
row++)
if (col[row + 1]) {
const float *new_channel =
diff --git a/libavcodec/dcadec.c b/libavcodec/dcadec.c
index 9c1f878239..7cde57f8a7 100644
--- a/libavcodec/dcadec.c
+++ b/libavcodec/dcadec.c
@@ -1269,10 +1269,13 @@ static int set_channel_layout(AVCodecContext *avctx, int channels)
int i;

if (s->amode < 16) {
- avctx->channel_layout = dca_core_channel_layout[s->amode];
+ static const AVChannelLayout stereo = AV_CHANNEL_LAYOUT_STEREO;
+ uint64_t mask = dca_core_channel_layout[s->amode];

if (s->audio_header.prim_channels + !!s->lfe > 2 &&
- avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) {
+ !av_channel_layout_compare(&s->downmix_layout, &stereo)) {
+ avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
+
/*
* Neither the core's auxiliary data nor our default tables contain
* downmix coefficients for the additional channel coded in the XCh
@@ -1282,9 +1285,9 @@ static int set_channel_layout(AVCodecContext *avctx, int channels)
}

if (s->xch_present && !s->xch_disable) {
- avctx->channel_layout |= AV_CH_BACK_CENTER;
+ mask |= AV_CH_BACK_CENTER;
if (s->lfe) {
- avctx->channel_layout |= AV_CH_LOW_FREQUENCY;
+ mask |= AV_CH_LOW_FREQUENCY;
s->channel_order_tab = ff_dca_channel_reorder_lfe_xch[s->amode];
} else {
s->channel_order_tab = ff_dca_channel_reorder_nolfe_xch[s->amode];
@@ -1293,7 +1296,7 @@ static int set_channel_layout(AVCodecContext *avctx, int channels)
channels = num_core_channels + !!s->lfe;
s->xch_present = 0; /* disable further xch processing */
if (s->lfe) {
- avctx->channel_layout |= AV_CH_LOW_FREQUENCY;
+ mask |= AV_CH_LOW_FREQUENCY;
s->channel_order_tab = ff_dca_channel_reorder_lfe[s->amode];
} else
s->channel_order_tab = ff_dca_channel_reorder_nolfe[s->amode];
@@ -1307,10 +1310,10 @@ static int set_channel_layout(AVCodecContext *avctx, int channels)
return AVERROR_INVALIDDATA;

if (num_core_channels + !!s->lfe > 2 &&
- avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) {
+ !av_channel_layout_compare(&s->downmix_layout, &stereo)) {
+ avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
channels = 2;
s->output = s->audio_header.prim_channels == 2 ? s->amode : DCA_STEREO;
- avctx->channel_layout = AV_CH_LAYOUT_STEREO;

/* Stereo downmix coefficients
*
@@ -1352,6 +1355,8 @@ static int set_channel_layout(AVCodecContext *avctx, int channels)
}
ff_dlog(s->avctx, "\n");
}
+ av_channel_layout_uninit(&avctx->ch_layout);
+ av_channel_layout_from_mask(&avctx->ch_layout, mask);
} else {
av_log(avctx, AV_LOG_ERROR, "Nonstandard configuration %d !\n", s->amode);
return AVERROR_INVALIDDATA;
@@ -1379,6 +1384,8 @@ static int dca_decode_frame(AVCodecContext *avctx, void *data,
int upsample = 0;
int downmix;

+ static const AVChannelLayout stereo = AV_CHANNEL_LAYOUT_STEREO;
+
s->exss_ext_mask = 0;
s->xch_present = 0;

@@ -1420,7 +1427,6 @@ static int dca_decode_frame(AVCodecContext *avctx, void *data,
ret = set_channel_layout(avctx, channels);
if (ret < 0)
return ret;
- avctx->channels = channels;

/* get output buffer */
frame->nb_samples = 256 * (s->sample_blocks / SAMPLES_PER_SUBBAND);
@@ -1451,15 +1457,15 @@ static int dca_decode_frame(AVCodecContext *avctx, void *data,
/* If downmixing to stereo, don't decode additional channels.
* FIXME: Using the xch_disable flag for this doesn't seem right. */
if (!s->xch_disable)
- avctx->channels += s->xll_channels - s->xll_residual_channels;
+ channels += s->xll_channels - s->xll_residual_channels;
}
}

- /* FIXME: This is an ugly hack, to just revert to the default
- * layout if we have additional channels. Need to convert the XLL
- * channel masks to libav channel_layout mask. */
- if (av_get_channel_layout_nb_channels(avctx->channel_layout) != avctx->channels)
- avctx->channel_layout = 0;
+ if (avctx->ch_layout.nb_channels != channels) {
+ av_channel_layout_uninit(&avctx->ch_layout);
+ avctx->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ avctx->ch_layout.nb_channels = channels;
+ }

if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) {
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
@@ -1468,7 +1474,7 @@ static int dca_decode_frame(AVCodecContext *avctx, void *data,
samples_flt = (float **) frame->extended_data;

/* allocate buffer for extra channels if downmixing */
- if (avctx->channels < full_channels) {
+ if (avctx->ch_layout.nb_channels < full_channels) {
ret = av_samples_get_buffer_size(NULL, full_channels - channels,
frame->nb_samples,
avctx->sample_fmt, 0);
@@ -1489,7 +1495,7 @@ static int dca_decode_frame(AVCodecContext *avctx, void *data,
}

downmix = s->audio_header.prim_channels > 2 &&
- avctx->request_channel_layout == AV_CH_LAYOUT_STEREO;
+ !av_channel_layout_compare(&s->downmix_layout, &stereo);

/* filter to get final output */
for (i = 0; i < (s->sample_blocks / SAMPLES_PER_SUBBAND); i++) {
@@ -1546,6 +1552,7 @@ static int dca_decode_frame(AVCodecContext *avctx, void *data,
static av_cold int dca_decode_init(AVCodecContext *avctx)
{
DCAContext *s = avctx->priv_data;
+ static const AVChannelLayout stereo = AV_CHANNEL_LAYOUT_STEREO;

s->avctx = avctx;
dca_init_vlcs();
@@ -1559,9 +1566,17 @@ static av_cold int dca_decode_init(AVCodecContext *avctx)
avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;

/* allow downmixing to stereo */
- if (avctx->channels > 2 &&
- avctx->request_channel_layout == AV_CH_LAYOUT_STEREO)
- avctx->channels = 2;
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+ if (avctx->request_channel_layout)
+ av_channel_layout_from_mask(&s->downmix_layout, avctx->request_channel_layout);
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+ if (avctx->ch_layout.nb_channels > 2 &&
+ !av_channel_layout_compare(&s->downmix_layout, &stereo)) {
+ av_channel_layout_uninit(&avctx->ch_layout);
+ avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
+ }

return 0;
}
@@ -1579,6 +1594,7 @@ static av_cold int dca_decode_end(AVCodecContext *avctx)
static const AVOption options[] = {
{ "disable_xch", "disable decoding of the XCh extension", offsetof(DCAContext, xch_disable), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM },
{ "disable_xll", "disable decoding of the XLL extension", offsetof(DCAContext, xll_disable), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM },
+ { "downmix", "Request a specific channel layout from the decoder", offsetof(DCAContext, downmix_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.str = NULL}, .flags = AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM },
{ NULL },
};

diff --git a/libavcodec/dpcm.c b/libavcodec/dpcm.c
index 7567643d45..20560b4281 100644
--- a/libavcodec/dpcm.c
+++ b/libavcodec/dpcm.c
@@ -117,7 +117,7 @@ static av_cold int dpcm_decode_init(AVCodecContext *avctx)
DPCMContext *s = avctx->priv_data;
int i;

- if (avctx->channels < 1 || avctx->channels > 2) {
+ if (avctx->ch_layout.nb_channels < 1 || avctx->ch_layout.nb_channels > 2) {
av_log(avctx, AV_LOG_INFO, "invalid number of channels\n");
return AVERROR(EINVAL);
}
@@ -175,7 +175,7 @@ static int dpcm_decode_frame(AVCodecContext *avctx, void *data,
int out = 0, ret;
int predictor[2];
int ch = 0;
- int stereo = avctx->channels - 1;
+ int stereo = avctx->ch_layout.nb_channels - 1;
int16_t *output_samples, *samples_end;
GetByteContext gb;

@@ -189,10 +189,10 @@ static int dpcm_decode_frame(AVCodecContext *avctx, void *data,
out = buf_size - 8;
break;
case AV_CODEC_ID_INTERPLAY_DPCM:
- out = buf_size - 6 - avctx->channels;
+ out = buf_size - 6 - avctx->ch_layout.nb_channels;
break;
case AV_CODEC_ID_XAN_DPCM:
- out = buf_size - 2 * avctx->channels;
+ out = buf_size - 2 * avctx->ch_layout.nb_channels;
break;
case AV_CODEC_ID_SOL_DPCM:
if (avctx->codec_tag != 3)
@@ -207,7 +207,7 @@ static int dpcm_decode_frame(AVCodecContext *avctx, void *data,
}

/* get output buffer */
- frame->nb_samples = out / avctx->channels;
+ frame->nb_samples = out / avctx->ch_layout.nb_channels;
if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) {
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
return ret;
@@ -241,7 +241,7 @@ static int dpcm_decode_frame(AVCodecContext *avctx, void *data,
case AV_CODEC_ID_INTERPLAY_DPCM:
bytestream2_skipu(&gb, 6); /* skip over the stream mask and stream length */

- for (ch = 0; ch < avctx->channels; ch++) {
+ for (ch = 0; ch < avctx->ch_layout.nb_channels; ch++) {
predictor[ch] = sign_extend(bytestream2_get_le16u(&gb), 16);
*output_samples++ = predictor[ch];
}
@@ -261,7 +261,7 @@ static int dpcm_decode_frame(AVCodecContext *avctx, void *data,
{
int shift[2] = { 4, 4 };

- for (ch = 0; ch < avctx->channels; ch++)
+ for (ch = 0; ch < avctx->ch_layout.nb_channels; ch++)
predictor[ch] = sign_extend(bytestream2_get_le16u(&gb), 16);

ch = 0;
diff --git a/libavcodec/dsicinaudio.c b/libavcodec/dsicinaudio.c
index e0fecbeb03..421a379029 100644
--- a/libavcodec/dsicinaudio.c
+++ b/libavcodec/dsicinaudio.c
@@ -80,8 +80,8 @@ static av_cold int cinaudio_decode_init(AVCodecContext *avctx)
cin->initial_decode_frame = 1;
cin->delta = 0;
avctx->sample_fmt = AV_SAMPLE_FMT_S16;
- avctx->channels = 1;
- avctx->channel_layout = AV_CH_LAYOUT_MONO;
+ av_channel_layout_uninit(&avctx->ch_layout);
+ avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;

return 0;
}
diff --git a/libavcodec/dss_sp.c b/libavcodec/dss_sp.c
index 4fe784c055..239a235d7e 100644
--- a/libavcodec/dss_sp.c
+++ b/libavcodec/dss_sp.c
@@ -289,10 +289,10 @@ static const int32_t dss_sp_sinc[67] = {
static av_cold int dss_sp_decode_init(AVCodecContext *avctx)
{
DssSpContext *p = avctx->priv_data;
- avctx->channel_layout = AV_CH_LAYOUT_MONO;
avctx->sample_fmt = AV_SAMPLE_FMT_S16;
- avctx->channels = 1;
avctx->sample_rate = 11025;
+ av_channel_layout_uninit(&avctx->ch_layout);
+ avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;

memset(p->history, 0, sizeof(p->history));
p->pulse_dec_mode = 1;
diff --git a/libavcodec/flac.c b/libavcodec/flac.c
index 3e51fdeb98..eb9051ab50 100644
--- a/libavcodec/flac.c
+++ b/libavcodec/flac.c
@@ -29,15 +29,15 @@

static const int8_t sample_size_table[] = { 0, 8, 12, 0, 16, 20, 24, 0 };

-static const uint64_t flac_channel_layouts[8] = {
- AV_CH_LAYOUT_MONO,
- AV_CH_LAYOUT_STEREO,
- AV_CH_LAYOUT_SURROUND,
- AV_CH_LAYOUT_QUAD,
- AV_CH_LAYOUT_5POINT0,
- AV_CH_LAYOUT_5POINT1,
- AV_CH_LAYOUT_6POINT1,
- AV_CH_LAYOUT_7POINT1
+static const AVChannelLayout flac_channel_layouts[8] = {
+ AV_CHANNEL_LAYOUT_MONO,
+ AV_CHANNEL_LAYOUT_STEREO,
+ AV_CHANNEL_LAYOUT_SURROUND,
+ AV_CHANNEL_LAYOUT_QUAD,
+ AV_CHANNEL_LAYOUT_5POINT0,
+ AV_CHANNEL_LAYOUT_5POINT1,
+ AV_CHANNEL_LAYOUT_6POINT1,
+ AV_CHANNEL_LAYOUT_7POINT1
};

static int64_t get_utf8(GetBitContext *gb)
@@ -193,12 +193,17 @@ int ff_flac_is_extradata_valid(AVCodecContext *avctx,
return 1;
}

-void ff_flac_set_channel_layout(AVCodecContext *avctx)
+void ff_flac_set_channel_layout(AVCodecContext *avctx, int channels)
{
- if (avctx->channels <= FF_ARRAY_ELEMS(flac_channel_layouts))
- avctx->channel_layout = flac_channel_layouts[avctx->channels - 1];
+ if (channels == avctx->ch_layout.nb_channels)
+ return;
+
+ av_channel_layout_uninit(&avctx->ch_layout);
+ if (channels <= FF_ARRAY_ELEMS(flac_channel_layouts))
+ avctx->ch_layout = flac_channel_layouts[channels - 1];
else
- avctx->channel_layout = 0;
+ avctx->ch_layout = (AVChannelLayout){ .order = AV_CHANNEL_ORDER_UNSPEC,
+ .nb_channels = channels };
}

void ff_flac_parse_streaminfo(AVCodecContext *avctx, struct FLACStreaminfo *s,
@@ -222,13 +227,9 @@ void ff_flac_parse_streaminfo(AVCodecContext *avctx, struct FLACStreaminfo *s,
s->channels = get_bits(&gb, 3) + 1;
s->bps = get_bits(&gb, 5) + 1;

- avctx->channels = s->channels;
avctx->sample_rate = s->samplerate;
avctx->bits_per_raw_sample = s->bps;
-
- if (!avctx->channel_layout ||
- av_get_channel_layout_nb_channels(avctx->channel_layout) != avctx->channels)
- ff_flac_set_channel_layout(avctx);
+ ff_flac_set_channel_layout(avctx, s->channels);

s->samples = get_bits_long(&gb, 32) << 4;
s->samples |= get_bits(&gb, 4);
diff --git a/libavcodec/flac.h b/libavcodec/flac.h
index 3229682047..4ffdc3500a 100644
--- a/libavcodec/flac.h
+++ b/libavcodec/flac.h
@@ -137,7 +137,7 @@ int ff_flac_get_max_frame_size(int blocksize, int ch, int bps);
int ff_flac_decode_frame_header(AVCodecContext *avctx, GetBitContext *gb,
FLACFrameInfo *fi, int log_level_offset);

-void ff_flac_set_channel_layout(AVCodecContext *avctx);
+void ff_flac_set_channel_layout(AVCodecContext *avctx, int channels);

/**
* Parse the metadata block parameters from the header.
diff --git a/libavcodec/flac_parser.c b/libavcodec/flac_parser.c
index cb394f2bdb..34f5d52354 100644
--- a/libavcodec/flac_parser.c
+++ b/libavcodec/flac_parser.c
@@ -458,11 +458,8 @@ static int get_best_header(FLACParseContext* fpc, const uint8_t **poutbuf,
check_header_mismatch(fpc, header, child, 0);
}

- if (header->fi.channels != fpc->avctx->channels ||
- !fpc->avctx->channel_layout) {
- fpc->avctx->channels = header->fi.channels;
- ff_flac_set_channel_layout(fpc->avctx);
- }
+ ff_flac_set_channel_layout(fpc->avctx, header->fi.channels);
+
fpc->avctx->sample_rate = header->fi.samplerate;
fpc->pc->duration = header->fi.blocksize;
*poutbuf = flac_fifo_read_wrap(fpc, header->offset, *poutbuf_size,
diff --git a/libavcodec/flacdec.c b/libavcodec/flacdec.c
index 78be2adab3..8b2f780ff0 100644
--- a/libavcodec/flacdec.c
+++ b/libavcodec/flacdec.c
@@ -408,15 +408,15 @@ static int decode_frame(FLACContext *s)
}

if (s->channels && fi.channels != s->channels && s->got_streaminfo) {
- s->channels = s->avctx->channels = fi.channels;
- ff_flac_set_channel_layout(s->avctx);
+ s->channels = fi.channels;
+ ff_flac_set_channel_layout(s->avctx, s->channels);
ret = allocate_buffers(s);
if (ret < 0)
return ret;
}
- s->channels = s->avctx->channels = fi.channels;
- if (!s->avctx->channel_layout)
- ff_flac_set_channel_layout(s->avctx);
+ s->channels = fi.channels;
+ if (!s->avctx->ch_layout.nb_channels)
+ ff_flac_set_channel_layout(s->avctx, s->channels);
s->ch_mode = fi.ch_mode;

if (!s->bps && !fi.bps) {
diff --git a/libavcodec/flacenc.c b/libavcodec/flacenc.c
index 2745b17a1c..cd02500807 100644
--- a/libavcodec/flacenc.c
+++ b/libavcodec/flacenc.c
@@ -231,7 +231,7 @@ static av_cold void dprint_compression_options(FlacEncodeContext *s)
static av_cold int flac_encode_init(AVCodecContext *avctx)
{
int freq = avctx->sample_rate;
- int channels = avctx->channels;
+ int channels = avctx->ch_layout.nb_channels;
FlacEncodeContext *s = avctx->priv_data;
int i, level, ret;
uint8_t *streaminfo;
diff --git a/libavcodec/g722dec.c b/libavcodec/g722dec.c
index 07af0a082a..e08ea22591 100644
--- a/libavcodec/g722dec.c
+++ b/libavcodec/g722dec.c
@@ -60,8 +60,8 @@ static av_cold int g722_decode_init(AVCodecContext * avctx)
{
G722Context *c = avctx->priv_data;

- avctx->channels = 1;
- avctx->channel_layout = AV_CH_LAYOUT_MONO;
+ av_channel_layout_uninit(&avctx->ch_layout);
+ avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
avctx->sample_fmt = AV_SAMPLE_FMT_S16;

c->band[0].scale_factor = 8;
diff --git a/libavcodec/g722enc.c b/libavcodec/g722enc.c
index 545825b057..34bdbbd51d 100644
--- a/libavcodec/g722enc.c
+++ b/libavcodec/g722enc.c
@@ -60,11 +60,6 @@ static av_cold int g722_encode_init(AVCodecContext * avctx)
G722Context *c = avctx->priv_data;
int ret;

- if (avctx->channels != 1) {
- av_log(avctx, AV_LOG_ERROR, "Only mono tracks are allowed.\n");
- return AVERROR_INVALIDDATA;
- }
-
c->band[0].scale_factor = 8;
c->band[1].scale_factor = 2;
c->prev_samples_pos = 22;
@@ -393,4 +388,7 @@ AVCodec ff_adpcm_g722_encoder = {
.capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME,
.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
AV_SAMPLE_FMT_NONE },
+ .ch_layouts = (const AVChannelLayout[]){
+ AV_CHANNEL_LAYOUT_MONO, { 0 }
+ },
};
diff --git a/libavcodec/g723_1dec.c b/libavcodec/g723_1dec.c
index 0cb5ba70c5..4ec5555d4d 100644
--- a/libavcodec/g723_1dec.c
+++ b/libavcodec/g723_1dec.c
@@ -43,10 +43,10 @@ static av_cold int g723_1_decode_init(AVCodecContext *avctx)
{
G723_1_Context *p = avctx->priv_data;

- avctx->channel_layout = AV_CH_LAYOUT_MONO;
avctx->sample_fmt = AV_SAMPLE_FMT_S16;
- avctx->channels = 1;
avctx->sample_rate = 8000;
+ av_channel_layout_uninit(&avctx->ch_layout);
+ avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
p->pf_gain = 1 << 12;

memcpy(p->prev_lsp, dc_lsp, LPC_ORDER * sizeof(*p->prev_lsp));
diff --git a/libavcodec/g723_1enc.c b/libavcodec/g723_1enc.c
index 82f5cecfa2..c8d296dea5 100644
--- a/libavcodec/g723_1enc.c
+++ b/libavcodec/g723_1enc.c
@@ -49,11 +49,6 @@ static av_cold int g723_1_encode_init(AVCodecContext *avctx)
return AVERROR(EINVAL);
}

- if (avctx->channels != 1) {
- av_log(avctx, AV_LOG_ERROR, "Only mono supported\n");
- return AVERROR(EINVAL);
- }
-
if (avctx->bit_rate == 6300) {
p->cur_rate = RATE_6300;
} else if (avctx->bit_rate == 5300) {
@@ -1200,4 +1195,7 @@ AVCodec ff_g723_1_encoder = {
.sample_fmts = (const enum AVSampleFormat[]) {
AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE
},
+ .ch_layouts = (const AVChannelLayout[]){
+ AV_CHANNEL_LAYOUT_MONO, { 0 }
+ },
};
diff --git a/libavcodec/g726.c b/libavcodec/g726.c
index dab038f50c..112c29a13a 100644
--- a/libavcodec/g726.c
+++ b/libavcodec/g726.c
@@ -321,7 +321,7 @@ static av_cold int g726_encode_init(AVCodecContext *avctx)
return AVERROR(EINVAL);
}

- if(avctx->channels != 1){
+ if (avctx->ch_layout.nb_channels != 1) {
av_log(avctx, AV_LOG_ERROR, "Only mono is supported\n");
return AVERROR(EINVAL);
}
@@ -407,8 +407,8 @@ static av_cold int g726_decode_init(AVCodecContext *avctx)
{
G726Context* c = avctx->priv_data;

- avctx->channels = 1;
- avctx->channel_layout = AV_CH_LAYOUT_MONO;
+ av_channel_layout_uninit(&avctx->ch_layout);
+ avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;

c->code_size = avctx->bits_per_coded_sample;
if (c->code_size < 2 || c->code_size > 5) {
diff --git a/libavcodec/gsmdec.c b/libavcodec/gsmdec.c
index 0205fafad0..036917b679 100644
--- a/libavcodec/gsmdec.c
+++ b/libavcodec/gsmdec.c
@@ -35,8 +35,8 @@

static av_cold int gsm_init(AVCodecContext *avctx)
{
- avctx->channels = 1;
- avctx->channel_layout = AV_CH_LAYOUT_MONO;
+ av_channel_layout_uninit(&avctx->ch_layout);
+ avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
if (!avctx->sample_rate)
avctx->sample_rate = 8000;
avctx->sample_fmt = AV_SAMPLE_FMT_S16;
diff --git a/libavcodec/imc.c b/libavcodec/imc.c
index 100e6f8941..9eef41b86e 100644
--- a/libavcodec/imc.c
+++ b/libavcodec/imc.c
@@ -180,15 +180,17 @@ static av_cold int imc_decode_init(AVCodecContext *avctx)
IMCContext *q = avctx->priv_data;
double r1, r2;

- if (avctx->codec_id == AV_CODEC_ID_IMC)
- avctx->channels = 1;
+ if (avctx->codec_id == AV_CODEC_ID_IMC) {
+ av_channel_layout_uninit(&avctx->ch_layout);
+ avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
+ }

- if (avctx->channels > 2) {
+ if (avctx->ch_layout.nb_channels > 2) {
avpriv_request_sample(avctx, "Number of channels > 2");
return AVERROR_PATCHWELCOME;
}

- for (j = 0; j < avctx->channels; j++) {
+ for (j = 0; j < avctx->ch_layout.nb_channels; j++) {
q->chctx[j].decoder_reset = 1;

for (i = 0; i < BANDS; i++)
@@ -250,8 +252,6 @@ static av_cold int imc_decode_init(AVCodecContext *avctx)
ff_bswapdsp_init(&q->bdsp);
avpriv_float_dsp_init(&q->fdsp, avctx->flags & AV_CODEC_FLAG_BITEXACT);
avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
- avctx->channel_layout = avctx->channels == 1 ? AV_CH_LAYOUT_MONO
- : AV_CH_LAYOUT_STEREO;

return 0;
}
@@ -983,7 +983,7 @@ static int imc_decode_block(AVCodecContext *avctx, IMCContext *q, int ch)

memset(chctx->skipFlags, 0, sizeof(chctx->skipFlags));

- imc_imdct256(q, chctx, avctx->channels);
+ imc_imdct256(q, chctx, avctx->ch_layout.nb_channels);

return 0;
}
@@ -1000,7 +1000,7 @@ static int imc_decode_frame(AVCodecContext *avctx, void *data,

LOCAL_ALIGNED_16(uint16_t, buf16, [(IMC_BLOCK_SIZE + AV_INPUT_BUFFER_PADDING_SIZE) / 2]);

- if (buf_size < IMC_BLOCK_SIZE * avctx->channels) {
+ if (buf_size < IMC_BLOCK_SIZE * avctx->ch_layout.nb_channels) {
av_log(avctx, AV_LOG_ERROR, "frame too small!\n");
return AVERROR_INVALIDDATA;
}
@@ -1012,7 +1012,7 @@ static int imc_decode_frame(AVCodecContext *avctx, void *data,
return ret;
}

- for (i = 0; i < avctx->channels; i++) {
+ for (i = 0; i < avctx->ch_layout.nb_channels; i++) {
q->out_samples = (float *)frame->extended_data[i];

q->bdsp.bswap16_buf(buf16, (const uint16_t *) buf, IMC_BLOCK_SIZE / 2);
@@ -1025,14 +1025,14 @@ static int imc_decode_frame(AVCodecContext *avctx, void *data,
return ret;
}

- if (avctx->channels == 2) {
+ if (avctx->ch_layout.nb_channels == 2) {
q->fdsp.butterflies_float((float *)frame->extended_data[0],
(float *)frame->extended_data[1], COEFFS);
}

*got_frame_ptr = 1;

- return IMC_BLOCK_SIZE * avctx->channels;
+ return IMC_BLOCK_SIZE * avctx->ch_layout.nb_channels;
}


diff --git a/libavcodec/libdcadec.c b/libavcodec/libdcadec.c
index b88f80763b..c276a5f8f1 100644
--- a/libavcodec/libdcadec.c
+++ b/libavcodec/libdcadec.c
@@ -75,8 +75,8 @@ static int dcadec_decode_frame(AVCodecContext *avctx, void *data,
return AVERROR_UNKNOWN;
}

- avctx->channels = av_get_channel_layout_nb_channels(channel_mask);
- avctx->channel_layout = channel_mask;
+ av_channel_layout_uninit(&avctx->ch_layout);
+ av_channel_layout_from_mask(&avctx->ch_layout, channel_mask);
avctx->sample_rate = sample_rate;

if (bits_per_sample == 16)
@@ -128,7 +128,7 @@ static int dcadec_decode_frame(AVCodecContext *avctx, void *data,
if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
return ret;

- for (i = 0; i < avctx->channels; i++) {
+ for (i = 0; i < avctx->ch_layout.nb_channels; i++) {
if (frame->format == AV_SAMPLE_FMT_S16P) {
int16_t *plane = (int16_t *)frame->extended_data[i];
for (k = 0; k < nsamples; k++)
diff --git a/libavcodec/libfdk-aacdec.c b/libavcodec/libfdk-aacdec.c
index aa30f93ef6..6a77e90392 100644
--- a/libavcodec/libfdk-aacdec.c
+++ b/libavcodec/libfdk-aacdec.c
@@ -50,6 +50,7 @@ typedef struct FDKAACDecContext {
int drc_heavy;
int drc_cut;
int level_limit;
+ AVChannelLayout downmix_layout;
} FDKAACDecContext;


@@ -75,6 +76,7 @@ static const AVOption fdk_aac_dec_options[] = {
#ifdef AACDECODER_LIB_VL0
{ "level_limit", "Signal level limiting", OFFSET(level_limit), AV_OPT_TYPE_INT, { .i64 = 0 }, -1, 1, AD },
#endif
+ { "downmix", "Request a specific channel layout from the decoder", OFFSET(downmix_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.str = NULL}, .flags = AD },
{ NULL }
};

@@ -181,17 +183,15 @@ static int get_stream_info(AVCodecContext *avctx)
ch_error = 1;
}
}
- if (!ch_error &&
- av_get_channel_layout_nb_channels(ch_layout) != info->numChannels) {
+
+ av_channel_layout_uninit(&avctx->ch_layout);
+ av_channel_layout_from_mask(&avctx->ch_layout, ch_layout);
+ if (!ch_error && avctx->ch_layout.nb_channels != info->numChannels) {
av_log(avctx, AV_LOG_WARNING, "unsupported channel configuration\n");
ch_error = 1;
}
if (ch_error)
- avctx->channel_layout = 0;
- else
- avctx->channel_layout = ch_layout;
-
- avctx->channels = info->numChannels;
+ avctx->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;

return 0;
}
@@ -233,11 +233,19 @@ static av_cold int fdk_aac_decode_init(AVCodecContext *avctx)
return AVERROR_UNKNOWN;
}

- if (avctx->request_channel_layout > 0 &&
- avctx->request_channel_layout != AV_CH_LAYOUT_NATIVE) {
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+ if (avctx->request_channel_layout) {
+ av_channel_layout_uninit(&s->downmix_layout);
+ av_channel_layout_from_mask(&s->downmix_layout, avctx->request_channel_layout);
+ }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+ if (s->downmix_layout.nb_channels > 0 &&
+ s->downmix_layout.order != AV_CHANNEL_ORDER_NATIVE) {
int downmix_channels = -1;

- switch (avctx->request_channel_layout) {
+ switch (s->downmix_layout.u.mask) {
case AV_CH_LAYOUT_STEREO:
case AV_CH_LAYOUT_STEREO_DOWNMIX:
downmix_channels = 2;
@@ -246,7 +254,7 @@ static av_cold int fdk_aac_decode_init(AVCodecContext *avctx)
downmix_channels = 1;
break;
default:
- av_log(avctx, AV_LOG_WARNING, "Invalid request_channel_layout\n");
+ av_log(avctx, AV_LOG_WARNING, "Invalid downmix option\n");
break;
}

@@ -349,7 +357,7 @@ static int fdk_aac_decode_frame(AVCodecContext *avctx, void *data,
goto end;
}
memcpy(frame->extended_data[0], s->decoder_buffer,
- avctx->channels * avctx->frame_size *
+ avctx->ch_layout.nb_channels * avctx->frame_size *
av_get_bytes_per_sample(avctx->sample_fmt));

*got_frame_ptr = 1;
diff --git a/libavcodec/libfdk-aacenc.c b/libavcodec/libfdk-aacenc.c
index 03879bbf5a..f92c14d65f 100644
--- a/libavcodec/libfdk-aacenc.c
+++ b/libavcodec/libfdk-aacenc.c
@@ -114,7 +114,7 @@ static av_cold int aac_encode_init(AVCodecContext *avctx)
int aot = FF_PROFILE_AAC_LOW + 1;
int sce = 0, cpe = 0;

- if ((err = aacEncOpen(&s->handle, 0, avctx->channels)) != AACENC_OK) {
+ if ((err = aacEncOpen(&s->handle, 0, avctx->ch_layout.nb_channels)) != AACENC_OK) {
av_log(avctx, AV_LOG_ERROR, "Unable to open the encoder: %s\n",
aac_get_error(err));
goto error;
@@ -145,7 +145,7 @@ static av_cold int aac_encode_init(AVCodecContext *avctx)
goto error;
}

- switch (avctx->channels) {
+ switch (avctx->ch_layout.nb_channels) {
case 1: mode = MODE_1; sce = 1; cpe = 0; break;
case 2: mode = MODE_2; sce = 0; cpe = 1; break;
case 3: mode = MODE_1_2; sce = 1; cpe = 1; break;
@@ -158,7 +158,7 @@ static av_cold int aac_encode_init(AVCodecContext *avctx)
case 8:
sce = 2;
cpe = 3;
- if (avctx->channel_layout == AV_CH_LAYOUT_7POINT1) {
+ if (avctx->ch_layout.u.mask == AV_CH_LAYOUT_7POINT1) {
mode = MODE_7_1_REAR_SURROUND;
} else {
// MODE_1_2_2_2_1 and MODE_7_1_FRONT_CENTER use the same channel layout
@@ -168,7 +168,7 @@ static av_cold int aac_encode_init(AVCodecContext *avctx)
#endif
default:
av_log(avctx, AV_LOG_ERROR,
- "Unsupported number of channels %d\n", avctx->channels);
+ "Unsupported number of channels %d\n", avctx->ch_layout.nb_channels);
goto error;
}

@@ -329,10 +329,10 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
in_args.numInSamples = -1;
} else {
in_ptr = frame->data[0];
- in_buffer_size = 2 * avctx->channels * frame->nb_samples;
+ in_buffer_size = 2 * avctx->ch_layout.nb_channels * frame->nb_samples;
in_buffer_element_size = 2;

- in_args.numInSamples = avctx->channels * frame->nb_samples;
+ in_args.numInSamples = avctx->ch_layout.nb_channels * frame->nb_samples;
in_buf.numBufs = 1;
in_buf.bufs = &in_ptr;
in_buf.bufferIdentifiers = &in_buffer_identifier;
@@ -345,7 +345,7 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
}

/* The maximum packet size is 6144 bits aka 768 bytes per channel. */
- if ((ret = ff_alloc_packet(avpkt, FFMAX(8192, 768 * avctx->channels)))) {
+ if ((ret = ff_alloc_packet(avpkt, FFMAX(8192, 768 * avctx->ch_layout.nb_channels)))) {
av_log(avctx, AV_LOG_ERROR, "Error getting output packet\n");
return ret;
}
@@ -394,6 +394,7 @@ static const AVCodecDefault aac_encode_defaults[] = {
{ NULL }
};

+#if FF_API_OLD_CHANNEL_LAYOUT
static const uint64_t aac_channel_layout[] = {
AV_CH_LAYOUT_MONO,
AV_CH_LAYOUT_STEREO,
@@ -407,6 +408,21 @@ static const uint64_t aac_channel_layout[] = {
#endif
0,
};
+#endif /* FF_API_OLD_CHANNEL_LAYOUT */
+
+static const AVChannelLayout aac_ch_layouts[16] = {
+ AV_CHANNEL_LAYOUT_MONO,
+ AV_CHANNEL_LAYOUT_STEREO,
+ AV_CHANNEL_LAYOUT_SURROUND,
+ AV_CHANNEL_LAYOUT_4POINT0,
+ AV_CHANNEL_LAYOUT_5POINT0_BACK,
+ AV_CHANNEL_LAYOUT_5POINT1_BACK,
+#ifdef AACENCODER_LIB_VL0
+ AV_CHANNEL_LAYOUT_7POINT1_WIDE_BACK,
+ AV_CHANNEL_LAYOUT_7POINT1,
+#endif
+ { 0 },
+};

static const int aac_sample_rates[] = {
96000, 88200, 64000, 48000, 44100, 32000,
@@ -429,5 +445,10 @@ AVCodec ff_libfdk_aac_encoder = {
.defaults = aac_encode_defaults,
.profiles = profiles,
.supported_samplerates = aac_sample_rates,
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
.channel_layouts = aac_channel_layout,
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+ .ch_layouts = aac_ch_layouts,
};
diff --git a/libavcodec/libgsmdec.c b/libavcodec/libgsmdec.c
index 4c21ff6728..0f6962fa1e 100644
--- a/libavcodec/libgsmdec.c
+++ b/libavcodec/libgsmdec.c
@@ -48,8 +48,8 @@ typedef struct LibGSMDecodeContext {
static av_cold int libgsm_decode_init(AVCodecContext *avctx) {
LibGSMDecodeContext *s = avctx->priv_data;

- avctx->channels = 1;
- avctx->channel_layout = AV_CH_LAYOUT_MONO;
+ av_channel_layout_uninit(&avctx->ch_layout);
+ avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
avctx->sample_rate = 8000;
avctx->sample_fmt = AV_SAMPLE_FMT_S16;

diff --git a/libavcodec/libgsmenc.c b/libavcodec/libgsmenc.c
index 8f51321d46..048baeef35 100644
--- a/libavcodec/libgsmenc.c
+++ b/libavcodec/libgsmenc.c
@@ -41,9 +41,9 @@
#include "gsm.h"

static av_cold int libgsm_encode_init(AVCodecContext *avctx) {
- if (avctx->channels > 1) {
+ if (avctx->ch_layout.nb_channels > 1) {
av_log(avctx, AV_LOG_ERROR, "Mono required for GSM, got %d channels\n",
- avctx->channels);
+ avctx->ch_layout.nb_channels);
return -1;
}

diff --git a/libavcodec/libilbc.c b/libavcodec/libilbc.c
index 80b69a562c..8131a25da6 100644
--- a/libavcodec/libilbc.c
+++ b/libavcodec/libilbc.c
@@ -69,8 +69,8 @@ static av_cold int ilbc_decode_init(AVCodecContext *avctx)

WebRtcIlbcfix_InitDecode(&s->decoder, mode, s->enhance);

- avctx->channels = 1;
- avctx->channel_layout = AV_CH_LAYOUT_MONO;
+ av_channel_layout_uninit(&avctx->ch_layout);
+ avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
avctx->sample_rate = 8000;
avctx->sample_fmt = AV_SAMPLE_FMT_S16;

diff --git a/libavcodec/libopencore-amr.c b/libavcodec/libopencore-amr.c
index 8200f6719c..4f47483545 100644
--- a/libavcodec/libopencore-amr.c
+++ b/libavcodec/libopencore-amr.c
@@ -35,13 +35,13 @@ static int amr_decode_fix_avctx(AVCodecContext *avctx)

avctx->sample_rate = 8000 * is_amr_wb;

- if (avctx->channels > 1) {
+ if (avctx->ch_layout.nb_channels > 1) {
avpriv_report_missing_feature(avctx, "multi-channel AMR");
return AVERROR_PATCHWELCOME;
}

- avctx->channels = 1;
- avctx->channel_layout = AV_CH_LAYOUT_MONO;
+ av_channel_layout_uninit(&avctx->ch_layout);
+ avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
avctx->sample_fmt = AV_SAMPLE_FMT_S16;
return 0;
}
@@ -199,7 +199,7 @@ static av_cold int amr_nb_encode_init(AVCodecContext *avctx)
return AVERROR(ENOSYS);
}

- if (avctx->channels != 1) {
+ if (avctx->ch_layout.nb_channels != 1) {
av_log(avctx, AV_LOG_ERROR, "Only mono supported\n");
return AVERROR(ENOSYS);
}
diff --git a/libavcodec/libopusdec.c b/libavcodec/libopusdec.c
index 781635615c..0c31d3a182 100644
--- a/libavcodec/libopusdec.c
+++ b/libavcodec/libopusdec.c
@@ -41,58 +41,52 @@ static av_cold int libopus_decode_init(AVCodecContext *avc)
struct libopus_context *opus = avc->priv_data;
int ret, channel_map = 0, gain_db = 0, nb_streams, nb_coupled;
uint8_t mapping_arr[8] = { 0, 1 }, *mapping;
-
- if (avc->channels <= 0) {
- av_log(avc, AV_LOG_WARNING,
- "Invalid number of channels %d, defaulting to stereo\n", avc->channels);
- avc->channels = 2;
- }
-
- avc->channels = avc->extradata_size >= 10 ? avc->extradata[9] : (avc->channels == 1) ? 1 : 2;
- if (avc->channels <= 0) {
- av_log(avc, AV_LOG_WARNING,
- "Invalid number of channels %d, defaulting to stereo\n", avc->channels);
- avc->channels = 2;
- }
+ int channels = avc->ch_layout.nb_channels;

avc->sample_rate = 48000;
avc->sample_fmt = avc->request_sample_fmt == AV_SAMPLE_FMT_FLT ?
AV_SAMPLE_FMT_FLT : AV_SAMPLE_FMT_S16;
- avc->channel_layout = avc->channels > 8 ? 0 :
- ff_vorbis_channel_layouts[avc->channels - 1];
+
+ if (channels <= 0) {
+ av_log(avc, AV_LOG_ERROR, "Invalid channel count.\n");
+ return AVERROR(EINVAL);
+ } else if (channels < 8) {
+ av_channel_layout_uninit(&avc->ch_layout);
+ avc->ch_layout = ff_vorbis_ch_layouts[channels - 1];
+ }

if (avc->extradata_size >= OPUS_HEAD_SIZE) {
gain_db = sign_extend(AV_RL16(avc->extradata + 16), 16);
channel_map = AV_RL8 (avc->extradata + 18);
}
- if (avc->extradata_size >= OPUS_HEAD_SIZE + 2 + avc->channels) {
+ if (avc->extradata_size >= OPUS_HEAD_SIZE + 2 + channels) {
nb_streams = avc->extradata[OPUS_HEAD_SIZE + 0];
nb_coupled = avc->extradata[OPUS_HEAD_SIZE + 1];
- if (nb_streams + nb_coupled != avc->channels)
+ if (nb_streams + nb_coupled != channels)
av_log(avc, AV_LOG_WARNING, "Inconsistent channel mapping.\n");
mapping = avc->extradata + OPUS_HEAD_SIZE + 2;
} else {
- if (avc->channels > 2 || channel_map) {
+ if (channels > 2 || channel_map) {
av_log(avc, AV_LOG_ERROR,
- "No channel mapping for %d channels.\n", avc->channels);
+ "No channel mapping for %d channels.\n", channels);
return AVERROR(EINVAL);
}
nb_streams = 1;
- nb_coupled = avc->channels > 1;
+ nb_coupled = channels > 1;
mapping = mapping_arr;
}

- if (avc->channels > 2 && avc->channels <= 8) {
- const uint8_t *vorbis_offset = ff_vorbis_channel_layout_offsets[avc->channels - 1];
+ if (channels > 2 && channels <= 8) {
+ const uint8_t *vorbis_offset = ff_vorbis_channel_layout_offsets[channels - 1];
int ch;

/* Remap channels from Vorbis order to libav order */
- for (ch = 0; ch < avc->channels; ch++)
+ for (ch = 0; ch < channels; ch++)
mapping_arr[ch] = mapping[vorbis_offset[ch]];
mapping = mapping_arr;
}

- opus->dec = opus_multistream_decoder_create(avc->sample_rate, avc->channels,
+ opus->dec = opus_multistream_decoder_create(avc->sample_rate, channels,
nb_streams, nb_coupled,
mapping, &ret);
if (!opus->dec) {
diff --git a/libavcodec/libopusenc.c b/libavcodec/libopusenc.c
index 500e58c85e..cdae1af64d 100644
--- a/libavcodec/libopusenc.c
+++ b/libavcodec/libopusenc.c
@@ -82,7 +82,7 @@ static void libopus_write_header(AVCodecContext *avctx, int stream_count,
const uint8_t *channel_mapping)
{
uint8_t *p = avctx->extradata;
- int channels = avctx->channels;
+ int channels = avctx->ch_layout.nb_channels;

bytestream_put_buffer(&p, "OpusHead", 8);
bytestream_put_byte(&p, 1); /* Version */
@@ -152,21 +152,22 @@ static int libopus_configure_encoder(AVCodecContext *avctx, OpusMSEncoder *enc,
static int av_cold libopus_encode_init(AVCodecContext *avctx)
{
LibopusEncContext *opus = avctx->priv_data;
+ int channels = avctx->ch_layout.nb_channels;
const uint8_t *channel_mapping;
OpusMSEncoder *enc;
int ret = OPUS_OK;
int coupled_stream_count, header_size, frame_size;

- coupled_stream_count = opus_coupled_streams[avctx->channels - 1];
- opus->stream_count = avctx->channels - coupled_stream_count;
- channel_mapping = libav_libopus_channel_map[avctx->channels - 1];
+ coupled_stream_count = opus_coupled_streams[channels - 1];
+ opus->stream_count = channels - coupled_stream_count;
+ channel_mapping = libav_libopus_channel_map[channels - 1];

/* FIXME: Opus can handle up to 255 channels. However, the mapping for
* anything greater than 8 is undefined. */
- if (avctx->channels > 8) {
+ if (channels > 8) {
avpriv_report_missing_feature(avctx,
"Undefined channel layout for %d channels",
- avctx->channels);
+ channels);
return AVERROR_PATCHWELCOME;
}
if (!avctx->bit_rate) {
@@ -177,10 +178,10 @@ static int av_cold libopus_encode_init(AVCodecContext *avctx)
"No bit rate set. Defaulting to %d bps.\n", avctx->bit_rate);
}

- if (avctx->bit_rate < 500 || avctx->bit_rate > 256000 * avctx->channels) {
+ if (avctx->bit_rate < 500 || avctx->bit_rate > 256000 * channels) {
av_log(avctx, AV_LOG_ERROR, "The bit rate %d bps is unsupported. "
"Please choose a value between 500 and %d.\n", avctx->bit_rate,
- 256000 * avctx->channels);
+ 256000 * channels);
return AVERROR(EINVAL);
}

@@ -245,7 +246,7 @@ static int av_cold libopus_encode_init(AVCodecContext *avctx)
}
}

- enc = opus_multistream_encoder_create(avctx->sample_rate, avctx->channels,
+ enc = opus_multistream_encoder_create(avctx->sample_rate, channels,
opus->stream_count,
coupled_stream_count,
channel_mapping,
@@ -262,7 +263,7 @@ static int av_cold libopus_encode_init(AVCodecContext *avctx)
goto fail;
}

- header_size = 19 + (avctx->channels > 2 ? 2 + avctx->channels : 0);
+ header_size = 19 + (channels > 2 ? 2 + channels : 0);
avctx->extradata = av_malloc(header_size + AV_INPUT_BUFFER_PADDING_SIZE);
if (!avctx->extradata) {
av_log(avctx, AV_LOG_ERROR, "Failed to allocate extradata.\n");
@@ -271,7 +272,7 @@ static int av_cold libopus_encode_init(AVCodecContext *avctx)
}
avctx->extradata_size = header_size;

- opus->samples = av_mallocz(frame_size * avctx->channels *
+ opus->samples = av_mallocz(frame_size * channels *
av_get_bytes_per_sample(avctx->sample_fmt));
if (!opus->samples) {
av_log(avctx, AV_LOG_ERROR, "Failed to allocate samples buffer.\n");
@@ -286,7 +287,7 @@ static int av_cold libopus_encode_init(AVCodecContext *avctx)
opus_strerror(ret));

libopus_write_header(avctx, opus->stream_count, coupled_stream_count,
- opus_vorbis_channel_map[avctx->channels - 1]);
+ opus_vorbis_channel_map[channels - 1]);

ff_af_queue_init(avctx, &opus->afq);

@@ -304,7 +305,7 @@ static int libopus_encode(AVCodecContext *avctx, AVPacket *avpkt,
const AVFrame *frame, int *got_packet_ptr)
{
LibopusEncContext *opus = avctx->priv_data;
- const int sample_size = avctx->channels *
+ const int sample_size = avctx->ch_layout.nb_channels *
av_get_bytes_per_sample(avctx->sample_fmt);
uint8_t *audio;
int ret;
@@ -418,7 +419,12 @@ AVCodec ff_libopus_encoder = {
.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
AV_SAMPLE_FMT_FLT,
AV_SAMPLE_FMT_NONE },
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
.channel_layouts = ff_vorbis_channel_layouts,
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+ .ch_layouts = ff_vorbis_ch_layouts,
.supported_samplerates = libopus_sample_rates,
.priv_class = &libopus_class,
.defaults = libopus_defaults,
diff --git a/libavcodec/libspeexdec.c b/libavcodec/libspeexdec.c
index 949a9344c1..f3af4be50f 100644
--- a/libavcodec/libspeexdec.c
+++ b/libavcodec/libspeexdec.c
@@ -41,6 +41,7 @@ static av_cold int libspeex_decode_init(AVCodecContext *avctx)
LibSpeexContext *s = avctx->priv_data;
const SpeexMode *mode;
SpeexHeader *header = NULL;
+ int channels;
int spx_mode;

avctx->sample_fmt = AV_SAMPLE_FMT_S16;
@@ -51,10 +52,11 @@ static av_cold int libspeex_decode_init(AVCodecContext *avctx)
av_log(avctx, AV_LOG_WARNING, "Invalid Speex header\n");
}
if (header) {
- avctx->channels = header->nb_channels;
+ channels = header->nb_channels;
spx_mode = header->mode;
speex_header_free(header);
} else {
+ channels = avctx->ch_layout.nb_channels;
switch (avctx->sample_rate) {
case 8000: spx_mode = 0; break;
case 16000: spx_mode = 1; break;
@@ -76,14 +78,14 @@ static av_cold int libspeex_decode_init(AVCodecContext *avctx)
avctx->sample_rate = 8000 << spx_mode;
s->frame_size = 160 << spx_mode;

- if (avctx->channels < 1 || avctx->channels > 2) {
+ if (channels < 1 || channels > 2) {
/* libspeex can handle mono or stereo if initialized as stereo */
av_log(avctx, AV_LOG_ERROR, "Invalid channel count: %d.\n"
- "Decoding as stereo.\n", avctx->channels);
- avctx->channels = 2;
+ "Decoding as stereo.\n", channels);
+ channels = 2;
}
- avctx->channel_layout = avctx->channels == 2 ? AV_CH_LAYOUT_STEREO :
- AV_CH_LAYOUT_MONO;
+ av_channel_layout_uninit(&avctx->ch_layout);
+ av_channel_layout_default(&avctx->ch_layout, channels);

speex_bits_init(&s->bits);
s->dec_state = speex_decoder_init(mode);
@@ -92,7 +94,7 @@ static av_cold int libspeex_decode_init(AVCodecContext *avctx)
return -1;
}

- if (avctx->channels == 2) {
+ if (channels == 2) {
SpeexCallback callback;
callback.callback_id = SPEEX_INBAND_STEREO;
callback.func = speex_std_stereo_request_handler;
@@ -144,7 +146,7 @@ static int libspeex_decode_frame(AVCodecContext *avctx, void *data,
av_log(avctx, AV_LOG_ERROR, "Error decoding Speex frame.\n");
return AVERROR_INVALIDDATA;
}
- if (avctx->channels == 2)
+ if (avctx->ch_layout.nb_channels == 2)
speex_decode_stereo_int(output, s->frame_size, &s->stereo);

*got_frame_ptr = 1;
diff --git a/libavcodec/mace.c b/libavcodec/mace.c
index c6eddc05da..30ab57f3ac 100644
--- a/libavcodec/mace.c
+++ b/libavcodec/mace.c
@@ -226,7 +226,7 @@ static void chomp6(ChannelData *chd, int16_t *output, uint8_t val, int tab_idx)

static av_cold int mace_decode_init(AVCodecContext * avctx)
{
- if (avctx->channels > 2 || avctx->channels < 1)
+ if (avctx->ch_layout.nb_channels > 2 || avctx->ch_layout.nb_channels < 1)
return AVERROR(EINVAL);
avctx->sample_fmt = AV_SAMPLE_FMT_S16P;

@@ -239,26 +239,27 @@ static int mace_decode_frame(AVCodecContext *avctx, void *data,
AVFrame *frame = data;
const uint8_t *buf = avpkt->data;
int buf_size = avpkt->size;
+ int channels = avctx->ch_layout.nb_channels;
int16_t **samples;
MACEContext *ctx = avctx->priv_data;
int i, j, k, l, ret;
int is_mace3 = (avctx->codec_id == AV_CODEC_ID_MACE3);

/* get output buffer */
- frame->nb_samples = 3 * (buf_size << (1 - is_mace3)) / avctx->channels;
+ frame->nb_samples = 3 * (buf_size << (1 - is_mace3)) / channels;
if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) {
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
return ret;
}
samples = (int16_t **)frame->extended_data;

- for(i = 0; i < avctx->channels; i++) {
+ for(i = 0; i < channels; i++) {
int16_t *output = samples[i];

- for (j=0; j < buf_size / (avctx->channels << is_mace3); j++)
+ for (j=0; j < buf_size / (channels << is_mace3); j++)
for (k=0; k < (1 << is_mace3); k++) {
uint8_t pkt = buf[(i << is_mace3) +
- (j*avctx->channels << is_mace3) + k];
+ (j * channels << is_mace3) + k];

uint8_t val[2][3] = {{pkt >> 5, (pkt >> 3) & 3, pkt & 7 },
{pkt & 7 , (pkt >> 3) & 3, pkt >> 5}};
diff --git a/libavcodec/metasound.c b/libavcodec/metasound.c
index 4cd9051dbd..b58e3087f4 100644
--- a/libavcodec/metasound.c
+++ b/libavcodec/metasound.c
@@ -65,8 +65,9 @@ static void decode_ppc(TwinVQContext *tctx, int period_coef, int g_coef,
const float *shape, float *speech)
{
const TwinVQModeTab *mtab = tctx->mtab;
+ int channels = tctx->avctx->ch_layout.nb_channels;
int isampf = tctx->avctx->sample_rate / 1000;
- int ibps = tctx->avctx->bit_rate / (1000 * tctx->avctx->channels);
+ int ibps = tctx->avctx->bit_rate / (1000 * channels);
int width;

float ratio = (float)mtab->size / isampf;
@@ -75,7 +76,7 @@ static void decode_ppc(TwinVQContext *tctx, int period_coef, int g_coef,

float pgain_base, pgain_step, ppc_gain;

- if (tctx->avctx->channels == 1) {
+ if (channels == 1) {
min_period = log2(ratio * 0.2);
max_period = min_period + log2(6);
} else {
@@ -85,7 +86,7 @@ static void decode_ppc(TwinVQContext *tctx, int period_coef, int g_coef,
period_range = max_period - min_period;
period = min_period + period_coef * period_range /
((1 << mtab->ppc_period_bit) - 1);
- if (tctx->avctx->channels == 1)
+ if (channels == 1)
period = powf(2.0, period);
else
period = (int)(period * 400 + 0.5) / 400.0;
@@ -103,7 +104,7 @@ static void decode_ppc(TwinVQContext *tctx, int period_coef, int g_coef,
if (isampf == 22 && ibps == 32)
width = (int)((2.0 / period + 1) * width + 0.5);

- pgain_base = tctx->avctx->channels == 2 ? 25000.0 : 20000.0;
+ pgain_base = channels == 2 ? 25000.0 : 20000.0;
pgain_step = pgain_base / ((1 << mtab->pgain_bit) - 1);
ppc_gain = 1.0 / 8192 *
twinvq_mulawinv(pgain_step * g_coef + pgain_step / 2,
@@ -123,8 +124,9 @@ static void dec_bark_env(TwinVQContext *tctx, const uint8_t *in, int use_hist,
int bark_n_coef = mtab->fmode[ftype].bark_n_coef;
int fw_cb_len = mtab->fmode[ftype].bark_env_size / bark_n_coef;
int idx = 0;
+ int channels = tctx->avctx->ch_layout.nb_channels;

- if (tctx->avctx->channels == 1)
+ if (channels == 1)
val = 0.5;
for (i = 0; i < fw_cb_len; i++)
for (j = 0; j < bark_n_coef; j++, idx++) {
@@ -132,7 +134,7 @@ static void dec_bark_env(TwinVQContext *tctx, const uint8_t *in, int use_hist,
(1.0 / 2048);
float st;

- if (tctx->avctx->channels == 1)
+ if (channels == 1)
st = use_hist ?
tmp2 + val * hist[idx] + 1.0 : tmp2 + 1.0;
else
@@ -167,7 +169,7 @@ static int metasound_read_bitstream(AVCodecContext *avctx, TwinVQContext *tctx,
{
TwinVQFrameData *bits;
const TwinVQModeTab *mtab = tctx->mtab;
- int channels = tctx->avctx->channels;
+ int channels = tctx->avctx->ch_layout.nb_channels;
int sub;
BitstreamContext bc;
int i, j, k;
@@ -275,6 +277,7 @@ static av_cold int metasound_decode_init(AVCodecContext *avctx)
TwinVQContext *tctx = avctx->priv_data;
uint32_t tag;
const MetasoundProps *props = codec_props;
+ int channels;

if (!avctx->extradata || avctx->extradata_size < 16) {
av_log(avctx, AV_LOG_ERROR, "Missing or incomplete extradata\n");
@@ -290,7 +293,7 @@ static av_cold int metasound_decode_init(AVCodecContext *avctx)
}
if (props->tag == tag) {
avctx->sample_rate = props->sample_rate;
- avctx->channels = props->channels;
+ channels = props->channels;
avctx->bit_rate = props->bit_rate * 1000;
isampf = avctx->sample_rate / 1000;
break;
@@ -298,17 +301,17 @@ static av_cold int metasound_decode_init(AVCodecContext *avctx)
props++;
}

- if (avctx->channels <= 0 || avctx->channels > TWINVQ_CHANNELS_MAX) {
+ if (channels <= 0 || channels > TWINVQ_CHANNELS_MAX) {
av_log(avctx, AV_LOG_ERROR, "Unsupported number of channels: %i\n",
- avctx->channels);
+ channels);
return AVERROR_INVALIDDATA;
}
- avctx->channel_layout = avctx->channels == 1 ? AV_CH_LAYOUT_MONO
- : AV_CH_LAYOUT_STEREO;
+ av_channel_layout_uninit(&avctx->ch_layout);
+ av_channel_layout_default(&avctx->ch_layout, channels);

- ibps = avctx->bit_rate / (1000 * avctx->channels);
+ ibps = avctx->bit_rate / (1000 * channels);

- switch ((avctx->channels << 16) + (isampf << 8) + ibps) {
+ switch ((channels << 16) + (isampf << 8) + ibps) {
case (1 << 16) + ( 8 << 8) + 6:
tctx->mtab = &ff_metasound_mode0806;
break;
diff --git a/libavcodec/mlp_parser.c b/libavcodec/mlp_parser.c
index bff6258cba..a7d6bba5bd 100644
--- a/libavcodec/mlp_parser.c
+++ b/libavcodec/mlp_parser.c
@@ -40,11 +40,6 @@ static const uint8_t mlp_quants[16] = {
0, 0, 0, 0, 0, 0, 0, 0,
};

-static const uint8_t mlp_channels[32] = {
- 1, 2, 3, 4, 3, 4, 5, 3, 4, 5, 4, 5, 6, 4, 5, 4,
- 5, 6, 5, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-};
-
static const uint64_t mlp_layout[32] = {
AV_CH_LAYOUT_MONO,
AV_CH_LAYOUT_STEREO,
@@ -70,11 +65,6 @@ static const uint64_t mlp_layout[32] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};

-static const uint8_t thd_chancount[13] = {
-// LR C LFE LRs LRvh LRc LRrs Cs Ts LRsd LRw Cvh LFE2
- 2, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1
-};
-
static const uint64_t thd_layout[13] = {
AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT, // LR
AV_CH_FRONT_CENTER, // C
@@ -99,16 +89,6 @@ static int mlp_samplerate(int in)
return (in & 8 ? 44100 : 48000) << (in & 7) ;
}

-static int truehd_channels(int chanmap)
-{
- int channels = 0, i;
-
- for (i = 0; i < 13; i++)
- channels += thd_chancount[i] * ((chanmap >> i) & 1);
-
- return channels;
-}
-
static uint64_t truehd_layout(int chanmap)
{
int i;
@@ -179,7 +159,6 @@ int ff_mlp_read_major_sync(void *log, MLPHeaderInfo *mh, BitstreamContext *bc)
bitstream_skip(bc, 11);

channel_arrangement = bitstream_read(bc, 5);
- mh->channels_mlp = mlp_channels[channel_arrangement];
mh->channel_layout_mlp = mlp_layout[channel_arrangement];
} else if (mh->stream_type == 0xba) {
mh->group1_bits = 24; // TODO: Is this information actually conveyed anywhere?
@@ -195,13 +174,11 @@ int ff_mlp_read_major_sync(void *log, MLPHeaderInfo *mh, BitstreamContext *bc)
mh->channel_modifier_thd_stream1 = bitstream_read(bc, 2);

channel_arrangement = bitstream_read(bc, 5);
- mh->channels_thd_stream1 = truehd_channels(channel_arrangement);
mh->channel_layout_thd_stream1 = truehd_layout(channel_arrangement);

mh->channel_modifier_thd_stream2 = bitstream_read(bc, 2);

channel_arrangement = bitstream_read(bc, 13);
- mh->channels_thd_stream2 = truehd_channels(channel_arrangement);
mh->channel_layout_thd_stream2 = truehd_layout(channel_arrangement);
} else
return AVERROR_INVALIDDATA;
@@ -346,16 +323,13 @@ static int mlp_parse(AVCodecParserContext *s,

if (mh.stream_type == 0xbb) {
/* MLP stream */
- avctx->channels = mh.channels_mlp;
- avctx->channel_layout = mh.channel_layout_mlp;
+ av_channel_layout_from_mask(&avctx->ch_layout, mh.channel_layout_mlp);
} else { /* mh.stream_type == 0xba */
/* TrueHD stream */
- if (!mh.channels_thd_stream2) {
- avctx->channels = mh.channels_thd_stream1;
- avctx->channel_layout = mh.channel_layout_thd_stream1;
+ if (!mh.channel_layout_thd_stream2) {
+ av_channel_layout_from_mask(&avctx->ch_layout, mh.channel_layout_thd_stream1);
} else {
- avctx->channels = mh.channels_thd_stream2;
- avctx->channel_layout = mh.channel_layout_thd_stream2;
+ av_channel_layout_from_mask(&avctx->ch_layout, mh.channel_layout_thd_stream2);
}
}

diff --git a/libavcodec/mlp_parser.h b/libavcodec/mlp_parser.h
index 871b96db20..5cca73f26f 100644
--- a/libavcodec/mlp_parser.h
+++ b/libavcodec/mlp_parser.h
@@ -28,6 +28,7 @@
#define AVCODEC_MLP_PARSER_H

#include "bitstream.h"
+#include "libavutil/channel_layout.h"

typedef struct MLPHeaderInfo
{
@@ -44,9 +45,6 @@ typedef struct MLPHeaderInfo
int channel_modifier_thd_stream1; ///< Channel modifier for substream 1 of TrueHD streams ("6-channel presentation")
int channel_modifier_thd_stream2; ///< Channel modifier for substream 2 of TrueHD streams ("8-channel presentation")

- int channels_mlp; ///< Channel count for MLP streams
- int channels_thd_stream1; ///< Channel count for substream 1 of TrueHD streams ("6-channel presentation")
- int channels_thd_stream2; ///< Channel count for substream 2 of TrueHD streams ("8-channel presentation")
uint64_t channel_layout_mlp; ///< Channel layout for MLP streams
uint64_t channel_layout_thd_stream1; ///< Channel layout for substream 1 of TrueHD streams ("6-channel presentation")
uint64_t channel_layout_thd_stream2; ///< Channel layout for substream 2 of TrueHD streams ("8-channel presentation")
diff --git a/libavcodec/mlpdec.c b/libavcodec/mlpdec.c
index b377fd7e2b..2b75ad61df 100644
--- a/libavcodec/mlpdec.c
+++ b/libavcodec/mlpdec.c
@@ -30,6 +30,7 @@
#include "libavutil/intreadwrite.h"
#include "libavutil/channel_layout.h"
#include "libavutil/crc.h"
+#include "libavutil/opt.h"

#include "avcodec.h"
#include "bitstream.h"
@@ -129,6 +130,7 @@ typedef struct SubStream {
} SubStream;

typedef struct MLPDecodeContext {
+ const AVClass *class;
AVCodecContext *avctx;

/// Current access unit being read has a major sync.
@@ -161,41 +163,14 @@ typedef struct MLPDecodeContext {
int32_t sample_buffer[MAX_BLOCKSIZE][MAX_CHANNELS];

MLPDSPContext dsp;
+ AVChannelLayout downmix_layout;
} MLPDecodeContext;

-static const uint64_t thd_channel_order[] = {
- AV_CH_FRONT_LEFT, AV_CH_FRONT_RIGHT, // LR
- AV_CH_FRONT_CENTER, // C
- AV_CH_LOW_FREQUENCY, // LFE
- AV_CH_SIDE_LEFT, AV_CH_SIDE_RIGHT, // LRs
- AV_CH_TOP_FRONT_LEFT, AV_CH_TOP_FRONT_RIGHT, // LRvh
- AV_CH_FRONT_LEFT_OF_CENTER, AV_CH_FRONT_RIGHT_OF_CENTER, // LRc
- AV_CH_BACK_LEFT, AV_CH_BACK_RIGHT, // LRrs
- AV_CH_BACK_CENTER, // Cs
- AV_CH_TOP_CENTER, // Ts
- AV_CH_SURROUND_DIRECT_LEFT, AV_CH_SURROUND_DIRECT_RIGHT, // LRsd
- AV_CH_WIDE_LEFT, AV_CH_WIDE_RIGHT, // LRw
- AV_CH_TOP_FRONT_CENTER, // Cvh
- AV_CH_LOW_FREQUENCY_2, // LFE2
-};
-
-static int mlp_channel_layout_subset(uint64_t channel_layout, uint64_t mask)
-{
- return channel_layout && ((channel_layout & mask) == channel_layout);
-}
-
-static uint64_t thd_channel_layout_extract_channel(uint64_t channel_layout,
- int index)
+static int mlp_channel_layout_subset(AVChannelLayout *ch_layout, uint64_t mask)
{
- int i;
-
- if (av_get_channel_layout_nb_channels(channel_layout) <= index)
- return 0;
-
- for (i = 0; i < FF_ARRAY_ELEMS(thd_channel_order); i++)
- if (channel_layout & thd_channel_order[i] && !index--)
- return thd_channel_order[i];
- return 0;
+ return av_channel_layout_check(ch_layout) &&
+ av_channel_layout_subset(ch_layout, mask) ==
+ av_channel_layout_subset(ch_layout, UINT64_MAX);
}

static VLC huff_vlc[3];
@@ -288,6 +263,14 @@ static av_cold int mlp_decode_init(AVCodecContext *avctx)
m->substream[substr].lossless_check_data = 0xffffffff;
ff_mlpdsp_init(&m->dsp);

+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+ if (avctx->request_channel_layout) {
+ av_channel_layout_uninit(&m->downmix_layout);
+ av_channel_layout_from_mask(&m->downmix_layout, avctx->request_channel_layout);
+ }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
return 0;
}

@@ -517,7 +500,7 @@ static int read_restart_header(MLPDecodeContext *m, BitstreamContext *bc,
s->max_channel = max_channel;
s->max_matrix_channel = max_matrix_channel;

- if (mlp_channel_layout_subset(m->avctx->request_channel_layout, s->mask) &&
+ if (mlp_channel_layout_subset(&m->downmix_layout, s->mask) &&
m->max_decoded_substream > substr) {
av_log(m->avctx, AV_LOG_DEBUG,
"Extracting %d-channel downmix (0x%"PRIx64") from substream %d. "
@@ -549,10 +532,12 @@ static int read_restart_header(MLPDecodeContext *m, BitstreamContext *bc,
for (ch = 0; ch <= s->max_matrix_channel; ch++) {
int ch_assign = bitstream_read(bc, 6);
if (m->avctx->codec_id == AV_CODEC_ID_TRUEHD) {
- uint64_t channel = thd_channel_layout_extract_channel(s->mask,
- ch_assign);
- ch_assign = av_get_channel_layout_channel_index(s->mask,
- channel);
+ AVChannelLayout ch_layout = { 0 };
+ enum AVChannel channel;
+
+ av_channel_layout_from_mask(&ch_layout, s->mask);
+ channel = av_channel_layout_get_channel(&ch_layout, ch_assign);
+ ch_assign = av_channel_layout_channel_index(&ch_layout, channel);
}
if (ch_assign < 0 || ch_assign > s->max_matrix_channel) {
avpriv_request_sample(m->avctx,
@@ -592,14 +577,21 @@ static int read_restart_header(MLPDecodeContext *m, BitstreamContext *bc,
}

if (substr == m->max_decoded_substream) {
- m->avctx->channels = s->max_matrix_channel + 1;
- m->avctx->channel_layout = s->mask;
+ av_channel_layout_uninit(&m->avctx->ch_layout);
+ av_channel_layout_from_mask(&m->avctx->ch_layout, s->mask);
m->dsp.mlp_pack_output = m->dsp.mlp_select_pack_output(s->ch_assign,
s->output_shift,
s->max_matrix_channel,
m->avctx->sample_fmt == AV_SAMPLE_FMT_S32);
}

+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
+ m->avctx->channel_layout = m->avctx->ch_layout.u.mask;
+ m->avctx->channels = m->avctx->ch_layout.nb_channels;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+
return 0;
}

@@ -1039,7 +1031,7 @@ static int output_data(MLPDecodeContext *m, unsigned int substr,
int ret;
int is32 = (m->avctx->sample_fmt == AV_SAMPLE_FMT_S32);

- if (m->avctx->channels != s->max_matrix_channel + 1) {
+ if (m->avctx->ch_layout.nb_channels != s->max_matrix_channel + 1) {
av_log(m->avctx, AV_LOG_ERROR, "channel count mismatch\n");
return AVERROR_INVALIDDATA;
}
@@ -1273,24 +1265,48 @@ error:
return AVERROR_INVALIDDATA;
}

+#define OFFSET(x) offsetof(MLPDecodeContext, x)
+#define A AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM
+static const AVOption options[] = {
+ { "downmix", "Request a specific channel layout from the decoder",
+ OFFSET(downmix_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.str = NULL}, .flags = A },
+ { NULL },
+};
+
+static const AVClass mlpdec_class = {
+ .class_name = "MLP decoder",
+ .item_name = av_default_item_name,
+ .option = options,
+ .version = LIBAVUTIL_VERSION_INT,
+};
+
AVCodec ff_mlp_decoder = {
.name = "mlp",
.long_name = NULL_IF_CONFIG_SMALL("MLP (Meridian Lossless Packing)"),
.type = AVMEDIA_TYPE_AUDIO,
.id = AV_CODEC_ID_MLP,
.priv_data_size = sizeof(MLPDecodeContext),
+ .priv_class = &mlpdec_class,
.init = mlp_decode_init,
.decode = read_access_unit,
.capabilities = AV_CODEC_CAP_DR1,
};

#if CONFIG_TRUEHD_DECODER
+static const AVClass thddec_class = {
+ .class_name = "TrueHD decoder",
+ .item_name = av_default_item_name,
+ .option = options,
+ .version = LIBAVUTIL_VERSION_INT,
+};
+
AVCodec ff_truehd_decoder = {
.name = "truehd",
.long_name = NULL_IF_CONFIG_SMALL("TrueHD"),
.type = AVMEDIA_TYPE_AUDIO,
.id = AV_CODEC_ID_TRUEHD,
.priv_data_size = sizeof(MLPDecodeContext),
+ .priv_class = &thddec_class,
.init = mlp_decode_init,
.decode = read_access_unit,
.capabilities = AV_CODEC_CAP_DR1,
diff --git a/libavcodec/mpc7.c b/libavcodec/mpc7.c
index ebc3f5293b..a0e2b2aa57 100644
--- a/libavcodec/mpc7.c
+++ b/libavcodec/mpc7.c
@@ -65,8 +65,8 @@ static av_cold int mpc7_decode_init(AVCodecContext * avctx)
static VLC_TYPE quant_tables[7224][2];

/* Musepack SV7 is always stereo */
- if (avctx->channels != 2) {
- avpriv_request_sample(avctx, "%d channels", avctx->channels);
+ if (avctx->ch_layout.nb_channels != 2) {
+ avpriv_request_sample(avctx, "%d channels", avctx->ch_layout.nb_channels);
return AVERROR_PATCHWELCOME;
}

@@ -97,7 +97,8 @@ static av_cold int mpc7_decode_init(AVCodecContext * avctx)
c->frames_to_skip = 0;

avctx->sample_fmt = AV_SAMPLE_FMT_S16P;
- avctx->channel_layout = AV_CH_LAYOUT_STEREO;
+ av_channel_layout_uninit(&avctx->ch_layout);
+ avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;

if(vlc_initialized) return 0;
av_log(avctx, AV_LOG_DEBUG, "Initing VLC\n");
diff --git a/libavcodec/mpc8.c b/libavcodec/mpc8.c
index 649eb02e2e..affa240028 100644
--- a/libavcodec/mpc8.c
+++ b/libavcodec/mpc8.c
@@ -137,7 +137,8 @@ static av_cold int mpc8_decode_init(AVCodecContext * avctx)
c->frames = 1 << (bitstream_read(&bc, 3) * 2);

avctx->sample_fmt = AV_SAMPLE_FMT_S16P;
- avctx->channel_layout = (avctx->channels==2) ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO;
+ av_channel_layout_uninit(&avctx->ch_layout);
+ av_channel_layout_default(&avctx->ch_layout, channels);

if(vlc_initialized) return 0;
av_log(avctx, AV_LOG_DEBUG, "Initing VLC\n");
@@ -406,7 +407,7 @@ static int mpc8_decode_frame(AVCodecContext * avctx, void *data,

ff_mpc_dequantize_and_synth(c, maxband - 1,
(int16_t **)frame->extended_data,
- avctx->channels);
+ avctx->ch_layout.nb_channels);

c->cur_frame++;

diff --git a/libavcodec/mpegaudio_parser.c b/libavcodec/mpegaudio_parser.c
index c44c02417c..1da244789f 100644
--- a/libavcodec/mpegaudio_parser.c
+++ b/libavcodec/mpegaudio_parser.c
@@ -80,7 +80,7 @@ static int mpegaudio_parse(AVCodecParserContext *s1,

if (s->header_count > 0) {
avctx->sample_rate= sr;
- avctx->channels = channels;
+ av_channel_layout_default(&avctx->ch_layout, channels);
s1->duration = frame_size;
if (s->no_bitrate || !avctx->bit_rate) {
s->no_bitrate = 1;
diff --git a/libavcodec/mpegaudiodec_template.c b/libavcodec/mpegaudiodec_template.c
index e9ea65eed1..b636e26ed5 100644
--- a/libavcodec/mpegaudiodec_template.c
+++ b/libavcodec/mpegaudiodec_template.c
@@ -1636,8 +1636,8 @@ static int decode_frame(AVCodecContext * avctx, void *data, int *got_frame_ptr,
return AVERROR_INVALIDDATA;
}
/* update codec info */
- avctx->channels = s->nb_channels;
- avctx->channel_layout = s->nb_channels == 1 ? AV_CH_LAYOUT_MONO : AV_CH_LAYOUT_STEREO;
+ av_channel_layout_uninit(&avctx->ch_layout);
+ av_channel_layout_default(&avctx->ch_layout, s->nb_channels);
if (!avctx->bit_rate)
avctx->bit_rate = s->bit_rate;

@@ -1707,8 +1707,9 @@ static int decode_frame_adu(AVCodecContext *avctx, void *data,
}
/* update codec info */
avctx->sample_rate = s->sample_rate;
- avctx->channels = s->nb_channels;
- avctx->channel_layout = s->nb_channels == 1 ? AV_CH_LAYOUT_MONO : AV_CH_LAYOUT_STEREO;
+ av_channel_layout_uninit(&avctx->ch_layout);
+ avctx->ch_layout = s->nb_channels == 1 ? (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO
+ : (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
if (!avctx->bit_rate)
avctx->bit_rate = s->bit_rate;

@@ -1760,15 +1761,15 @@ static const uint8_t chan_offset[8][5] = {
};

/* mp3on4 channel layouts */
-static const int16_t chan_layout[8] = {
- 0,
- AV_CH_LAYOUT_MONO,
- AV_CH_LAYOUT_STEREO,
- AV_CH_LAYOUT_SURROUND,
- AV_CH_LAYOUT_4POINT0,
- AV_CH_LAYOUT_5POINT0,
- AV_CH_LAYOUT_5POINT1,
- AV_CH_LAYOUT_7POINT1
+static const AVChannelLayout chan_layout[8] = {
+ { 0 },
+ AV_CHANNEL_LAYOUT_MONO,
+ AV_CHANNEL_LAYOUT_STEREO,
+ AV_CHANNEL_LAYOUT_SURROUND,
+ AV_CHANNEL_LAYOUT_4POINT0,
+ AV_CHANNEL_LAYOUT_5POINT0,
+ AV_CHANNEL_LAYOUT_5POINT1,
+ AV_CHANNEL_LAYOUT_7POINT1
};

static av_cold int decode_close_mp3on4(AVCodecContext * avctx)
@@ -1802,8 +1803,8 @@ static av_cold int decode_init_mp3on4(AVCodecContext * avctx)
}
s->frames = mp3Frames[cfg.chan_config];
s->coff = chan_offset[cfg.chan_config];
- avctx->channels = ff_mpeg4audio_channels[cfg.chan_config];
- avctx->channel_layout = chan_layout[cfg.chan_config];
+ av_channel_layout_uninit(&avctx->ch_layout);
+ avctx->ch_layout = chan_layout[cfg.chan_config];

if (cfg.sample_rate < 16000)
s->syncword = 0xffe00000;
@@ -1900,8 +1901,8 @@ static int decode_frame_mp3on4(AVCodecContext *avctx, void *data,
if (ret < 0) // Bad header, discard block
break;

- if (ch + m->nb_channels > avctx->channels ||
- s->coff[fr] + m->nb_channels > avctx->channels) {
+ if (ch + m->nb_channels > avctx->ch_layout.nb_channels ||
+ s->coff[fr] + m->nb_channels > avctx->ch_layout.nb_channels) {
av_log(avctx, AV_LOG_ERROR, "frame channel count exceeds codec "
"channel count\n");
return AVERROR_INVALIDDATA;
@@ -1925,7 +1926,7 @@ static int decode_frame_mp3on4(AVCodecContext *avctx, void *data,
/* update codec info */
avctx->sample_rate = s->mp3decctx[0]->sample_rate;

- frame->nb_samples = out_size / (avctx->channels * sizeof(OUT_INT));
+ frame->nb_samples = out_size / (avctx->ch_layout.nb_channels * sizeof(OUT_INT));
*got_frame_ptr = 1;

return buf_size;
diff --git a/libavcodec/mpegaudioenc.c b/libavcodec/mpegaudioenc.c
index 2be8b7fd4c..72099d2b9b 100644
--- a/libavcodec/mpegaudioenc.c
+++ b/libavcodec/mpegaudioenc.c
@@ -73,7 +73,7 @@ static av_cold int MPA_encode_init(AVCodecContext *avctx)
MpegAudioContext *s = avctx->priv_data;
int freq = avctx->sample_rate;
int bitrate = avctx->bit_rate;
- int channels = avctx->channels;
+ int channels = avctx->ch_layout.nb_channels;
int i, v, table;
float a;

@@ -760,8 +760,17 @@ AVCodec ff_mp2_encoder = {
.supported_samplerates = (const int[]){
44100, 48000, 32000, 22050, 24000, 16000, 0
},
+#if FF_API_OLD_CHANNEL_LAYOUT
+FF_DISABLE_DEPRECATION_WARNINGS
.channel_layouts = (const uint64_t[]){ AV_CH_LAYOUT_MONO,
AV_CH_LAYOUT_STEREO,
0 },
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+ .ch_layouts = (const AVChannelLayout[]){
+ AV_CHANNEL_LAYOUT_MONO,
+ AV_CHANNEL_LAYOUT_STEREO,
+ { 0 },
+ },
.defaults = mp2_defaults,
};
diff --git a/libavcodec/nellymoserdec.c b/libavcodec/nellymoserdec.c
index 8d9af5fff6..0fb0d7c7d2 100644
--- a/libavcodec/nellymoserdec.c
+++ b/libavcodec/nellymoserdec.c
@@ -130,8 +130,8 @@ static av_cold int decode_init(AVCodecContext * avctx) {
if (!ff_sine_128[127])
ff_init_ff_sine_windows(7);

- avctx->channels = 1;
- avctx->channel_layout = AV_CH_LAYOUT_MONO;
+ av_channel_layout_uninit(&avctx->ch_layout);
+ avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;

return 0;
}
diff --git a/libavcodec/nellymoserenc.c b/libavcodec/nellymoserenc.c
index 9d120816e0..948d928d7e 100644
--- a/libavcodec/nellymoserenc.c
+++ b/libavcodec/nellymoserenc.c
@@ -151,11 +151,6 @@ static av_cold int encode_init(AVCodecContext *avctx)
NellyMoserEncodeContext *s = avctx->priv_data;
int i, ret;

- if (avctx->channels != 1) {
- av_log(avctx, AV_LOG_ERROR, "Nellymoser supports only 1 channel\n");
- return AVERROR(EINVAL);
- }
-
if (avctx->sample_rate != 8000 && avctx->sample_rate != 16000 &&
avctx->sample_rate != 11025 &&
avctx->sample_rate != 22050 && avctx->sample_rate != 44100 &&
@@ -418,4 +413,5 @@ AVCodec ff_nellymoser_encoder = {
.capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_DELAY,
.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLT,
AV_SAMPLE_FMT_NONE },
+ .ch_layouts = (const AVChannelLayout[]){ AV_CHANNEL_LAYOUT_MONO, { 0 } },
};
diff --git a/libavcodec/on2avc.c b/libavcodec/on2avc.c
index 39ae1178f1..d543e5ba3f 100644
--- a/libavcodec/on2avc.c
+++ b/libavcodec/on2avc.c
@@ -801,6 +801,7 @@ static int on2avc_decode_subframe(On2AVCContext *c, const uint8_t *buf,
{
BitstreamContext bc;
int i, ret;
+ int channels = c->avctx->ch_layout.nb_channels;

bitstream_init8(&bc, buf, buf_size);
if (bitstream_read_bit(&bc)) {
@@ -809,7 +810,7 @@ static int on2avc_decode_subframe(On2AVCContext *c, const uint8_t *buf,
}
c->prev_window_type = c->window_type;
c->window_type = bitstream_read(&bc, 3);
- if (c->window_type >= WINDOW_TYPE_EXT4 && c->avctx->channels == 1) {
+ if (c->window_type >= WINDOW_TYPE_EXT4 && channels == 1) {
av_log(c->avctx, AV_LOG_ERROR, "stereo mode window for mono audio\n");
return AVERROR_INVALIDDATA;
}
@@ -824,13 +825,13 @@ static int on2avc_decode_subframe(On2AVCContext *c, const uint8_t *buf,
c->grouping[i] = !bitstream_read_bit(&bc);

on2avc_read_ms_info(c, &bc);
- for (i = 0; i < c->avctx->channels; i++)
+ for (i = 0; i < channels; i++)
if ((ret = on2avc_read_channel_data(c, &bc, i)) < 0)
return AVERROR_INVALIDDATA;
- if (c->avctx->channels == 2 && c->ms_present)
+ if (channels == 2 && c->ms_present)
on2avc_apply_ms(c);
if (c->window_type < WINDOW_TYPE_EXT4) {
- for (i = 0; i < c->avctx->channels; i++)
+ for (i = 0; i < channels; i++)
on2avc_reconstruct_channel(c, i, dst, offset);
} else {
on2avc_reconstruct_stereo(c, dst, offset);
@@ -917,19 +918,17 @@ static av_cold int on2avc_decode_init(AVCodecContext *avctx)

c->avctx = avctx;
avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
- avctx->channel_layout = (avctx->channels == 2) ? AV_CH_LAYOUT_STEREO
- : AV_CH_LAYOUT_MONO;

c->is_av500 = (avctx->codec_tag == 0x500);
- if (c->is_av500 && avctx->channels == 2) {
+ if (c->is_av500 && avctx->ch_layout.nb_channels == 2) {
av_log(avctx, AV_LOG_ERROR, "0x500 version should be mono\n");
return AVERROR_INVALIDDATA;
}
- if (avctx->channels > 2) {
+ if (avctx->ch_layout.nb_channels > 2) {
av_log(avctx, AV_LOG_ERROR, "Only 1 or 2 channels are supported.\n");
return AVERROR(EINVAL);
}
- if (avctx->channels == 2)
+ if (avctx->ch_layout.nb_channels == 2)
av_log(avctx, AV_LOG_WARNING,
"Stereo mode support is not good, patch is welcome\n");

@@ -938,7 +937,7 @@ static av_cold int on2avc_decode_init(AVCodecContext *avctx)
for (; i < 128; i++)
c->scale_tab[i] = ceil(pow(10.0, i * 0.1) * 0.5);

- if (avctx->sample_rate < 32000 || avctx->channels == 1)
+ if (avctx->sample_rate < 32000 || avctx->ch_layout.nb_channels == 1)
memcpy(c->long_win, ff_on2avc_window_long_24000,
1024 * sizeof(*c->long_win));
else
diff --git a/libavcodec/opus.c b/libavcodec/opus.c
index 8e896dd5d4..308d104212 100644
--- a/libavcodec/opus.c
+++ b/libavcodec/opus.c
@@ -295,11 +295,12 @@ av_cold int ff_opus_parse_extradata(AVCodecContext *avctx,

const uint8_t *extradata, *channel_map;
int extradata_size;
- int version, channels, map_type, streams, stereo_streams, i, j;
+ int channels = avctx->ch_layout.nb_channels;
+ int version, map_type, streams, stereo_streams, i, j;
uint64_t layout;

if (!avctx->extradata) {
- if (avctx->channels > 2) {
+ if (channels > 2) {
av_log(avctx, AV_LOG_ERROR,
"Multichannel configuration without extradata.\n");
return AVERROR(EINVAL);
@@ -325,7 +326,7 @@ av_cold int ff_opus_parse_extradata(AVCodecContext *avctx,

avctx->delay = AV_RL16(extradata + 10);

- channels = avctx->extradata ? extradata[9] : (avctx->channels == 1) ? 1 : 2;
+ channels = avctx->extradata ? extradata[9] : (channels == 1) ? 1 : 2;
if (!channels) {
av_log(avctx, AV_LOG_ERROR, "Zero channel count specified in the extadata\n");
return AVERROR_INVALIDDATA;
@@ -368,7 +369,7 @@ av_cold int ff_opus_parse_extradata(AVCodecContext *avctx,
"Channel mapping 1 is only specified for up to 8 channels\n");
return AVERROR_INVALIDDATA;
}
- layout = ff_vorbis_channel_layouts[channels - 1];
+ layout = ff_vorbis_ch_layouts[channels - 1].u.mask;
channel_reorder = channel_reorder_vorbis;
} else
layout = 0;
@@ -414,8 +415,11 @@ av_cold int ff_opus_parse_extradata(AVCodecContext *avctx,
}
}

- avctx->channels = channels;
- avctx->channel_layout = layout;
+ av_channel_layout_uninit(&avctx->ch_layout);
+ if (layout)
+ av_channel_layout_from_mask(&avctx->ch_layout, layout);
+ else
+ av_channel_layout_default(&avctx->ch_layout, channels);
s->nb_streams = streams;
s->nb_stereo_streams = stereo_streams;

diff --git a/libavcodec/opusdec.c b/libavcodec/opusdec.c
index 163f0d5ed5..4a3088beca 100644
--- a/libavcodec/opusdec.c
+++ b/libavcodec/opusdec.c
@@ -494,7 +494,7 @@ static int opus_decode_packet(AVCodecContext *avctx, void *data,
frame->nb_samples = 0;

memset(c->out, 0, c->nb_streams * 2 * sizeof(*c->out));
- for (i = 0; i < avctx->channels; i++) {
+ for (i = 0; i < avctx->ch_layout.nb_channels; i++) {
ChannelMap *map = &c->channel_maps[i];
if (!map->copy)
c->out[2 * map->stream_idx + map->channel_idx] = (float*)frame->extended_data[i];
@@ -575,7 +575,7 @@ static int opus_decode_packet(AVCodecContext *avctx, void *data,
}
}

- for (i = 0; i < avctx->channels; i++) {
+ for (i = 0; i < avctx->ch_layout.nb_channels; i++) {
ChannelMap *map = &c->channel_maps[i];

/* handle copied channels */
@@ -687,7 +687,7 @@ static av_cold int opus_decode_init(AVCodecContext *avctx)

for (i = 0; i < c->nb_streams; i++) {
OpusStreamContext *s = &c->streams[i];
- uint64_t layout;
+ AVChannelLayout ch_layout = { 0 };

s->output_channels = (i < c->nb_stereo_streams) ? 2 : 1;

@@ -705,11 +705,12 @@ static av_cold int opus_decode_init(AVCodecContext *avctx)
if (!s->avr)
goto fail;

- layout = (s->output_channels == 1) ? AV_CH_LAYOUT_MONO : AV_CH_LAYOUT_STEREO;
+ av_channel_layout_from_mask(&ch_layout, (s->output_channels == 1) ? AV_CH_LAYOUT_MONO
+ : AV_CH_LAYOUT_STEREO);
+ av_opt_set_channel_layout(s->avr, "in_ch_layout", &ch_layout, 0);
+ av_opt_set_channel_layout(s->avr, "out_ch_layout", &ch_layout, 0);
av_opt_set_int(s->avr, "in_sample_fmt", avctx->sample_fmt, 0);
av_opt_set_int(s->avr, "out_sample_fmt", avctx->sample_fmt, 0);
- av_opt_set_int(s->avr, "in_channel_layout", layout, 0);
- av_opt_set_int(s->avr, "out_channel_layout", layout, 0);
av_opt_set_int(s->avr, "out_sample_rate", avctx->sample_rate, 0);

ret = ff_silk_init(avctx, &s->silk, s->output_channels);
diff --git a/libavcodec/pafaudio.c b/libavcodec/pafaudio.c
index c83e7f5cfc..4df5d4874f 100644
--- a/libavcodec/pafaudio.c
+++ b/libavcodec/pafaudio.c
@@ -30,12 +30,13 @@

static av_cold int paf_audio_init(AVCodecContext *avctx)
{
- if (avctx->channels != 2) {
+ if (avctx->ch_layout.nb_channels != 2) {
av_log(avctx, AV_LOG_ERROR, "invalid number of channels\n");
return AVERROR_INVALIDDATA;
}

- avctx->channel_layout = AV_CH_LAYOUT_STEREO;
+ av_channel_layout_uninit(&avctx->ch_layout);
+ avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
avctx->sample_fmt = AV_SAMPLE_FMT_S16;

return 0;
diff --git a/libavcodec/pcm-bluray.c b/libavcodec/pcm-bluray.c
index 51fcd2d007..1878fe59b2 100644
--- a/libavcodec/pcm-bluray.c
+++ b/libavcodec/pcm-bluray.c
@@ -54,14 +54,12 @@ static int pcm_bluray_parse_header(AVCodecContext *avctx,
const uint8_t *header)
{
static const uint8_t bits_per_samples[4] = { 0, 16, 20, 24 };
- static const uint32_t channel_layouts[16] = {
- 0, AV_CH_LAYOUT_MONO, 0, AV_CH_LAYOUT_STEREO, AV_CH_LAYOUT_SURROUND,
- AV_CH_LAYOUT_2_1, AV_CH_LAYOUT_4POINT0, AV_CH_LAYOUT_2_2,
- AV_CH_LAYOUT_5POINT0, AV_CH_LAYOUT_5POINT1, AV_CH_LAYOUT_7POINT0,
- AV_CH_LAYOUT_7POINT1, 0, 0, 0, 0
- };
- static const uint8_t channels[16] = {
- 0, 1, 0, 2, 3, 3, 4, 4, 5, 6, 7, 8, 0, 0, 0, 0
+ static const AVChannelLayout channel_layouts[16] = {
+ { 0 }, AV_CHANNEL_LAYOUT_MONO, { 0 },
+ AV_CHANNEL_LAYOUT_STEREO, AV_CHANNEL_LAYOUT_SURROUND, AV_CHANNEL_LAYOUT_2_1,
+ AV_CHANNEL_LAYOUT_4POINT0, AV_CHANNEL_LAYOUT_2_2, AV_CHANNEL_LAYOUT_5POINT0,
+ AV_CHANNEL_LAYOUT_5POINT1, AV_CHANNEL_LAYOUT_7POINT0, AV_CHANNEL_LAYOUT_7POINT1,
+ { 0 }, { 0 }, { 0 }, { 0 },
};
uint8_t channel_layout = header[2] >> 4;

@@ -103,21 +101,21 @@ static int pcm_bluray_parse_header(AVCodecContext *avctx,
* differ from the actual meaningful number, e.g. mono audio still has two
* channels, one being empty.
*/
- avctx->channel_layout = channel_layouts[channel_layout];
- avctx->channels = channels[channel_layout];
- if (!avctx->channels) {
+ av_channel_layout_uninit(&avctx->ch_layout);
+ avctx->ch_layout = channel_layouts[channel_layout];
+ if (!avctx->ch_layout.nb_channels) {
av_log(avctx, AV_LOG_ERROR, "reserved channel configuration (%d)\n",
channel_layout);
return AVERROR_INVALIDDATA;
}

- avctx->bit_rate = FFALIGN(avctx->channels, 2) * avctx->sample_rate *
+ avctx->bit_rate = FFALIGN(avctx->ch_layout.nb_channels, 2) * avctx->sample_rate *
avctx->bits_per_coded_sample;

if (avctx->debug & FF_DEBUG_PICT_INFO)
ff_dlog(avctx,
"pcm_bluray_parse_header: %d channels, %d bits per sample, %d Hz, %d bit/s\n",
- avctx->channels, avctx->bits_per_coded_sample,
+ avctx->ch_layout.nb_channels, avctx->bits_per_coded_sample,
avctx->sample_rate, avctx->bit_rate);
return 0;
}
@@ -147,7 +145,7 @@ static int pcm_bluray_decode_frame(AVCodecContext *avctx, void *data,
bytestream2_init(&gb, src, buf_size);

/* There's always an even number of channels in the source */
- num_source_channels = FFALIGN(avctx->channels, 2);
+ num_source_channels = FFALIGN(avctx->ch_layout.nb_channels, 2);
sample_size = (num_source_channels *
(avctx->sample_fmt == AV_SAMPLE_FMT_S16 ? 16 : 24)) >> 3;
samples = buf_size / sample_size;
@@ -162,7 +160,7 @@ static int pcm_bluray_decode_frame(AVCodecContext *avctx, void *data,
dst32 = (int32_t *)frame->data[0];

if (samples) {
- switch (avctx->channel_layout) {
+ switch (avctx->ch_layout.u.mask) {
/* cases with same number of source and coded channels */
case AV_CH_LAYOUT_STEREO:
case AV_CH_LAYOUT_4POINT0:
@@ -190,10 +188,10 @@ static int pcm_bluray_decode_frame(AVCodecContext *avctx, void *data,
if (AV_SAMPLE_FMT_S16 == avctx->sample_fmt) {
do {
#if HAVE_BIGENDIAN
- bytestream2_get_buffer(&gb, dst16, avctx->channels * 2);
- dst16 += avctx->channels;
+ bytestream2_get_buffer(&gb, dst16, avctx->ch_layout.nb_channels * 2);
+ dst16 += avctx->ch_layout.nb_channels;
#else
- channel = avctx->channels;
+ channel = avctx->ch_layout.nb_channels;
do {
*dst16++ = bytestream2_get_be16u(&gb);
} while (--channel);
@@ -202,7 +200,7 @@ static int pcm_bluray_decode_frame(AVCodecContext *avctx, void *data,
} while (--samples);
} else {
do {
- channel = avctx->channels;
+ channel = avctx->ch_layout.nb_channels;
do {
*dst32++ = bytestream2_get_be24u(&gb) << 8;
} while (--channel);
diff --git a/libavcodec/pcm-dvd.c b/libavcodec/pcm-dvd.c
index 62aacf829a..98254f846a 100644
--- a/libavcodec/pcm-dvd.c
+++ b/libavcodec/pcm-dvd.c
@@ -65,6 +65,7 @@ static int pcm_dvd_pa