Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
* [FFmpeg-devel] [PATCH 000/279 v2] New channel layout API
@ 2021-12-16 13:21 James Almer
  2021-12-16 13:21 ` [FFmpeg-devel] [PATCH 001/279 v2] Add a new " James Almer
                   ` (2 more replies)
  0 siblings, 3 replies; 20+ messages in thread
From: James Almer @ 2021-12-16 13:21 UTC (permalink / raw)
  To: ffmpeg-devel

Resending the first two patches only, since this is meant to
show the implementation of one of the several suggestions made
in the previous set that need to be discussed and hopefully
resolved in a call.

The proposals so far to extend the API to support either custom
labels for channels are, or some form of extra user information.

- Fixed array of bytes to hold a label. Simple solution, but
  the labels will have a hard limit that can only be extended
  with a major bump. This is what i implemented in this version.
- "char *name" per channel that the user may allocate and the
  API will manage, duplicate and free. Simple solution, and the
  name can be arbitrarily long, but inefficient (av_strdup() per
  channel with a custom label on layout copy).
- "const char *name" per channel for compile time constants, or
  that the user may allocate and free. Very efficient, but for
  non compile time strings ensuring they outlive the layout can
  be tricky.
- Refcounted AVChannelCustom with a dictionary. This can't be
  done with AVBufferRef, so it would require some other form
  of reference counting. And a dictionary may add quite a bit of
  complexity to the API, as you can set anything on them.
- Opaque id/s or pointer/s that the API will not touch beyond
  passing them around (So unlike the above, the helpers would not
  benefit from this). This can be combined with any of the above,
  too, and i did as much in this version.
- Leave API as it was in v1.

Anton Khirnov (136):
  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
  lavf: add a temporary compat layer for the channel layout API change
  lavf: convert the generic layer to the new channel layout
  3dostr: convert to new channel layout API
  aa: convert to new channel layout API
  acm: convert to new channel layout API
  act: convert to new channel layout API
  adp: convert to new channel layout API
  ads: convert to new channel layout API
  afc: convert to new channel layout API
  aixdec: convert to new channel layout API
  aptxdec: convert to new channel layout API
  argo: convert to new channel layout API
  ast: convert to new channel layout API
  avr: convert to new channel layout API
  bit: convert to new channel layout API
  boa: convert to new channel layout API
  brstm: convert to new channel layout API
  codec2: convert to new channel layout API
  dcstr: convert to new channel layout API
  dhav: convert to new channel layout API
  dtshddec: convert to new channel layout API
  dsfdec: convert to new channel layout API
  epafdec: convert to new channel layout API
  framehash: convert to new channel layout API
  fsb: convert to new channel layout API
  g726: convert to new channel layout API
  gdv: convert to new channel layout API
  genh: convert to new channel layout API
  hcom: convert to new channel layout API
  ifv: convert to new channel layout API
  ircam: convert to new channel layout API
  jack: port to new channel layout API
  libcdio: port to new channel layout API
  lvf: convert to new channel layout API
  mpeg: convert to new channel layout API
  mpegtsenc: convert to new channel layout API
  msf: convert to new channel layout API
  mtaf: convert to new channel layout API
  musx: convert to new channel layout API
  nistspheredec: convert to new channel layout API
  nspdec: convert to new channel layout API
  oss: port to new channel layout API
  pvf: convert to new channel layout API
  rawenc: convert to new channel layout API
  redspark: convert to new channel layout API
  rsd: convert to new channel layout API
  sbg: convert to new channel layout API
  sdr2: convert to new channel layout API
  sds: convert to new channel layout API
  sdx: convert to new channel layout API
  svag: convert to new channel layout API
  vag: convert to new channel layout API
  vividas: convert to new channel layout API
  vivo: convert to new channel layout API
  vpk: convert to new channel layout API
  lavf: drop the channel layout compat layer for old-style (de)muxers
  8svx: convert to new channel layout API
  aac: convert to new channel layout API
  adpcm: convert to new channel layout API
  alac: convert to new channel layout API
  amr: convert to new channel layout API
  aptx: convert to new channel layout API
  atrac9: convert to new channel layout API
  apedec: convert to new channel layout API
  audiotoolbox: convert to new channel layout API
  binkaudio: convert to new channel layout API
  bmvaudio: convert to new channel layout API
  cng: convert to new channel layout API
  cook: convert to new channel layout API
  dca: convert to new channel layout API
  dolby_e: convert to new channel layout API
  dsd: convert to new channel layout API
  dsicinav: convert to new channel layout API
  dst: convert to new channel layout API
  dvaudio: convert to new channel layout API
  evrc: convert to new channel layout API
  ffwavesynth: convert to new channel layout API
  flac: convert to new channel layout API
  g722: convert to new channel layout API
  g723_1: convert to new channel layout API
  g726: convert to new channel layout API
  g729: convert to new channel layout API
  gsmdec: convert to new channel layout API
  hcom: convert to new channel layout API
  ilbc: convert to new channel layout API
  imc: convert to new channel layout API
  interplayacm: convert to new channel layout API
  libcelt: convert to new channel layout API
  libcodec2: convert to new channel layout API
  libilbc: convert to new channel layout API
  libgsm: convert to new channel layout API
  libmp3lame: convert to new channel layout API
  libopencore-amr: convert to new channel layout API
  libopus: convert to new channel layout API
  libshine: convert to new channel layout API
  libspeexdec: convert to new channel layout API
  libtwolame: convert to new channel layout API
  libvo-amrwbenc: convert to new channel layout API
  libvorbis: convert to new channel layout API
  mace: convert to new channel layout API
  metasound: convert to new channel layout API
  mlp: convert to new channel layout API
  mpc7: convert to new channel layout API
  mpc8: convert to new channel layout API
  mpegaudio: convert to new channel layout API
  nellymoser: convert to new channel layout API
  on2avc: convert to new channel layout API
  opus: convert to new channel layout API
  pcm: convert to new channel layout API
  qcelpdec: convert to new channel layout API
  qdmc: convert to new channel layout API
  qdm2: convert to new channel layout API
  ra144: convert to new channel layout API
  ra288: convert to new channel layout API
  ralf: convert to new channel layout API
  roqaudioenc: convert to new channel layout API
  s302m: convert to new channel layout API
  sbc: convert to new channel layout API
  shorten: convert to new channel layout API
  sipr: convert to new channel layout API
  smacker: convert to new channel layout API
  sonic: convert to new channel layout API
  tak: convert to new channel layout API
  truespeech: convert to new channel layout API
  tta: convert to new channel layout API
  vmdaudio: convert to new channel layout API
  vorbis: convert to new channel layout API
  wavpack: convert to new channel layout API
  wma: convert to new channel layout API
  ws-snd1: convert to new channel layout API
  lavc: drop temporary compat wrappers for channel layout API change
  opus: export mapping family 2 (Ambisonic) as Ambisonic layout

James Almer (30):
  fate: add a channel_layout API test
  aax: convert to new channel layout API
  ace: convert to new channel layout API
  alsa: convert to new channel layout API
  alp: convert to new channel layout API
  amv: convert to new channel layout API
  apm: convert to new channel layout API
  derf: convert to new channel layout API
  dshow: convert to new channel layout API
  fwse: convert to new channel layout API
  hca: convert to new channel layout API
  hls_sample_encryption: convert to new channel layout API
  imx: convert to new channel layout API
  kvag: convert to new channel layout API
  avdevice/lavfi: convert to new channel layout API
  mca: convert to new channel layout API
  moflex: convert to new channel layout API
  pp_bnk: convert to new channel layout API
  scd: convert to new channel layout API
  sga: convert to new channel layout API
  svs: convert to new channel layout API
  fastaudio: convert to new channel layout API
  hca: convert to new channel layout API
  mf: convert to new channel layout API
  siren: convert to new channel layout API
  speex: convert to new channel layout API
  swresample: convert to new channel layout API
  avfilter: convert to new channel layout API
  ffmpeg: convert to new channel layout-API
  ffprobe: convert to new channel layout-API

