tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

channel_layout.c (35054B)


      1 /*
      2 * Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
      3 *
      4 * This file is part of FFmpeg.
      5 *
      6 * FFmpeg is free software; you can redistribute it and/or
      7 * modify it under the terms of the GNU Lesser General Public
      8 * License as published by the Free Software Foundation; either
      9 * version 2.1 of the License, or (at your option) any later version.
     10 *
     11 * FFmpeg is distributed in the hope that it will be useful,
     12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14 * Lesser General Public License for more details.
     15 *
     16 * You should have received a copy of the GNU Lesser General Public
     17 * License along with FFmpeg; if not, write to the Free Software
     18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     19 */
     20 
     21 /**
     22 * @file
     23 * audio channel layout utility functions
     24 */
     25 
     26 #include <stdint.h>
     27 #include <stdlib.h>
     28 #include <string.h>
     29 
     30 #include "avassert.h"
     31 #include "channel_layout.h"
     32 #include "bprint.h"
     33 #include "common.h"
     34 #include "error.h"
     35 #include "macros.h"
     36 #include "mem.h"
     37 #include "opt.h"
     38 
     39 #define CHAN_IS_AMBI(x) ((x) >= AV_CHAN_AMBISONIC_BASE &&\
     40                         (x) <= AV_CHAN_AMBISONIC_END)
     41 
     42 struct channel_name {
     43    const char *name;
     44    const char *description;
     45 };
     46 
     47 static const struct channel_name channel_names[] = {
     48    [AV_CHAN_FRONT_LEFT           ] = { "FL",        "front left"            },
     49    [AV_CHAN_FRONT_RIGHT          ] = { "FR",        "front right"           },
     50    [AV_CHAN_FRONT_CENTER         ] = { "FC",        "front center"          },
     51    [AV_CHAN_LOW_FREQUENCY        ] = { "LFE",       "low frequency"         },
     52    [AV_CHAN_BACK_LEFT            ] = { "BL",        "back left"             },
     53    [AV_CHAN_BACK_RIGHT           ] = { "BR",        "back right"            },
     54    [AV_CHAN_FRONT_LEFT_OF_CENTER ] = { "FLC",       "front left-of-center"  },
     55    [AV_CHAN_FRONT_RIGHT_OF_CENTER] = { "FRC",       "front right-of-center" },
     56    [AV_CHAN_BACK_CENTER          ] = { "BC",        "back center"           },
     57    [AV_CHAN_SIDE_LEFT            ] = { "SL",        "side left"             },
     58    [AV_CHAN_SIDE_RIGHT           ] = { "SR",        "side right"            },
     59    [AV_CHAN_TOP_CENTER           ] = { "TC",        "top center"            },
     60    [AV_CHAN_TOP_FRONT_LEFT       ] = { "TFL",       "top front left"        },
     61    [AV_CHAN_TOP_FRONT_CENTER     ] = { "TFC",       "top front center"      },
     62    [AV_CHAN_TOP_FRONT_RIGHT      ] = { "TFR",       "top front right"       },
     63    [AV_CHAN_TOP_BACK_LEFT        ] = { "TBL",       "top back left"         },
     64    [AV_CHAN_TOP_BACK_CENTER      ] = { "TBC",       "top back center"       },
     65    [AV_CHAN_TOP_BACK_RIGHT       ] = { "TBR",       "top back right"        },
     66    [AV_CHAN_STEREO_LEFT          ] = { "DL",        "downmix left"          },
     67    [AV_CHAN_STEREO_RIGHT         ] = { "DR",        "downmix right"         },
     68    [AV_CHAN_WIDE_LEFT            ] = { "WL",        "wide left"             },
     69    [AV_CHAN_WIDE_RIGHT           ] = { "WR",        "wide right"            },
     70    [AV_CHAN_SURROUND_DIRECT_LEFT ] = { "SDL",       "surround direct left"  },
     71    [AV_CHAN_SURROUND_DIRECT_RIGHT] = { "SDR",       "surround direct right" },
     72    [AV_CHAN_LOW_FREQUENCY_2      ] = { "LFE2",      "low frequency 2"       },
     73    [AV_CHAN_TOP_SIDE_LEFT        ] = { "TSL",       "top side left"         },
     74    [AV_CHAN_TOP_SIDE_RIGHT       ] = { "TSR",       "top side right"        },
     75    [AV_CHAN_BOTTOM_FRONT_CENTER  ] = { "BFC",       "bottom front center"   },
     76    [AV_CHAN_BOTTOM_FRONT_LEFT    ] = { "BFL",       "bottom front left"     },
     77    [AV_CHAN_BOTTOM_FRONT_RIGHT   ] = { "BFR",       "bottom front right"    },
     78    [AV_CHAN_SIDE_SURROUND_LEFT   ] = { "SSL",       "side surround left"    },
     79    [AV_CHAN_SIDE_SURROUND_RIGHT  ] = { "SSR",       "side surround right"   },
     80    [AV_CHAN_TOP_SURROUND_LEFT    ] = { "TTL",       "top surround left"     },
     81    [AV_CHAN_TOP_SURROUND_RIGHT   ] = { "TTR",       "top surround right"    },
     82    [AV_CHAN_BINAURAL_LEFT        ] = { "BIL",       "binaural left"         },
     83    [AV_CHAN_BINAURAL_RIGHT       ] = { "BIR",       "binaural right"        },
     84 };
     85 
     86 void av_channel_name_bprint(AVBPrint *bp, enum AVChannel channel_id)
     87 {
     88    if (channel_id >= AV_CHAN_AMBISONIC_BASE &&
     89        channel_id <= AV_CHAN_AMBISONIC_END)
     90        av_bprintf(bp, "AMBI%d", channel_id - AV_CHAN_AMBISONIC_BASE);
     91    else if ((unsigned)channel_id < FF_ARRAY_ELEMS(channel_names) &&
     92             channel_names[channel_id].name)
     93        av_bprintf(bp, "%s", channel_names[channel_id].name);
     94    else if (channel_id == AV_CHAN_NONE)
     95        av_bprintf(bp, "NONE");
     96    else if (channel_id == AV_CHAN_UNKNOWN)
     97        av_bprintf(bp, "UNK");
     98    else if (channel_id == AV_CHAN_UNUSED)
     99        av_bprintf(bp, "UNSD");
    100    else
    101        av_bprintf(bp, "USR%d", channel_id);
    102 }
    103 
    104 int av_channel_name(char *buf, size_t buf_size, enum AVChannel channel_id)
    105 {
    106    AVBPrint bp;
    107 
    108    if (!buf && buf_size)
    109        return AVERROR(EINVAL);
    110 
    111    av_bprint_init_for_buffer(&bp, buf, buf_size);
    112    av_channel_name_bprint(&bp, channel_id);
    113 
    114    if (bp.len >= INT_MAX)
    115        return AVERROR(ERANGE);
    116    return bp.len + 1;
    117 }
    118 
    119 void av_channel_description_bprint(AVBPrint *bp, enum AVChannel channel_id)
    120 {
    121    if (channel_id >= AV_CHAN_AMBISONIC_BASE &&
    122        channel_id <= AV_CHAN_AMBISONIC_END)
    123        av_bprintf(bp, "ambisonic ACN %d", channel_id - AV_CHAN_AMBISONIC_BASE);
    124    else if ((unsigned)channel_id < FF_ARRAY_ELEMS(channel_names) &&
    125             channel_names[channel_id].description)
    126        av_bprintf(bp, "%s", channel_names[channel_id].description);
    127    else if (channel_id == AV_CHAN_NONE)
    128        av_bprintf(bp, "none");
    129    else if (channel_id == AV_CHAN_UNKNOWN)
    130        av_bprintf(bp, "unknown");
    131    else if (channel_id == AV_CHAN_UNUSED)
    132        av_bprintf(bp, "unused");
    133    else
    134        av_bprintf(bp, "user %d", channel_id);
    135 }
    136 
    137 int av_channel_description(char *buf, size_t buf_size, enum AVChannel channel_id)
    138 {
    139    AVBPrint bp;
    140 
    141    if (!buf && buf_size)
    142        return AVERROR(EINVAL);
    143 
    144    av_bprint_init_for_buffer(&bp, buf, buf_size);
    145    av_channel_description_bprint(&bp, channel_id);
    146 
    147    if (bp.len >= INT_MAX)
    148        return AVERROR(ERANGE);
    149    return bp.len + 1;
    150 }
    151 
    152 enum AVChannel av_channel_from_string(const char *str)
    153 {
    154    int i;
    155    char *endptr = (char *)str;
    156    enum AVChannel id = AV_CHAN_NONE;
    157 
    158    if (!strncmp(str, "AMBI", 4)) {
    159        i = strtol(str + 4, NULL, 0);
    160        if (i < 0 || i > AV_CHAN_AMBISONIC_END - AV_CHAN_AMBISONIC_BASE)
    161            return AV_CHAN_NONE;
    162        return AV_CHAN_AMBISONIC_BASE + i;
    163    }
    164 
    165    for (i = 0; i < FF_ARRAY_ELEMS(channel_names); i++) {
    166        if (channel_names[i].name && !strcmp(str, channel_names[i].name))
    167            return i;
    168    }
    169    if (!strcmp(str, "UNK"))
    170        return AV_CHAN_UNKNOWN;
    171    if (!strcmp(str, "UNSD"))
    172        return AV_CHAN_UNUSED;
    173 
    174    if (!strncmp(str, "USR", 3)) {
    175        const char *p = str + 3;
    176        id = strtol(p, &endptr, 0);
    177    }
    178    if (id >= 0 && !*endptr)
    179        return id;
    180 
    181    return AV_CHAN_NONE;
    182 }
    183 
    184 struct channel_layout_name {
    185    const char *name;
    186    AVChannelLayout layout;
    187 };
    188 
    189 static const struct channel_layout_name channel_layout_map[] = {
    190    { "mono",           AV_CHANNEL_LAYOUT_MONO                },
    191    { "stereo",         AV_CHANNEL_LAYOUT_STEREO              },
    192    { "2.1",            AV_CHANNEL_LAYOUT_2POINT1             },
    193    { "3.0",            AV_CHANNEL_LAYOUT_SURROUND            },
    194    { "3.0(back)",      AV_CHANNEL_LAYOUT_2_1                 },
    195    { "4.0",            AV_CHANNEL_LAYOUT_4POINT0             },
    196    { "quad",           AV_CHANNEL_LAYOUT_QUAD                },
    197    { "quad(side)",     AV_CHANNEL_LAYOUT_2_2                 },
    198    { "3.1",            AV_CHANNEL_LAYOUT_3POINT1             },
    199    { "5.0",            AV_CHANNEL_LAYOUT_5POINT0_BACK        },
    200    { "5.0(side)",      AV_CHANNEL_LAYOUT_5POINT0             },
    201    { "4.1",            AV_CHANNEL_LAYOUT_4POINT1             },
    202    { "5.1",            AV_CHANNEL_LAYOUT_5POINT1_BACK        },
    203    { "5.1(side)",      AV_CHANNEL_LAYOUT_5POINT1             },
    204    { "6.0",            AV_CHANNEL_LAYOUT_6POINT0             },
    205    { "6.0(front)",     AV_CHANNEL_LAYOUT_6POINT0_FRONT       },
    206    { "3.1.2",          AV_CHANNEL_LAYOUT_3POINT1POINT2       },
    207    { "hexagonal",      AV_CHANNEL_LAYOUT_HEXAGONAL           },
    208    { "6.1",            AV_CHANNEL_LAYOUT_6POINT1             },
    209    { "6.1(back)",      AV_CHANNEL_LAYOUT_6POINT1_BACK        },
    210    { "6.1(front)",     AV_CHANNEL_LAYOUT_6POINT1_FRONT       },
    211    { "7.0",            AV_CHANNEL_LAYOUT_7POINT0             },
    212    { "7.0(front)",     AV_CHANNEL_LAYOUT_7POINT0_FRONT       },
    213    { "7.1",            AV_CHANNEL_LAYOUT_7POINT1             },
    214    { "7.1(wide)",      AV_CHANNEL_LAYOUT_7POINT1_WIDE_BACK   },
    215    { "7.1(wide-side)", AV_CHANNEL_LAYOUT_7POINT1_WIDE        },
    216    { "5.1.2",          AV_CHANNEL_LAYOUT_5POINT1POINT2       },
    217    { "5.1.2(back)",    AV_CHANNEL_LAYOUT_5POINT1POINT2_BACK  },
    218    { "octagonal",      AV_CHANNEL_LAYOUT_OCTAGONAL           },
    219    { "cube",           AV_CHANNEL_LAYOUT_CUBE                },
    220    { "5.1.4",          AV_CHANNEL_LAYOUT_5POINT1POINT4_BACK  },
    221    { "7.1.2",          AV_CHANNEL_LAYOUT_7POINT1POINT2       },
    222    { "7.1.4",          AV_CHANNEL_LAYOUT_7POINT1POINT4_BACK  },
    223    { "7.2.3",          AV_CHANNEL_LAYOUT_7POINT2POINT3       },
    224    { "9.1.4",          AV_CHANNEL_LAYOUT_9POINT1POINT4_BACK  },
    225    { "9.1.6",          AV_CHANNEL_LAYOUT_9POINT1POINT6       },
    226    { "hexadecagonal",  AV_CHANNEL_LAYOUT_HEXADECAGONAL       },
    227    { "binaural",       AV_CHANNEL_LAYOUT_BINAURAL            },
    228    { "downmix",        AV_CHANNEL_LAYOUT_STEREO_DOWNMIX,     },
    229    { "22.2",           AV_CHANNEL_LAYOUT_22POINT2,           },
    230 };
    231 
    232 int av_channel_layout_custom_init(AVChannelLayout *channel_layout, int nb_channels)
    233 {
    234    AVChannelCustom *map;
    235 
    236    if (nb_channels <= 0)
    237        return AVERROR(EINVAL);
    238 
    239    map = av_calloc(nb_channels, sizeof(*channel_layout->u.map));
    240    if (!map)
    241        return AVERROR(ENOMEM);
    242    for (int i = 0; i < nb_channels; i++)
    243        map[i].id = AV_CHAN_UNKNOWN;
    244 
    245    channel_layout->order       = AV_CHANNEL_ORDER_CUSTOM;
    246    channel_layout->nb_channels = nb_channels;
    247    channel_layout->u.map       = map;
    248 
    249    return 0;
    250 }
    251 
    252 int av_channel_layout_from_mask(AVChannelLayout *channel_layout,
    253                                uint64_t mask)
    254 {
    255    if (!mask)
    256        return AVERROR(EINVAL);
    257 
    258    channel_layout->order       = AV_CHANNEL_ORDER_NATIVE;
    259    channel_layout->nb_channels = av_popcount64(mask);
    260    channel_layout->u.mask      = mask;
    261 
    262    return 0;
    263 }
    264 
    265 static int parse_channel_list(AVChannelLayout *ch_layout, const char *str)
    266 {
    267    int ret;
    268    int nb_channels = 0;
    269    AVChannelCustom *map = NULL;
    270    AVChannelCustom custom = {0};
    271 
    272    while (*str) {
    273        char *channel, *chname;
    274        int ret = av_opt_get_key_value(&str, "@", "+", AV_OPT_FLAG_IMPLICIT_KEY, &channel, &chname);
    275        if (ret < 0) {
    276            av_freep(&map);
    277            return ret;
    278        }
    279        if (*str)
    280            str++; // skip separator
    281        if (!channel) {
    282            channel = chname;
    283            chname = NULL;
    284        }
    285        av_strlcpy(custom.name, chname ? chname : "", sizeof(custom.name));
    286        custom.id = av_channel_from_string(channel);
    287        av_free(channel);
    288        av_free(chname);
    289        if (custom.id == AV_CHAN_NONE) {
    290            av_freep(&map);
    291            return AVERROR(EINVAL);
    292        }
    293 
    294        av_dynarray2_add((void **)&map, &nb_channels, sizeof(custom), (void *)&custom);
    295        if (!map)
    296            return AVERROR(ENOMEM);
    297    }
    298 
    299    if (!nb_channels)
    300        return AVERROR(EINVAL);
    301 
    302    ch_layout->order = AV_CHANNEL_ORDER_CUSTOM;
    303    ch_layout->u.map = map;
    304    ch_layout->nb_channels = nb_channels;
    305 
    306    ret = av_channel_layout_retype(ch_layout, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL);
    307    av_assert0(ret == 0);
    308 
    309    return 0;
    310 }
    311 
    312 int av_channel_layout_from_string(AVChannelLayout *channel_layout,
    313                                  const char *str)
    314 {
    315    int i, matches, ret;
    316    int channels = 0, nb_channels = 0;
    317    char *chlist, *end;
    318    uint64_t mask = 0;
    319 
    320    /* channel layout names */
    321    for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); i++) {
    322        if (channel_layout_map[i].name && !strcmp(str, channel_layout_map[i].name)) {
    323            *channel_layout = channel_layout_map[i].layout;
    324            return 0;
    325        }
    326    }
    327 
    328    /* This function is a channel layout initializer, so we have to
    329     * zero-initialize before we start setting fields individually. */
    330    memset(channel_layout, 0, sizeof(*channel_layout));
    331 
    332    /* ambisonic */
    333    if (!strncmp(str, "ambisonic ", 10)) {
    334        const char *p = str + 10;
    335        char *endptr;
    336        AVChannelLayout extra = {0};
    337        int order;
    338 
    339        order = strtol(p, &endptr, 0);
    340        if (order < 0 || order + 1  > INT_MAX / (order + 1) ||
    341            (*endptr && *endptr != '+'))
    342            return AVERROR(EINVAL);
    343 
    344        channel_layout->order       = AV_CHANNEL_ORDER_AMBISONIC;
    345        channel_layout->nb_channels = (order + 1) * (order + 1);
    346 
    347        if (*endptr) {
    348            int ret = av_channel_layout_from_string(&extra, endptr + 1);
    349            if (ret < 0)
    350                return ret;
    351            if (extra.nb_channels >= INT_MAX - channel_layout->nb_channels) {
    352                av_channel_layout_uninit(&extra);
    353                return AVERROR(EINVAL);
    354            }
    355 
    356            if (extra.order == AV_CHANNEL_ORDER_NATIVE) {
    357                channel_layout->u.mask = extra.u.mask;
    358            } else {
    359                channel_layout->order = AV_CHANNEL_ORDER_CUSTOM;
    360                channel_layout->u.map =
    361                    av_calloc(channel_layout->nb_channels + extra.nb_channels,
    362                              sizeof(*channel_layout->u.map));
    363                if (!channel_layout->u.map) {
    364                    av_channel_layout_uninit(&extra);
    365                    return AVERROR(ENOMEM);
    366                }
    367 
    368                for (i = 0; i < channel_layout->nb_channels; i++)
    369                    channel_layout->u.map[i].id = AV_CHAN_AMBISONIC_BASE + i;
    370                for (i = 0; i < extra.nb_channels; i++) {
    371                    enum AVChannel ch = av_channel_layout_channel_from_index(&extra, i);
    372                    if (CHAN_IS_AMBI(ch)) {
    373                        av_channel_layout_uninit(channel_layout);
    374                        av_channel_layout_uninit(&extra);
    375                        return AVERROR(EINVAL);
    376                    }
    377                    channel_layout->u.map[channel_layout->nb_channels + i].id = ch;
    378                    if (extra.order == AV_CHANNEL_ORDER_CUSTOM &&
    379                        extra.u.map[i].name[0])
    380                        av_strlcpy(channel_layout->u.map[channel_layout->nb_channels + i].name,
    381                                   extra.u.map[i].name,
    382                                   sizeof(channel_layout->u.map[channel_layout->nb_channels + i].name));
    383                }
    384            }
    385            channel_layout->nb_channels += extra.nb_channels;
    386            av_channel_layout_uninit(&extra);
    387        }
    388 
    389        return 0;
    390    }
    391 
    392    chlist = av_strdup(str);
    393    if (!chlist)
    394        return AVERROR(ENOMEM);
    395 
    396    /* channel names */
    397    matches = av_sscanf(str, "%d channels (%[^)]", &nb_channels, chlist);
    398    ret = parse_channel_list(channel_layout, chlist);
    399    av_freep(&chlist);
    400    if (ret < 0 && ret != AVERROR(EINVAL))
    401        return ret;
    402 
    403    if (ret >= 0) {
    404        end = strchr(str, ')');
    405        if (matches == 2 && (nb_channels != channel_layout->nb_channels || !end || *++end)) {
    406            av_channel_layout_uninit(channel_layout);
    407            return AVERROR(EINVAL);
    408        }
    409        return 0;
    410    }
    411 
    412    errno = 0;
    413    mask = strtoull(str, &end, 0);
    414 
    415    /* channel layout mask */
    416    if (!errno && !*end && !strchr(str, '-') && mask) {
    417        av_channel_layout_from_mask(channel_layout, mask);
    418        return 0;
    419    }
    420 
    421    errno = 0;
    422    channels = strtol(str, &end, 10);
    423 
    424    /* number of channels */
    425    if (!errno && !strcmp(end, "c") && channels > 0) {
    426        av_channel_layout_default(channel_layout, channels);
    427        if (channel_layout->order == AV_CHANNEL_ORDER_NATIVE)
    428            return 0;
    429    }
    430 
    431    /* number of unordered channels */
    432    if (!errno && (!strcmp(end, "C") || !strcmp(end, " channels"))
    433        && channels > 0) {
    434        channel_layout->order = AV_CHANNEL_ORDER_UNSPEC;
    435        channel_layout->nb_channels = channels;
    436        return 0;
    437    }
    438 
    439    return AVERROR(EINVAL);
    440 }
    441 
    442 void av_channel_layout_uninit(AVChannelLayout *channel_layout)
    443 {
    444    if (channel_layout->order == AV_CHANNEL_ORDER_CUSTOM)
    445        av_freep(&channel_layout->u.map);
    446    memset(channel_layout, 0, sizeof(*channel_layout));
    447 }
    448 
    449 int av_channel_layout_copy(AVChannelLayout *dst, const AVChannelLayout *src)
    450 {
    451    av_channel_layout_uninit(dst);
    452    *dst = *src;
    453    if (src->order == AV_CHANNEL_ORDER_CUSTOM) {
    454        dst->u.map = av_malloc_array(src->nb_channels, sizeof(*dst->u.map));
    455        if (!dst->u.map)
    456            return AVERROR(ENOMEM);
    457        memcpy(dst->u.map, src->u.map, src->nb_channels * sizeof(*src->u.map));
    458    }
    459    return 0;
    460 }
    461 
    462 static int64_t masked_description(const AVChannelLayout *channel_layout, int start_channel)
    463 {
    464    uint64_t mask = 0;
    465    for (int i = start_channel; i < channel_layout->nb_channels; i++) {
    466        enum AVChannel ch = channel_layout->u.map[i].id;
    467        if (ch >= 0 && ch < 63 && mask < (1ULL << ch))
    468            mask |= (1ULL << ch);
    469        else
    470            return AVERROR(EINVAL);
    471    }
    472    return mask;
    473 }
    474 
    475 static int has_channel_names(const AVChannelLayout *channel_layout)
    476 {
    477    if (channel_layout->order != AV_CHANNEL_ORDER_CUSTOM)
    478        return 0;
    479    for (int i = 0; i < channel_layout->nb_channels; i++)
    480        if (channel_layout->u.map[i].name[0])
    481            return 1;
    482    return 0;
    483 }
    484 
    485 int av_channel_layout_ambisonic_order(const AVChannelLayout *channel_layout)
    486 {
    487    int i, highest_ambi, order;
    488 
    489    if (channel_layout->order != AV_CHANNEL_ORDER_AMBISONIC &&
    490        channel_layout->order != AV_CHANNEL_ORDER_CUSTOM)
    491        return AVERROR(EINVAL);
    492 
    493    highest_ambi = -1;
    494    if (channel_layout->order == AV_CHANNEL_ORDER_AMBISONIC)
    495        highest_ambi = channel_layout->nb_channels - av_popcount64(channel_layout->u.mask) - 1;
    496    else {
    497        const AVChannelCustom *map = channel_layout->u.map;
    498        av_assert0(channel_layout->order == AV_CHANNEL_ORDER_CUSTOM);
    499 
    500        for (i = 0; i < channel_layout->nb_channels; i++) {
    501            int is_ambi = CHAN_IS_AMBI(map[i].id);
    502 
    503            /* ambisonic following non-ambisonic */
    504            if (i > 0 && is_ambi && !CHAN_IS_AMBI(map[i - 1].id))
    505                return AVERROR(EINVAL);
    506 
    507            /* non-default ordering */
    508            if (is_ambi && map[i].id - AV_CHAN_AMBISONIC_BASE != i)
    509                return AVERROR(EINVAL);
    510 
    511            if (CHAN_IS_AMBI(map[i].id))
    512                highest_ambi = i;
    513        }
    514    }
    515    /* no ambisonic channels*/
    516    if (highest_ambi < 0)
    517        return AVERROR(EINVAL);
    518 
    519    order = floor(sqrt(highest_ambi));
    520    /* incomplete order - some harmonics are missing */
    521    if ((order + 1) * (order + 1) != highest_ambi + 1)
    522        return AVERROR(EINVAL);
    523 
    524    return order;
    525 }
    526 
    527 static enum AVChannelOrder canonical_order(AVChannelLayout *channel_layout)
    528 {
    529    int has_known_channel = 0;
    530    int order;
    531 
    532    if (channel_layout->order != AV_CHANNEL_ORDER_CUSTOM)
    533        return channel_layout->order;
    534 
    535    if (has_channel_names(channel_layout))
    536        return AV_CHANNEL_ORDER_CUSTOM;
    537 
    538    for (int i = 0; i < channel_layout->nb_channels && !has_known_channel; i++)
    539        if (channel_layout->u.map[i].id != AV_CHAN_UNKNOWN)
    540            has_known_channel = 1;
    541    if (!has_known_channel)
    542        return AV_CHANNEL_ORDER_UNSPEC;
    543 
    544    if (masked_description(channel_layout, 0) > 0)
    545        return AV_CHANNEL_ORDER_NATIVE;
    546 
    547    order = av_channel_layout_ambisonic_order(channel_layout);
    548    if (order >= 0 && masked_description(channel_layout, (order + 1) * (order + 1)) >= 0)
    549        return AV_CHANNEL_ORDER_AMBISONIC;
    550 
    551    return AV_CHANNEL_ORDER_CUSTOM;
    552 }
    553 
    554 /**
    555 * If the custom layout is n-th order standard-order ambisonic, with optional
    556 * extra non-diegetic channels at the end, write its string description in bp.
    557 * Return a negative error code otherwise.
    558 */
    559 static int try_describe_ambisonic(AVBPrint *bp, const AVChannelLayout *channel_layout)
    560 {
    561    int nb_ambi_channels;
    562    int order = av_channel_layout_ambisonic_order(channel_layout);
    563    if (order < 0)
    564        return order;
    565 
    566    av_bprintf(bp, "ambisonic %d", order);
    567 
    568    /* extra channels present */
    569    nb_ambi_channels = (order + 1) * (order + 1);
    570    if (nb_ambi_channels < channel_layout->nb_channels) {
    571        AVChannelLayout extra = { 0 };
    572 
    573        if (channel_layout->order == AV_CHANNEL_ORDER_AMBISONIC) {
    574            extra.order       = AV_CHANNEL_ORDER_NATIVE;
    575            extra.nb_channels = av_popcount64(channel_layout->u.mask);
    576            extra.u.mask      = channel_layout->u.mask;
    577        } else {
    578            int64_t mask;
    579            if (!has_channel_names(channel_layout) &&
    580                (mask = masked_description(channel_layout, nb_ambi_channels)) > 0) {
    581                extra.order       = AV_CHANNEL_ORDER_NATIVE;
    582                extra.nb_channels = av_popcount64(mask);
    583                extra.u.mask      = mask;
    584            } else {
    585                extra.order       = AV_CHANNEL_ORDER_CUSTOM;
    586                extra.nb_channels = channel_layout->nb_channels - nb_ambi_channels;
    587                extra.u.map       = channel_layout->u.map + nb_ambi_channels;
    588            }
    589        }
    590 
    591        av_bprint_chars(bp, '+', 1);
    592        av_channel_layout_describe_bprint(&extra, bp);
    593        /* Not calling uninit here on extra because we don't own the u.map pointer */
    594    }
    595 
    596    return 0;
    597 }
    598 
    599 int av_channel_layout_describe_bprint(const AVChannelLayout *channel_layout,
    600                                      AVBPrint *bp)
    601 {
    602    int i;
    603 
    604    switch (channel_layout->order) {
    605    case AV_CHANNEL_ORDER_NATIVE:
    606        for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); i++)
    607            if (channel_layout->u.mask == channel_layout_map[i].layout.u.mask) {
    608                av_bprintf(bp, "%s", channel_layout_map[i].name);
    609                return 0;
    610            }
    611        // fall-through
    612    case AV_CHANNEL_ORDER_CUSTOM:
    613        if (channel_layout->order == AV_CHANNEL_ORDER_CUSTOM) {
    614            int64_t mask;
    615            int res = try_describe_ambisonic(bp, channel_layout);
    616            if (res >= 0)
    617                return 0;
    618            if (!has_channel_names(channel_layout) &&
    619                (mask = masked_description(channel_layout, 0)) > 0) {
    620                AVChannelLayout native = { .order       = AV_CHANNEL_ORDER_NATIVE,
    621                                           .nb_channels = av_popcount64(mask),
    622                                           .u.mask      = mask };
    623                return av_channel_layout_describe_bprint(&native, bp);
    624            }
    625        }
    626        if (channel_layout->nb_channels)
    627            av_bprintf(bp, "%d channels (", channel_layout->nb_channels);
    628        for (i = 0; i < channel_layout->nb_channels; i++) {
    629            enum AVChannel ch = av_channel_layout_channel_from_index(channel_layout, i);
    630 
    631            if (i)
    632                av_bprintf(bp, "+");
    633            av_channel_name_bprint(bp, ch);
    634            if (channel_layout->order == AV_CHANNEL_ORDER_CUSTOM &&
    635                channel_layout->u.map[i].name[0])
    636                av_bprintf(bp, "@%s", channel_layout->u.map[i].name);
    637        }
    638        if (channel_layout->nb_channels) {
    639            av_bprintf(bp, ")");
    640            return 0;
    641        }
    642        // fall-through
    643    case AV_CHANNEL_ORDER_UNSPEC:
    644        av_bprintf(bp, "%d channels", channel_layout->nb_channels);
    645        return 0;
    646    case AV_CHANNEL_ORDER_AMBISONIC:
    647        return try_describe_ambisonic(bp, channel_layout);
    648    default:
    649        return AVERROR(EINVAL);
    650    }
    651 }
    652 
    653 int av_channel_layout_describe(const AVChannelLayout *channel_layout,
    654                               char *buf, size_t buf_size)
    655 {
    656    AVBPrint bp;
    657    int ret;
    658 
    659    if (!buf && buf_size)
    660        return AVERROR(EINVAL);
    661 
    662    av_bprint_init_for_buffer(&bp, buf, buf_size);
    663    ret = av_channel_layout_describe_bprint(channel_layout, &bp);
    664    if (ret < 0)
    665        return ret;
    666 
    667    if (bp.len >= INT_MAX)
    668        return AVERROR(ERANGE);
    669    return bp.len + 1;
    670 }
    671 
    672 enum AVChannel
    673 av_channel_layout_channel_from_index(const AVChannelLayout *channel_layout,
    674                                     unsigned int idx)
    675 {
    676    int i;
    677 
    678    if (idx >= channel_layout->nb_channels)
    679        return AV_CHAN_NONE;
    680 
    681    switch (channel_layout->order) {
    682    case AV_CHANNEL_ORDER_CUSTOM:
    683        return channel_layout->u.map[idx].id;
    684    case AV_CHANNEL_ORDER_AMBISONIC: {
    685        int ambi_channels = channel_layout->nb_channels - av_popcount64(channel_layout->u.mask);
    686        if (idx < ambi_channels)
    687            return AV_CHAN_AMBISONIC_BASE + idx;
    688        idx -= ambi_channels;
    689        }
    690    // fall-through
    691    case AV_CHANNEL_ORDER_NATIVE:
    692        for (i = 0; i < 64; i++) {
    693            if ((1ULL << i) & channel_layout->u.mask && !idx--)
    694                return i;
    695        }
    696    default:
    697        return AV_CHAN_NONE;
    698    }
    699 }
    700 
    701 enum AVChannel
    702 av_channel_layout_channel_from_string(const AVChannelLayout *channel_layout,
    703                                      const char *str)
    704 {
    705    int index = av_channel_layout_index_from_string(channel_layout, str);
    706 
    707    if (index < 0)
    708        return AV_CHAN_NONE;
    709 
    710    return av_channel_layout_channel_from_index(channel_layout, index);
    711 }
    712 
    713 int av_channel_layout_index_from_channel(const AVChannelLayout *channel_layout,
    714                                         enum AVChannel channel)
    715 {
    716    int i;
    717 
    718    if (channel == AV_CHAN_NONE)
    719        return AVERROR(EINVAL);
    720 
    721    switch (channel_layout->order) {
    722    case AV_CHANNEL_ORDER_CUSTOM:
    723        for (i = 0; i < channel_layout->nb_channels; i++)
    724            if (channel_layout->u.map[i].id == channel)
    725                return i;
    726        return AVERROR(EINVAL);
    727    case AV_CHANNEL_ORDER_AMBISONIC:
    728    case AV_CHANNEL_ORDER_NATIVE: {
    729        uint64_t mask = channel_layout->u.mask;
    730        int ambi_channels = channel_layout->nb_channels - av_popcount64(mask);
    731        if (channel_layout->order == AV_CHANNEL_ORDER_AMBISONIC &&
    732            channel >= AV_CHAN_AMBISONIC_BASE) {
    733            if (channel - AV_CHAN_AMBISONIC_BASE >= ambi_channels)
    734                return AVERROR(EINVAL);
    735            return channel - AV_CHAN_AMBISONIC_BASE;
    736        }
    737        if ((unsigned)channel > 63 || !(mask & (1ULL << channel)))
    738            return AVERROR(EINVAL);
    739        mask &= (1ULL << channel) - 1;
    740        return av_popcount64(mask) + ambi_channels;
    741        }
    742    default:
    743        return AVERROR(EINVAL);
    744    }
    745 }
    746 
    747 int av_channel_layout_index_from_string(const AVChannelLayout *channel_layout,
    748                                        const char *str)
    749 {
    750    char *chname;
    751    enum AVChannel ch = AV_CHAN_NONE;
    752 
    753    switch (channel_layout->order) {
    754    case AV_CHANNEL_ORDER_CUSTOM:
    755        chname = strstr(str, "@");
    756        if (chname) {
    757            char buf[16];
    758            chname++;
    759            av_strlcpy(buf, str, FFMIN(sizeof(buf), chname - str));
    760            if (!*chname)
    761                chname = NULL;
    762            ch = av_channel_from_string(buf);
    763            if (ch == AV_CHAN_NONE && *buf)
    764                return AVERROR(EINVAL);
    765        }
    766        for (int i = 0; chname && i < channel_layout->nb_channels; i++) {
    767            if (!strcmp(chname, channel_layout->u.map[i].name) &&
    768                (ch == AV_CHAN_NONE || ch == channel_layout->u.map[i].id))
    769                return i;
    770        }
    771        // fall-through
    772    case AV_CHANNEL_ORDER_AMBISONIC:
    773    case AV_CHANNEL_ORDER_NATIVE:
    774        ch = av_channel_from_string(str);
    775        if (ch == AV_CHAN_NONE)
    776            return AVERROR(EINVAL);
    777        return av_channel_layout_index_from_channel(channel_layout, ch);
    778    }
    779 
    780    return AVERROR(EINVAL);
    781 }
    782 
    783 int av_channel_layout_check(const AVChannelLayout *channel_layout)
    784 {
    785    if (channel_layout->nb_channels <= 0)
    786        return 0;
    787 
    788    switch (channel_layout->order) {
    789    case AV_CHANNEL_ORDER_NATIVE:
    790        return av_popcount64(channel_layout->u.mask) == channel_layout->nb_channels;
    791    case AV_CHANNEL_ORDER_CUSTOM:
    792        if (!channel_layout->u.map)
    793            return 0;
    794        for (int i = 0; i < channel_layout->nb_channels; i++) {
    795            if (channel_layout->u.map[i].id == AV_CHAN_NONE)
    796                return 0;
    797        }
    798        return 1;
    799    case AV_CHANNEL_ORDER_AMBISONIC:
    800        /* If non-diegetic channels are present, ensure they are taken into account */
    801        return av_popcount64(channel_layout->u.mask) < channel_layout->nb_channels;
    802    case AV_CHANNEL_ORDER_UNSPEC:
    803        return 1;
    804    default:
    805        return 0;
    806    }
    807 }
    808 
    809 int av_channel_layout_compare(const AVChannelLayout *chl, const AVChannelLayout *chl1)
    810 {
    811    int i;
    812 
    813    /* different channel counts -> not equal */
    814    if (chl->nb_channels != chl1->nb_channels)
    815        return 1;
    816 
    817    /* if only one is unspecified -> not equal */
    818    if ((chl->order  == AV_CHANNEL_ORDER_UNSPEC) !=
    819        (chl1->order == AV_CHANNEL_ORDER_UNSPEC))
    820        return 1;
    821    /* both are unspecified -> equal */
    822    else if (chl->order == AV_CHANNEL_ORDER_UNSPEC)
    823        return 0;
    824 
    825    /* can compare masks directly */
    826    if ((chl->order == AV_CHANNEL_ORDER_NATIVE ||
    827         chl->order == AV_CHANNEL_ORDER_AMBISONIC) &&
    828        chl->order == chl1->order)
    829        return chl->u.mask != chl1->u.mask;
    830 
    831    /* compare channel by channel */
    832    for (i = 0; i < chl->nb_channels; i++)
    833        if (av_channel_layout_channel_from_index(chl,  i) !=
    834            av_channel_layout_channel_from_index(chl1, i))
    835            return 1;
    836    return 0;
    837 }
    838 
    839 void av_channel_layout_default(AVChannelLayout *ch_layout, int nb_channels)
    840 {
    841    int i;
    842    for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); i++)
    843        if (nb_channels == channel_layout_map[i].layout.nb_channels) {
    844            *ch_layout = channel_layout_map[i].layout;
    845            return;
    846        }
    847 
    848    ch_layout->order       = AV_CHANNEL_ORDER_UNSPEC;
    849    ch_layout->nb_channels = nb_channels;
    850 }
    851 
    852 const AVChannelLayout *av_channel_layout_standard(void **opaque)
    853 {
    854    uintptr_t i = (uintptr_t)*opaque;
    855    const AVChannelLayout *ch_layout = NULL;
    856 
    857    if (i < FF_ARRAY_ELEMS(channel_layout_map)) {
    858        ch_layout = &channel_layout_map[i].layout;
    859        *opaque = (void*)(i + 1);
    860    }
    861 
    862    return ch_layout;
    863 }
    864 
    865 uint64_t av_channel_layout_subset(const AVChannelLayout *channel_layout,
    866                                  uint64_t mask)
    867 {
    868    uint64_t ret = 0;
    869    int i;
    870 
    871    switch (channel_layout->order) {
    872    case AV_CHANNEL_ORDER_NATIVE:
    873    case AV_CHANNEL_ORDER_AMBISONIC:
    874        return channel_layout->u.mask & mask;
    875    case AV_CHANNEL_ORDER_CUSTOM:
    876        for (i = 0; i < 64; i++)
    877            if (mask & (1ULL << i) && av_channel_layout_index_from_channel(channel_layout, i) >= 0)
    878                ret |= (1ULL << i);
    879        break;
    880    }
    881 
    882    return ret;
    883 }
    884 
    885 int av_channel_layout_retype(AVChannelLayout *channel_layout, enum AVChannelOrder order, int flags)
    886 {
    887    int allow_lossy = !(flags & AV_CHANNEL_LAYOUT_RETYPE_FLAG_LOSSLESS);
    888    int lossy;
    889 
    890    if (!av_channel_layout_check(channel_layout))
    891        return AVERROR(EINVAL);
    892 
    893    if (flags & AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL)
    894        order = canonical_order(channel_layout);
    895 
    896    if (channel_layout->order == order)
    897        return 0;
    898 
    899    switch (order) {
    900    case AV_CHANNEL_ORDER_UNSPEC: {
    901        int nb_channels = channel_layout->nb_channels;
    902        if (channel_layout->order == AV_CHANNEL_ORDER_CUSTOM) {
    903            lossy = 0;
    904            for (int i = 0; i < nb_channels; i++) {
    905                if (channel_layout->u.map[i].id != AV_CHAN_UNKNOWN || channel_layout->u.map[i].name[0]) {
    906                    lossy = 1;
    907                    break;
    908                }
    909            }
    910        } else {
    911            lossy = 1;
    912        }
    913        if (!lossy || allow_lossy) {
    914            void *opaque = channel_layout->opaque;
    915            av_channel_layout_uninit(channel_layout);
    916            channel_layout->order       = AV_CHANNEL_ORDER_UNSPEC;
    917            channel_layout->nb_channels = nb_channels;
    918            channel_layout->opaque      = opaque;
    919            return lossy;
    920        }
    921        return AVERROR(ENOSYS);
    922        }
    923    case AV_CHANNEL_ORDER_NATIVE:
    924        if (channel_layout->order == AV_CHANNEL_ORDER_CUSTOM) {
    925            int64_t mask = masked_description(channel_layout, 0);
    926            if (mask < 0)
    927                return AVERROR(ENOSYS);
    928            lossy = has_channel_names(channel_layout);
    929            if (!lossy || allow_lossy) {
    930                void *opaque = channel_layout->opaque;
    931                av_channel_layout_uninit(channel_layout);
    932                av_channel_layout_from_mask(channel_layout, mask);
    933                channel_layout->opaque = opaque;
    934                return lossy;
    935            }
    936        }
    937        return AVERROR(ENOSYS);
    938    case AV_CHANNEL_ORDER_CUSTOM: {
    939        AVChannelLayout custom = { 0 };
    940        int ret = av_channel_layout_custom_init(&custom, channel_layout->nb_channels);
    941        void *opaque = channel_layout->opaque;
    942        if (ret < 0)
    943            return ret;
    944        if (channel_layout->order != AV_CHANNEL_ORDER_UNSPEC)
    945            for (int i = 0; i < channel_layout->nb_channels; i++)
    946                custom.u.map[i].id = av_channel_layout_channel_from_index(channel_layout, i);
    947        av_channel_layout_uninit(channel_layout);
    948        *channel_layout = custom;
    949        channel_layout->opaque = opaque;
    950        return 0;
    951        }
    952    case AV_CHANNEL_ORDER_AMBISONIC:
    953        if (channel_layout->order == AV_CHANNEL_ORDER_CUSTOM) {
    954            int64_t mask;
    955            int nb_channels = channel_layout->nb_channels;
    956            int order = av_channel_layout_ambisonic_order(channel_layout);
    957            if (order < 0)
    958                return AVERROR(ENOSYS);
    959            mask = masked_description(channel_layout, (order + 1) * (order + 1));
    960            if (mask < 0)
    961                return AVERROR(ENOSYS);
    962            lossy = has_channel_names(channel_layout);
    963            if (!lossy || allow_lossy) {
    964                void *opaque = channel_layout->opaque;
    965                av_channel_layout_uninit(channel_layout);
    966                channel_layout->order       = AV_CHANNEL_ORDER_AMBISONIC;
    967                channel_layout->nb_channels = nb_channels;
    968                channel_layout->u.mask      = mask;
    969                channel_layout->opaque      = opaque;
    970                return lossy;
    971            }
    972        }
    973        return AVERROR(ENOSYS);
    974    default:
    975        return AVERROR(EINVAL);
    976    }
    977 }