Vittorio Giovara (113):
  avcodecpar: switch to the new channel layout API
  4xm: convert to new channel layout API
  adxdec: convert to new channel layout API
  aea: convert to new channel layout API
  aiff: convert to new channel layout API
  amr: convert to new channel layout API
  apc: convert to new channel layout API
  ape: convert to new channel layout API
  au: convert to new channel layout API
  bethsoftvid: convert to new channel layout API
  bfi: convert to new channel layout API
  bink: convert to new channel layout API
  bmv: convert to new channel layout API
  caf: convert to new channel layout API
  cdxl: convert to new channel layout API
  dash: convert to new channel layout API
  dsicin: convert to new channel layout API
  dss: convert to new channel layout API
  dv: convert to new channel layout API
  eac: convert to new channel layout API
  electronicarts: convert to new channel layout API
  flac: convert to new channel layout API
  flic: convert to new channel layout API
  flv: convert to new channel layout API
  g722: convert to new channel layout API
  g723_1: convert to new channel layout API
  g729: convert to new channel layout API
  gsm: convert to new channel layout API
  gxf: convert to new channel layout API
  idcin: convert to new channel layout API
  idroq: convert to new channel layout API
  iff: convert to new channel layout API
  ilbc: convert to new channel layout API
  ipmovie: convert to new channel layout API
  iss: convert to new channel layout API
  jvdec: convert to new channel layout API
  lxfdec: convert to new channel layout API
  matroska: convert to new channel layout API
  mm: convert to new channel layout API
  mmf: convert to new channel layout API
  mov: convert to new channel layout API
  movenc-test: convert to new channel layout API
  mp3: convert to new channel layout API
  mpc: convert to new channel layout API
  mpc8: convert to new channel layout API
  mpegenc: convert to new channel layout API
  mvdec: convert to new channel layout API
  mvi: convert to new channel layout API
  mxf: convert to new channel layout API
  mxg: convert to new channel layout API
  nsvdec: convert to new channel layout API
  nutdec: convert to new channel layout API
  nuv: convert to new channel layout API
  ogg: convert to new channel layout API
  oma: convert to new channel layout API
  paf: convert to new channel layout API
  pcm: convert to new channel layout API
  pmp: convert to new channel layout API
  psxstr: convert to new channel layout API
  qcp: convert to new channel layout API
  r3d: convert to new channel layout API
  riff: convert to new channel layout API
  rl2: convert to new channel layout API
  rm: convert to new channel layout API
  rpl: convert to new channel layout API
  rso: convert to new channel layout API
  rtp: convert to new channel layout API
  sdp: convert to new channel layout API
  segafilm: convert to new channel layout API
  sierravmd: convert to new channel layout API
  siff: convert to new channel layout API
  smacker: convert to new channel layout API
  smjpegenc: convert to new channel layout API
  smoothstreaming: convert to new channel layout API
  smush: convert to new channel layout API
  sol: convert to new channel layout API
  sox: convert to new channel layout API
  swf: convert to new channel layout API
  tak: convert to new channel layout API
  thp: convert to new channel layout API
  tiertexseq: convert to new channel layout API
  tmv: convert to new channel layout API
  tta: convert to new channel layout API
  voc: convert to new channel layout API
  vqf: convert to new channel layout API
  wav: convert to new channel layout API
  wc3movie: convert to new channel layout API
  westwood: convert to new channel layout API
  wtv: convert to new channel layout API
  wv: convert to new channel layout API
  xa: convert to new channel layout API
  xmv: convert to new channel layout API
  xwma: convert to new channel layout API
  yop: convert to new channel layout API
  wsd: convert to new channel layout API
  wve: convert to new channel layout API
  xvag: convert to new channel layout API
  lavc: switch to the new channel layout API
  ac3: convert to new channel layout API
  adx: convert to new channel layout API
  als: convert to new channel layout API
  atrac1: convert to new channel layout API
  atrac3: convert to new channel layout API
  atrac3plus: convert to new channel layout API
  dpcm: convert to new channel layout API
  dss_sp: convert to new channel layout API
  libfdk-aac: convert to new channel layout API
  pafaudio: convert to new channel layout API
  twinvq: convert to new channel layout API
  vima: convert to new channel layout API
  lavf: Add non diegetic stream disposition flag
  channel_layout: add support for Ambisonic
  mov: Implement spatial audio support

 fftools/cmdutils.c                            |  42 +-
 fftools/cmdutils.h                            |   8 -
 fftools/ffmpeg.c                              |  47 +-
 fftools/ffmpeg.h                              |   7 +-
 fftools/ffmpeg_filter.c                       |  43 +-
 fftools/ffmpeg_opt.c                          |  62 +-
 fftools/ffprobe.c                             |  19 +-
 libavcodec/8svx.c                             |  19 +-
 libavcodec/aac.h                              |  11 +-
 libavcodec/aac_ac3_parser.c                   |  13 +-
 libavcodec/aaccoder.c                         |  10 +-
 libavcodec/aaccoder_twoloop.h                 |   4 +-
 libavcodec/aacdec_template.c                  |  52 +-
 libavcodec/aacenc.c                           |  13 +-
 libavcodec/aacenc.h                           |  64 +-
 libavcodec/aacenctab.h                        |  16 +-
 libavcodec/aacpsy.c                           |   8 +-
 libavcodec/ac3dec.c                           |  57 +-
 libavcodec/ac3dec.h                           |   2 +
 libavcodec/ac3dec_fixed.c                     |   1 +
 libavcodec/ac3dec_float.c                     |   2 +
 libavcodec/ac3enc.c                           |  78 +-
 libavcodec/ac3enc.h                           |   4 +-
 libavcodec/ac3enc_fixed.c                     |   5 +
 libavcodec/ac3enc_float.c                     |   5 +
 libavcodec/adpcm.c                            | 151 ++--
 libavcodec/adpcmenc.c                         | 122 +--
 libavcodec/adx.c                              |  16 +-
 libavcodec/adxdec.c                           |   6 +-
 libavcodec/adxenc.c                           |  11 +-
 libavcodec/alac.c                             |  16 +-
 libavcodec/alac_data.c                        |  20 +-
 libavcodec/alac_data.h                        |   6 +
 libavcodec/alacenc.c                          |  37 +-
 libavcodec/alsdec.c                           |  90 +-
 libavcodec/amr_parser.c                       |  10 +-
 libavcodec/amrnbdec.c                         |  12 +-
 libavcodec/amrwbdec.c                         |  12 +-
 libavcodec/apedec.c                           |   9 +-
 libavcodec/aptx.c                             |   2 +-
 libavcodec/atrac1.c                           |  10 +-
 libavcodec/atrac3.c                           |  41 +-
 libavcodec/atrac3plusdec.c                    |  25 +-
 libavcodec/atrac9dec.c                        |   4 +-
 libavcodec/atrac9tab.h                        |  14 +-
 libavcodec/audiotoolboxdec.c                  |  27 +-
 libavcodec/audiotoolboxenc.c                  |  95 +--
 libavcodec/avcodec.c                          |  51 +-
 libavcodec/avcodec.h                          |  23 +-
 libavcodec/binkaudio.c                        |  19 +-
 libavcodec/bmvaudio.c                         |   4 +-
 libavcodec/cngdec.c                           |   3 +-
 libavcodec/cngenc.c                           |   6 +-
 libavcodec/codec.h                            |  11 +
 libavcodec/codec_par.c                        |  65 +-
 libavcodec/codec_par.h                        |  12 +
 libavcodec/cook.c                             |  25 +-
 libavcodec/cook_parser.c                      |   4 +-
 libavcodec/dca_core.c                         |   6 +-
 libavcodec/dca_lbr.c                          |  13 +-
 libavcodec/dca_xll.c                          |   2 +-
 libavcodec/dcadec.c                           |  63 +-
 libavcodec/dcadec.h                           |   7 +
 libavcodec/dcaenc.c                           |  39 +-
 libavcodec/decode.c                           |  73 +-
 libavcodec/dolby_e.c                          |  52 +-
 libavcodec/dolby_e.h                          |   2 +
 libavcodec/dolby_e_parser.c                   |  11 +-
 libavcodec/dpcm.c                             |  16 +-
 libavcodec/dsddec.c                           |  14 +-
 libavcodec/dsicinaudio.c                      |   4 +-
 libavcodec/dss_sp.c                           |   4 +-
 libavcodec/dstdec.c                           |   8 +-
 libavcodec/dvaudiodec.c                       |   8 +-
 libavcodec/eac3enc.c                          |   5 +
 libavcodec/encode.c                           |  43 +-
 libavcodec/evrcdec.c                          |   4 +-
 libavcodec/fastaudio.c                        |   6 +-
 libavcodec/ffwavesynth.c                      |   6 +-
 libavcodec/flac.c                             |  39 +-
 libavcodec/flac.h                             |   2 +-
 libavcodec/flac_parser.c                      |   7 +-
 libavcodec/flacdec.c                          |   9 +-
 libavcodec/flacenc.c                          |  26 +-
 libavcodec/g722dec.c                          |   4 +-
 libavcodec/g722enc.c                          |   5 +
 libavcodec/g723_1_parser.c                    |   2 +-
 libavcodec/g723_1dec.c                        |  19 +-
 libavcodec/g723_1enc.c                        |   8 +-
 libavcodec/g726.c                             |   8 +-
 libavcodec/g729_parser.c                      |   2 +-
 libavcodec/g729dec.c                          |  20 +-
 libavcodec/gsmdec.c                           |   4 +-
 libavcodec/hcadec.c                           |  16 +-
 libavcodec/hcom.c                             |   2 +-
 libavcodec/ilbcdec.c                          |   4 +-
 libavcodec/imc.c                              |  22 +-
 libavcodec/interplayacm.c                     |  10 +-
 libavcodec/libcelt_dec.c                      |  10 +-
 libavcodec/libcodec2.c                        |   4 +-
 libavcodec/libfdk-aacdec.c                    |  34 +-
 libavcodec/libfdk-aacenc.c                    |  37 +-
 libavcodec/libgsmdec.c                        |   4 +-
 libavcodec/libgsmenc.c                        |   4 +-
 libavcodec/libilbc.c                          |   6 +-
 libavcodec/libmp3lame.c                       |   9 +-
 libavcodec/libopencore-amr.c                  |   8 +-
 libavcodec/libopusdec.c                       |  39 +-
 libavcodec/libopusenc.c                       |  65 +-
 libavcodec/libshine.c                         |   6 +-
 libavcodec/libspeexdec.c                      |  19 +-
 libavcodec/libspeexenc.c                      |  17 +-
 libavcodec/libtwolame.c                       |   2 +-
 libavcodec/libvo-amrwbenc.c                   |   2 +-
 libavcodec/libvorbisdec.c                     |   4 +-
 libavcodec/libvorbisenc.c                     |  42 +-
 libavcodec/mace.c                             |  15 +-
 libavcodec/metasound.c                        |  31 +-
 libavcodec/mfenc.c                            |   8 +-
 libavcodec/mlp_parser.c                       |  12 +-
 libavcodec/mlpdec.c                           | 116 ++-
 libavcodec/mlpenc.c                           |  95 +--
 libavcodec/mp3_header_decompress_bsf.c        |   2 +-
 libavcodec/mpc7.c                             |   7 +-
 libavcodec/mpc8.c                             |   6 +-
 libavcodec/mpegaudio_parser.c                 |   4 +-
 libavcodec/mpegaudiodec_template.c            |  22 +-
 libavcodec/mpegaudioenc_template.c            |   2 +-
 libavcodec/nellymoserdec.c                    |   4 +-
 libavcodec/nellymoserenc.c                    |   6 +-
 libavcodec/on2avc.c                           |  20 +-
 libavcodec/options_table.h                    |   3 +
 libavcodec/opus.c                             |  73 +-
 libavcodec/opusdec.c                          |   4 +-
 libavcodec/opusenc.c                          |  11 +-
 libavcodec/opusenc_psy.c                      |  20 +-
 libavcodec/packet.h                           |   5 +
 libavcodec/pafaudio.c                         |   5 +-
 libavcodec/pcm-bluray.c                       |  36 +-
 libavcodec/pcm-dvd.c                          |  28 +-
 libavcodec/pcm-dvdenc.c                       |  20 +-
 libavcodec/pcm.c                              |  39 +-
 libavcodec/pcm_rechunk_bsf.c                  |   5 +-
 libavcodec/psymodel.c                         |   8 +-
 libavcodec/psymodel.h                         |   2 +-
 libavcodec/pthread_frame.c                    |  10 +-
 libavcodec/qcelpdec.c                         |   4 +-
 libavcodec/qdm2.c                             |   6 +-
 libavcodec/qdmc.c                             |   9 +-
 libavcodec/ra144dec.c                         |   4 +-
 libavcodec/ra144enc.c                         |   8 +-
 libavcodec/ra288.c                            |   4 +-
 libavcodec/ralf.c                             |  18 +-
 libavcodec/roqaudioenc.c                      |  20 +-
 libavcodec/s302m.c                            |  31 +-
 libavcodec/s302menc.c                         |  18 +-
 libavcodec/sbc_parser.c                       |   8 +-
 libavcodec/sbcdec.c                           |   4 +-
 libavcodec/sbcenc.c                           |  10 +-
 libavcodec/shorten.c                          |   6 +-
 libavcodec/sipr.c                             |   4 +-
 libavcodec/siren.c                            |   4 +-
 libavcodec/smacker.c                          |  12 +-
 libavcodec/sonic.c                            |  14 +-
 libavcodec/speexdec.c                         |   8 +-
 libavcodec/takdec.c                           |  41 +-
 libavcodec/truespeech.c                       |   7 +-
 libavcodec/tta.c                              |  18 +-
 libavcodec/ttaenc.c                           |  14 +-
 libavcodec/twinvq.c                           |  20 +-
 libavcodec/twinvqdec.c                        |  18 +-
 libavcodec/utils.c                            |  24 +-
 libavcodec/vima.c                             |   5 +-
 libavcodec/vmdaudio.c                         |  26 +-
 libavcodec/vorbisdec.c                        |  24 +-
 libavcodec/vorbisenc.c                        |   7 +-
 libavcodec/wavpack.c                          |  51 +-
 libavcodec/wavpackenc.c                       |  29 +-
 libavcodec/wma.c                              |  11 +-
 libavcodec/wmadec.c                           |  29 +-
 libavcodec/wmaenc.c                           |  27 +-
 libavcodec/wmalosslessdec.c                   |  13 +-
 libavcodec/wmaprodec.c                        |  28 +-
 libavcodec/wmavoice.c                         |   4 +-
 libavcodec/ws-snd1.c                          |   4 +-
 libavdevice/alsa.c                            |  19 +-
 libavdevice/alsa_dec.c                        |   3 +-
 libavdevice/alsa_enc.c                        |   2 +-
 libavdevice/dshow.c                           |   3 +-
 libavdevice/jack.c                            |   3 +-
 libavdevice/lavfi.c                           |   7 +-
 libavdevice/libcdio.c                         |   5 +-
 libavdevice/oss_dec.c                         |   3 +-
 libavdevice/oss_enc.c                         |   2 +-
 libavfilter/aeval.c                           |  19 +-
 libavfilter/af_afir.c                         |   9 +-
 libavfilter/af_aformat.c                      |  32 +-
 libavfilter/af_amerge.c                       |  38 +-
 libavfilter/af_amix.c                         |   2 +-
 libavfilter/af_apulsator.c                    |   2 +-
 libavfilter/af_aresample.c                    |  41 +-
 libavfilter/af_ashowinfo.c                    |  13 +-
 libavfilter/af_asr.c                          |   2 +-
 libavfilter/af_biquads.c                      |  42 +-
 libavfilter/af_bs2b.c                         |   2 +-
 libavfilter/af_channelmap.c                   |  86 +-
 libavfilter/af_channelsplit.c                 |  42 +-
 libavfilter/af_compand.c                      |   6 +
 libavfilter/af_compensationdelay.c            |   7 +
 libavfilter/af_crossfeed.c                    |   2 +-
 libavfilter/af_earwax.c                       |   2 +-
 libavfilter/af_extrastereo.c                  |   2 +-
 libavfilter/af_firequalizer.c                 |   5 +-
 libavfilter/af_haas.c                         |   2 +-
 libavfilter/af_hdcd.c                         |   4 +-
 libavfilter/af_headphone.c                    |  22 +-
 libavfilter/af_join.c                         | 268 ++++--
 libavfilter/af_ladspa.c                       |  16 +-
 libavfilter/af_lv2.c                          |  17 +-
 libavfilter/af_pan.c                          |  62 +-
 libavfilter/af_replaygain.c                   |   2 +-
 libavfilter/af_sofalizer.c                    |  86 +-
 libavfilter/af_speechnorm.c                   |  12 +-
 libavfilter/af_stereotools.c                  |   2 +-
 libavfilter/af_stereowiden.c                  |   2 +-
 libavfilter/af_surround.c                     |  72 +-
 libavfilter/asrc_afirsrc.c                    |   2 +-
 libavfilter/asrc_anoisesrc.c                  |   2 +-
 libavfilter/asrc_anullsrc.c                   |  13 +-
 libavfilter/asrc_flite.c                      |   6 +-
 libavfilter/asrc_hilbert.c                    |   2 +-
 libavfilter/asrc_sinc.c                       |   2 +-
 libavfilter/asrc_sine.c                       |   2 +-
 libavfilter/audio.c                           |  11 +-
 libavfilter/avf_aphasemeter.c                 |   2 +-
 libavfilter/avf_avectorscope.c                |   2 +-
 libavfilter/avf_showcqt.c                     |   3 +-
 libavfilter/avf_showspatial.c                 |   2 +-
 libavfilter/avf_showspectrum.c                |   3 +-
 libavfilter/avf_showvolume.c                  |   9 +-
 libavfilter/avfilter.c                        |  15 +-
 libavfilter/avfilter.h                        |  10 +-
 libavfilter/avfiltergraph.c                   |  84 +-
 libavfilter/buffersink.c                      |  29 +-
 libavfilter/buffersink.h                      |   7 +-
 libavfilter/buffersrc.c                       |  92 +-
 libavfilter/buffersrc.h                       |   9 +
 libavfilter/f_ebur128.c                       |  10 +-
 libavfilter/f_streamselect.c                  |   4 +
 libavfilter/formats.c                         | 131 ++-
 libavfilter/formats.h                         |  16 +-
 libavfilter/graphdump.c                       |   4 +-
 libavfilter/internal.h                        |   2 +-
 libavfilter/src_movie.c                       |  19 +-
 libavfilter/tests/filtfmts.c                  |   3 +-
 libavfilter/tests/formats.c                   |   4 +-
 libavfilter/vaf_spectrumsynth.c               |   2 +-
 libavformat/3dostr.c                          |  13 +-
 libavformat/4xm.c                             |   7 +-
 libavformat/aadec.c                           |   6 +-
 libavformat/aaxdec.c                          |   7 +-
 libavformat/acedec.c                          |   5 +-
 libavformat/acm.c                             |   7 +-
 libavformat/act.c                             |   3 +-
 libavformat/adp.c                             |   3 +-
 libavformat/ads.c                             |  11 +-
 libavformat/adxdec.c                          |  22 +-
 libavformat/aea.c                             |  11 +-
 libavformat/afc.c                             |   5 +-
 libavformat/aiffdec.c                         |  13 +-
 libavformat/aiffenc.c                         |   8 +-
 libavformat/aixdec.c                          |   3 +-
 libavformat/alp.c                             |  16 +-
 libavformat/amr.c                             |  20 +-
 libavformat/amvenc.c                          |   4 +-
 libavformat/apc.c                             |  12 +-
 libavformat/ape.c                             |   3 +-
 libavformat/apm.c                             |  22 +-
 libavformat/aptxdec.c                         |   3 +-
 libavformat/argo_asf.c                        |  18 +-
 libavformat/argo_cvg.c                        |   5 +-
 libavformat/astdec.c                          |  18 +-
 libavformat/astenc.c                          |   4 +-
 libavformat/au.c                              |   9 +-
 libavformat/avformat.h                        |   7 +
 libavformat/avr.c                             |   7 +-
 libavformat/bethsoftvid.c                     |   3 +-
 libavformat/bfi.c                             |   3 +-
 libavformat/bink.c                            |   8 +-
 libavformat/binka.c                           |   3 +-
 libavformat/bit.c                             |   7 +-
 libavformat/bmv.c                             |   3 +-
 libavformat/boadec.c                          |   8 +-
 libavformat/brstm.c                           |  44 +-
 libavformat/cafdec.c                          |   7 +-
 libavformat/cafenc.c                          |  12 +-
 libavformat/cdxl.c                            |   4 +-
 libavformat/codec2.c                          |   3 +-
 libavformat/dashenc.c                         |   2 +-
 libavformat/dauddec.c                         |   3 +-
 libavformat/daudenc.c                         |   2 +-
 libavformat/dcstr.c                           |  15 +-
 libavformat/demux.c                           |  18 +-
 libavformat/derf.c                            |  12 +-
 libavformat/dhav.c                            |   3 +-
 libavformat/dsfdec.c                          |  60 +-
 libavformat/dsicin.c                          |   7 +-
 libavformat/dss.c                             |   3 +-
 libavformat/dtshddec.c                        |   3 +-
 libavformat/dump.c                            |  11 +-
 libavformat/dv.c                              |   3 +-
 libavformat/dvenc.c                           |   2 +-
 libavformat/eacdata.c                         |  22 +-
 libavformat/electronicarts.c                  |   7 +-
 libavformat/epafdec.c                         |   6 +-
 libavformat/flacdec.c                         |   3 +-
 libavformat/flacenc.c                         |   7 +-
 libavformat/flic.c                            |   4 +-
 libavformat/flvdec.c                          |  15 +-
 libavformat/flvenc.c                          |  10 +-
 libavformat/framehash.c                       |   8 +-
 libavformat/fsb.c                             |  36 +-
 libavformat/fwse.c                            |  10 +-
 libavformat/g722.c                            |   2 +-
 libavformat/g723_1.c                          |   3 +-
 libavformat/g726.c                            |   3 +-
 libavformat/g729dec.c                         |   2 +-
 libavformat/gdv.c                             |   6 +-
 libavformat/genh.c                            |  38 +-
 libavformat/gsmdec.c                          |   3 +-
 libavformat/gxf.c                             |   9 +-
 libavformat/gxfenc.c                          |   2 +-
 libavformat/hca.c                             |   3 +-
 libavformat/hcom.c                            |   3 +-
 libavformat/hls_sample_encryption.c           |  12 +-
 libavformat/idcin.c                           |   4 +-
 libavformat/idroqdec.c                        |  12 +-
 libavformat/iff.c                             |  63 +-
 libavformat/ifv.c                             |   3 +-
 libavformat/ilbc.c                            |   2 +-
 libavformat/imx.c                             |   3 +-
 libavformat/ipmovie.c                         |   8 +-
 libavformat/ircamdec.c                        |   8 +-
 libavformat/ircamenc.c                        |   2 +-
 libavformat/isom.c                            |   5 +-
 libavformat/iss.c                             |  17 +-
 libavformat/jvdec.c                           |   3 +-
 libavformat/kvag.c                            |  19 +-
 libavformat/lvfdec.c                          |   3 +-
 libavformat/lxfdec.c                          |   3 +-
 libavformat/matroskadec.c                     |   8 +-
 libavformat/matroskaenc.c                     |  10 +-
 libavformat/mca.c                             |  25 +-
 libavformat/mm.c                              |   3 +-
 libavformat/mmf.c                             |   5 +-
 libavformat/moflex.c                          |   3 +-
 libavformat/mov.c                             | 172 +++-
 libavformat/mov_chan.c                        |  21 +-
 libavformat/mov_chan.h                        |   3 +-
 libavformat/movenc.c                          |  25 +-
 libavformat/mp3enc.c                          |   2 +-
 libavformat/mpc.c                             |   3 +-
 libavformat/mpc8.c                            |   5 +-
 libavformat/mpeg.c                            |   3 +-
 libavformat/mpegenc.c                         |  10 +-
 libavformat/mpegtsenc.c                       |  30 +-
 libavformat/msf.c                             |  16 +-
 libavformat/mtaf.c                            |   5 +-
 libavformat/musx.c                            |  49 +-
 libavformat/mux.c                             |  19 +-
 libavformat/mvdec.c                           |  10 +-
 libavformat/mvi.c                             |   3 +-
 libavformat/mxfdec.c                          |  23 +-
 libavformat/mxfenc.c                          |  20 +-
 libavformat/mxg.c                             |   3 +-
 libavformat/nistspheredec.c                   |   8 +-
 libavformat/nspdec.c                          |   3 +-
 libavformat/nsvdec.c                          |   2 +-
 libavformat/nutdec.c                          |   3 +-
 libavformat/nutenc.c                          |   4 +-
 libavformat/nuv.c                             |  11 +-
 libavformat/oggparsecelt.c                    |   3 +-
 libavformat/oggparseogm.c                     |   6 +-
 libavformat/oggparseopus.c                    |   3 +-
 libavformat/oggparsespeex.c                   |   8 +-
 libavformat/oggparsevorbis.c                  |   6 +-
 libavformat/oma.h                             |   2 +
 libavformat/omadec.c                          |  35 +-
 libavformat/omaenc.c                          |   4 +-
 libavformat/paf.c                             |   3 +-
 libavformat/pcm.c                             |   2 +-
 libavformat/pcmdec.c                          |   7 +-
 libavformat/pmpdec.c                          |   3 +-
 libavformat/pp_bnk.c                          |  12 +-
 libavformat/psxstr.c                          |  10 +-
 libavformat/pvfdec.c                          |   5 +-
 libavformat/qcp.c                             |   3 +-
 libavformat/r3d.c                             |   3 +-
 libavformat/rawenc.c                          |   2 +-
 libavformat/redspark.c                        |  15 +-
 libavformat/riffdec.c                         |  20 +-
 libavformat/riffenc.c                         |  18 +-
 libavformat/rl2.c                             |   7 +-
 libavformat/rmdec.c                           |   6 +-
 libavformat/rmenc.c                           |   2 +-
 libavformat/rpl.c                             |   7 +-
 libavformat/rsd.c                             |  27 +-
 libavformat/rsodec.c                          |   3 +-
 libavformat/rsoenc.c                          |   2 +-
 libavformat/rtp.c                             |  10 +-
 libavformat/rtpdec.c                          |   4 +-
 libavformat/rtpdec_amr.c                      |   3 +-
 libavformat/rtpenc.c                          |  14 +-
 libavformat/rtsp.c                            |   6 +-
 libavformat/rtsp.h                            |   1 -
 libavformat/sbgdec.c                          |   3 +-
 libavformat/scd.c                             |   9 +-
 libavformat/sdp.c                             |  36 +-
 libavformat/sdr2.c                            |   3 +-
 libavformat/sdsdec.c                          |   3 +-
 libavformat/sdxdec.c                          |   3 +-
 libavformat/segafilm.c                        |   9 +-
 libavformat/segafilmenc.c                     |   2 +-
 libavformat/sga.c                             |   3 +-
 libavformat/sierravmd.c                       |  15 +-
 libavformat/siff.c                            |   3 +-
 libavformat/smacker.c                         |  11 +-
 libavformat/smjpegdec.c                       |   3 +-
 libavformat/smjpegenc.c                       |   2 +-
 libavformat/smoothstreamingenc.c              |   4 +-
 libavformat/smush.c                           |   4 +-
 libavformat/sol.c                             |   4 +-
 libavformat/soxdec.c                          |  14 +-
 libavformat/soxenc.c                          |   4 +-
 libavformat/svag.c                            |  12 +-
 libavformat/svs.c                             |   3 +-
 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/ttaenc.c                          |   2 +-
 libavformat/utils.c                           |  13 +-
 libavformat/vag.c                             |  11 +-
 libavformat/vividas.c                         |   8 +-
 libavformat/vivo.c                            |   3 +-
 libavformat/voc_packet.c                      |   9 +-
 libavformat/vocenc.c                          |   9 +-
 libavformat/vpk.c                             |  15 +-
 libavformat/vqf.c                             |  13 +-
 libavformat/wavdec.c                          |  32 +-
 libavformat/wavenc.c                          |  14 +-
 libavformat/wc3movie.c                        |   8 +-
 libavformat/westwood_aud.c                    |  10 +-
 libavformat/westwood_audenc.c                 |   2 +-
 libavformat/westwood_vqa.c                    |   2 +-
 libavformat/wsddec.c                          |  12 +-
 libavformat/wtvdec.c                          |   6 +-
 libavformat/wvdec.c                           |   3 +-
 libavformat/wvedec.c                          |   6 +-
 libavformat/xa.c                              |   9 +-
 libavformat/xmv.c                             |   3 +-
 libavformat/xvag.c                            |  10 +-
 libavformat/xwma.c                            |  10 +-
 libavformat/yop.c                             |   3 +-
 libavutil/Makefile                            |   1 +
 libavutil/channel_layout.c                    | 783 ++++++++++++++++--
 libavutil/channel_layout.h                    | 589 ++++++++++++-
 libavutil/frame.c                             | 112 ++-
 libavutil/frame.h                             |  12 +-
 libavutil/opt.c                               | 126 ++-
 libavutil/opt.h                               |  12 +
 libavutil/tests/channel_layout.c              | 253 ++++++
 libavutil/tests/opt.c                         |   8 +-
 libavutil/version.h                           |   1 +
 libswresample/options.c                       |  33 +-
 libswresample/rematrix.c                      | 227 +++--
 libswresample/rematrix_template.c             |   7 +-
 libswresample/swresample.c                    | 158 +++-
 libswresample/swresample.h                    |  63 ++
 libswresample/swresample_frame.c              |  65 +-
 libswresample/swresample_internal.h           |  10 +-
 tests/fate/aac.mak                            |   2 +-
 tests/fate/ac3.mak                            |  16 +-
 tests/fate/cover-art.mak                      |   2 +-
 tests/fate/lavf-container.mak                 |   2 +-
 tests/fate/libavutil.mak                      |   4 +
 tests/ref/fate/8bps                           |   1 -
 tests/ref/fate/aa-demux                       |   1 -
 tests/ref/fate/aac-autobsf-adtstoasc          |   1 -
 tests/ref/fate/adpcm-4xm                      |   1 -
 tests/ref/fate/adpcm-afc                      |   1 -
 tests/ref/fate/adpcm-dtk                      |   1 -
 tests/ref/fate/adpcm-ea-1                     |   1 -
 tests/ref/fate/adpcm-ea-2                     |   1 -
 tests/ref/fate/adpcm-ea-maxis-xa              |   1 -
 tests/ref/fate/adpcm-ea-r1                    |   1 -
 tests/ref/fate/adpcm-ima-amv                  |   1 -
 tests/ref/fate/adpcm-ima-ea-eacs              |   1 -
 tests/ref/fate/adpcm-ima-ea-sead              |   1 -
 tests/ref/fate/adpcm-ima-smjpeg               |   1 -
 tests/ref/fate/adpcm-ima-ws                   |   1 -
 tests/ref/fate/adpcm-ima-ws-vqa3              |   1 -
 tests/ref/fate/adpcm-ms-mono                  |   1 -
 tests/ref/fate/adpcm-thp                      |   1 -
 tests/ref/fate/adpcm-vima                     |   1 -
 tests/ref/fate/adpcm-xa                       |   1 -
 tests/ref/fate/adts-id3v1-demux               |   1 -
 tests/ref/fate/adts-id3v2-demux               |   1 -
 tests/ref/fate/adts-id3v2-two-tags-demux      |   1 -
 tests/ref/fate/adtstoasc_ticket3715           |   1 -
 tests/ref/fate/armovie-escape124              |   1 -
 tests/ref/fate/bethsoft-vid                   |   1 -
 tests/ref/fate/bfi                            |   1 -
 tests/ref/fate/bmv-audio                      |   1 -
 tests/ref/fate/caf-alac-remux                 |   1 -
 tests/ref/fate/caf-amr_nb-remux               |   1 -
 tests/ref/fate/caf-mace6-remux                |   1 -
 tests/ref/fate/caf-pcm_s24-remux              |   1 -
 tests/ref/fate/caf-pcm_s24le-remux            |   1 -
 tests/ref/fate/caf-qdm2-remux                 |   1 -
 tests/ref/fate/cdxl-demux                     |   1 -
 tests/ref/fate/channel_layout                 | 111 +++
 tests/ref/fate/copy-psp                       |   1 -
 tests/ref/fate/copy-shortest1                 |   1 -
 tests/ref/fate/copy-shortest2                 |   1 -
 tests/ref/fate/copy-trac236                   |   1 -
 tests/ref/fate/copy-trac3074                  |   1 -
 tests/ref/fate/copy-trac4914                  |   1 -
 tests/ref/fate/copy-trac4914-avi              |   1 -
 tests/ref/fate/corepng                        |   1 -
 tests/ref/fate/cover-art-aiff-id3v2-remux     |   1 -
 tests/ref/fate/cover-art-flac-remux           |   6 +-
 tests/ref/fate/cover-art-mp3-id3v2-remux      |   1 -
 tests/ref/fate/creatureshock-avs              |   1 -
 tests/ref/fate/cyberia-c93                    |   1 -
 tests/ref/fate/d-cinema-demux                 |   1 -
 tests/ref/fate/dca-xll_51_16_192_768_0        |   1 -
 tests/ref/fate/dca-xll_51_16_192_768_0-dmix_2 |   1 -
 tests/ref/fate/dca-xll_51_16_192_768_0-dmix_6 |   1 -
 tests/ref/fate/dca-xll_51_16_192_768_1        |   1 -
 tests/ref/fate/dca-xll_51_16_192_768_1-dmix_2 |   1 -
 tests/ref/fate/dca-xll_51_16_192_768_1-dmix_6 |   1 -
 tests/ref/fate/dca-xll_51_24_48_768           |   1 -
 tests/ref/fate/dca-xll_51_24_48_768-dmix_2    |   1 -
 tests/ref/fate/dca-xll_51_24_48_768-dmix_6    |   1 -
 tests/ref/fate/dca-xll_51_24_48_none          |   1 -
 tests/ref/fate/dca-xll_51_24_48_none-dmix_2   |   1 -
 tests/ref/fate/dca-xll_51_24_48_none-dmix_6   |   1 -
 tests/ref/fate/dca-xll_71_24_48_768_0         |   1 -
 tests/ref/fate/dca-xll_71_24_48_768_0-dmix_2  |   1 -
 tests/ref/fate/dca-xll_71_24_48_768_0-dmix_6  |   1 -
 tests/ref/fate/dca-xll_71_24_48_768_1         |   1 -
 tests/ref/fate/dca-xll_71_24_48_768_1-dmix_2  |   1 -
 tests/ref/fate/dca-xll_71_24_48_768_1-dmix_6  |   1 -
 tests/ref/fate/dca-xll_71_24_96_768           |   1 -
 tests/ref/fate/dca-xll_71_24_96_768-dmix_2    |   1 -
 tests/ref/fate/dca-xll_71_24_96_768-dmix_6    |   1 -
 tests/ref/fate/dca-xll_x96_51_24_96_1509      |   1 -
 .../ref/fate/dca-xll_x96_51_24_96_1509-dmix_2 |   1 -
 .../ref/fate/dca-xll_x96_51_24_96_1509-dmix_6 |   1 -
 tests/ref/fate/dca-xll_xch_61_24_48_768       |   1 -
 .../ref/fate/dca-xll_xch_61_24_48_768-dmix_2  |   1 -
 .../ref/fate/dca-xll_xch_61_24_48_768-dmix_6  |   1 -
 tests/ref/fate/dcinema-encode                 |   1 -
 tests/ref/fate/delphine-cin-audio             |   1 -
 tests/ref/fate/dpcm-idroq                     |   1 -
 tests/ref/fate/dpcm-interplay                 |   1 -
 tests/ref/fate/dss-lp                         |   1 -
 tests/ref/fate/dss-sp                         |   1 -
 tests/ref/fate/ffmpeg-attached_pics           |   1 -
 tests/ref/fate/ffmpeg-filter_complex_audio    |   1 -
 tests/ref/fate/filter-acrossfade              |   1 -
 tests/ref/fate/filter-adelay                  |   1 -
 tests/ref/fate/filter-aecho                   |   1 -
 tests/ref/fate/filter-aemphasis               |   2 -
 tests/ref/fate/filter-aemphasis-50fm          |   1 -
 tests/ref/fate/filter-aemphasis-75kf          |   1 -
 tests/ref/fate/filter-afade-esin              |   1 -
 tests/ref/fate/filter-afade-exp               |   1 -
 tests/ref/fate/filter-afade-hsin              |   1 -
 tests/ref/fate/filter-afade-iqsin             |   1 -
 tests/ref/fate/filter-afade-log               |   1 -
 tests/ref/fate/filter-afade-qsin              |   1 -
 tests/ref/fate/filter-agate                   |   1 -
 tests/ref/fate/filter-alimiter                |   1 -
 tests/ref/fate/filter-amerge                  |   1 -
 tests/ref/fate/filter-anequalizer             |   1 -
 tests/ref/fate/filter-apad                    |   1 -
 tests/ref/fate/filter-asetnsamples-nopad      |   1 -
 tests/ref/fate/filter-asetnsamples-pad        |   1 -
 tests/ref/fate/filter-asetrate                |   1 -
 tests/ref/fate/filter-atrim-duration          |   1 -
 tests/ref/fate/filter-atrim-mixed             |   1 -
 tests/ref/fate/filter-atrim-samples           |   1 -
 tests/ref/fate/filter-atrim-time              |   1 -
 tests/ref/fate/filter-chorus                  |   1 -
 tests/ref/fate/filter-compand                 |   1 -
 tests/ref/fate/filter-concat                  |   1 -
 tests/ref/fate/filter-concat-vfr              |   1 -
 tests/ref/fate/filter-dcshift                 |   1 -
 tests/ref/fate/filter-earwax                  |   1 -
 tests/ref/fate/filter-extrastereo             |   1 -
 tests/ref/fate/filter-formats                 |  20 +-
 tests/ref/fate/filter-hls                     |   1 -
 tests/ref/fate/filter-hls-append              |   1 -
 tests/ref/fate/filter-meta-4560-rotate0       |   1 -
 tests/ref/fate/filter-overlay-dvdsub-2397     |   1 -
 tests/ref/fate/filter-pan-downmix1            |   1 -
 tests/ref/fate/filter-pan-downmix2            |   1 -
 tests/ref/fate/filter-pan-mono1               |   1 -
 tests/ref/fate/filter-pan-mono2               |   1 -
 tests/ref/fate/filter-pan-stereo1             |   1 -
 tests/ref/fate/filter-pan-stereo2             |   1 -
 tests/ref/fate/filter-pan-stereo3             |   1 -
 tests/ref/fate/filter-pan-stereo4             |   1 -
 tests/ref/fate/filter-pan-upmix1              |   1 -
 tests/ref/fate/filter-pan-upmix2              |   1 -
 tests/ref/fate/filter-silenceremove           |   1 -
 tests/ref/fate/filter-stereotools             |   1 -
 tests/ref/fate/g722-encode                    |   1 -
 tests/ref/fate/g722dec-1                      |   1 -
 tests/ref/fate/g723_1-dec-1                   |   1 -
 tests/ref/fate/g723_1-dec-2                   |   1 -
 tests/ref/fate/g723_1-dec-3                   |   1 -
 tests/ref/fate/g723_1-dec-4                   |   1 -
 tests/ref/fate/g723_1-dec-5                   |   1 -
 tests/ref/fate/g723_1-dec-6                   |   1 -
 tests/ref/fate/g723_1-dec-7                   |   1 -
 tests/ref/fate/g723_1-dec-8                   |   1 -
 tests/ref/fate/g726-encode-2bit               |   1 -
 tests/ref/fate/g726-encode-3bit               |   1 -
 tests/ref/fate/g726-encode-4bit               |   1 -
 tests/ref/fate/g726-encode-5bit               |   1 -
 tests/ref/fate/gapless-mp3                    |   6 +-
 tests/ref/fate/gsm-ms                         |   1 -
 tests/ref/fate/gsm-toast                      |   1 -
 tests/ref/fate/h264-skip-nointra              |   1 -
 tests/ref/fate/h264-skip-nokey                |   1 -
 tests/ref/fate/h264-xavc-4389                 |   1 -
 tests/ref/fate/hls-fmp4                       |   1 -
 tests/ref/fate/hls-init-time                  |   1 -
 tests/ref/fate/hls-list-size                  |   1 -
 tests/ref/fate/hls-segment-single             |   1 -
 tests/ref/fate/hls-segment-size               |   1 -
 tests/ref/fate/id-cin-video                   |   1 -
 tests/ref/fate/id3v2-chapters                 |   1 -
 tests/ref/fate/id3v2-priv-remux               |   1 -
 tests/ref/fate/jv-demux                       |   1 -
 tests/ref/fate/lmlm4-demux                    |   1 -
 tests/ref/fate/matroska-flac-channel-mapping  |   2 -
 tests/ref/fate/matroska-flac-extradata-update |   3 -
 tests/ref/fate/matroska-lzo-decompression     |   1 -
 .../fate/matroska-mastering-display-metadata  |   2 -
 tests/ref/fate/matroska-mpegts-remux          |   2 -
 .../matroska-wavpack-missing-codecprivate     |   1 -
 tests/ref/fate/matroska-xiph-lacing           |   1 -
 tests/ref/fate/maxis-xa                       |   1 -
 tests/ref/fate/mkv                            |   1 -
 tests/ref/fate/mkv-1242                       |   1 -
 tests/ref/fate/mov-440hz-10ms                 |   1 -
 tests/ref/fate/mov-bbi-elst-starts-b          |   1 -
 tests/ref/fate/mov-cover-image                |   1 -
 tests/ref/fate/mov-mp3-demux                  |   1 -
 .../ref/fate/mov-mp4-disposition-mpegts-remux |   2 -
 tests/ref/fate/mpegps-remuxed-pcm-demux       |   1 -
 tests/ref/fate/mtv                            |   1 -
 tests/ref/fate/mxf-demux                      |   1 -
 tests/ref/fate/nsv-demux                      |   1 -
 tests/ref/fate/oma-atrac3-remux               |   1 -
 tests/ref/fate/oma-atrac3p-remux              |   1 -
 tests/ref/fate/on2avc                         |   1 -
 tests/ref/fate/opt                            |  16 +-
 tests/ref/fate/paf-audio                      |   1 -
 tests/ref/fate/paf-demux                      |   1 -
 tests/ref/fate/pcm-planar                     |   1 -
 tests/ref/fate/pcm_dvd                        |   1 -
 tests/ref/fate/pmp-demux                      |   1 -
 tests/ref/fate/prores-gray                    |   1 -
 tests/ref/fate/prores-transparency            |   1 -
 tests/ref/fate/prores-transparency_skip       |   1 -
 tests/ref/fate/psx-str-demux                  |   1 -
 tests/ref/fate/pva-demux                      |   1 -
 tests/ref/fate/ra3-144                        |   1 -
 tests/ref/fate/redcode-demux                  |   1 -
 tests/ref/fate/s337m-demux                    |   1 -
 tests/ref/fate/segment-adts-to-mkv-header-000 |   1 -
 tests/ref/fate/segment-adts-to-mkv-header-001 |   1 -
 tests/ref/fate/segment-adts-to-mkv-header-002 |   1 -
 tests/ref/fate/segment-adts-to-mkv-header-all |   1 -
 tests/ref/fate/shortest                       |   1 -
 tests/ref/fate/sierra-vmd-audio               |   1 -
 tests/ref/fate/siff-demux                     |   1 -
 tests/ref/fate/smacker-audio                  |   1 -
 tests/ref/fate/smjpeg-demux                   |   1 -
 tests/ref/fate/sp5x                           |   1 -
 tests/ref/fate/tiertex-seq                    |   1 -
 tests/ref/fate/tmv                            |   1 -
 tests/ref/fate/tscc-15bit                     |   1 -
 tests/ref/fate/vqf-demux                      |   2 +-
 tests/ref/fate/wav-ac3                        |   1 -
 tests/ref/fate/wc3movie-xan                   |   1 -
 tests/ref/fate/webm-dash-chapters             |   1 -
 tests/ref/fate/westwood-aud                   |   1 -
 tests/ref/fate/wmv3-drm-nodec                 |   1 -
 tests/ref/fate/wtv-demux                      |   1 -
 tests/ref/fate/xmv-demux                      |   1 -
 710 files changed, 6627 insertions(+), 3444 deletions(-)
 create mode 100644 libavutil/tests/channel_layout.c
 create mode 100644 tests/ref/fate/channel_layout

-- 
2.34.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [FFmpeg-devel] [PATCH 001/279 v2] Add a new channel layout API
  2021-12-16 13:21 [FFmpeg-devel] [PATCH 000/279 v2] New channel layout API James Almer
@ 2021-12-16 13:21 ` James Almer
  2021-12-16 17:20   ` Paul B Mahol
  2021-12-16 23:27   ` Marton Balint
  2021-12-16 13:21 ` [FFmpeg-devel] [PATCH 002/279 v2] fate: add a channel_layout API test James Almer
  2021-12-17  0:04 ` [FFmpeg-devel] [PATCH 000/279 v2] New channel layout API Marton Balint
  2 siblings, 2 replies; 20+ messages in thread
From: James Almer @ 2021-12-16 13:21 UTC (permalink / raw)
  To: ffmpeg-devel

From: Anton Khirnov <anton@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 <vittorio.giovara@gmail.com>
and James Almer <jamrial@gmail.com>.
Signed-off-by: Vittorio Giovara <vittorio.giovara@gmail.com>
Signed-off-by: James Almer <jamrial@gmail.com>
---
Changes since last time, starting with the two changes that are
in discussion:

- Added a 16 byte fixed array to AVChannelCustom to give custom
  labels to channels in Custom order layouts. These labes will
  be used by the helpers when querying channels by name or
  describing the layout.
- Added an opaque pointer to both AVChannelLayout and
  AVChannelCustom, to hold private data from the user. These
  fields will be copied but never read or accessed in any way
  by the API.
- Renamed AV_CHAN_SILENT into AV_CHAN_UNUSED, and added
  AV_CHAN_UNKNOWN.
- Added bprint variants for functions returning a string.
- Added a %dC syntax to create unordered channel layouts, same
  as in the old API.
- Channels without a know name or custom label will be
  addressable by the generic label USR%d by all helpers.

 libavutil/channel_layout.c | 623 ++++++++++++++++++++++++++++++++-----
 libavutil/channel_layout.h | 539 ++++++++++++++++++++++++++++++--
 libavutil/version.h        |   1 +
 3 files changed, 1061 insertions(+), 102 deletions(-)

diff --git a/libavutil/channel_layout.c b/libavutil/channel_layout.c
index ac773a9e63..fd20263a0f 100644
--- a/libavutil/channel_layout.c
+++ b/libavutil/channel_layout.c
@@ -37,81 +37,151 @@ struct channel_name {
 };
 
 static const struct channel_name 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"       },
-    [36] = { "TSL",       "top side left"         },
-    [37] = { "TSR",       "top side right"        },
-    [38] = { "BFC",       "bottom front center"   },
-    [39] = { "BFL",       "bottom front left"     },
-    [40] = { "BFR",       "bottom front right"    },
+    [AV_CHAN_FRONT_LEFT           ] = { "FL",        "front left"            },
+    [AV_CHAN_FRONT_RIGHT          ] = { "FR",        "front right"           },
+    [AV_CHAN_FRONT_CENTER         ] = { "FC",        "front center"          },
+    [AV_CHAN_LOW_FREQUENCY        ] = { "LFE",       "low frequency"         },
+    [AV_CHAN_BACK_LEFT            ] = { "BL",        "back left"             },
+    [AV_CHAN_BACK_RIGHT           ] = { "BR",        "back right"            },
+    [AV_CHAN_FRONT_LEFT_OF_CENTER ] = { "FLC",       "front left-of-center"  },
+    [AV_CHAN_FRONT_RIGHT_OF_CENTER] = { "FRC",       "front right-of-center" },
+    [AV_CHAN_BACK_CENTER          ] = { "BC",        "back center"           },
+    [AV_CHAN_SIDE_LEFT            ] = { "SL",        "side left"             },
+    [AV_CHAN_SIDE_RIGHT           ] = { "SR",        "side right"            },
+    [AV_CHAN_TOP_CENTER           ] = { "TC",        "top center"            },
+    [AV_CHAN_TOP_FRONT_LEFT       ] = { "TFL",       "top front left"        },
+    [AV_CHAN_TOP_FRONT_CENTER     ] = { "TFC",       "top front center"      },
+    [AV_CHAN_TOP_FRONT_RIGHT      ] = { "TFR",       "top front right"       },
+    [AV_CHAN_TOP_BACK_LEFT        ] = { "TBL",       "top back left"         },
+    [AV_CHAN_TOP_BACK_CENTER      ] = { "TBC",       "top back center"       },
+    [AV_CHAN_TOP_BACK_RIGHT       ] = { "TBR",       "top back right"        },
+    [AV_CHAN_STEREO_LEFT          ] = { "DL",        "downmix left"          },
+    [AV_CHAN_STEREO_RIGHT         ] = { "DR",        "downmix right"         },
+    [AV_CHAN_WIDE_LEFT            ] = { "WL",        "wide left"             },
+    [AV_CHAN_WIDE_RIGHT           ] = { "WR",        "wide right"            },
+    [AV_CHAN_SURROUND_DIRECT_LEFT ] = { "SDL",       "surround direct left"  },
+    [AV_CHAN_SURROUND_DIRECT_RIGHT] = { "SDR",       "surround direct right" },
+    [AV_CHAN_LOW_FREQUENCY_2      ] = { "LFE2",      "low frequency 2"       },
+    [AV_CHAN_TOP_SIDE_LEFT        ] = { "TSL",       "top side left"         },
+    [AV_CHAN_TOP_SIDE_RIGHT       ] = { "TSR",       "top side right"        },
+    [AV_CHAN_BOTTOM_FRONT_CENTER  ] = { "BFC",       "bottom front center"   },
+    [AV_CHAN_BOTTOM_FRONT_LEFT    ] = { "BFL",       "bottom front left"     },
+    [AV_CHAN_BOTTOM_FRONT_RIGHT   ] = { "BFR",       "bottom front right"    },
 };
 
-static const char *get_channel_name(int channel_id)
+static const char *get_channel_name(enum AVChannel channel_id)
 {
-    if (channel_id < 0 || channel_id >= FF_ARRAY_ELEMS(channel_names))
+    if ((unsigned) channel_id >= FF_ARRAY_ELEMS(channel_names) ||
+        !channel_names[channel_id].name)
         return NULL;
     return channel_names[channel_id].name;
 }
 
-static const struct {
+void av_channel_name_bprint(AVBPrint *bp, enum AVChannel channel_id)
+{
+    av_bprint_clear(bp);
+
+    if ((unsigned)channel_id < FF_ARRAY_ELEMS(channel_names))
+        av_bprintf(bp, "%s", channel_names[channel_id].name);
+    else
+        av_bprintf(bp, "USR%d", channel_id);
+}
+
+int av_channel_name(char *buf, size_t buf_size, enum AVChannel channel_id)
+{
+    AVBPrint bp;
+
+    if (!buf && buf_size)
+        return AVERROR(EINVAL);
+
+    av_bprint_init_for_buffer(&bp, buf, buf_size);
+    av_channel_name_bprint(&bp, channel_id);
+
+    return bp.len;
+}
+
+void av_channel_description_bprint(AVBPrint *bp, enum AVChannel channel_id)
+{
+    av_bprint_clear(bp);
+
+    if ((unsigned)channel_id < FF_ARRAY_ELEMS(channel_names))
+        av_bprintf(bp, "%s", channel_names[channel_id].description);
+    else
+        av_bprintf(bp, "user %d", channel_id);
+}
+
+int av_channel_description(char *buf, size_t buf_size, enum AVChannel channel_id)
+{
+    AVBPrint bp;
+
+    if (!buf && buf_size)
+        return AVERROR(EINVAL);
+
+    av_bprint_init_for_buffer(&bp, buf, buf_size);
+    av_channel_description_bprint(&bp, channel_id);
+
+    return bp.len;
+}
+
+enum AVChannel av_channel_from_string(const char *str)
+{
+    int i;
+    char *endptr = (char *)str;
+    enum AVChannel id = AV_CHAN_NONE;
+    for (i = 0; i < FF_ARRAY_ELEMS(channel_names); i++) {
+        if (channel_names[i].name && !strcmp(str, channel_names[i].name))
+            return i;
+    }
+    if (!strncmp(str, "USR", 3)) {
+        const char *p = str + 3;
+        id = strtol(p, &endptr, 0);
+    }
+    if (id > 0 && !*endptr)
+        return id;
+
+    return AV_CHAN_NONE;
+}
+
+struct channel_layout_name {
     const char *name;
-    int         nb_channels;
-    uint64_t     layout;
-} channel_layout_map[] = {
-    { "mono",        1,  AV_CH_LAYOUT_MONO },
-    { "stereo",      2,  AV_CH_LAYOUT_STEREO },
-    { "2.1",         3,  AV_CH_LAYOUT_2POINT1 },
-    { "3.0",         3,  AV_CH_LAYOUT_SURROUND },
-    { "3.0(back)",   3,  AV_CH_LAYOUT_2_1 },
-    { "4.0",         4,  AV_CH_LAYOUT_4POINT0 },
-    { "quad",        4,  AV_CH_LAYOUT_QUAD },
-    { "quad(side)",  4,  AV_CH_LAYOUT_2_2 },
-    { "3.1",         4,  AV_CH_LAYOUT_3POINT1 },
-    { "5.0",         5,  AV_CH_LAYOUT_5POINT0_BACK },
-    { "5.0(side)",   5,  AV_CH_LAYOUT_5POINT0 },
-    { "4.1",         5,  AV_CH_LAYOUT_4POINT1 },
-    { "5.1",         6,  AV_CH_LAYOUT_5POINT1_BACK },
-    { "5.1(side)",   6,  AV_CH_LAYOUT_5POINT1 },
-    { "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(back)",   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_BACK },
-    { "7.1(wide-side)",   8,  AV_CH_LAYOUT_7POINT1_WIDE },
-    { "octagonal",   8,  AV_CH_LAYOUT_OCTAGONAL },
-    { "hexadecagonal", 16, AV_CH_LAYOUT_HEXADECAGONAL },
-    { "downmix",     2,  AV_CH_LAYOUT_STEREO_DOWNMIX, },
-    { "22.2",          24, AV_CH_LAYOUT_22POINT2, },
+    AVChannelLayout layout;
+};
+
+static const struct channel_layout_name channel_layout_map[] = {
+    { "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                 },
+    { "4.0",            AV_CHANNEL_LAYOUT_4POINT0             },
+    { "quad",           AV_CHANNEL_LAYOUT_QUAD                },
+    { "quad(side)",     AV_CHANNEL_LAYOUT_2_2                 },
+    { "3.1",            AV_CHANNEL_LAYOUT_3POINT1             },
+    { "5.0",            AV_CHANNEL_LAYOUT_5POINT0_BACK        },
+    { "5.0(side)",      AV_CHANNEL_LAYOUT_5POINT0             },
+    { "4.1",            AV_CHANNEL_LAYOUT_4POINT1             },
+    { "5.1",            AV_CHANNEL_LAYOUT_5POINT1_BACK        },
+    { "5.1(side)",      AV_CHANNEL_LAYOUT_5POINT1             },
+    { "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_BACK   },
+    { "7.1(wide-side)", AV_CHANNEL_LAYOUT_7POINT1_WIDE        },
+    { "octagonal",      AV_CHANNEL_LAYOUT_OCTAGONAL           },
+    { "hexadecagonal",  AV_CHANNEL_LAYOUT_HEXADECAGONAL       },
+    { "downmix",        AV_CHANNEL_LAYOUT_STEREO_DOWNMIX,     },
+    { "22.2",           AV_CHANNEL_LAYOUT_22POINT2,           },
 };
 
+#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;
@@ -121,7 +191,7 @@ static uint64_t get_channel_layout_single(const char *name, int name_len)
     for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); 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].name &&
@@ -189,8 +259,8 @@ void av_bprint_channel_layout(struct AVBPrint *bp,
         nb_channels = av_get_channel_layout_nb_channels(channel_layout);
 
     for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); 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_bprintf(bp, "%s", channel_layout_map[i].name);
             return;
         }
@@ -231,8 +301,8 @@ int av_get_channel_layout_nb_channels(uint64_t channel_layout)
 int64_t av_get_default_channel_layout(int nb_channels) {
     int i;
     for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); i++)
-        if (nb_channels == channel_layout_map[i].nb_channels)
-            return channel_layout_map[i].layout;
+        if (nb_channels == channel_layout_map[i].layout.nb_channels)
+            return channel_layout_map[i].layout.u.mask;
     return 0;
 }
 
@@ -287,7 +357,418 @@ int av_get_standard_channel_layout(unsigned index, uint64_t *layout,
 {
     if (index >= FF_ARRAY_ELEMS(channel_layout_map))
         return AVERROR_EOF;
-    if (layout) *layout = channel_layout_map[index].layout;
+    if (layout) *layout = channel_layout_map[index].layout.u.mask;
     if (name)   *name   = channel_layout_map[index].name;
     return 0;
 }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+
+int av_channel_layout_from_mask(AVChannelLayout *channel_layout,
+                                uint64_t mask)
+{
+    if (!mask)
+        return AVERROR(EINVAL);
+
+    channel_layout->order       = AV_CHANNEL_ORDER_NATIVE;
+    channel_layout->nb_channels = av_popcount64(mask);
+    channel_layout->u.mask      = mask;
+
+    return 0;
+}
+
+int av_channel_layout_from_string(AVChannelLayout *channel_layout,
+                                  const char *str)
+{
+    int i;
+    int channels = 0, native = 1;
+    enum AVChannel highest_channel = AV_CHAN_NONE;
+    const char *dup = str;
+    char *end;
+    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].name && !strcmp(chname, channel_names[i].name)) {
+                if (i < highest_channel)
+                    native = 0; // Not a native layout, use a custom one
+                highest_channel = i;
+                mask |= 1ULL << i;
+                break;
+            }
+        }
+
+        if (i >= FF_ARRAY_ELEMS(channel_names)) {
+            char *endptr = chname;
+            enum AVChannel id = AV_CHAN_NONE;
+
+            if (!strncmp(chname, "USR", 3)) {
+                const char *p = chname + 3;
+                id = strtol(p, &endptr, 0);
+            }
+            if (id > 63 && !*endptr)
+                native = 0; // Not a native layout, use a custom one
+            if (id < 0 || *endptr) {
+                native = 0; // Unknown channel name
+                channels = 0;
+                mask = 0;
+                break;
+            }
+            mask |= 1ULL << id;
+        }
+        channels++;
+        av_free(chname);
+    }
+    if (mask && native) {
+        av_channel_layout_from_mask(channel_layout, mask);
+        return 0;
+    }
+
+    /* custom layout of channel names */
+    if (mask && !native) {
+        int idx = 0;
+
+        channel_layout->u.map = av_calloc(channels, sizeof(*channel_layout->u.map));
+        if (!channel_layout->u.map)
+            return AVERROR(ENOMEM);
+
+        channel_layout->order = AV_CHANNEL_ORDER_CUSTOM;
+        channel_layout->nb_channels = channels;
+
+        dup = str;
+        while (*dup) {
+            char *chname = av_get_token(&dup, "|");
+            if (!chname) {
+                av_freep(&channel_layout->u.map);
+                return AVERROR(ENOMEM);
+            }
+            if (*dup)
+                dup++; // skip separator
+            for (i = 0; i < FF_ARRAY_ELEMS(channel_names); i++) {
+                if (channel_names[i].name && !strcmp(chname, channel_names[i].name)) {
+                    channel_layout->u.map[idx++].id = i;
+                    break;
+                }
+            }
+            if (i >= FF_ARRAY_ELEMS(channel_names)) {
+                const char *p = chname + 3;
+                channel_layout->u.map[idx++].id = strtol(p, NULL, 0);
+            }
+            av_free(chname);
+        }
+
+        return 0;
+    }
+
+    /* channel layout mask */
+    if (!strncmp(str, "0x", 2) && sscanf(str + 2, "%"SCNx64, &mask) == 1) {
+        av_channel_layout_from_mask(channel_layout, mask);
+        return 0;
+    }
+
+    errno = 0;
+    channels = strtol(str, &end, 10);
+
+    /* number of channels */
+    if (!errno && *end == 'c' && !*(end + 1) && channels >= 0) {
+        av_channel_layout_default(channel_layout, channels);
+        return 0;
+    }
+
+    /* number of unordered channels */
+    if (!errno && (!*end || (*end == 'C' && !*(end + 1)) || av_strnstr(str, "channels", strlen(str)))
+        && channels >= 0) {
+        channel_layout->order = AV_CHANNEL_ORDER_UNSPEC;
+        channel_layout->nb_channels = channels;
+        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;
+}
+
+int av_channel_layout_describe_bprint(const AVChannelLayout *channel_layout,
+                                      AVBPrint *bp)
+{
+    int i;
+
+    av_bprint_clear(bp);
+
+    switch (channel_layout->order) {
+    case AV_CHANNEL_ORDER_NATIVE:
+        for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); i++)
+            if (channel_layout->u.mask == channel_layout_map[i].layout.u.mask) {
+                av_bprintf(bp, "%s", channel_layout_map[i].name);
+                return 0;
+            }
+        // fall-through
+    case AV_CHANNEL_ORDER_CUSTOM:
+        for (i = 0; i < channel_layout->nb_channels; i++) {
+            const char *ch_name = NULL;
+            enum AVChannel ch = AV_CHAN_NONE;
+
+            if (channel_layout->order == AV_CHANNEL_ORDER_CUSTOM &&
+                channel_layout->u.map[i].name[0])
+                ch_name = channel_layout->u.map[i].name;
+            if (channel_layout->order == AV_CHANNEL_ORDER_NATIVE || !ch_name) {
+                ch = av_channel_layout_channel_from_index(channel_layout, i);
+                ch_name = get_channel_name(ch);
+            }
+
+            if (i)
+                av_bprintf(bp, "|");
+            if (ch_name)
+                av_bprintf(bp, "%s", ch_name);
+            else
+                av_bprintf(bp, "USR%d", ch);
+        }
+        if (channel_layout->nb_channels)
+            return 0;
+        // fall-through
+    case AV_CHANNEL_ORDER_UNSPEC:
+        av_bprintf(bp, "%d channels", channel_layout->nb_channels);
+        return 0;
+    default:
+        return AVERROR(EINVAL);
+    }
+}
+
+int av_channel_layout_describe(const AVChannelLayout *channel_layout,
+                               char *buf, size_t buf_size)
+{
+    AVBPrint bp;
+    int ret;
+
+    if (!buf && buf_size)
+        return AVERROR(EINVAL);
+
+    av_bprint_init_for_buffer(&bp, buf, buf_size);
+    ret = av_channel_layout_describe_bprint(channel_layout, &bp);
+    if (ret < 0)
+        return ret;
+
+    return bp.len;
+}
+
+enum AVChannel
+av_channel_layout_channel_from_index(const AVChannelLayout *channel_layout,
+                                     unsigned int idx)
+{
+    int i;
+
+    if (idx >= channel_layout->nb_channels)
+        return AV_CHAN_NONE;
+
+    switch (channel_layout->order) {
+    case AV_CHANNEL_ORDER_CUSTOM:
+        return channel_layout->u.map[idx].id;
+    case AV_CHANNEL_ORDER_NATIVE:
+        for (i = 0; i < 64; i++) {
+            if ((1ULL << i) & channel_layout->u.mask && !idx--)
+                return i;
+        }
+    default:
+        return AV_CHAN_NONE;
+    }
+}
+
+enum AVChannel
+av_channel_layout_channel_from_string(const AVChannelLayout *channel_layout,
+                                      const char *name)
+{
+    int channel, ret;
+
+    switch (channel_layout->order) {
+    case AV_CHANNEL_ORDER_CUSTOM:
+        for (int i = 0; i < channel_layout->nb_channels; i++) {
+            if (channel_layout->u.map[i].name[0] && !strcmp(name, channel_layout->u.map[i].name))
+                return channel_layout->u.map[i].id;
+        }
+        // fall-through
+    case AV_CHANNEL_ORDER_NATIVE:
+        channel = av_channel_from_string(name);
+        if (channel == AV_CHAN_NONE)
+            return channel;
+        ret = av_channel_layout_index_from_channel(channel_layout, channel);
+        if (ret < 0)
+            return AV_CHAN_NONE;
+        return channel;
+    }
+
+    return AV_CHAN_NONE;
+}
+
+int av_channel_layout_index_from_channel(const AVChannelLayout *channel_layout,
+                                         enum AVChannel channel)
+{
+    int i;
+
+    if (channel == AV_CHAN_NONE)
+        return AVERROR(EINVAL);
+
+    switch (channel_layout->order) {
+    case AV_CHANNEL_ORDER_CUSTOM:
+        for (i = 0; i < channel_layout->nb_channels; i++)
+            if (channel_layout->u.map[i].id == 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_index_from_string(const AVChannelLayout *channel_layout,
+                                        const char *name)
+{
+    enum AVChannel ch;
+
+    switch (channel_layout->order) {
+    case AV_CHANNEL_ORDER_CUSTOM:
+        for (int i = 0; i < channel_layout->nb_channels; i++) {
+            if (channel_layout->u.map[i].name[0] && !strcmp(name, channel_layout->u.map[i].name))
+                return i;
+        }
+        // fall-through
+    case AV_CHANNEL_ORDER_NATIVE:
+        ch = av_channel_from_string(name);
+        if (ch == AV_CHAN_NONE)
+            return AVERROR(EINVAL);
+        return av_channel_layout_index_from_channel(channel_layout, ch);
+    }
+
+    return AVERROR(EINVAL);
+}
+
+int av_channel_layout_check(const AVChannelLayout *channel_layout)
+{
+    if (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:
+        if (!channel_layout->u.map)
+            return 0;
+        for (int i = 0; i < channel_layout->nb_channels; i++) {
+            if (channel_layout->u.map[i].id == AV_CHAN_NONE)
+                return 0;
+        }
+        return 0;
+    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_channel_from_index(chl,  i) !=
+            av_channel_layout_channel_from_index(chl1, i))
+            return 1;
+    return 0;
+}
+
+void av_channel_layout_default(AVChannelLayout *ch_layout, int nb_channels)
+{
+    int i;
+    for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); i++)
+        if (nb_channels == channel_layout_map[i].layout.nb_channels) {
+            *ch_layout = channel_layout_map[i].layout;
+            return;
+        }
+
+    ch_layout->order       = AV_CHANNEL_ORDER_UNSPEC;
+    ch_layout->nb_channels = nb_channels;
+}
+
+const AVChannelLayout *av_channel_layout_standard(void **opaque)
+{
+    uintptr_t i = (uintptr_t)*opaque;
+    const AVChannelLayout *ch_layout = NULL;
+
+    if (i < FF_ARRAY_ELEMS(channel_layout_map)) {
+        ch_layout = &channel_layout_map[i].layout;
+        *opaque = (void*)(i + 1);
+    }
+
+    return ch_layout;
+}
+
+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_index_from_channel(channel_layout, i) >= 0)
+            ret |= (1ULL << i);
+
+    return ret;
+}
diff --git a/libavutil/channel_layout.h b/libavutil/channel_layout.h
index d39ae1177a..c97be82a3a 100644
--- a/libavutil/channel_layout.h
+++ b/libavutil/channel_layout.h
@@ -23,6 +23,10 @@
 #define AVUTIL_CHANNEL_LAYOUT_H
 
 #include <stdint.h>
+#include <stdlib.h>
+
+#include "version.h"
+#include "attributes.h"
 
 /**
  * @file
@@ -34,6 +38,71 @@
  * @{
  */
 
+enum AVChannel {
+    ///< Invalid channel index
+    AV_CHAN_NONE = -1,
+    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,
+    AV_CHAN_TOP_SIDE_LEFT,
+    AV_CHAN_TOP_SIDE_RIGHT,
+    AV_CHAN_BOTTOM_FRONT_CENTER,
+    AV_CHAN_BOTTOM_FRONT_LEFT,
+    AV_CHAN_BOTTOM_FRONT_RIGHT,
+
+    /** Channel is empty can be safely skipped. */
+    AV_CHAN_UNUSED = 64,
+
+    /** Channel contains data, but its position is unknown. */
+    AV_CHAN_UNKWNOWN = 128,
+};
+
+enum AVChannelOrder {
+    /**
+     * Only the channel count is specified, without any further information
+     * about the channel order.
+     */
+    AV_CHANNEL_ORDER_UNSPEC,
+    /**
+     * 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 empty/skipped (AV_CHAN_SILENCE)
+     * channels at arbitrary positions.
+     */
+    AV_CHANNEL_ORDER_CUSTOM,
+};
+
+
 /**
  * @defgroup channel_masks Audio channel masks
  *
@@ -46,41 +115,46 @@
  *
  * @{
  */
-#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_TOP_SIDE_LEFT          0x0000001000000000ULL
-#define AV_CH_TOP_SIDE_RIGHT         0x0000002000000000ULL
-#define AV_CH_BOTTOM_FRONT_CENTER    0x0000004000000000ULL
-#define AV_CH_BOTTOM_FRONT_LEFT      0x0000008000000000ULL
-#define AV_CH_BOTTOM_FRONT_RIGHT     0x0000010000000000ULL
+#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      )
+#define AV_CH_TOP_SIDE_LEFT          (1ULL << AV_CHAN_TOP_SIDE_LEFT        )
+#define AV_CH_TOP_SIDE_RIGHT         (1ULL << AV_CHAN_TOP_SIDE_RIGHT       )
+#define AV_CH_BOTTOM_FRONT_CENTER    (1ULL << AV_CHAN_BOTTOM_FRONT_CENTER  )
+#define AV_CH_BOTTOM_FRONT_LEFT      (1ULL << AV_CHAN_BOTTOM_FRONT_LEFT    )
+#define AV_CH_BOTTOM_FRONT_RIGHT     (1ULL << AV_CHAN_BOTTOM_FRONT_RIGHT   )
 
+#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
 
 /**
  * @}
@@ -128,6 +202,165 @@ enum AVMatrixEncoding {
     AV_MATRIX_ENCODING_NB
 };
 
+/**
+ * @}
+ */
+
+/**
+ * An AVChannelCustom defines a single channel within a custom order layout
+ *
+ * Unlike most structures in FFmpeg, sizeof(AVChannelCustom) is a part of the
+ * public ABI.
+ *
+ * No new fields may be added to it without a major version bump.
+ */
+typedef struct AVChannelCustom {
+    enum AVChannel id;
+    char name[16];
+    void *opaque;
+} AVChannelCustom;
+
+/**
+ * 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
+ * or embedded in caller-defined structs.
+ *
+ * AVChannelLayout can be initialized as follows:
+ * - default initialization with {0}, followed by by setting all used fields
+ *   correctly;
+ * - by assigning one of the predefined AV_CHANNEL_LAYOUT_* initializers;
+ * - with a constructor function, such as av_channel_layout_default(),
+ *   av_channel_layout_from_mask() or av_channel_layout_from_string().
+ *
+ * The channel layout must be unitialized with av_channel_layout_uninit()
+ *
+ * Copying an AVChannelLayout via assigning is forbidden,
+ * av_channel_layout_copy() must be used. instead (and its return value should
+ * be checked)
+ *
+ * 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).
+ */
+typedef struct AVChannelLayout {
+    /**
+     * Channel order used in this layout.
+     * This is a mandatory field.
+     */
+    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 presence of the AVChannel with the
+         * corresponding value in map[i].id.
+         *
+         * I.e. when map[i].id is equal to AV_CHAN_FOO, then AV_CH_FOO is the
+         * i-th channel in the audio data.
+         *
+         * map[i].name may be filled with a 0-terminated string, in which case
+         * it will be used for the purpose of identifying the channel with the
+         * convenience functions below. Otherise it must be zeroed.
+         */
+        AVChannelCustom *map;
+    } u;
+
+    /**
+     * For some private data of the user.
+     */
+    void *opaque;
+} 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 }}
+#define AV_CHANNEL_LAYOUT_22POINT2 \
+    { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 24, .u = { .mask = AV_CH_LAYOUT_22POINT2 }}
+
+#if FF_API_OLD_CHANNEL_LAYOUT
 /**
  * Return a channel layout id that matches name, or 0 if no match is found.
  *
@@ -144,7 +377,10 @@ enum AVMatrixEncoding {
  *   AV_CH_* macros).
  *
  * Example: "stereo+FC" = "2c+FC" = "2c+1c" = "0x7"
+ *
+ * @deprecated use av_channel_layout_from_string()
  */
+attribute_deprecated
 uint64_t av_get_channel_layout(const char *name);
 
 /**
@@ -158,7 +394,9 @@ uint64_t av_get_channel_layout(const char *name);
  * @param[out] nb_channels      number of channels
  *
  * @return 0 on success, AVERROR(EINVAL) if the parsing fails.
+ * @deprecated use av_channel_layout_from_string()
  */
+attribute_deprecated
 int av_get_extended_channel_layout(const char *name, uint64_t* channel_layout, int* nb_channels);
 
 /**
@@ -167,23 +405,32 @@ int av_get_extended_channel_layout(const char *name, uint64_t* channel_layout, i
  *
  * @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);
 
 struct AVBPrint;
 /**
  * Append a description of a channel layout to a bprint buffer.
+ * @deprecated use av_channel_layout_describe()
  */
+attribute_deprecated
 void av_bprint_channel_layout(struct AVBPrint *bp, 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
 int64_t av_get_default_channel_layout(int nb_channels);
 
 /**
@@ -194,20 +441,28 @@ int64_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_index_from_channel()
  */
+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_channel_from_index()
  */
+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);
 
 /**
@@ -215,7 +470,9 @@ const char *av_get_channel_name(uint64_t channel);
  *
  * @param channel  a channel layout with a single channel
  * @return  channel description on success, NULL on error
+ * @deprecated use av_channel_description()
  */
+attribute_deprecated
 const char *av_get_channel_description(uint64_t channel);
 
 /**
@@ -226,9 +483,229 @@ const char *av_get_channel_description(uint64_t channel);
  * @param[out] name    name of the layout
  * @return  0  if the layout exists,
  *          <0 if index is beyond the limits
+ * @deprecated use av_channel_layout_standard()
  */
+attribute_deprecated
 int av_get_standard_channel_layout(unsigned index, uint64_t *layout,
                                    const char **name);
+#endif
+
+/**
+ * Get a human readable string in an abbreviated form describing a given channel,
+ * or "?" if not found.
+ * This is the inverse function of @ref av_channel_from_string().
+ *
+ * @param buf pre-allocated buffer where to put the generated string
+ * @param buf_size size in bytes of the buffer.
+ * @return amount of bytes needed to hold the output string, or a negative AVERROR
+ *         on failure. If the returned value is bigger than buf_size, then the
+ *         string was truncated.
+ */
+int av_channel_name(char *buf, size_t buf_size, enum AVChannel channel);
+
+/**
+ * bprint variant of av_channel_name().
+ */
+void av_channel_name_bprint(struct AVBPrint *bp, enum AVChannel channel_id);
+
+/**
+ * Get a human readable string describing a given channel, or "?" if not found.
+ *
+ * @param buf pre-allocated buffer where to put the generated string
+ * @param buf_size size in bytes of the buffer.
+ * @return amount of bytes needed to hold the output string, or a negative AVERROR
+ *         on failure. If the returned value is bigger than buf_size, then the
+ *         string was truncated.
+ */
+int av_channel_description(char *buf, size_t buf_size, enum AVChannel channel);
+
+/**
+ * bprint variant of av_channel_description().
+ */
+void av_channel_description_bprint(struct AVBPrint *bp, enum AVChannel channel_id);
+
+/**
+ * This is the inverse function of @ref av_channel_name().
+ *
+ * @return the channel with the given name
+ *         AV_CHAN_NONE when name does not identify a known channel
+ */
+enum AVChannel av_channel_from_string(const char *name);
+
+/**
+ * Initialize a native channel layout from a bitmask indicating which channels
+ * are present.
+ *
+ * @param channel_layout the layout structure to be initialized
+ * @param mask bitmask describing the channel layout
+ *
+ * @return 0 on success
+ *         AVERROR(EINVAL) for invalid mask values
+ */
+int 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. "5c")
+ *  - the number of unordered channels (eg. "4", "4C", or "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.
+ *
+ * @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);
+
+/**
+ * Iterate over all standard channel layouts.
+ *
+ * @param opaque a pointer where libavutil will store the iteration state. Must
+ *               point to NULL to start the iteration.
+ *
+ * @return the standard channel layout or NULL when the iteration is
+ *         finished
+ */
+const AVChannelLayout *av_channel_layout_standard(void **opaque);
+
+/**
+ * Free any allocated data in the channel layout and reset the channel
+ * count to 0.
+ *
+ * @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.
+ * The string will be in the same format that is accepted by
+ * @ref av_channel_layout_from_string().
+ *
+ * @param channel_layout channel layout to be described
+ * @param buf pre-allocated buffer where to put the generated string
+ * @param buf_size size in bytes of the buffer.
+ * @return amount of bytes needed to hold the output string, or a negative AVERROR
+ *         on failure. If the returned value is bigger than buf_size, then the
+ *         string was truncated.
+ */
+int av_channel_layout_describe(const AVChannelLayout *channel_layout,
+                               char *buf, size_t buf_size);
+
+/**
+ * bprint variant of av_channel_layout_describe().
+ *
+ * @return 0 on success, or a negative AVERROR value on failure.
+ */
+int av_channel_layout_describe_bprint(const AVChannelLayout *channel_layout,
+                                      struct AVBPrint *bp);
+
+/**
+ * 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
+ *         AV_CHAN_NONE on failure (if idx is not valid or the channel order is
+ *         unspecified)
+ */
+enum AVChannel
+av_channel_layout_channel_from_index(const AVChannelLayout *channel_layout, unsigned 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_index_from_channel(const AVChannelLayout *channel_layout,
+                                         enum AVChannel channel);
+
+/**
+ * Get the index in a channel layout of a channel described by the given string.
+ * In case multiple channels are found, only the first match will be returned.
+ *
+ * This function accepts channel names in the same format as
+ * @ref av_channel_from_string().
+ *
+ * @param channel_layout input channel layout
+ * @return a channel index described by the given string, or a negative AVERROR
+ *         value.
+ */
+int av_channel_layout_index_from_string(const AVChannelLayout *channel_layout,
+                                        const char *name);
+
+/**
+ * Get a channel described by the given string.
+ *
+ * This function accepts channel names in the same format as
+ * @ref av_channel_from_string().
+ *
+ * @param channel_layout input channel layout
+ * @return a channel described by the given string, or a negative AVERROR value.
+ */
+int av_channel_layout_channel_from_string(const AVChannelLayout *channel_layout,
+                                          const char *name);
+
+/**
+ * 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 0e7b36865a..b9ef96fdd7 100644
--- a/libavutil/version.h
+++ b/libavutil/version.h
@@ -109,6 +109,7 @@
 #define FF_API_DECLARE_ALIGNED          (LIBAVUTIL_VERSION_MAJOR < 58)
 #define FF_API_COLORSPACE_NAME          (LIBAVUTIL_VERSION_MAJOR < 58)
 #define FF_API_AV_MALLOCZ_ARRAY         (LIBAVUTIL_VERSION_MAJOR < 58)
+#define FF_API_OLD_CHANNEL_LAYOUT       (LIBAVUTIL_VERSION_MAJOR < 58)
 
 /**
  * @}
-- 
2.34.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [FFmpeg-devel] [PATCH 002/279 v2] fate: add a channel_layout API test
  2021-12-16 13:21 [FFmpeg-devel] [PATCH 000/279 v2] New channel layout API James Almer
  2021-12-16 13:21 ` [FFmpeg-devel] [PATCH 001/279 v2] Add a new " James Almer
@ 2021-12-16 13:21 ` James Almer
  2021-12-17  0:04 ` [FFmpeg-devel] [PATCH 000/279 v2] New channel layout API Marton Balint
  2 siblings, 0 replies; 20+ messages in thread
From: James Almer @ 2021-12-16 13:21 UTC (permalink / raw)
  To: ffmpeg-devel

Signed-off-by: James Almer <jamrial@gmail.com>
---
Changes since last time:

- Added and adapted some tests to cover the new additions to
  the API.
- Now using the AVBPrint variants of some functions.

 libavutil/Makefile               |   1 +
 libavutil/tests/channel_layout.c | 233 +++++++++++++++++++++++++++++++
 tests/fate/libavutil.mak         |   4 +
 tests/ref/fate/channel_layout    |  98 +++++++++++++
 4 files changed, 336 insertions(+)
 create mode 100644 libavutil/tests/channel_layout.c
 create mode 100644 tests/ref/fate/channel_layout

diff --git a/libavutil/Makefile b/libavutil/Makefile
index 529046dbc8..8915575cfa 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -219,6 +219,7 @@ TESTPROGS = adler32                                                     \
             bprint                                                      \
             cast5                                                       \
             camellia                                                    \
+            channel_layout                                              \
             color_utils                                                 \
             cpu                                                         \
             crc                                                         \
diff --git a/libavutil/tests/channel_layout.c b/libavutil/tests/channel_layout.c
new file mode 100644
index 0000000000..73ed0a6666
--- /dev/null
+++ b/libavutil/tests/channel_layout.c
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) 2021 James Almer
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/channel_layout.c"
+
+#define CHANNEL_LAYOUT_FROM_MASK(layout, x)                                \
+    av_channel_layout_uninit(&layout);                                     \
+    if (!av_channel_layout_from_mask(&layout, x))                          \
+        av_channel_layout_describe_bprint(&layout, &bp);
+
+#define CHANNEL_LAYOUT_FROM_STRING(layout, x)                              \
+    av_channel_layout_uninit(&layout);                                     \
+    if (!av_channel_layout_from_string(&layout, x))                        \
+        av_channel_layout_describe_bprint(&layout, &bp);
+
+#define CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(layout, x)                       \
+    ret = av_channel_layout_channel_from_index(&layout, x);                \
+    if (ret < 0)                                                           \
+        ret = -1
+
+#define CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(layout, x)                       \
+    ret = av_channel_layout_index_from_channel(&layout, x);                \
+    if (ret < 0)                                                           \
+        ret = -1
+
+#define CHANNEL_LAYOUT_CHANNEL_FROM_STRING(layout, x)                      \
+    ret = av_channel_layout_channel_from_string(&layout, x);               \
+    if (ret < 0)                                                           \
+        ret = -1
+
+#define CHANNEL_LAYOUT_INDEX_FROM_STRING(layout, x)                        \
+    ret = av_channel_layout_index_from_string(&layout, x);                 \
+    if (ret < 0)                                                           \
+        ret = -1
+
+int main(void)
+{
+    AVChannelLayout surround = { 0 };
+    AVChannelLayout custom = { 0 };
+    AVBPrint bp;
+    int ret;
+
+    av_bprint_init(&bp, 64, AV_BPRINT_SIZE_AUTOMATIC);
+
+    printf("Testing av_channel_name\n");
+    av_channel_name_bprint(&bp, AV_CHAN_FRONT_LEFT);
+    printf("With AV_CHAN_FRONT_LEFT: %27s\n", bp.str);
+    av_channel_name_bprint(&bp, AV_CHAN_FRONT_RIGHT);
+    printf("With AV_CHAN_FRONT_RIGHT: %26s\n", bp.str);
+    av_channel_name_bprint(&bp, 63);
+    printf("With 63: %43s\n", bp.str);
+
+    printf("Testing av_channel_description\n");
+    av_channel_description_bprint(&bp, AV_CHAN_FRONT_LEFT);
+    printf("With AV_CHAN_FRONT_LEFT: %27s\n", bp.str);
+    av_channel_description_bprint(&bp, AV_CHAN_FRONT_RIGHT);
+    printf("With AV_CHAN_FRONT_RIGHT: %26s\n", bp.str);
+    av_channel_description_bprint(&bp, 63);
+    printf("With 63: %43s\n", bp.str);
+
+    printf("\nTesting av_channel_from_string\n");
+    printf("With \"FL\": %41d\n", av_channel_from_string("FL"));
+    printf("With \"FR\": %41d\n", av_channel_from_string("FR"));
+    printf("With \"USR63\": %38d\n", av_channel_from_string("USR63"));
+
+    printf("\n==Native layouts==\n");
+
+    printf("\nTesting av_channel_layout_from_string\n");
+    CHANNEL_LAYOUT_FROM_STRING(surround, "0x3f");
+    printf("With \"0x3f\": %39s\n", bp.str);
+    CHANNEL_LAYOUT_FROM_STRING(surround, "6c");
+    printf("With \"6c\": %41s\n", bp.str);
+    CHANNEL_LAYOUT_FROM_STRING(surround, "6C");
+    printf("With \"6C\": %41s\n", bp.str);
+    CHANNEL_LAYOUT_FROM_STRING(surround, "6");
+    printf("With \"6\": %42s\n", bp.str);
+    CHANNEL_LAYOUT_FROM_STRING(surround, "6 channels");
+    printf("With \"6 channels\": %33s\n", bp.str);
+    CHANNEL_LAYOUT_FROM_STRING(surround, "FL|FR|FC|LFE|BL|BR");
+    printf("With \"FL|FR|FC|LFE|BL|BR\": %25s\n", bp.str);
+    CHANNEL_LAYOUT_FROM_STRING(surround, "5.1");
+    printf("With \"5.1\": %40s\n", bp.str);
+    CHANNEL_LAYOUT_FROM_STRING(surround, "FL|FR|USR63");
+    printf("With \"FL|FR|USR63\": %32s\n", bp.str);
+    CHANNEL_LAYOUT_FROM_STRING(surround, "FL|FR|FC|LFE|SL|SR");
+    printf("With \"FL|FR|FC|LFE|SL|SR\": %25s\n", bp.str);
+    CHANNEL_LAYOUT_FROM_STRING(surround, "5.1(side)");
+    printf("With \"5.1(side)\": %34s\n", bp.str);
+
+    printf("\nTesting av_channel_layout_from_mask\n");
+    CHANNEL_LAYOUT_FROM_MASK(surround, AV_CH_LAYOUT_5POINT1);
+    printf("With AV_CH_LAYOUT_5POINT1: %25s\n", bp.str);
+
+    printf("\nTesting av_channel_layout_channel_from_index\n");
+    CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(surround, 0);
+    printf("On 5.1(side) layout with 0: %24d\n", ret);
+    CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(surround, 1);
+    printf("On 5.1(side) layout with 1: %24d\n", ret);
+    CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(surround, 2);
+    printf("On 5.1(side) layout with 2: %24d\n", ret);
+    CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(surround, 3);
+    printf("On 5.1(side) layout with 3: %24d\n", ret);
+    CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(surround, 4);
+    printf("On 5.1(side) layout with 4: %24d\n", ret);
+    CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(surround, 5);
+    printf("On 5.1(side) layout with 5: %24d\n", ret);
+    CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(surround, 6);
+    printf("On 5.1(side) layout with 6: %24d\n", ret);
+
+    printf("\nTesting av_channel_layout_index_from_channel\n");
+    CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(surround, AV_CHAN_FRONT_LEFT);
+    printf("On 5.1(side) layout with AV_CHAN_FRONT_LEFT: %7d\n", ret);
+    CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(surround, AV_CHAN_FRONT_RIGHT);
+    printf("On 5.1(side) layout with AV_CHAN_FRONT_RIGHT: %6d\n", ret);
+    CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(surround, AV_CHAN_FRONT_CENTER);
+    printf("On 5.1(side) layout with AV_CHAN_FRONT_CENTER: %5d\n", ret);
+    CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(surround, AV_CHAN_LOW_FREQUENCY);
+    printf("On 5.1(side) layout with AV_CHAN_LOW_FREQUENCY: %4d\n", ret);
+    CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(surround, AV_CHAN_SIDE_LEFT);
+    printf("On 5.1(side) layout with AV_CHAN_SIDE_LEFT: %8d\n", ret);
+    CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(surround, AV_CHAN_SIDE_RIGHT);
+    printf("On 5.1(side) layout with AV_CHAN_SIDE_RIGHT: %7d\n", ret);
+    CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(surround, AV_CHAN_BACK_CENTER);
+    printf("On 5.1(side) layout with AV_CHAN_BACK_CENTER: %6d\n", ret);
+
+    printf("\nTesting av_channel_layout_channel_from_string\n");
+    CHANNEL_LAYOUT_CHANNEL_FROM_STRING(surround, "FL");
+    printf("On 5.1(side) layout with \"FL\": %21d\n", ret);
+    CHANNEL_LAYOUT_CHANNEL_FROM_STRING(surround, "FR");
+    printf("On 5.1(side) layout with \"FR\": %21d\n", ret);
+    CHANNEL_LAYOUT_CHANNEL_FROM_STRING(surround, "FC");
+    printf("On 5.1(side) layout with \"FC\": %21d\n", ret);
+    CHANNEL_LAYOUT_CHANNEL_FROM_STRING(surround, "LFE");
+    printf("On 5.1(side) layout with \"LFE\": %20d\n", ret);
+    CHANNEL_LAYOUT_CHANNEL_FROM_STRING(surround, "SL");
+    printf("On 5.1(side) layout with \"SL\": %21d\n", ret);
+    CHANNEL_LAYOUT_CHANNEL_FROM_STRING(surround, "SR");
+    printf("On 5.1(side) layout with \"SR\": %21d\n", ret);
+    CHANNEL_LAYOUT_CHANNEL_FROM_STRING(surround, "BC");
+    printf("On 5.1(side) layout with \"BC\": %21d\n", ret);
+
+    printf("\nTesting av_channel_layout_index_from_string\n");
+    CHANNEL_LAYOUT_INDEX_FROM_STRING(surround, "FL");
+    printf("On 5.1(side) layout with \"FL\": %21d\n", ret);
+    CHANNEL_LAYOUT_INDEX_FROM_STRING(surround, "FR");
+    printf("On 5.1(side) layout with \"FR\": %21d\n", ret);
+    CHANNEL_LAYOUT_INDEX_FROM_STRING(surround, "FC");
+    printf("On 5.1(side) layout with \"FC\": %21d\n", ret);
+    CHANNEL_LAYOUT_INDEX_FROM_STRING(surround, "LFE");
+    printf("On 5.1(side) layout with \"LFE\": %20d\n", ret);
+    CHANNEL_LAYOUT_INDEX_FROM_STRING(surround, "SL");
+    printf("On 5.1(side) layout with \"SL\": %21d\n", ret);
+    CHANNEL_LAYOUT_INDEX_FROM_STRING(surround, "SR");
+    printf("On 5.1(side) layout with \"SR\": %21d\n", ret);
+    CHANNEL_LAYOUT_INDEX_FROM_STRING(surround, "BC");
+    printf("On 5.1(side) layout with \"BC\": %21d\n", ret);
+
+    printf("\n==Custom layouts==\n");
+
+    printf("\nTesting av_channel_layout_from_string\n");
+    CHANNEL_LAYOUT_FROM_STRING(custom, "FL|FR|FC|BL|BR|LFE");
+    printf("With \"FL|FR|FC|BL|BR|LFE\": %25s\n", bp.str);
+    CHANNEL_LAYOUT_FROM_STRING(custom, "FR|FL|USR63");
+    printf("With \"FR|FL|USR63\" layout: %25s\n", bp.str);
+
+    av_strlcpy(custom.u.map[2].name, "CUS", sizeof(custom.u.map[2].name));
+    printf("\nTesting av_channel_layout_index_from_string\n");
+    CHANNEL_LAYOUT_INDEX_FROM_STRING(custom, "FR");
+    printf("On \"FR|FL|USR63\" layout with \"FR\": %17d\n", ret);
+    CHANNEL_LAYOUT_INDEX_FROM_STRING(custom, "FL");
+    printf("On \"FR|FL|USR63\" layout with \"FL\": %17d\n", ret);
+    CHANNEL_LAYOUT_INDEX_FROM_STRING(custom, "USR63");
+    printf("On \"FR|FL|USR63\" layout with \"USR63\": %14d\n", ret);
+    CHANNEL_LAYOUT_INDEX_FROM_STRING(custom, "CUS");
+    printf("On \"FR|FL|USR63\" layout with custom label \"CUS\": %3d\n", ret);
+    CHANNEL_LAYOUT_INDEX_FROM_STRING(custom, "BC");
+    printf("On \"FR|FL|USR63\" layout with \"BC\": %17d\n", ret);
+
+    printf("\nTesting av_channel_layout_channel_from_string\n");
+    CHANNEL_LAYOUT_CHANNEL_FROM_STRING(custom, "FR");
+    printf("On \"FR|FL|USR63\" layout with \"FR\": %17d\n", ret);
+    CHANNEL_LAYOUT_CHANNEL_FROM_STRING(custom, "FL");
+    printf("On \"FR|FL|USR63\" layout with \"FL\": %17d\n", ret);
+    CHANNEL_LAYOUT_CHANNEL_FROM_STRING(custom, "USR63");
+    printf("On \"FR|FL|USR63\" layout with \"USR63\": %14d\n", ret);
+    CHANNEL_LAYOUT_CHANNEL_FROM_STRING(custom, "CUS");
+    printf("On \"FR|FL|USR63\" layout with custom label \"CUS\": %3d\n", ret);
+    CHANNEL_LAYOUT_CHANNEL_FROM_STRING(custom, "BC");
+    printf("On \"FR|FL|USR63\" layout with \"BC\": %17d\n", ret);
+
+    printf("\nTesting av_channel_layout_index_from_channel\n");
+    CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(custom, AV_CHAN_FRONT_RIGHT);
+    printf("On \"FR|FL|USR63\" layout with AV_CHAN_FRONT_RIGHT: %2d\n", ret);
+    CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(custom, AV_CHAN_FRONT_LEFT);
+    printf("On \"FR|FL|USR63\" layout with AV_CHAN_FRONT_LEFT: %3d\n", ret);
+    CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(custom, 63);
+    printf("On \"FR|FL|USR63\" layout with 63: %19d\n", ret);
+    CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(custom, AV_CHAN_BACK_CENTER);
+    printf("On \"FR|FL|USR63\" layout with AV_CHAN_BACK_CENTER: %2d\n", ret);
+
+    printf("\nTesting av_channel_layout_channel_from_index\n");
+    CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(custom, 0);
+    printf("On \"FR|FL|USR63\" layout with 0: %20d\n", ret);
+    CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(custom, 1);
+    printf("On \"FR|FL|USR63\" layout with 1: %20d\n", ret);
+    CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(custom, 2);
+    printf("On \"FR|FL|USR63\" layout with 2: %20d\n", ret);
+    CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(custom, 3);
+    printf("On \"FR|FL|USR63\" layout with 3: %20d\n", ret);
+
+    av_channel_layout_uninit(&surround);
+    av_channel_layout_uninit(&custom);
+    av_bprint_finalize(&bp, NULL);
+
+    return 0;
+}
diff --git a/tests/fate/libavutil.mak b/tests/fate/libavutil.mak
index 1ec9ed00ad..c32cf2e706 100644
--- a/tests/fate/libavutil.mak
+++ b/tests/fate/libavutil.mak
@@ -23,6 +23,10 @@ fate-cast5: libavutil/tests/cast5$(EXESUF)
 fate-cast5: CMD = run libavutil/tests/cast5$(EXESUF)
 fate-cast5: CMP = null
 
+FATE_LIBAVUTIL += fate-channel_layout
+fate-channel_layout: libavutil/tests/channel_layout$(EXESUF)
+fate-channel_layout: CMD = run libavutil/tests/channel_layout$(EXESUF)
+
 FATE_LIBAVUTIL += fate-audio_fifo
 fate-audio_fifo: libavutil/tests/audio_fifo$(EXESUF)
 fate-audio_fifo: CMD = run libavutil/tests/audio_fifo$(EXESUF)
diff --git a/tests/ref/fate/channel_layout b/tests/ref/fate/channel_layout
new file mode 100644
index 0000000000..1b42d5d983
--- /dev/null
+++ b/tests/ref/fate/channel_layout
@@ -0,0 +1,98 @@
+Testing av_channel_name
+With AV_CHAN_FRONT_LEFT:                          FL
+With AV_CHAN_FRONT_RIGHT:                         FR
+With 63:                                       USR63
+Testing av_channel_description
+With AV_CHAN_FRONT_LEFT:                  front left
+With AV_CHAN_FRONT_RIGHT:                front right
+With 63:                                     user 63
+
+Testing av_channel_from_string
+With "FL":                                         0
+With "FR":                                         1
+With "USR63":                                     63
+
+==Native layouts==
+
+Testing av_channel_layout_from_string
+With "0x3f":                                     5.1
+With "6c":                                       5.1
+With "6C":                                6 channels
+With "6":                                 6 channels
+With "6 channels":                        6 channels
+With "FL|FR|FC|LFE|BL|BR":                       5.1
+With "5.1":                                      5.1
+With "FL|FR|USR63":                      FL|FR|USR63
+With "FL|FR|FC|LFE|SL|SR":                 5.1(side)
+With "5.1(side)":                          5.1(side)
+
+Testing av_channel_layout_from_mask
+With AV_CH_LAYOUT_5POINT1:                 5.1(side)
+
+Testing av_channel_layout_channel_from_index
+On 5.1(side) layout with 0:                        0
+On 5.1(side) layout with 1:                        1
+On 5.1(side) layout with 2:                        2
+On 5.1(side) layout with 3:                        3
+On 5.1(side) layout with 4:                        9
+On 5.1(side) layout with 5:                       10
+On 5.1(side) layout with 6:                       -1
+
+Testing av_channel_layout_index_from_channel
+On 5.1(side) layout with AV_CHAN_FRONT_LEFT:       0
+On 5.1(side) layout with AV_CHAN_FRONT_RIGHT:      1
+On 5.1(side) layout with AV_CHAN_FRONT_CENTER:     2
+On 5.1(side) layout with AV_CHAN_LOW_FREQUENCY:    3
+On 5.1(side) layout with AV_CHAN_SIDE_LEFT:        4
+On 5.1(side) layout with AV_CHAN_SIDE_RIGHT:       5
+On 5.1(side) layout with AV_CHAN_BACK_CENTER:     -1
+
+Testing av_channel_layout_channel_from_string
+On 5.1(side) layout with "FL":                     0
+On 5.1(side) layout with "FR":                     1
+On 5.1(side) layout with "FC":                     2
+On 5.1(side) layout with "LFE":                    3
+On 5.1(side) layout with "SL":                     9
+On 5.1(side) layout with "SR":                    10
+On 5.1(side) layout with "BC":                    -1
+
+Testing av_channel_layout_index_from_string
+On 5.1(side) layout with "FL":                     0
+On 5.1(side) layout with "FR":                     1
+On 5.1(side) layout with "FC":                     2
+On 5.1(side) layout with "LFE":                    3
+On 5.1(side) layout with "SL":                     4
+On 5.1(side) layout with "SR":                     5
+On 5.1(side) layout with "BC":                    -1
+
+==Custom layouts==
+
+Testing av_channel_layout_from_string
+With "FL|FR|FC|BL|BR|LFE":        FL|FR|FC|BL|BR|LFE
+With "FR|FL|USR63" layout:               FR|FL|USR63
+
+Testing av_channel_layout_index_from_string
+On "FR|FL|USR63" layout with "FR":                 0
+On "FR|FL|USR63" layout with "FL":                 1
+On "FR|FL|USR63" layout with "USR63":              2
+On "FR|FL|USR63" layout with custom label "CUS":   2
+On "FR|FL|USR63" layout with "BC":                -1
+
+Testing av_channel_layout_channel_from_string
+On "FR|FL|USR63" layout with "FR":                 1
+On "FR|FL|USR63" layout with "FL":                 0
+On "FR|FL|USR63" layout with "USR63":             63
+On "FR|FL|USR63" layout with custom label "CUS":  63
+On "FR|FL|USR63" layout with "BC":                -1
+
+Testing av_channel_layout_index_from_channel
+On "FR|FL|USR63" layout with AV_CHAN_FRONT_RIGHT:  0
+On "FR|FL|USR63" layout with AV_CHAN_FRONT_LEFT:   1
+On "FR|FL|USR63" layout with 63:                   2
+On "FR|FL|USR63" layout with AV_CHAN_BACK_CENTER: -1
+
+Testing av_channel_layout_channel_from_index
+On "FR|FL|USR63" layout with 0:                    1
+On "FR|FL|USR63" layout with 1:                    0
+On "FR|FL|USR63" layout with 2:                   63
+On "FR|FL|USR63" layout with 3:                   -1
-- 
2.34.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [FFmpeg-devel] [PATCH 001/279 v2] Add a new channel layout API
  2021-12-16 13:21 ` [FFmpeg-devel] [PATCH 001/279 v2] Add a new " James Almer
@ 2021-12-16 17:20   ` Paul B Mahol
  2021-12-16 18:27     ` James Almer
  2021-12-16 23:27   ` Marton Balint
  1 sibling, 1 reply; 20+ messages in thread
From: Paul B Mahol @ 2021-12-16 17:20 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

You can not use '|' as separator for channel layout definition.
Use '+' instead.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [FFmpeg-devel] [PATCH 001/279 v2] Add a new channel layout API
  2021-12-16 17:20   ` Paul B Mahol
@ 2021-12-16 18:27     ` James Almer
  2021-12-16 18:31       ` Paul B Mahol
  0 siblings, 1 reply; 20+ messages in thread
From: James Almer @ 2021-12-16 18:27 UTC (permalink / raw)
  To: ffmpeg-devel



On 12/16/2021 2:20 PM, Paul B Mahol wrote:
> You can not use '|' as separator for channel layout definition.
> Use '+' instead.

Is there a technical reason, or just a preference?
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [FFmpeg-devel] [PATCH 001/279 v2] Add a new channel layout API
  2021-12-16 18:27     ` James Almer
@ 2021-12-16 18:31       ` Paul B Mahol
  2021-12-16 19:14         ` James Almer
  0 siblings, 1 reply; 20+ messages in thread
From: Paul B Mahol @ 2021-12-16 18:31 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

On Thu, Dec 16, 2021 at 7:28 PM James Almer <jamrial@gmail.com> wrote:

>
>
> On 12/16/2021 2:20 PM, Paul B Mahol wrote:
> > You can not use '|' as separator for channel layout definition.
> > Use '+' instead.
>
> Is there a technical reason, or just a preference?
>

Only for cases when you need to provide multiple channel layouts at once as
string.
How it is currently done with this set?


> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [FFmpeg-devel] [PATCH 001/279 v2] Add a new channel layout API
  2021-12-16 18:31       ` Paul B Mahol
@ 2021-12-16 19:14         ` James Almer
  0 siblings, 0 replies; 20+ messages in thread
From: James Almer @ 2021-12-16 19:14 UTC (permalink / raw)
  To: ffmpeg-devel



On 12/16/2021 3:31 PM, Paul B Mahol wrote:
> On Thu, Dec 16, 2021 at 7:28 PM James Almer <jamrial@gmail.com> wrote:
> 
>>
>>
>> On 12/16/2021 2:20 PM, Paul B Mahol wrote:
>>> You can not use '|' as separator for channel layout definition.
>>> Use '+' instead.
>>
>> Is there a technical reason, or just a preference?
>>
> 
> Only for cases when you need to provide multiple channel layouts at once as
> string.
> How it is currently done with this set?

Mmh, guess you're right. aformat uses | to split layouts, so it would 
break if you pass it a combination of channels instead of a mask or a 
standard layout name. So we may need to use +.

> 
> 
>> _______________________________________________
>> ffmpeg-devel mailing list
>> ffmpeg-devel@ffmpeg.org
>> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>>
>> To unsubscribe, visit link above, or email
>> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [FFmpeg-devel] [PATCH 001/279 v2] Add a new channel layout API
  2021-12-16 13:21 ` [FFmpeg-devel] [PATCH 001/279 v2] Add a new " James Almer
  2021-12-16 17:20   ` Paul B Mahol
@ 2021-12-16 23:27   ` Marton Balint
  2021-12-17  2:34     ` James Almer
  2021-12-17 12:43     ` James Almer
  1 sibling, 2 replies; 20+ messages in thread
From: Marton Balint @ 2021-12-16 23:27 UTC (permalink / raw)
  To: FFmpeg development discussions and patches



On Thu, 16 Dec 2021, James Almer wrote:

> - Added a 16 byte fixed array to AVChannelCustom to give custom
>  labels to channels in Custom order layouts. These labes will
>  be used by the helpers when querying channels by name or
>  describing the layout.

I don't think this is a good idea to use the labels directly in helpers 
instead of the channel designation names. See more below.

It is also not great that if the user wants to label a channel, he has to 
use a custom layout. So I'd rather remove the name field from 
AVChannelCustom, I find it limited anyway.

[..]

> +enum AVChannel av_channel_from_string(const char *str)
> +{
> +    int i;
> +    char *endptr = (char *)str;
> +    enum AVChannel id = AV_CHAN_NONE;
> +    for (i = 0; i < FF_ARRAY_ELEMS(channel_names); i++) {
> +        if (channel_names[i].name && !strcmp(str, channel_names[i].name))
> +            return i;
> +    }
> +    if (!strncmp(str, "USR", 3)) {
> +        const char *p = str + 3;
> +        id = strtol(p, &endptr, 0);
> +    }
> +    if (id > 0 && !*endptr)

id >= 0

[..]


> +int av_channel_layout_from_mask(AVChannelLayout *channel_layout,
> +                                uint64_t mask)
> +{
> +    if (!mask)
> +        return AVERROR(EINVAL);
> +
> +    channel_layout->order       = AV_CHANNEL_ORDER_NATIVE;
> +    channel_layout->nb_channels = av_popcount64(mask);
> +    channel_layout->u.mask      = mask;
> +
> +    return 0;
> +}

Probably a constructor for custom layout would also make sense:

int av_channel_layout_custom(AVChannelLayout *channel_layout, int nb_channels)

[...]

> +
> +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));

av_malloc_array()

> +int av_channel_layout_describe_bprint(const AVChannelLayout *channel_layout,
> +                                      AVBPrint *bp)
> +{
> +    int i;
> +
> +    av_bprint_clear(bp);
> +
> +    switch (channel_layout->order) {
> +    case AV_CHANNEL_ORDER_NATIVE:
> +        for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); i++)
> +            if (channel_layout->u.mask == channel_layout_map[i].layout.u.mask) {
> +                av_bprintf(bp, "%s", channel_layout_map[i].name);
> +                return 0;
> +            }
> +        // fall-through
> +    case AV_CHANNEL_ORDER_CUSTOM:
> +        for (i = 0; i < channel_layout->nb_channels; i++) {
> +            const char *ch_name = NULL;
> +            enum AVChannel ch = AV_CHAN_NONE;
> +
> +            if (channel_layout->order == AV_CHANNEL_ORDER_CUSTOM &&
> +                channel_layout->u.map[i].name[0])
> +                ch_name = channel_layout->u.map[i].name;
> +            if (channel_layout->order == AV_CHANNEL_ORDER_NATIVE || !ch_name) {
> +                ch = av_channel_layout_channel_from_index(channel_layout, i);
> +                ch_name = get_channel_name(ch);
> +            }

You are mixing channel labels and channel designations, and it can be the 
source of confusion. I guess the main problem is that the label of the 
channel can be totally unrelated to the channel designation.

You could show it as some combination. E.g. FL@label. This way there 
will be no confusion, that part before @ is the designation, part after 
the @ is the channel label.

[..]

> +enum AVChannel
> +av_channel_layout_channel_from_string(const AVChannelLayout *channel_layout,
> +                                      const char *name)
> +{
> +    int channel, ret;
> +
> +    switch (channel_layout->order) {
> +    case AV_CHANNEL_ORDER_CUSTOM:
> +        for (int i = 0; i < channel_layout->nb_channels; i++) {
> +            if (channel_layout->u.map[i].name[0] && !strcmp(name, channel_layout->u.map[i].name))
> +                return channel_layout->u.map[i].id;

This is the reverse case, I also find it confusing that name can be a 
label and a designation at the same time and it depends on the channel 
layout type which one is it... Yet again, some syntax could help. E.g. a 
string without @ is a designation, @label is a label without any filter 
for channel designation, designation@label filters both.

[..]

> +int av_channel_layout_index_from_string(const AVChannelLayout *channel_layout,
> +                                        const char *name)
> +{
> +    enum AVChannel ch;
> +
> +    switch (channel_layout->order) {
> +    case AV_CHANNEL_ORDER_CUSTOM:
> +        for (int i = 0; i < channel_layout->nb_channels; i++) {
> +            if (channel_layout->u.map[i].name[0] && !strcmp(name, channel_layout->u.map[i].name))
> +                return i;

Same here.

[..]

> +int av_channel_layout_check(const AVChannelLayout *channel_layout)

av_channel_layout_valid would be more readable.

Thanks,
Marton
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [FFmpeg-devel] [PATCH 000/279 v2] New channel layout API
  2021-12-16 13:21 [FFmpeg-devel] [PATCH 000/279 v2] New channel layout API James Almer
  2021-12-16 13:21 ` [FFmpeg-devel] [PATCH 001/279 v2] Add a new " James Almer
  2021-12-16 13:21 ` [FFmpeg-devel] [PATCH 002/279 v2] fate: add a channel_layout API test James Almer
@ 2021-12-17  0:04 ` Marton Balint
  2021-12-17  2:37   ` James Almer
  2021-12-17 11:24   ` Michael Niedermayer
  2 siblings, 2 replies; 20+ messages in thread
From: Marton Balint @ 2021-12-17  0:04 UTC (permalink / raw)
  To: FFmpeg development discussions and patches



On Thu, 16 Dec 2021, James Almer wrote:

> Resending the first two patches only, since this is meant to
> show the implementation of one of the several suggestions made
> in the previous set that need to be discussed and hopefully
> resolved in a call.

Can you push the full branch somewhere?

>
> The proposals so far to extend the API to support either custom
> labels for channels are, or some form of extra user information.
>
> - Fixed array of bytes to hold a label. Simple solution, but
>  the labels will have a hard limit that can only be extended
>  with a major bump. This is what i implemented in this version.
> - "char *name" per channel that the user may allocate and the
>  API will manage, duplicate and free. Simple solution, and the
>  name can be arbitrarily long, but inefficient (av_strdup() per
>  channel with a custom label on layout copy).
> - "const char *name" per channel for compile time constants, or
>  that the user may allocate and free. Very efficient, but for
>  non compile time strings ensuring they outlive the layout can
>  be tricky.
> - Refcounted AVChannelCustom with a dictionary. This can't be
>  done with AVBufferRef, so it would require some other form
>  of reference counting. And a dictionary may add quite a bit of
>  complexity to the API, as you can set anything on them.

Until we have proper refcounting API we can make the AVBufferRef in 
AVChannelLayout a void *, and only allow channel_layout functions to 
dereference it as an AVBufferRef. This would mean adding some extra 
helper functions to channel layout, but overall it is not unsolvable.

The real question is that if you want to use refcounting and add helpers 
to query / replace per-channel metadata, or you find the idea too heavy 
weight and would like to stick to flat structs.

> - Opaque id/s or pointer/s that the API will not touch beyond
>  passing them around (So unlike the above, the helpers would not
>  benefit from this). This can be combined with any of the above,
>  too, and i did as much in this version.
> - Leave API as it was in v1.

Maybe it is not said enough times, but thanks to everybody who worked on 
this. It certainly was huge work, and I know that it is a thankless effort 
to get such a big change merged. Any change based on my suggestions is 
appreciated, even if some of my ideas get rejected in the end.

Thanks,
Marton
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [FFmpeg-devel] [PATCH 001/279 v2] Add a new channel layout API
  2021-12-16 23:27   ` Marton Balint
@ 2021-12-17  2:34     ` James Almer
  2021-12-17 12:43     ` James Almer
  1 sibling, 0 replies; 20+ messages in thread
From: James Almer @ 2021-12-17  2:34 UTC (permalink / raw)
  To: ffmpeg-devel

On 12/16/2021 8:27 PM, Marton Balint wrote:
> 
> 
> On Thu, 16 Dec 2021, James Almer wrote:
> 
>> - Added a 16 byte fixed array to AVChannelCustom to give custom
>>  labels to channels in Custom order layouts. These labes will
>>  be used by the helpers when querying channels by name or
>>  describing the layout.
> 
> I don't think this is a good idea to use the labels directly in helpers 
> instead of the channel designation names. See more below.
> 
> It is also not great that if the user wants to label a channel, he has 
> to use a custom layout. So I'd rather remove the name field from 
> AVChannelCustom, I find it limited anyway.
> 
> [..]
> 
>> +enum AVChannel av_channel_from_string(const char *str)
>> +{
>> +    int i;
>> +    char *endptr = (char *)str;
>> +    enum AVChannel id = AV_CHAN_NONE;
>> +    for (i = 0; i < FF_ARRAY_ELEMS(channel_names); i++) {
>> +        if (channel_names[i].name && !strcmp(str, 
>> channel_names[i].name))
>> +            return i;
>> +    }
>> +    if (!strncmp(str, "USR", 3)) {
>> +        const char *p = str + 3;
>> +        id = strtol(p, &endptr, 0);
>> +    }
>> +    if (id > 0 && !*endptr)
> 
> id >= 0
> 
> [..]
> 
> 
>> +int av_channel_layout_from_mask(AVChannelLayout *channel_layout,
>> +                                uint64_t mask)
>> +{
>> +    if (!mask)
>> +        return AVERROR(EINVAL);
>> +
>> +    channel_layout->order       = AV_CHANNEL_ORDER_NATIVE;
>> +    channel_layout->nb_channels = av_popcount64(mask);
>> +    channel_layout->u.mask      = mask;
>> +
>> +    return 0;
>> +}
> 
> Probably a constructor for custom layout would also make sense:
> 
> int av_channel_layout_custom(AVChannelLayout *channel_layout, int 
> nb_channels)
> 
> [...]
> 
>> +
>> +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));
> 
> av_malloc_array()
> 
>> +int av_channel_layout_describe_bprint(const AVChannelLayout 
>> *channel_layout,
>> +                                      AVBPrint *bp)
>> +{
>> +    int i;
>> +
>> +    av_bprint_clear(bp);
>> +
>> +    switch (channel_layout->order) {
>> +    case AV_CHANNEL_ORDER_NATIVE:
>> +        for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); i++)
>> +            if (channel_layout->u.mask == 
>> channel_layout_map[i].layout.u.mask) {
>> +                av_bprintf(bp, "%s", channel_layout_map[i].name);
>> +                return 0;
>> +            }
>> +        // fall-through
>> +    case AV_CHANNEL_ORDER_CUSTOM:
>> +        for (i = 0; i < channel_layout->nb_channels; i++) {
>> +            const char *ch_name = NULL;
>> +            enum AVChannel ch = AV_CHAN_NONE;
>> +
>> +            if (channel_layout->order == AV_CHANNEL_ORDER_CUSTOM &&
>> +                channel_layout->u.map[i].name[0])
>> +                ch_name = channel_layout->u.map[i].name;
>> +            if (channel_layout->order == AV_CHANNEL_ORDER_NATIVE || 
>> !ch_name) {
>> +                ch = 
>> av_channel_layout_channel_from_index(channel_layout, i);
>> +                ch_name = get_channel_name(ch);
>> +            }
> 
> You are mixing channel labels and channel designations, and it can be 
> the source of confusion. I guess the main problem is that the label of 
> the channel can be totally unrelated to the channel designation.
> 
> You could show it as some combination. E.g. FL@label. This way there 
> will be no confusion, that part before @ is the designation, part after 
> the @ is the channel label.

The custom names are meant for channels without a known name. If you 
want to call FL something else you can, and address it by it or FL, but 
it's not the main objective.

> 
> [..]
> 
>> +enum AVChannel
>> +av_channel_layout_channel_from_string(const AVChannelLayout 
>> *channel_layout,
>> +                                      const char *name)
>> +{
>> +    int channel, ret;
>> +
>> +    switch (channel_layout->order) {
>> +    case AV_CHANNEL_ORDER_CUSTOM:
>> +        for (int i = 0; i < channel_layout->nb_channels; i++) {
>> +            if (channel_layout->u.map[i].name[0] && !strcmp(name, 
>> channel_layout->u.map[i].name))
>> +                return channel_layout->u.map[i].id;
> 
> This is the reverse case, I also find it confusing that name can be a 
> label and a designation at the same time and it depends on the channel 
> layout type which one is it... Yet again, some syntax could help. E.g. a 
> string without @ is a designation, @label is a label without any filter 
> for channel designation, designation@label filters both.

Again, the custom names are not meant to be something separate from the 
standard names. The latter exists for like 25 ids, so adding custom 
names will let you address the rest in some form.

> 
> [..]
> 
>> +int av_channel_layout_index_from_string(const AVChannelLayout 
>> *channel_layout,
>> +                                        const char *name)
>> +{
>> +    enum AVChannel ch;
>> +
>> +    switch (channel_layout->order) {
>> +    case AV_CHANNEL_ORDER_CUSTOM:
>> +        for (int i = 0; i < channel_layout->nb_channels; i++) {
>> +            if (channel_layout->u.map[i].name[0] && !strcmp(name, 
>> channel_layout->u.map[i].name))
>> +                return i;
> 
> Same here.
> 
> [..]
> 
>> +int av_channel_layout_check(const AVChannelLayout *channel_layout)
> 
> av_channel_layout_valid would be more readable.

Ok.

> 
> Thanks,
> Marton
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [FFmpeg-devel] [PATCH 000/279 v2] New channel layout API
  2021-12-17  0:04 ` [FFmpeg-devel] [PATCH 000/279 v2] New channel layout API Marton Balint
@ 2021-12-17  2:37   ` James Almer
  2021-12-17 19:20     ` Marton Balint
  2021-12-17 11:24   ` Michael Niedermayer
  1 sibling, 1 reply; 20+ messages in thread
From: James Almer @ 2021-12-17  2:37 UTC (permalink / raw)
  To: ffmpeg-devel



On 12/16/2021 9:04 PM, Marton Balint wrote:
> 
> 
> On Thu, 16 Dec 2021, James Almer wrote:
> 
>> Resending the first two patches only, since this is meant to
>> show the implementation of one of the several suggestions made
>> in the previous set that need to be discussed and hopefully
>> resolved in a call.
> 
> Can you push the full branch somewhere?

Just force pushed the latest version to the same repo as last time in 
https://github.com/jamrial/FFmpeg/commits/channel_layout

> 
>>
>> The proposals so far to extend the API to support either custom
>> labels for channels are, or some form of extra user information.
>>
>> - Fixed array of bytes to hold a label. Simple solution, but
>>  the labels will have a hard limit that can only be extended
>>  with a major bump. This is what i implemented in this version.
>> - "char *name" per channel that the user may allocate and the
>>  API will manage, duplicate and free. Simple solution, and the
>>  name can be arbitrarily long, but inefficient (av_strdup() per
>>  channel with a custom label on layout copy).
>> - "const char *name" per channel for compile time constants, or
>>  that the user may allocate and free. Very efficient, but for
>>  non compile time strings ensuring they outlive the layout can
>>  be tricky.
>> - Refcounted AVChannelCustom with a dictionary. This can't be
>>  done with AVBufferRef, so it would require some other form
>>  of reference counting. And a dictionary may add quite a bit of
>>  complexity to the API, as you can set anything on them.
> 
> Until we have proper refcounting API we can make the AVBufferRef in 
> AVChannelLayout a void *, and only allow channel_layout functions to 
> dereference it as an AVBufferRef. This would mean adding some extra 
> helper functions to channel layout, but overall it is not unsolvable.
> 
> The real question is that if you want to use refcounting and add helpers 
> to query / replace per-channel metadata, or you find the idea too heavy 
> weight and would like to stick to flat structs.
> 
>> - Opaque id/s or pointer/s that the API will not touch beyond
>>  passing them around (So unlike the above, the helpers would not
>>  benefit from this). This can be combined with any of the above,
>>  too, and i did as much in this version.
>> - Leave API as it was in v1.
> 
> Maybe it is not said enough times, but thanks to everybody who worked on 
> this. It certainly was huge work, and I know that it is a thankless 
> effort to get such a big change merged. Any change based on my 
> suggestions is appreciated, even if some of my ideas get rejected in the 
> end.
> 
> Thanks,
> Marton
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [FFmpeg-devel] [PATCH 000/279 v2] New channel layout API
  2021-12-17  0:04 ` [FFmpeg-devel] [PATCH 000/279 v2] New channel layout API Marton Balint
  2021-12-17  2:37   ` James Almer
@ 2021-12-17 11:24   ` Michael Niedermayer
  2021-12-17 18:04     ` Marton Balint
  1 sibling, 1 reply; 20+ messages in thread
From: Michael Niedermayer @ 2021-12-17 11:24 UTC (permalink / raw)
  To: FFmpeg development discussions and patches


[-- Attachment #1.1: Type: text/plain, Size: 2520 bytes --]

On Fri, Dec 17, 2021 at 01:04:19AM +0100, Marton Balint wrote:
> 
> 
> On Thu, 16 Dec 2021, James Almer wrote:
> 
> > Resending the first two patches only, since this is meant to
> > show the implementation of one of the several suggestions made
> > in the previous set that need to be discussed and hopefully
> > resolved in a call.
> 
> Can you push the full branch somewhere?
> 
> > 
> > The proposals so far to extend the API to support either custom
> > labels for channels are, or some form of extra user information.
> > 
> > - Fixed array of bytes to hold a label. Simple solution, but
> >  the labels will have a hard limit that can only be extended
> >  with a major bump. This is what i implemented in this version.
> > - "char *name" per channel that the user may allocate and the
> >  API will manage, duplicate and free. Simple solution, and the
> >  name can be arbitrarily long, but inefficient (av_strdup() per
> >  channel with a custom label on layout copy).
> > - "const char *name" per channel for compile time constants, or
> >  that the user may allocate and free. Very efficient, but for
> >  non compile time strings ensuring they outlive the layout can
> >  be tricky.
> > - Refcounted AVChannelCustom with a dictionary. This can't be
> >  done with AVBufferRef, so it would require some other form
> >  of reference counting. And a dictionary may add quite a bit of
> >  complexity to the API, as you can set anything on them.
> 
> Until we have proper refcounting API we can make the AVBufferRef in
> AVChannelLayout a void *, and only allow channel_layout functions to
> dereference it as an AVBufferRef. This would mean adding some extra helper
> functions to channel layout, but overall it is not unsolvable.
> 
> The real question is that if you want to use refcounting and add helpers to
> query / replace per-channel metadata, or you find the idea too heavy weight
> and would like to stick to flat structs.

what is the advantage of refcounting for channel metadata ?
is it about the used memory, about the reduced need to copy ?

what kind of metadata and what size do you expect ?
bytes, kilobytes, megabytes, gigabytes per channel ?

what is the overhead for dynamic allocation and ref counting?
that is at which point does it even make sense ?

thx

[...]

-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Nations do behave wisely once they have exhausted all other alternatives. 
-- Abba Eban

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

[-- Attachment #2: Type: text/plain, Size: 251 bytes --]

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [FFmpeg-devel] [PATCH 001/279 v2] Add a new channel layout API
  2021-12-16 23:27   ` Marton Balint
  2021-12-17  2:34     ` James Almer
@ 2021-12-17 12:43     ` James Almer
  1 sibling, 0 replies; 20+ messages in thread
From: James Almer @ 2021-12-17 12:43 UTC (permalink / raw)
  To: ffmpeg-devel



On 12/16/2021 8:27 PM, Marton Balint wrote:
> 
> 
> On Thu, 16 Dec 2021, James Almer wrote:
> 
>> - Added a 16 byte fixed array to AVChannelCustom to give custom
>>  labels to channels in Custom order layouts. These labes will
>>  be used by the helpers when querying channels by name or
>>  describing the layout.
> 
> I don't think this is a good idea to use the labels directly in helpers 
> instead of the channel designation names. See more below.
> 
> It is also not great that if the user wants to label a channel, he has 
> to use a custom layout. So I'd rather remove the name field from 
> AVChannelCustom, I find it limited anyway.
> 
> [..]
> 
>> +enum AVChannel av_channel_from_string(const char *str)
>> +{
>> +    int i;
>> +    char *endptr = (char *)str;
>> +    enum AVChannel id = AV_CHAN_NONE;
>> +    for (i = 0; i < FF_ARRAY_ELEMS(channel_names); i++) {
>> +        if (channel_names[i].name && !strcmp(str, 
>> channel_names[i].name))
>> +            return i;
>> +    }
>> +    if (!strncmp(str, "USR", 3)) {
>> +        const char *p = str + 3;
>> +        id = strtol(p, &endptr, 0);
>> +    }
>> +    if (id > 0 && !*endptr)
> 
> id >= 0
> 
> [..]
> 
> 
>> +int av_channel_layout_from_mask(AVChannelLayout *channel_layout,
>> +                                uint64_t mask)
>> +{
>> +    if (!mask)
>> +        return AVERROR(EINVAL);
>> +
>> +    channel_layout->order       = AV_CHANNEL_ORDER_NATIVE;
>> +    channel_layout->nb_channels = av_popcount64(mask);
>> +    channel_layout->u.mask      = mask;
>> +
>> +    return 0;
>> +}
> 
> Probably a constructor for custom layout would also make sense:
> 
> int av_channel_layout_custom(AVChannelLayout *channel_layout, int 
> nb_channels)

Doesn't seem too useful to me. It will basically just call av_malloc for 
u.map for you. You still need to fill the array with the channels in the 
order you want it, unlike av_channel_layout_from_mask() which gives you 
a usable layout directly on return.

You can use av_channel_layout_from_string() for this instead, thanks to 
your suggestion to use generic USR%d designations for no-name ids. In 
the tests from patch 2 i have a couple examples of it.

> 
> [...]
> 
>> +
>> +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));
> 
> av_malloc_array()
> 
>> +int av_channel_layout_describe_bprint(const AVChannelLayout 
>> *channel_layout,
>> +                                      AVBPrint *bp)
>> +{
>> +    int i;
>> +
>> +    av_bprint_clear(bp);
>> +
>> +    switch (channel_layout->order) {
>> +    case AV_CHANNEL_ORDER_NATIVE:
>> +        for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); i++)
>> +            if (channel_layout->u.mask == 
>> channel_layout_map[i].layout.u.mask) {
>> +                av_bprintf(bp, "%s", channel_layout_map[i].name);
>> +                return 0;
>> +            }
>> +        // fall-through
>> +    case AV_CHANNEL_ORDER_CUSTOM:
>> +        for (i = 0; i < channel_layout->nb_channels; i++) {
>> +            const char *ch_name = NULL;
>> +            enum AVChannel ch = AV_CHAN_NONE;
>> +
>> +            if (channel_layout->order == AV_CHANNEL_ORDER_CUSTOM &&
>> +                channel_layout->u.map[i].name[0])
>> +                ch_name = channel_layout->u.map[i].name;
>> +            if (channel_layout->order == AV_CHANNEL_ORDER_NATIVE || 
>> !ch_name) {
>> +                ch = 
>> av_channel_layout_channel_from_index(channel_layout, i);
>> +                ch_name = get_channel_name(ch);
>> +            }
> 
> You are mixing channel labels and channel designations, and it can be 
> the source of confusion. I guess the main problem is that the label of 
> the channel can be totally unrelated to the channel designation.
> 
> You could show it as some combination. E.g. FL@label. This way there 
> will be no confusion, that part before @ is the designation, part after 
> the @ is the channel label.
> 
> [..]
> 
>> +enum AVChannel
>> +av_channel_layout_channel_from_string(const AVChannelLayout 
>> *channel_layout,
>> +                                      const char *name)
>> +{
>> +    int channel, ret;
>> +
>> +    switch (channel_layout->order) {
>> +    case AV_CHANNEL_ORDER_CUSTOM:
>> +        for (int i = 0; i < channel_layout->nb_channels; i++) {
>> +            if (channel_layout->u.map[i].name[0] && !strcmp(name, 
>> channel_layout->u.map[i].name))
>> +                return channel_layout->u.map[i].id;
> 
> This is the reverse case, I also find it confusing that name can be a 
> label and a designation at the same time and it depends on the channel 
> layout type which one is it... Yet again, some syntax could help. E.g. a 
> string without @ is a designation, @label is a label without any filter 
> for channel designation, designation@label filters both.
> 
> [..]
> 
>> +int av_channel_layout_index_from_string(const AVChannelLayout 
>> *channel_layout,
>> +                                        const char *name)
>> +{
>> +    enum AVChannel ch;
>> +
>> +    switch (channel_layout->order) {
>> +    case AV_CHANNEL_ORDER_CUSTOM:
>> +        for (int i = 0; i < channel_layout->nb_channels; i++) {
>> +            if (channel_layout->u.map[i].name[0] && !strcmp(name, 
>> channel_layout->u.map[i].name))
>> +                return i;
> 
> Same here.
> 
> [..]
> 
>> +int av_channel_layout_check(const AVChannelLayout *channel_layout)
> 
> av_channel_layout_valid would be more readable.
> 
> Thanks,
> Marton
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [FFmpeg-devel] [PATCH 000/279 v2] New channel layout API
  2021-12-17 11:24   ` Michael Niedermayer
@ 2021-12-17 18:04     ` Marton Balint
  2021-12-18 13:36       ` Michael Niedermayer
  0 siblings, 1 reply; 20+ messages in thread
From: Marton Balint @ 2021-12-17 18:04 UTC (permalink / raw)
  To: FFmpeg development discussions and patches



On Fri, 17 Dec 2021, Michael Niedermayer wrote:

> On Fri, Dec 17, 2021 at 01:04:19AM +0100, Marton Balint wrote:
>>
>>
>> On Thu, 16 Dec 2021, James Almer wrote:
>>
>>> Resending the first two patches only, since this is meant to
>>> show the implementation of one of the several suggestions made
>>> in the previous set that need to be discussed and hopefully
>>> resolved in a call.
>>
>> Can you push the full branch somewhere?
>>
>>>
>>> The proposals so far to extend the API to support either custom
>>> labels for channels are, or some form of extra user information.
>>>
>>> - Fixed array of bytes to hold a label. Simple solution, but
>>>  the labels will have a hard limit that can only be extended
>>>  with a major bump. This is what i implemented in this version.
>>> - "char *name" per channel that the user may allocate and the
>>>  API will manage, duplicate and free. Simple solution, and the
>>>  name can be arbitrarily long, but inefficient (av_strdup() per
>>>  channel with a custom label on layout copy).
>>> - "const char *name" per channel for compile time constants, or
>>>  that the user may allocate and free. Very efficient, but for
>>>  non compile time strings ensuring they outlive the layout can
>>>  be tricky.
>>> - Refcounted AVChannelCustom with a dictionary. This can't be
>>>  done with AVBufferRef, so it would require some other form
>>>  of reference counting. And a dictionary may add quite a bit of
>>>  complexity to the API, as you can set anything on them.
>>
>> Until we have proper refcounting API we can make the AVBufferRef in
>> AVChannelLayout a void *, and only allow channel_layout functions to
>> dereference it as an AVBufferRef. This would mean adding some extra helper
>> functions to channel layout, but overall it is not unsolvable.
>>
>> The real question is that if you want to use refcounting and add helpers to
>> query / replace per-channel metadata, or you find the idea too heavy weight
>> and would like to stick to flat structs.
>
> what is the advantage of refcounting for channel metadata ?
> is it about the used memory, about the reduced need to copy ?

Basicly it is the ability to store per-channel metadata in avdictionary, 
because otherwise it would have to be copyed, and avdictionary is very 
ineffective at copying because of many mallocs.

>
> what kind of metadata and what size do you expect ?
> bytes, kilobytes, megabytes, gigabytes per channel ?

Usually, nothing, because most format don't have support for per-channel 
metadata. In some cases it is going to be a couple of textual metadata 
key-value pairs, such as language, label, group, speaker, positon, so 4-5 
dynamically allocated string pairs, plus the AVDictionary itself, 
multiplied by the number of channels in a layout.

>
> what is the overhead for dynamic allocation and ref counting?
> that is at which point does it even make sense ?

I don't have exact measurements. It is generally felt that copying 
AVDictionary per-channel is a huge overhead for something as lightweight 
as an audio frame which is a 2-4 kB per channel at most and only a couple 
of allocs usually not dependant on the number of channels. That's why 
refcounting was proposed.

Also some people simply don't want to store extendable channel metadata in 
channel layout, and want to keep it simple.

Regards,
Marton
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [FFmpeg-devel] [PATCH 000/279 v2] New channel layout API
  2021-12-17  2:37   ` James Almer
@ 2021-12-17 19:20     ` Marton Balint
  2021-12-17 19:32       ` James Almer
  0 siblings, 1 reply; 20+ messages in thread
From: Marton Balint @ 2021-12-17 19:20 UTC (permalink / raw)
  To: FFmpeg development discussions and patches



On Thu, 16 Dec 2021, James Almer wrote:

>
>
> On 12/16/2021 9:04 PM, Marton Balint wrote:
>>
>>
>>  On Thu, 16 Dec 2021, James Almer wrote:
>>
>>>  Resending the first two patches only, since this is meant to
>>>  show the implementation of one of the several suggestions made
>>>  in the previous set that need to be discussed and hopefully
>>>  resolved in a call.
>>
>>  Can you push the full branch somewhere?
>
> Just force pushed the latest version to the same repo as last time in 
> https://github.com/jamrial/FFmpeg/commits/channel_layout

Can you check the libfdk-aac patch? The decoder has some garbage text 
before the drc_boost context variable, the encoder does not compile with 
gcc because of the deprecation warning pragmas at the very end of the 
file.

Thanks,
Marton
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [FFmpeg-devel] [PATCH 000/279 v2] New channel layout API
  2021-12-17 19:20     ` Marton Balint
@ 2021-12-17 19:32       ` James Almer
  0 siblings, 0 replies; 20+ messages in thread
From: James Almer @ 2021-12-17 19:32 UTC (permalink / raw)
  To: ffmpeg-devel



On 12/17/2021 4:20 PM, Marton Balint wrote:
> 
> 
> On Thu, 16 Dec 2021, James Almer wrote:
> 
>>
>>
>> On 12/16/2021 9:04 PM, Marton Balint wrote:
>>>
>>>
>>>  On Thu, 16 Dec 2021, James Almer wrote:
>>>
>>>>  Resending the first two patches only, since this is meant to
>>>>  show the implementation of one of the several suggestions made
>>>>  in the previous set that need to be discussed and hopefully
>>>>  resolved in a call.
>>>
>>>  Can you push the full branch somewhere?
>>
>> Just force pushed the latest version to the same repo as last time in 
>> https://github.com/jamrial/FFmpeg/commits/channel_layout
> 
> Can you check the libfdk-aac patch? The decoder has some garbage text 
> before the drc_boost context variable, the encoder does not compile with 
> gcc because of the deprecation warning pragmas at the very end of the file.
> 
> Thanks,
> Marton

Should be fixed, sorry about that.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [FFmpeg-devel] [PATCH 000/279 v2] New channel layout API
  2021-12-17 18:04     ` Marton Balint
@ 2021-12-18 13:36       ` Michael Niedermayer
  2021-12-18 14:15         ` Michael Niedermayer
  0 siblings, 1 reply; 20+ messages in thread
From: Michael Niedermayer @ 2021-12-18 13:36 UTC (permalink / raw)
  To: FFmpeg development discussions and patches


[-- Attachment #1.1: Type: text/plain, Size: 4010 bytes --]

On Fri, Dec 17, 2021 at 07:04:08PM +0100, Marton Balint wrote:
> 
> 
> On Fri, 17 Dec 2021, Michael Niedermayer wrote:
> 
> > On Fri, Dec 17, 2021 at 01:04:19AM +0100, Marton Balint wrote:
> > > 
> > > 
> > > On Thu, 16 Dec 2021, James Almer wrote:
> > > 
> > > > Resending the first two patches only, since this is meant to
> > > > show the implementation of one of the several suggestions made
> > > > in the previous set that need to be discussed and hopefully
> > > > resolved in a call.
> > > 
> > > Can you push the full branch somewhere?
> > > 
> > > > 
> > > > The proposals so far to extend the API to support either custom
> > > > labels for channels are, or some form of extra user information.
> > > > 
> > > > - Fixed array of bytes to hold a label. Simple solution, but
> > > >  the labels will have a hard limit that can only be extended
> > > >  with a major bump. This is what i implemented in this version.
> > > > - "char *name" per channel that the user may allocate and the
> > > >  API will manage, duplicate and free. Simple solution, and the
> > > >  name can be arbitrarily long, but inefficient (av_strdup() per
> > > >  channel with a custom label on layout copy).
> > > > - "const char *name" per channel for compile time constants, or
> > > >  that the user may allocate and free. Very efficient, but for
> > > >  non compile time strings ensuring they outlive the layout can
> > > >  be tricky.
> > > > - Refcounted AVChannelCustom with a dictionary. This can't be
> > > >  done with AVBufferRef, so it would require some other form
> > > >  of reference counting. And a dictionary may add quite a bit of
> > > >  complexity to the API, as you can set anything on them.
> > > 
> > > Until we have proper refcounting API we can make the AVBufferRef in
> > > AVChannelLayout a void *, and only allow channel_layout functions to
> > > dereference it as an AVBufferRef. This would mean adding some extra helper
> > > functions to channel layout, but overall it is not unsolvable.
> > > 
> > > The real question is that if you want to use refcounting and add helpers to
> > > query / replace per-channel metadata, or you find the idea too heavy weight
> > > and would like to stick to flat structs.
> > 
> > what is the advantage of refcounting for channel metadata ?
> > is it about the used memory, about the reduced need to copy ?
> 
> Basicly it is the ability to store per-channel metadata in avdictionary,
> because otherwise it would have to be copyed, and avdictionary is very
> ineffective at copying because of many mallocs.
> 
> > 
> > what kind of metadata and what size do you expect ?
> > bytes, kilobytes, megabytes, gigabytes per channel ?
> 
> Usually, nothing, because most format don't have support for per-channel
> metadata. In some cases it is going to be a couple of textual metadata
> key-value pairs, such as language, label, group, speaker, positon, so 4-5
> dynamically allocated string pairs, plus the AVDictionary itself, multiplied
> by the number of channels in a layout.
> 
> > 
> > what is the overhead for dynamic allocation and ref counting?
> > that is at which point does it even make sense ?
> 
> I don't have exact measurements. It is generally felt that copying
> AVDictionary per-channel is a huge overhead for something as lightweight as
> an audio frame which is a 2-4 kB per channel at most and only a couple of
> allocs usually not dependant on the number of channels. That's why
> refcounting was proposed.

I was thinking more at a AVStream / AVCodecParameters level.
How will a demuxer transport such metadata over a AVPacket into a decoder
outputting metadata-filled AVFrames?

thx

[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Let us carefully observe those good qualities wherein our enemies excel us
and endeavor to excel them, by avoiding what is faulty, and imitating what
is excellent in them. -- Plutarch

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

[-- Attachment #2: Type: text/plain, Size: 251 bytes --]

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [FFmpeg-devel] [PATCH 000/279 v2] New channel layout API
  2021-12-18 13:36       ` Michael Niedermayer
@ 2021-12-18 14:15         ` Michael Niedermayer
  2021-12-19 11:35           ` Marton Balint
  0 siblings, 1 reply; 20+ messages in thread
From: Michael Niedermayer @ 2021-12-18 14:15 UTC (permalink / raw)
  To: FFmpeg development discussions and patches


[-- Attachment #1.1: Type: text/plain, Size: 4354 bytes --]

On Sat, Dec 18, 2021 at 02:36:12PM +0100, Michael Niedermayer wrote:
> On Fri, Dec 17, 2021 at 07:04:08PM +0100, Marton Balint wrote:
> > 
> > 
> > On Fri, 17 Dec 2021, Michael Niedermayer wrote:
> > 
> > > On Fri, Dec 17, 2021 at 01:04:19AM +0100, Marton Balint wrote:
> > > > 
> > > > 
> > > > On Thu, 16 Dec 2021, James Almer wrote:
> > > > 
> > > > > Resending the first two patches only, since this is meant to
> > > > > show the implementation of one of the several suggestions made
> > > > > in the previous set that need to be discussed and hopefully
> > > > > resolved in a call.
> > > > 
> > > > Can you push the full branch somewhere?
> > > > 
> > > > > 
> > > > > The proposals so far to extend the API to support either custom
> > > > > labels for channels are, or some form of extra user information.
> > > > > 
> > > > > - Fixed array of bytes to hold a label. Simple solution, but
> > > > >  the labels will have a hard limit that can only be extended
> > > > >  with a major bump. This is what i implemented in this version.
> > > > > - "char *name" per channel that the user may allocate and the
> > > > >  API will manage, duplicate and free. Simple solution, and the
> > > > >  name can be arbitrarily long, but inefficient (av_strdup() per
> > > > >  channel with a custom label on layout copy).
> > > > > - "const char *name" per channel for compile time constants, or
> > > > >  that the user may allocate and free. Very efficient, but for
> > > > >  non compile time strings ensuring they outlive the layout can
> > > > >  be tricky.
> > > > > - Refcounted AVChannelCustom with a dictionary. This can't be
> > > > >  done with AVBufferRef, so it would require some other form
> > > > >  of reference counting. And a dictionary may add quite a bit of
> > > > >  complexity to the API, as you can set anything on them.
> > > > 
> > > > Until we have proper refcounting API we can make the AVBufferRef in
> > > > AVChannelLayout a void *, and only allow channel_layout functions to
> > > > dereference it as an AVBufferRef. This would mean adding some extra helper
> > > > functions to channel layout, but overall it is not unsolvable.
> > > > 
> > > > The real question is that if you want to use refcounting and add helpers to
> > > > query / replace per-channel metadata, or you find the idea too heavy weight
> > > > and would like to stick to flat structs.
> > > 
> > > what is the advantage of refcounting for channel metadata ?
> > > is it about the used memory, about the reduced need to copy ?
> > 
> > Basicly it is the ability to store per-channel metadata in avdictionary,
> > because otherwise it would have to be copyed, and avdictionary is very
> > ineffective at copying because of many mallocs.
> > 
> > > 
> > > what kind of metadata and what size do you expect ?
> > > bytes, kilobytes, megabytes, gigabytes per channel ?
> > 
> > Usually, nothing, because most format don't have support for per-channel
> > metadata. In some cases it is going to be a couple of textual metadata
> > key-value pairs, such as language, label, group, speaker, positon, so 4-5
> > dynamically allocated string pairs, plus the AVDictionary itself, multiplied
> > by the number of channels in a layout.
> > 
> > > 
> > > what is the overhead for dynamic allocation and ref counting?
> > > that is at which point does it even make sense ?
> > 
> > I don't have exact measurements. It is generally felt that copying
> > AVDictionary per-channel is a huge overhead for something as lightweight as
> > an audio frame which is a 2-4 kB per channel at most and only a couple of
> > allocs usually not dependant on the number of channels. That's why
> > refcounting was proposed.
> 
> I was thinking more at a AVStream / AVCodecParameters level.

> How will a demuxer transport such metadata over a AVPacket into a decoder
> outputting metadata-filled AVFrames?

or is this never needed ?

thx

[...]

-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Awnsering whenever a program halts or runs forever is
On a turing machine, in general impossible (turings halting problem).
On any real computer, always possible as a real computer has a finite number
of states N, and will either halt in less than N cycles or never halt.

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

[-- Attachment #2: Type: text/plain, Size: 251 bytes --]

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [FFmpeg-devel] [PATCH 000/279 v2] New channel layout API
  2021-12-18 14:15         ` Michael Niedermayer
@ 2021-12-19 11:35           ` Marton Balint
  2021-12-19 12:51             ` Michael Niedermayer
  0 siblings, 1 reply; 20+ messages in thread
From: Marton Balint @ 2021-12-19 11:35 UTC (permalink / raw)
  To: FFmpeg development discussions and patches



On Sat, 18 Dec 2021, Michael Niedermayer wrote:

> On Sat, Dec 18, 2021 at 02:36:12PM +0100, Michael Niedermayer wrote:
>> On Fri, Dec 17, 2021 at 07:04:08PM +0100, Marton Balint wrote:
>>>
>>>
>>> On Fri, 17 Dec 2021, Michael Niedermayer wrote:
>>>
>>>> On Fri, Dec 17, 2021 at 01:04:19AM +0100, Marton Balint wrote:
>>>>>
>>>>>
>>>>> On Thu, 16 Dec 2021, James Almer wrote:
>>>>>
>>>>>> Resending the first two patches only, since this is meant to
>>>>>> show the implementation of one of the several suggestions made
>>>>>> in the previous set that need to be discussed and hopefully
>>>>>> resolved in a call.
>>>>>
>>>>> Can you push the full branch somewhere?
>>>>>
>>>>>>
>>>>>> The proposals so far to extend the API to support either custom
>>>>>> labels for channels are, or some form of extra user information.
>>>>>>
>>>>>> - Fixed array of bytes to hold a label. Simple solution, but
>>>>>>  the labels will have a hard limit that can only be extended
>>>>>>  with a major bump. This is what i implemented in this version.
>>>>>> - "char *name" per channel that the user may allocate and the
>>>>>>  API will manage, duplicate and free. Simple solution, and the
>>>>>>  name can be arbitrarily long, but inefficient (av_strdup() per
>>>>>>  channel with a custom label on layout copy).
>>>>>> - "const char *name" per channel for compile time constants, or
>>>>>>  that the user may allocate and free. Very efficient, but for
>>>>>>  non compile time strings ensuring they outlive the layout can
>>>>>>  be tricky.
>>>>>> - Refcounted AVChannelCustom with a dictionary. This can't be
>>>>>>  done with AVBufferRef, so it would require some other form
>>>>>>  of reference counting. And a dictionary may add quite a bit of
>>>>>>  complexity to the API, as you can set anything on them.
>>>>>
>>>>> Until we have proper refcounting API we can make the AVBufferRef in
>>>>> AVChannelLayout a void *, and only allow channel_layout functions to
>>>>> dereference it as an AVBufferRef. This would mean adding some extra helper
>>>>> functions to channel layout, but overall it is not unsolvable.
>>>>>
>>>>> The real question is that if you want to use refcounting and add helpers to
>>>>> query / replace per-channel metadata, or you find the idea too heavy weight
>>>>> and would like to stick to flat structs.
>>>>
>>>> what is the advantage of refcounting for channel metadata ?
>>>> is it about the used memory, about the reduced need to copy ?
>>>
>>> Basicly it is the ability to store per-channel metadata in avdictionary,
>>> because otherwise it would have to be copyed, and avdictionary is very
>>> ineffective at copying because of many mallocs.
>>>
>>>>
>>>> what kind of metadata and what size do you expect ?
>>>> bytes, kilobytes, megabytes, gigabytes per channel ?
>>>
>>> Usually, nothing, because most format don't have support for per-channel
>>> metadata. In some cases it is going to be a couple of textual metadata
>>> key-value pairs, such as language, label, group, speaker, positon, so 4-5
>>> dynamically allocated string pairs, plus the AVDictionary itself, multiplied
>>> by the number of channels in a layout.
>>>
>>>>
>>>> what is the overhead for dynamic allocation and ref counting?
>>>> that is at which point does it even make sense ?
>>>
>>> I don't have exact measurements. It is generally felt that copying
>>> AVDictionary per-channel is a huge overhead for something as lightweight as
>>> an audio frame which is a 2-4 kB per channel at most and only a couple of
>>> allocs usually not dependant on the number of channels. That's why
>>> refcounting was proposed.
>>
>> I was thinking more at a AVStream / AVCodecParameters level.
>
>> How will a demuxer transport such metadata over a AVPacket into a decoder
>> outputting metadata-filled AVFrames?
>
> or is this never needed ?

I am not sure I understand. Usually metadata is passed from demuxer to 
decoder by avcodec_parameters_to_context(), this is used for all metadata 
which is in AVCodecParameters.

For per-packet metadata ff_decode_frame_props() has some automatic packet 
side data -> frame side data transfer.

AVStream side data may be transferred to AVPacket side data if 
av_format_inject_global_side_data() is used, but it is not enabled by 
default.

Regards,
Marton
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [FFmpeg-devel] [PATCH 000/279 v2] New channel layout API
  2021-12-19 11:35           ` Marton Balint
@ 2021-12-19 12:51             ` Michael Niedermayer
  0 siblings, 0 replies; 20+ messages in thread
From: Michael Niedermayer @ 2021-12-19 12:51 UTC (permalink / raw)
  To: FFmpeg development discussions and patches


[-- Attachment #1.1: Type: text/plain, Size: 6348 bytes --]

On Sun, Dec 19, 2021 at 12:35:11PM +0100, Marton Balint wrote:
> 
> 
> On Sat, 18 Dec 2021, Michael Niedermayer wrote:
> 
> > On Sat, Dec 18, 2021 at 02:36:12PM +0100, Michael Niedermayer wrote:
> > > On Fri, Dec 17, 2021 at 07:04:08PM +0100, Marton Balint wrote:
> > > > 
> > > > 
> > > > On Fri, 17 Dec 2021, Michael Niedermayer wrote:
> > > > 
> > > > > On Fri, Dec 17, 2021 at 01:04:19AM +0100, Marton Balint wrote:
> > > > > > 
> > > > > > 
> > > > > > On Thu, 16 Dec 2021, James Almer wrote:
> > > > > > 
> > > > > > > Resending the first two patches only, since this is meant to
> > > > > > > show the implementation of one of the several suggestions made
> > > > > > > in the previous set that need to be discussed and hopefully
> > > > > > > resolved in a call.
> > > > > > 
> > > > > > Can you push the full branch somewhere?
> > > > > > 
> > > > > > > 
> > > > > > > The proposals so far to extend the API to support either custom
> > > > > > > labels for channels are, or some form of extra user information.
> > > > > > > 
> > > > > > > - Fixed array of bytes to hold a label. Simple solution, but
> > > > > > >  the labels will have a hard limit that can only be extended
> > > > > > >  with a major bump. This is what i implemented in this version.
> > > > > > > - "char *name" per channel that the user may allocate and the
> > > > > > >  API will manage, duplicate and free. Simple solution, and the
> > > > > > >  name can be arbitrarily long, but inefficient (av_strdup() per
> > > > > > >  channel with a custom label on layout copy).
> > > > > > > - "const char *name" per channel for compile time constants, or
> > > > > > >  that the user may allocate and free. Very efficient, but for
> > > > > > >  non compile time strings ensuring they outlive the layout can
> > > > > > >  be tricky.
> > > > > > > - Refcounted AVChannelCustom with a dictionary. This can't be
> > > > > > >  done with AVBufferRef, so it would require some other form
> > > > > > >  of reference counting. And a dictionary may add quite a bit of
> > > > > > >  complexity to the API, as you can set anything on them.
> > > > > > 
> > > > > > Until we have proper refcounting API we can make the AVBufferRef in
> > > > > > AVChannelLayout a void *, and only allow channel_layout functions to
> > > > > > dereference it as an AVBufferRef. This would mean adding some extra helper
> > > > > > functions to channel layout, but overall it is not unsolvable.
> > > > > > 
> > > > > > The real question is that if you want to use refcounting and add helpers to
> > > > > > query / replace per-channel metadata, or you find the idea too heavy weight
> > > > > > and would like to stick to flat structs.
> > > > > 
> > > > > what is the advantage of refcounting for channel metadata ?
> > > > > is it about the used memory, about the reduced need to copy ?
> > > > 
> > > > Basicly it is the ability to store per-channel metadata in avdictionary,
> > > > because otherwise it would have to be copyed, and avdictionary is very
> > > > ineffective at copying because of many mallocs.
> > > > 
> > > > > 
> > > > > what kind of metadata and what size do you expect ?
> > > > > bytes, kilobytes, megabytes, gigabytes per channel ?
> > > > 
> > > > Usually, nothing, because most format don't have support for per-channel
> > > > metadata. In some cases it is going to be a couple of textual metadata
> > > > key-value pairs, such as language, label, group, speaker, positon, so 4-5
> > > > dynamically allocated string pairs, plus the AVDictionary itself, multiplied
> > > > by the number of channels in a layout.
> > > > 
> > > > > 
> > > > > what is the overhead for dynamic allocation and ref counting?
> > > > > that is at which point does it even make sense ?
> > > > 
> > > > I don't have exact measurements. It is generally felt that copying
> > > > AVDictionary per-channel is a huge overhead for something as lightweight as
> > > > an audio frame which is a 2-4 kB per channel at most and only a couple of
> > > > allocs usually not dependant on the number of channels. That's why
> > > > refcounting was proposed.
> > > 
> > > I was thinking more at a AVStream / AVCodecParameters level.
> > 
> > > How will a demuxer transport such metadata over a AVPacket into a decoder
> > > outputting metadata-filled AVFrames?
> > 
> > or is this never needed ?
> 
> I am not sure I understand. Usually metadata is passed from demuxer to
> decoder by avcodec_parameters_to_context(), this is used for all metadata
> which is in AVCodecParameters.
> 

> For per-packet metadata ff_decode_frame_props() has some automatic packet
> side data -> frame side data transfer.
> 
> AVStream side data may be transferred to AVPacket side data if
> av_format_inject_global_side_data() is used, but it is not enabled by
> default.

The sidedata in AVPacket is not channel specific, the data in AVFrames new
channels is.
The later is as you wrote expensive to copy/alloc so it needs ref counting

what i was trying to point to was that if we need a way to transfer this
data on a per packet base from demuxer forward then we need a flat format.
At least with the current AVPackets
And a flat format is much lighter to copy around so then one is pushed
toward the question, "should that be used for AVFrames too?"
a small <10kb audio frame with 8 audio channels and a ref counted dictionary
or whatever per each of the 8 channels vs. a flat description.
an extra is that a flat format is very simple to memcmp() to check if it
changed.
I have no position in this above, iam just wanting to make sure nothing
is missed in this somewhat rushed design.

also theres yet another orthogonal aspect which has been missed i think
This per channel description whatever its form will be is usefull for another
case. And that are the video/image channels. generally this is 
red/green/blue/(alpha) but there is material with other channels, 
IR/NIR/UV/... and i imagine probably depth from some lidar/radar system

Ideally such a future image channel API can share parts with the audio one

thx

[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Opposition brings concord. Out of discord comes the fairest harmony.
-- Heraclitus

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

[-- Attachment #2: Type: text/plain, Size: 251 bytes --]

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2021-12-19 12:51 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-12-16 13:21 [FFmpeg-devel] [PATCH 000/279 v2] New channel layout API James Almer
2021-12-16 13:21 ` [FFmpeg-devel] [PATCH 001/279 v2] Add a new " James Almer
2021-12-16 17:20   ` Paul B Mahol
2021-12-16 18:27     ` James Almer
2021-12-16 18:31       ` Paul B Mahol
2021-12-16 19:14         ` James Almer
2021-12-16 23:27   ` Marton Balint
2021-12-17  2:34     ` James Almer
2021-12-17 12:43     ` James Almer
2021-12-16 13:21 ` [FFmpeg-devel] [PATCH 002/279 v2] fate: add a channel_layout API test James Almer
2021-12-17  0:04 ` [FFmpeg-devel] [PATCH 000/279 v2] New channel layout API Marton Balint
2021-12-17  2:37   ` James Almer
2021-12-17 19:20     ` Marton Balint
2021-12-17 19:32       ` James Almer
2021-12-17 11:24   ` Michael Niedermayer
2021-12-17 18:04     ` Marton Balint
2021-12-18 13:36       ` Michael Niedermayer
2021-12-18 14:15         ` Michael Niedermayer
2021-12-19 11:35           ` Marton Balint
2021-12-19 12:51             ` Michael Niedermayer

Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
		ffmpegdev@gitmailbox.com
	public-inbox-index ffmpegdev

Example config snippet for mirrors.


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git